Drcom懒人版-Windows

整理归档的时候发现一个好玩的

代码来自https://github.com/drcoms/drcom-generic,我稍微改了点,方便懒人在Win-PC上面直接跑

Drcom正版是一个刚需软件,但它默认不能开热点,就很难受.

于是就有大佬抓包分析写出了Drcom破解版,破解版基本能够替代正版的功能,无论是登录,心跳包都能构造出来,使用起来很快乐.但是GitHub上的代码转化为能用的程序之间,有一定的工作量,即使有wiki的指导,抓包等配置步骤也有一定难度.

所以,即使以我这么懒的人,都舍小懒,为大懒,封装出了一个懒人版.(Windows版是封装好了的,如果你用的mac或linux系,需要自己运行python脚本)

Feature:

  • 电脑可以开热点 (继承自Github大佬破解版)
  • 电脑无需安装python,或者其他任何环境 (代价是软件有3.6MB)
  • 有一个我自认为比原版好看一点点的中文界面
  • 无需配置,开包即用,按提示输入帐号密码即可
  • 无广告,但卸载后可能会在”我的文档”文件夹下残留一个用来保存你帐号密码的txt

使用步骤:

  1. 下载软件
  2. 关闭正版Drcom
  3. 双击打开懒人Drcom
  4. 输入帐号,密码(第二次就不用了)
  5. 卸载方法:直接删除下载下来那个exe

Windows版点击此处下载exe

Mac,linux版点击此处下载py


使用者可以不用往下看了

以下为drcom_WIN3.py的源码

# -*- coding: gbk -*-
from __future__ import print_function
import socket, struct, time
from hashlib import md5

import sys
import os
import random
import threading
import os
import _winreg
global DEBUG

print('''
  _____                          ______                     _
 |  __ \                        |  ____|                   | |
 | |  | |_ __ ___ ___  _ __ ___ | |__  __  _____  ___ _   _| |_ ___  _ __
 | |  | | '__/ __/ _ \| '_ ` _ \|  __| \ \/ / _ \/ __| | | | __/ _ \| '__|
 | |__| | | | (_| (_) | | | | | | |____ >  <  __/ (__| |_| | || (_) | |
 |_____/|_|  \___\___/|_| |_| |_|______/_/\_\___|\___|\__,_|\__\___/|_|


''')
print("Version:WIN_3\nCode fork from:https://github.com/drcoms/drcom-generic")
print("=================================================================@LoopyTech")
def get_desktop():
    key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
    return _winreg.QueryValueEx(key, "Personal")[0]
if os.path.exists("./drcom_userdata"):
    filepath ="./drcom_userdata"
else:
    filepath=get_desktop()+"/drcom_userdata"
if os.path.exists(filepath):
    try:
        with open(filepath, 'r') as f:
            buffer = f.read()
        username, password, DEBUG = buffer.split(" ")
        username = str(username)
        password = str(password)
        if DEBUG == "True":
            DEBUG = True
        elif DEBUG == "False":
            DEBUG = False
        else:
            raise ERROR("drcom_userdata已损坏")
        print("[成功] 从我的文档的drcom_userdata读取到了帐号密码")
    except:
        print("[警告] 我的文档文件夹下的drcom_userdata已损坏,请先手动删除")
else:
    try:
        username = str(raw_input("# 输入帐号: "))
        password = str(raw_input("# 输入密码: "))
        DEBUG = False
        with open(filepath, 'w') as f:
            f.write("{} {} {}".format(username, password, str(False)))
        print("[成功] 帐号密码信息保存到了我的文档中的drcom_userdata.下次登录无需再输入密码了")
        print("       若不想保存帐号密码,请手动删除drcom_userdata文件")
    except Exception as r:
        print("[警告] 无法从我的文档中读取drcom_userdata" + str(r))

server = '10.254.7.4'
CONTROLCHECKSTATUS = '\x20'
ADAPTERNUM = '\x04'
host_ip = '10.251.94.26'
IPDOG = '\x01'
host_name = 'GILIGILIEYE'
PRIMARY_DNS = '202.202.0.33'
dhcp_server = '10.253.7.77'
AUTH_VERSION = '\x25\x00'
mac = 0x54e1ad0743be
host_os = 'NOTE7'
KEEP_ALIVE_VERSION = '\xdc\x02'
ror_version = False
nic_name = 'lee'
bind_ip = '0.0.0.0'


class ChallengeException(Exception):
    def __init__(self):
        pass


class LoginException(Exception):
    def __init__(self):
        pass


