首頁 > 軟體

Linux或Linux虛擬機器橋接模式使用Python2認證Drcom

2020-06-16 17:25:14

現在很多高校都是使用drcom用戶端管理學生的上網流量等資訊,在Linux下Drcom用戶端版本有的學校可能沒有發布,我們可以使用Python模擬登陸Drcom。

最主要的就是認證的伺服器地址,這個需要抓包分析出ip,自行谷歌,很容易可以實現的

Linux下執行py指令碼 (必須安裝Python2)

命令列: python drclient.py

下面附drclient.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket, struct, time
from hashlib import md5
import sys
import os
import random
 
# CONFIG
server = ''  #認證伺服器地址
username=''  #賬號
password=''  #密碼
CONTROLCHECKSTATUS = 'x08'
ADAPTERNUM = 'x01'
host_ip = ''  #ipv4地址
IPDOG = 'x01'
host_name = 'DRCOMFUCKER'
PRIMARY_DNS = ''  #DNS伺服器
dhcp_server = ''  #DHCP伺服器
AUTH_VERSION = 'x08x00'
mac = 0xMac地址    #Mac地址
host_os = 'WINDIAOS'
KEEP_ALIVE_VERSION = 'xdcx02'
AUTH_VERSION = 'x0ax00'
IPDOG = 'x01'
# CONFIG_END
 
nic_name = '' #Indicate your nic, e.g. 'eth0.2'.nic_name
bind_ip = '0.0.0.0'
 
class ChallengeException (Exception):
    def __init__(self):
        pass
 
class LoginException (Exception):
    def __init__(self):
        pass
 
def bind_nic():
    try:
        import fcntl
        def get_ip_address(ifname):
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            return socket.inet_ntoa(fcntl.ioctl(
                s.fileno(),
                0x8915,  # SIOCGIFADDR
                struct.pack('256s', ifname[:15])
            )[20:24])
        return get_ip_address(nic_name)
    except ImportError as e:
        print('Indicate nic feature need to be run under Unix based system.')
        return '0.0.0.0'
    except IOError as e:
        print(nic_name + 'is unacceptable !')
        return '0.0.0.0'
    finally:
        return '0.0.0.0'
 
if nic_name != '':
    bind_ip = bind_nic()
 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((bind_ip, 61440))
 
s.settimeout(3)
SALT = ''
IS_TEST = True
# specified fields based on version
CONF = "/etc/drcom.conf"
UNLIMITED_RETRY = True
EXCEPTION = False
DEBUG = False #log saves to file
LOG_PATH = '/var/log/drcom_client.log'
if IS_TEST:
    DEBUG = True
    LOG_PATH = 'drcom_client.log'
 
 
def log(*args, **kwargs):
    s = ' '.join(args)
    print s
    if DEBUG:
        with open(LOG_PATH,'a') as f:
            f.write(s + 'n')
 
def challenge(svr,ran):
    while True:
        t = struct.pack("<H", int(ran)%(0xFFFF))
        s.sendto("x01x02"+t+"x09"+"x00"*15, (svr, 61440))
        try:
            data, address = s.recvfrom(1024)
            log('[challenge] recv',data.encode('hex'))
        except:
            log('[challenge] timeout, retrying...')
            continue
       
        if address == (svr, 61440):
            break
        else:
            continue
    log('[DEBUG] challenge:n' + data.encode('hex'))
    if data[0] != 'x02':
        raise ChallengeException
    log('[challenge] challenge packet sent.')
    return data[4:8]
 
def md5sum(s):
    m = md5()
    m.update(s)
    return m.digest()
 
def dump(n):
    s = '%x' % n
    if len(s) & 1:
        s = '0' + s
    return s.decode('hex')
 
# def ror(md5, pwd):
#    ret = ''
#    for i in range(len(pwd)):
#        x = ord(md5[i]) ^ ord(pwd[i])
#        ret += chr(((x<<3)&0xFF) + (x>>5))
#    return ret
 
def keep_alive_package_builder(number,random,tail,type=1,first=False):
    data = 'x07'+ chr(number) + 'x28x00x0b' + chr(type)
    if first :
        data += 'x0fx27'
    else:
        data += KEEP_ALIVE_VERSION
    data += 'x2fx12' + 'x00' * 6
    data += tail
    data += 'x00' * 4
    #data += struct.pack("!H",0xdc02)
    if type == 3:
        foo = ''.join([chr(int(i)) for i in host_ip.split('.')]) # host_ip
        #CRC
        # edited on 2014/5/12, filled zeros to checksum
        # crc = packet_CRC(data+foo)
        crc = 'x00' * 4
        #data += struct.pack("!I",crc) + foo + 'x00' * 8
        data += crc + foo + 'x00' * 8
    else: #packet type = 1
        data += 'x00' * 16
    return data
 
