diff --git a/newclient.py b/newclient.py index 0dac576..9c8a15f 100644 --- a/newclient.py +++ b/newclient.py @@ -1,385 +1,331 @@ -#!/usr/bin/env python +#! /usr/bin/env python # -*- coding: utf-8 -*- -import socket, struct, time + +import socket, struct, random, time, re, os, datetime from hashlib import md5 -import sys -import os -import random -# CONFIG +########## Configuration ############### + +### Required ### +username='USERNAME' #用户名 +password='PASSWORD' #密码 +host_ip = 'IP_ADDR' #ip地址 +mac = 0x010203040506 #mac地址 echo 0x`ifconfig eth | egrep -io "([0-9a-f]{2}:){5}[0-9a-f]{2}" | tr -d ":"` + +### Optional ### +host_name = '++++++++' #计算机名 +host_os = 'Windows XP' #操作系统 +bind_ip = '0.0.0.0' #must be listed in your `ip a` results +LOG_PATH = '/var/log/drcom.log' +RETRY = False + +### for Development ### +IS_DEBUG=False + server = '10.100.61.3' -username='#@#@#@#@#@'#用户名 -password='@###@#@#@#'#密码 -host_ip = '202.198.171.190'#ip地址 -mac = 0x888888888888#mac地址 -host_name = '++++++++'#计算机名 -host_os = 'Windows 10'#操作系统 + +#used in mkpkt() CONTROLCHECKSTATUS = '\x20' ADAPTERNUM = '\x03' IPDOG = '\x01' PRIMARY_DNS = '10.10.10.10' dhcp_server = '0.0.0.0' AUTH_VERSION = '\x68\x00' + +# used in keep_alive KEEP_ALIVE_VERSION = '\xdc\x02' -# CONFIG_END +############## END ##################### -nic_name = '' #Indicate your nic, e.g. 'eth0.2'.nic_name -bind_ip = '0.0.0.0' +class LoginException (Exception): + def __init__(self): + pass -class ChallengeException (Exception): - def __init__(self): - pass +def setup_socket(bind_ip): + log('DEBUG', 'setup_socket()') + 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) + return s -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(" + data += '\00'*4 #your ipaddress 2 + data += '\00'*4 #your ipaddress 3 + data += '\00'*4 #your ipaddress 4 + data += md5sum(data + '\x14\x00\x07\x0b')[: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 += '\x00\x00\x00\x00' #secondary dns:0.0.0.0 + data += '\x00' * 8 #delimeter + data += '\x94\x00\x00\x00' # unknow + data += '\x06\x00\x00\x00' # os major + data += '\x02\x00\x00\x00' # os minor + data += '\xf0\x23\x00\x00' # OS build + data += '\x02\x00\x00\x00' #os unknown + data += '\x44\x72\x43\x4f\x4d\x00\xcf\x07\x68' + data += '\x00' * 55#unknown string + data += '\x33\x64\x63\x37\x39\x66\x35\x32\x31\x32\x65\x38\x31\x37\x30\x61\x63\x66\x61\x39\x65\x63\x39\x35\x66\x31\x64\x37\x34\x39\x31\x36\x35\x34\x32\x62\x65\x37\x62\x31' + data += '\x00' * 24 + data += AUTH_VERSION + data += '\x00' + chr(len(pwd)) + data += ror(md5sum('\x03\x01'+salt+pwd), pwd) + data += '\x02\x0c' + data += checksum(data+'\x01\x26\x07\x11\x00\x00'+dump(mac)) + data += '\x00\x00' #delimeter + data += dump(mac) + if (len(pwd) / 4) != 4: + data += '\x00' * (len(pwd) / 4)#strange。。。 + data += '\x60\xa2' #unknown, filled numbers randomly =w= + data += '\x00' * 28 + return data + + +def md5sum(str): + log('DEBUG', 'md5sum()') + m = md5() + m.update(str) + return m.digest() + def dump(n): - s = '%x' % n - if len(s) & 1: - s = '0' + s - return s.decode('hex') + log('DEBUG', 'dump()') + 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) + '\x28\x00\x0b' + chr(type) - if first : - data += '\x0f\x27' - else: - data += KEEP_ALIVE_VERSION - data += '\x2f\x12' + '\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('\x07\x00\x28\x00') or data.startswith('\x07' + chr(svr_num) + '\x28\x00'): - 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 4\n',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 return\n',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 5\n',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 return\n',data.encode('hex')) - i = (i+2) % 0xFF - time.sleep(20) - keep_alive1(*args) - except: - pass - - -import re + log('DEBUG', 'ror()') + ret = '' + for i in range(len(pwd)): + x = ord(md5[i]) ^ ord(pwd[i]) + ret += chr(((x<<3)&0xFF) + (x>>5)) + return ret + + 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(' - data += '\00'*4 #your ipaddress 2 - data += '\00'*4 #your ipaddress 3 - data += '\00'*4 #your ipaddress 4 - data += md5sum(data + '\x14\x00\x07\x0b')[: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 += '\x00\x00\x00\x00' #secondary dns:0.0.0.0 - data += '\x00' * 8 #delimeter - data += '\x94\x00\x00\x00' # unknow - data += '\x06\x00\x00\x00' # os major - data += '\x02\x00\x00\x00' # os minor - data += '\xf0\x23\x00\x00' # OS build - data += '\x02\x00\x00\x00' #os unknown - data += '\x44\x72\x43\x4f\x4d\x00\xcf\x07\x68' - data += '\x00' * 55#unknown string - data += '\x33\x64\x63\x37\x39\x66\x35\x32\x31\x32\x65\x38\x31\x37\x30\x61\x63\x66\x61\x39\x65\x63\x39\x35\x66\x31\x64\x37\x34\x39\x31\x36\x35\x34\x32\x62\x65\x37\x62\x31' - data += '\x00' * 24 - data += AUTH_VERSION - data += '\x00' + chr(len(pwd)) - data += ror(md5sum('\x03\x01'+salt+pwd), pwd) - data += '\x02\x0c' - data += checksum(data+'\x01\x26\x07\x11\x00\x00'+dump(mac)) - data += '\x00\x00' #delimeter - data += dump(mac) - if (len(pwd) / 4) != 4: - data += '\x00' * (len(pwd) / 4)#strange。。。 - data += '\x60\xa2' #unknown, filled numbers randomly =w= - data += '\x00' * 28 - log('[mkpkt]',data.encode('hex')) - return data - -def login(usr, pwd, svr): - import random - global SALT + +def keep_alive(pwd, salt, cookie, svr, socket): + log('DEBUG', 'keep_alive') + old_cookie = cookie + keep_alive1(salt, old_cookie, pwd, svr, socket) + + svr_num = 0 + + svr_num, cookie = keep_alive_pre_1(svr_num, cookie, svr, socket) + svr_num, cookie = keep_alive_pre_2(svr_num, cookie, svr, socket) + svr_num, cookie = keep_alive_pre_3(svr_num, cookie, svr, socket) + + i = svr_num + while True: + packet = keep_alive_package_builder(i, cookie, 1, False) + socket.sendto(packet, (svr, 61440)) + data, address = socket.recvfrom(1024) + cookie = data[16:20] - 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('\x03\x01'+salt+pwd) + '\x00\x00\x00' - data += tail - data += foo + '\x00\x00\x00\x00' - log('[keep_alive1] send',data.encode('hex')) - - s.sendto(data, (svr, 61440)) + packet = keep_alive_package_builder(i+1, cookie, 3, False) + socket.sendto(packet, (svr, 61440)) + data, address = socket.recvfrom(1024) + cookie = data[16:20] + + i = (i+2) % 0xFF + time.sleep(20) + keep_alive1(salt, old_cookie, pwd, svr, socket) + + +def keep_alive1(salt, cookie, pwd, svr, socket): + log('DEBUG', 'keep_alive1()') + foo = struct.pack('!H',int(time.time())%0xFFFF) + data = '\xff' + md5sum('\x03\x01'+salt+pwd) + '\x00\x00\x00' + data += cookie + data += foo + '\x00\x00\x00\x00' + log('DEBUG', 'send:'+data.encode('hex')) + socket.sendto(data, (svr, 61440)) + while True: + data, address = socket.recvfrom(1024) + log('DEBUG', 'recv:'+data.encode('hex')) + if data[0] == '\x07': + break + else: + log('WARN', 'unexpected recv:'+data.encode('hex')) + + +def keep_alive_pre_1(svr_num, cookie, svr, socket): + log('DEBUG', 'keep_alive_pre_1()') + packet = keep_alive_package_builder(svr_num, '\x00'*4, 1, True) + log('DEBUG', 'send:'+packet.encode('hex')) + while True: + socket.sendto(packet, (svr, 61440)) + data, address = socket.recvfrom(1024) + log('DEBUG', 'recv:'+data.encode('hex')) + if data.startswith('\x07\x00\x28\x00') or data.startswith('\x07' + chr(svr_num) + '\x28\x00'): + break + # 2014/10/15 add by latyas, maybe svr sends back a file packet + elif data[0] == '\x07' and data[2] == '\x10': + svr_num = svr_num + 1 + packet = keep_alive_package_builder(svr_num, '\x00'*4, 1, False) + else: + log('WARN', 'unexpected recv:'+data.encode('hex')) + return svr_num, None + +def keep_alive_pre_2(svr_num, cookie, svr, socket): + log('DEBUG', 'keep_alive_pre_2()') + packet = keep_alive_package_builder(svr_num, '\x00'*4, 1, False) + log('DEBUG', 'send:'+packet.encode('hex')) + socket.sendto(packet, (svr, 61440)) + while True: + data, address = socket.recvfrom(1024) + log('DEBUG', 'recv:'+data.encode('hex')) + if data[0] == '\x07': + svr_num = svr_num + 1 + break + else: + log('WARN', 'unexpected recv:'+data.encode('hex')) + cookie = data[16:20] + return svr_num, cookie + +def keep_alive_pre_3(svr_num, cookie, svr, socket): + log('DEBUG', 'keep_alive_pre_3') + packet = keep_alive_package_builder(svr_num, cookie, 3, False) + log('DEBUG', 'send:'+packet.encode('hex')) + socket.sendto(packet, (svr, 61440)) + while True: + data, address = socket.recvfrom(1024) + log('DEBUG', 'recv:'+data.encode('hex')) + if data[0] == '\x07': + svr_num = svr_num + 1 + break + else: + log('WARN', 'unexpected recv:'+data.encode('hex')) + cookie = data[16:20] + return svr_num, cookie + + +def keep_alive_package_builder(svr_number, cookie, type=1, first=False): + log('DEBUG', 'keep_alive_package_builder()') + data = '\x07'+ chr(svr_number) + '\x28\x00\x0b' + chr(type) + if first : + data += '\x0f\x27' + else: + data += KEEP_ALIVE_VERSION + data += '\x2f\x12' + '\x00' * 6 + data += cookie + data += '\x00' * 4 + if type == 3: + foo = ''.join([chr(int(i)) for i in host_ip.split('.')]) # host_ip + crc = '\x00' * 4 + data += crc + foo + '\x00' * 8 + else: #packet type = 1 + data += '\x00' * 16 + return data + + +def empty_socket_buffer(socket): + #empty buffer for some fucking schools + log('DEBUG', 'starting to empty socket buffer') + try: 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())) - + data, address = socket.recvfrom(1024) + log('DEBUG', 'recived sth unexpected'+data.encode('hex')) + if socket == '': + break + except: + # get exception means it has done. + log('DEBUG', 'exception in empty_socket_buffer') + log('DEBUG', 'emptyed') + + +def log(level, msg): + log_msg = '[%s]: %s (%s)' % (level, msg, datetime.datetime.now() ) + if IS_DEBUG: + print log_msg + return + if level == 'DEBUG': + return + try: + with open(LOG_PATH, 'a') as f: + f.write(log_msg+'\n') + except Exception as e: + print "Unable to log, %s" % e + 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) + os.environ["TZ"] = 'Asia/Shanghai' + time.tzset() + log('INFO', 'starting...') + is_first_time = True + while RETRY or is_first_time: + is_first_time = False + try: + socket = setup_socket(bind_ip) + salt = get_salt(socket, server, random.randint(0xF,0xFF)) + cookie = do_login(username, password, salt, mac, server, socket) + empty_socket_buffer(socket) + keep_alive(password, salt, cookie, server, socket) + except LoginException as e: + pass + except Exception as e: #normal exception is timeout, which mostly caused by multiplace login and this session is ticked out + log('WARN', e) + socket.close() + log('INFO', 'release socket') + time.sleep(15) + log('INFO', 'process quit') + if __name__ == "__main__": - main() + main()