class tt(threading.Thread):
    i = 2
    input_str = ""

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while 1:
            input_kb = str(sys.stdin.readline()).strip("\n")
            if input_kb == "":  # continue
                self.i = 0
                print("===========================================================================")
                print("3秒后自动退出")
                time.sleep(3)
                os._exit(0)
                self.input_str = input_kb
            else:
                self.input_str = input_kb


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:
        return '0.0.0.0'
    except IOError as e:
        return '0.0.0.0'
    finally:
        return '0.0.0.0'


if nic_name != '':
    bind_ip = bind_nic()

try:
    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)
except Exception as e:
    print("[错误] 无法同时打开两个Drcom认证软件(也可能是另一个软件未完全退出,推荐重启)")
    print("===========================================================================")
    print("5秒后自动退出")
    time.sleep(5)
    exit(-1)

IS_TEST = True
# specified fields based on version
CONF = "./drcom.conf"
UNLIMITED_RETRY = True
EXCEPTION = False
# log saves to file
LOG_PATH = './drcom_client.log'


def log(*args, **kwargs):
    global DEBUG
    s = ' '.join(args)
    if DEBUG:
        print(s)
        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("\x01\x02" + t + "\x09" + "\x00" * 15, (svr, 61440))
        try:
            data, address = s.recvfrom(1024)
            log('[challenge] recv', data.encode('hex'))
        except:
            log('[challenge] timeout, retrying...')
            print("[失败] Connect timeout")
            raise ERROR("Connect timeout")

        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) + '\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
    my_t = tt()
    my_t.start()
    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.")
    if check_update():
        print("[成功] 成功连接到互联网.")
    else:
        print("[警告] 网络连接可能失败.")

    print("\n[程序运行中] 敲击回车键以退出,请勿关闭该窗口")
    i = svr_num
    timeout_count = 0
    flag = 0
    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)
            timeout_count =0
            if flag ==1:
                print("                                  ",end="\r")
            if my_t.input_str=="c":
                exit(0)



        except Exception as e:
             if(str(e)=="timed out"):
                  print("({})[警告] 网络重连中".format(str(timeout_count)),end="\r")
                  flag =1
             else:
                  print("[警告] "+str(e),end="\r")
             if timeout_count>30:
                  print("[错误] 连接丢失                                 \n===========================================================================")
                  print("3秒后自动退出")
                  time.sleep(3)
                  os._exit(0)
             time.sleep(1)               
             timeout_count+=1
             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 = '\x03\x01\x00' + chr(len(usr) + 20)
    data += md5sum('\x03\x01' + 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 += '\x0a\x1e\x16\x11' #your ip address1, 10.30.22.17
    data += ''.join([chr(int(i)) for i in host_ip.split('.')])  # x.x.x.x ->
    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

    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')
                print("[成功] {}已成功登录".format(str(usr)))
                break
            else:
                print("[失败] 尝试通过{}来登录失败".format(usr))
                raise ERROR("login failed")
                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.')
                raise ERROR("login exception occured")
            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))
    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 check_update():
    try:
        address = 'loopy.tech'
        port = 6666
        buffsize = 1024
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((address, port))

        senddata = "Hello,Server. I'm drcom-3.py"
        s.send(senddata.encode())
        recvdata = s.recv(buffsize).decode('utf-8')
        if recvdata == "Hi":
            return True
        elif recvdata == "You can update":
            print("[警告] 新版本已可供下载,可见(http://file.loopy.tech/release/drcom.html)")
            return True
        s.close()
    except Exception as e:
        return False


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__":
    try:
        main()
    except Exception as err:
        if (str(err) == "[Errno 101] Network is unreachable"):
            print("[失败] 找不到网线连接\n===========================================================================")
            print("5秒后自动退出")
            time.sleep(5)
            os._exit(0)
        print("[失败] ERROR: " + str(err))
        print("If you meet unsolveable problem, you can find LoopyTech for help. \n    @57658689098a@gmail.com")
        print("===========================================================================")
        print("5秒后自动退出")
        time.sleep(5)
        os._exit(0)

以下为Drcom_WIN2的源码

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import socket, struct, time
from hashlib import md5
import sys
import os
import random
import threading
global DEBUG
import requests