# def packet_CRC(s):
#    ret = 0
#    for i in re.findall('..', s):
#        ret ^= struct.unpack('>h', i)[0]
#        ret &= 0xFFFF
#    ret = ret * 0x2c7
#    return ret
 
def keep_alive2(*args):
    #first keep_alive:
    #number = number (mod 7)
    #status = 1: first packet user sended
    #        2: first packet user recieved
    #        3: 2nd packet user sended
    #        4: 2nd packet user recieved
    #  Codes for test
    tail = ''
    packet = ''
    svr = server
    ran = random.randint(0,0xFFFF)
    ran += random.randint(1,10) 
    # 2014/10/15 add by latyas, maybe svr sends back a file packet
    svr_num = 0
    packet = keep_alive_package_builder(svr_num,dump(ran),'x00'*4,1,True)
    while True:
        log('[keep-alive2] send1',packet.encode('hex'))
        s.sendto(packet, (svr, 61440))
        data, address = s.recvfrom(1024)
        log('[keep-alive2] recv1',data.encode('hex'))
        if data.startswith('x07x00x28x00') or data.startswith('x07' + chr(svr_num)  + 'x28x00'):
            break
        elif data[0] == 'x07' and data[2] == 'x10':
            log('[keep-alive2] recv file, resending..')
            svr_num = svr_num + 1
            packet = keep_alive_package_builder(svr_num,dump(ran),'x00'*4,1, False)
        else:
            log('[keep-alive2] recv1/unexpected',data.encode('hex'))
    #log('[keep-alive2] recv1',data.encode('hex'))
   
    ran += random.randint(1,10) 
    packet = keep_alive_package_builder(svr_num, dump(ran),'x00'*4,1,False)
    log('[keep-alive2] send2',packet.encode('hex'))
    s.sendto(packet, (svr, 61440))
    while True:
        data, address = s.recvfrom(1024)
        if data[0] == 'x07':
            svr_num = svr_num + 1
            break
        else:
            log('[keep-alive2] recv2/unexpected',data.encode('hex'))
    log('[keep-alive2] recv2',data.encode('hex'))
    tail = data[16:20]
   
 
    ran += random.randint(1,10) 
    packet = keep_alive_package_builder(svr_num,dump(ran),tail,3,False)
    log('[keep-alive2] send3',packet.encode('hex'))
    s.sendto(packet, (svr, 61440))
    while True:
        data, address = s.recvfrom(1024)
        if data[0] == 'x07':
            svr_num = svr_num + 1
            break
        else:
            log('[keep-alive2] recv3/unexpected',data.encode('hex'))
    log('[keep-alive2] recv3',data.encode('hex'))
    tail = data[16:20]
    log("[keep-alive2] keep-alive2 loop was in daemon.")
   
    i = svr_num
    while True:
        try:
            ran += random.randint(1,10) 
            packet = keep_alive_package_builder(i,dump(ran),tail,1,False)
            #log('DEBUG: keep_alive2,packet 4n',packet.encode('hex'))
            log('[keep_alive2] send',str(i),packet.encode('hex'))
            s.sendto(packet, (svr, 61440))
            data, address = s.recvfrom(1024)
            log('[keep_alive2] recv',data.encode('hex'))
            tail = data[16:20]
            #log('DEBUG: keep_alive2,packet 4 returnn',data.encode('hex'))
       
            ran += random.randint(1,10) 
            packet = keep_alive_package_builder(i+1,dump(ran),tail,3,False)
            #log('DEBUG: keep_alive2,packet 5n',packet.encode('hex'))
            s.sendto(packet, (svr, 61440))
            log('[keep_alive2] send',str(i+1),packet.encode('hex'))
            data, address = s.recvfrom(1024)
            log('[keep_alive2] recv',data.encode('hex'))
            tail = data[16:20]
            #log('DEBUG: keep_alive2,packet 5 returnn',data.encode('hex'))
            i = (i+2) % 0xFF
            time.sleep(20)
            keep_alive1(*args)
        except:
            pass
 
   
import re
def checksum(s):
    ret = 1234
    for i in re.findall('....', s):
        ret ^= int(i[::-1].encode('hex'), 16)
    ret = (1968 * ret) & 0xffffffff
    return struct.pack('<I', ret)
 
def mkpkt(salt, usr, pwd, mac):
    data = 'x03x01x00'+chr(len(usr)+20)
    data += md5sum('x03x01'+salt+pwd)
    data += usr.ljust(36, 'x00')
    data += CONTROLCHECKSTATUS
    data += ADAPTERNUM
    data += dump(int(data[4:10].encode('hex'),16)^mac).rjust(6,'x00') #mac xor md51
    data += md5sum("x01" + pwd + salt + 'x00'*4) #md52
    data += 'x01' # number of ip
    #data += 'x0ax1ex16x11' #your ip address1, 10.30.22.17
    data += ''.join([chr(int(i)) for i in host_ip.split('.')]) #x.x.x.x ->
    data += '0'*4 #your ipaddress 2
    data += '0'*4 #your ipaddress 3
    data += '0'*4 #your ipaddress 4
    data += md5sum(data + 'x14x00x07x0b')[:8] #md53
    data += IPDOG
    data += 'x00'*4 #delimeter
    data += host_name.ljust(32, 'x00')
    data += ''.join([chr(int(i)) for i in PRIMARY_DNS.split('.')]) #primary dns
    data += ''.join([chr(int(i)) for i in dhcp_server.split('.')]) #DHCP server
    data += 'x00x00x00x00' #secondary dns:0.0.0.0
    data += 'x00' * 8 #delimeter
    data += 'x94x00x00x00' # unknow
    data += 'x05x00x00x00' # os major
    data += 'x01x00x00x00' # os minor
    data += 'x28x0ax00x00' # OS build
    data += 'x02x00x00x00' #os unknown
    data += host_os.ljust(32,'x00')
    data += 'x00' * 96
    #data += 'x01' + host_os.ljust(128, 'x00')
    #data += 'x0ax00x00'+chr(len(pwd)) # x0a represents version of client, algorithm: DRCOM_VER + 100
    #data += ror(md5sum('x03x01'+salt+pwd), pwd)
    data += AUTH_VERSION
    data += 'x02x0c'
    data += checksum(data+'x01x26x07x11x00x00'+dump(mac))
    data += 'x00x00' #delimeter
    data += dump(mac)
    data += 'x00' # auto logout / default: False
    data += 'x00' # broadcast mode / default : False
    data += 'xe9x13' #unknown, filled numbers randomly =w=
   
    log('[mkpkt]',data.encode('hex'))
    return data
 
def login(usr, pwd, svr):
    import random
    global SALT
 
    i = 0
    while True:
        salt = challenge(svr,time.time()+random.randint(0xF,0xFF))
        SALT = salt
        packet = mkpkt(salt, usr, pwd, mac)
        log('[login] send',packet.encode('hex'))
        s.sendto(packet, (svr, 61440))
        data, address = s.recvfrom(1024)
        log('[login] recv',data.encode('hex'))
        log('[login] packet sent.')
        if address == (svr, 61440):
            if data[0] == 'x04':
                log('[login] loged in')
                break
            else:
                log('[login] login failed.')
                if IS_TEST:
                    time.sleep(3)
                else:
                    time.sleep(30)
                continue
        else:
            if i >= 5 and UNLIMITED_RETRY == False :
                log('[login] exception occured.')
                sys.exit(1)
            else:
                continue
           
    log('[login] login sent')
    #0.8 changed:
    return data[23:39]
    #return data[-22:-6]
 
def keep_alive1(salt,tail,pwd,svr):
    foo = struct.pack('!H',int(time.time())%0xFFFF)
    data = 'xff' + md5sum('x03x01'+salt+pwd) + 'x00x00x00'
    data += tail
    data += foo + 'x00x00x00x00'
    log('[keep_alive1] send',data.encode('hex'))
 
    s.sendto(data, (svr, 61440))
    while True:
        data, address = s.recvfrom(1024)
        if data[0] == 'x07':
            break
        else:
            log('[keep-alive1]recv/not expected',data.encode('hex'))
    log('[keep-alive1] recv',data.encode('hex'))
 
def empty_socket_buffer():
#empty buffer for some fucking schools
    log('starting to empty socket buffer')
    try:
        while True:
            data, address = s.recvfrom(1024)
            log('recived sth unexpected',data.encode('hex'))
            if s == '':
                break
    except:
        # get exception means it has done.
        log('exception in empty_socket_buffer')
        pass
    log('emptyed')
def daemon():
    with open('/var/run/jludrcom.pid','w') as f:
        f.write(str(os.getpid()))
       
def main():
    if not IS_TEST:
        daemon()
        execfile(CONF, globals())
    log("auth svr:"+server+"nusername:"+username+"npassword:"+password+"nmac:"+str(hex(mac)))
    log(bind_ip)
    while True:
      try:
        package_tail = login(username, password, server)
      except LoginException:
        continue
      log('package_tail',package_tail.encode('hex'))
      #keep_alive1 is fucking bullshit!
      empty_socket_buffer()
      keep_alive1(SALT,package_tail,password,server)
      keep_alive2(SALT,package_tail,password,server)
if __name__ == "__main__":
    main()

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-12/138766.htm


IT145.com E-mail:sddin#qq.com