print("====================DRCOM======================")
print("Welcome to DrcomPortable@LOOPY.TECH\n")
if os.path.exists("./user.conf"):
    try:
        with open('./user.conf','r') as f:
            buffer = f.read()
        username,password,DEBUG = buffer.split(" ")
        username = str(username)
        password = str(password)
        if DEBUG =="True":
            DEBUG = True
        elif DEBUG == "False":
            DEBUG = False
        else:
            raise ERROR("user.conf is damaged")
        print("[SUCCESS] Get login information from user.conf")
    except:
        print("[WARNING] user.conf is damaged,please remove it.")
else:
    try:
        username = str(raw_input("Input username: "))
        password = str(raw_input("Input password:"))
        DEBUG = False
        with open("./user.conf",'w') as f:
            f.write("{} {} {}".format(username,password,str(False)))
        print("[SUCCESS] Login information save to user.conf.")
        print("          You can remove it if don't want to save it.")
    except Exception as r:
        print("[WARNING] Unable to save data to user.conf."+str(r))
server = '10.254.7.4'
CONTROLCHECKSTATUS = '\x20'
ADAPTERNUM = '\x04'
host_ip = '10.251.94.26'
IPDOG = '\x01'
host_name = 'GILIGILIEYE'
PRIMARY_DNS = '202.202.0.33'
dhcp_server = '10.253.7.77'
AUTH_VERSION = '\x25\x00'
mac = 0x54e1ad0743be
host_os = 'NOTE7'
KEEP_ALIVE_VERSION = '\xdc\x02'
ror_version = False
nic_name = 'lee'
bind_ip = '0.0.0.0'


class ChallengeException (Exception):
    def __init__(self):
        pass

class LoginException (Exception):
    def __init__(self):
        pass
class tt(threading.Thread):
    i=2
    input_str=""

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while 1:
            input_kb = str(sys.stdin.readline()).strip("\n")
            if input_kb=="":    #continue
                self.i=0
                print("=====================END=======================")
                print("Close in 5 seconds")
                time.sleep(5)
                os._exit(0)
                self.input_str=input_kb
            else:
                self.input_str=input_kb

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('[WARNING] ERROR: Indicate nic feature need to be run under Unix based system.')

        return '0.0.0.0'
    except IOError as e:
        print("[WARNING] ERROR: "+str(e))

        return '0.0.0.0'
    finally:
        return '0.0.0.0'

if nic_name != '':
    bind_ip = bind_nic()

try:
    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)
except Exception as e:
    print("[FAIL] ERROR:Open socket failed{}".format(str(e)))
    print("====================FAIL======================")
    print("Close in 5 seconds")
    time.sleep(5)
    exit(-1)

IS_TEST = True
# specified fields based on version
CONF = "./drcom.conf"
UNLIMITED_RETRY = True
EXCEPTION = False
#log saves to file
LOG_PATH = './drcom_client.log'



def log(*args, **kwargs):
    global DEBUG
    s = ' '.join(args)
    if DEBUG:
        print(s)
        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("\x01\x02"+t+"\x09"+"\x00"*15, (svr, 61440))
        try:
            data, address = s.recvfrom(1024)
            log('[challenge] recv',data.encode('hex'))
        except:
            log('[challenge] timeout, retrying...')
            print("[FAIL] Connect timeout")
            exit(-1)

        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) + '\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
    my_t = tt()
    my_t.start()
    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.")



    try:
        html = requests.get("http://www.baidu.com",timeout=2)
        print("[SUCCESS] Connected to the Internet in wall successfully.")
    except:
        print("[FAIL] Connect failed.")
        raise ERROR("Connect failed")

    try:
        html = requests.get("http://www.google.com",timeout=2)
        print("[SUCCESS] Connected to the worldwide Internet successfully.")
    except:
        print("[WARNING] Network bridge is not connected. Try to get ss from loopy.tech.")


    print("[RUNNING] click enter or close this window to quit")
    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)

            if my_t.input_str=="c":
                exit(0)



        except Exception as e:
            print("[WARNING] "+str(e))
            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 = '\x03\x01\x00'+chr(len(usr)+20)
    data += md5sum('\x03\x01'+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 += '\x0a\x1e\x16\x11' #your ip address1, 10.30.22.17
    data += ''.join([chr(int(i)) for i in host_ip.split('.')]) #x.x.x.x ->
    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

    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')
                print("[SUCCESS] Loged in with "+str(usr))
                break
            else:
                print("[FAIL] ERROR: Try to login with {} failed".format(usr))
                exit(-1)
                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))
    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__":
    try:
        main()
    except Exception,err:
        print("[FAIL] ERROR:"+str(err))
        print("====================FAIL======================")
        print("Close in 5 seconds")
        time.sleep(5)
本文总字数: 23731