Simulate login packet python implementation

大家讲道理
Release: 2016-11-09 11:25:38
Original
2189 people have browsed it

#!/usr/bin/env python
# encoding:utf-8
  
from socket import  *
from ctypes import create_string_buffer
from struct import *
import sysconfig
import random
from ctypes.wintypes import BYTE
from msilib import datasizemask
from _ctypes import sizeof
from random import randint
from time import sleep
  
CODEC = 'utf-8'
  
global RECVBUFSIZ
global  m_wRecvSize
global  m_cbSendRound #发送字节映射
global  m_cbRecvRound  #接收字节映射
global  m_dwSendXorKey  #发送密钥
global  m_dwRecvXorKey #接收密钥
  
  
m_cbSendRound = 0
m_cbRecvRound = 0
  
RECVBUFSIZ = 16384
m_wRecvSize = 0
m_cbSendRound = 0 #发送字节映射
m_cbRecvRound = 0  #接收字节映射
m_dwSendXorKey = 0  #发送密钥
m_dwRecvXorKey = 0 #接收密钥
  
  
def SendLogonPacket(ADDR,SENDBUFF):
    global RECVBUFSIZ
    cs = socket(AF_INET, SOCK_STREAM)
    cs.connect(ADDR)
    cs.send(SENDBUFF)
    lennum = len( cs.recv(RECVBUFSIZ))
    cs.close()
    return lennum
  
  
def md5(str1):
    import hashlib
    m = hashlib.md5()
    m.update(str1)
    str1 = m.hexdigest()
    return  str1.upper()
def a2u(buff1,str1,start):
    i=0
    for letter in str1:
        pack_into("B",buff1,start+i,ord(letter))
        i += 2
def MapSendByte (byte):
    global m_cbSendRound
    index = byte + m_cbSendRound
    b = g_SendByteMap[index % 0x100]
    m_cbSendRound += 3
    return b
def MapRecvByte (byte):
    global m_cbRecvRound
    b = g_RecvByteMap[byte] - m_cbRecvRound
    b = b % 0x100
    m_cbRecvRound += 3
    return b
def SeedRandMap(wSeed):
    num = int(wSeed)
    num = ( num * 241103 + 2533101 ) >> 16
    return ((num  | int(0xFFFF0000)) -0xFFFF0000) #返回一个WORD类型
  
def CrevasseBuffer(buff,wDataSize):
    global dwXorKey
    global m_dwSendXorKey
    global m_dwRecvXorKey
    i = 0
    while i  < wDataSize:
        print hex(ord (buff[i])),
        i += 1
    dwXorKey = m_dwRecvXorKey
    if (((wDataSize -4) % 4 ) != 0):
        print "recv data error"
        exit()
    wEncrypCount = (wDataSize - 4) /4
    #解密数据
    i = 0
    j = 4   #排除cmd_info,从CMD_Command起
    k = 4
    while i < (wEncrypCount):
        wSeed =  (unpack_from("H",buff,k)[0])
        k += 2
        dwXorKey = SeedRandMap(wSeed)
        dwXorKey |= int( SeedRandMap(unpack_from ("H", buff, k)[0]) ) << 16
        k += 2
        dwXorKey ^= g_dwPacketKey
        n = unpack_from( "I", buff, j)[0]
        n ^= m_dwRecvXorKey
        pack_into("I",buff,j,n)
        j += 4
        m_dwRecvXorKey = dwXorKey
        i += 1
  
    i = 4
    cbCheckCode = unpack_from(&#39;B&#39;,buff,1)[0]
    while i < wDataSize:
        pack_into ("B", buff, i, MapRecvByte ( ord ( buff[i] ) ) )
        cbCheckCode += ord(buff[i])
        cbCheckCode = cbCheckCode % 0x100
        i += 1
    if cbCheckCode != 0:
        print ""
        print &#39;cb&#39; , cbCheckCode
    i = 0
    while i  < wDataSize:
        print hex(ord(buff[i])),
        i += 1
    return wDataSize
  
  
def EncryptBuffer(buff,wDataSize):
    global dwXorKey
    global m_dwSendXorKey
    global m_dwRecvXorKey
    global SENDBUFF
    global m_dwSendPacketCount
    wEncryptSize = wDataSize - 4 #排除cmd_info4字节头不加密
    wSnapCount=0
    if ((wEncryptSize % 4) != 0): #待加密数据对齐粒度 4字节
        wSnapCount = 4 - ( wEncryptSize % 4 )  #不足4字节补-0
        n = 0
        t = wSnapCount
        while n < t:
            pack_into("B",buff,4 + wEncryptSize + n, 0x0)
            t += 1
  
    cbCheckCode = 0 #务必置0
    i = 4 #起始位置,排除CMD_INFO逐字节与发送映射表替换,并计算出校验和
    while i < wDataSize:
        #print hex(ord(buff[i]))
        cbCheckCode += ord(buff[i])
        #print cbCheckCode
        cbCheckCode = cbCheckCode % 0x100
        #print cbCheckCode
        t = MapSendByte(ord(buff[i]))
        #print t
        pack_into("B",buff,i,t)
        i += 1
  
    #填写计算出的校验码
    pack_into ("B", buff, 1, ( ~cbCheckCode + 1) % 0x100)
  
    dwXorKey = m_dwSendXorKey
    if ( m_dwSendPacketCount == 0 ):
        dwXorKey = random.randint(0x11111111, 0xeeeeeeee) #生成随机密钥
  
        dwXorKey = g_dwPacketKey
  
        m_dwSendXorKey = dwXorKey
        m_dwRecvXorKey = dwXorKey
  
  
    #加密数据
    i = 0
    j = 4   #排除cmd_info,从CMD_Command起
    k = 4
    while i < ((wEncryptSize + wSnapCount) / 4):
        n =  (unpack_from("I",buff,j)[0])
        n ^= dwXorKey
        pack_into("I", buff, j, n)
        j += 4 #逐4字节异或加密数据
        dwXorKey = SeedRandMap ( unpack_from ( "H", buff, k )[0])  #用加密后的数据加密生成新的密钥
        k += 2
        dwXorKey |= int( SeedRandMap( unpack_from ("H", buff, k)[0])) << 16 #
        k += 2
        dwXorKey ^= g_dwPacketKey
        i += 1
  
  
    if (m_dwSendPacketCount == 0):
        i = 0
        while i < 8:
            pack_into("B", SENDBUFF, i, ord ( buff[i] ) )      #前八个字节相同
            i += 1
        pack_into ( "I", SENDBUFF, 8, m_dwSendXorKey )  #插入异或密钥key
        PacketSize = wDataSize + 4 #因为插入了4B的密钥
        pack_into("H",SENDBUFF,2,PacketSize)
        j = 8
        while j <  wDataSize:
            pack_into("B", SENDBUFF, j+4, ord( buff[j] ) )
            j += 1
        pack_into("H",SENDBUFF,2,wDataSize + 4)
  
    #m_dwSendPacketCount += 1
    #m_dwSendXorKey = dwXorKey
  
#"网络数据定义"
SOCKET_VER = 0x05    #"#网络版本"  ida_pro 逆向找到EncryptBuffer函数后可以确定此值
SOCKET_BUFFER = 8192    #"#网络缓冲"
CMD_HEAD_SIZE = 4
DWORD_SIZE= 4
WORD_SIZE = 2
BYTE_SIZE = 1
SOCKET_PACKET = ( SOCKET_BUFFER - CMD_HEAD_SIZE - 2 * DWORD_SIZE )
g_dwPacketKey = 0xA55AA55A  #"加密密钥" #从WHSocket.dll获取
  
#"发送映射"  #从WHSocket.dll获取
g_SendByteMap = (0x70,  0x2F, 0x40, 0x5F, 0x44, 0x8E, 0x6E, 0x45, 0x7E, 0xAB, 0x2C, 0x1F, 0xB4, 0xAC, 0x9D, 0x91,
    0x0D, 0x36, 0x9B, 0x0B, 0xD4, 0xC4, 0x39, 0x74, 0xBF, 0x23, 0x16, 0x14, 0x06, 0xEB, 0x04, 0x3E,
    0x12, 0x5C, 0x8B, 0xBC, 0x61, 0x63, 0xF6, 0xA5, 0xE1, 0x65, 0xD8, 0xF5, 0x5A, 0x07, 0xF0, 0x13,
    0xF2, 0x20, 0x6B, 0x4A, 0x24, 0x59, 0x89, 0x64, 0xD7, 0x42, 0x6A, 0x5E, 0x3D, 0x0A, 0x77, 0xE0,
    0x80, 0x27, 0xB8, 0xC5, 0x8C, 0x0E, 0xFA, 0x8A, 0xD5, 0x29, 0x56, 0x57, 0x6C, 0x53, 0x67, 0x41,
    0xE8, 0x00, 0x1A, 0xCE, 0x86, 0x83, 0xB0, 0x22, 0x28, 0x4D, 0x3F, 0x26, 0x46, 0x4F, 0x6F, 0x2B,
    0x72, 0x3A, 0xF1, 0x8D, 0x97, 0x95, 0x49, 0x84, 0xE5, 0xE3, 0x79, 0x8F, 0x51, 0x10, 0xA8, 0x82,
    0xC6, 0xDD, 0xFF, 0xFC, 0xE4, 0xCF, 0xB3, 0x09, 0x5D, 0xEA, 0x9C, 0x34, 0xF9, 0x17, 0x9F, 0xDA,
    0x87, 0xF8, 0x15, 0x05, 0x3C, 0xD3, 0xA4, 0x85, 0x2E, 0xFB, 0xEE, 0x47, 0x3B, 0xEF, 0x37, 0x7F,
    0x93, 0xAF, 0x69, 0x0C, 0x71, 0x31, 0xDE, 0x21, 0x75, 0xA0, 0xAA, 0xBA, 0x7C, 0x38, 0x02, 0xB7,
    0x81, 0x01, 0xFD, 0xE7, 0x1D, 0xCC, 0xCD, 0xBD, 0x1B, 0x7A, 0x2A, 0xAD, 0x66, 0xBE, 0x55, 0x33,
    0x03, 0xDB, 0x88, 0xB2, 0x1E, 0x4E, 0xB9, 0xE6, 0xC2, 0xF7, 0xCB, 0x7D, 0xC9, 0x62, 0xC3, 0xA6,
    0xDC, 0xA7, 0x50, 0xB5, 0x4B, 0x94, 0xC0, 0x92, 0x4C, 0x11, 0x5B, 0x78, 0xD9, 0xB1, 0xED, 0x19,
    0xE9, 0xA1, 0x1C, 0xB6, 0x32, 0x99, 0xA3, 0x76, 0x9E, 0x7B, 0x6D, 0x9A, 0x30, 0xD6, 0xA9, 0x25,
    0xC7, 0xAE, 0x96, 0x35, 0xD0, 0xBB, 0xD2, 0xC8, 0xA2, 0x08, 0xF3, 0xD1, 0x73, 0xF4, 0x48, 0x2D,
    0x90, 0xCA, 0xE2, 0x58, 0xC1, 0x18, 0x52, 0xFE, 0xDF, 0x68, 0x98, 0x54, 0xEC, 0x60, 0x43, 0x0F)
#############################################################################################
  
HOST = "192.168.1.108"
PORT = 8300
ADDR = (HOST, PORT)
m_cbLogonMode = 0xB
LOGON_BY_GAME_ID = 0xB
LOGON_BY_ACCOUNTS = 0xC
MachineID = md5 (str(random.randint(0x11111111, 0xeeeeeeee)))
PassWord = md5(&#39;123456&#39;)
if m_cbLogonMode == LOGON_BY_ACCOUNTS:
    WPACKETSIZE = 0x100 #发送登录数据包的总大小,抓包可获取
    Accounts = &#39;youruser&#39;   #0x42B 登录账号
if m_cbLogonMode == LOGON_BY_GAME_ID:
    WPACKETSIZE = 0xC4
    GameID = 7990986
  
&#39;&#39;&#39;-----------------Packet_struct--------------------------------------------&#39;&#39;&#39;
#############CMD_Head###################
#CMD_Info
cbVersion  = SOCKET_VER  #1B    数据类型
cbCheckCode = 0x00  #1B   校验字段    发送数据的所有字节相加
wPacketSize = WPACKETSIZE  #2B   数据大小    发送登录数据包的总大小,抓包可获取
#CMD_Command
wMainCmdID = 0x000B #2B 主命令码 源码结合逆向分析出各个命令码意义
wSubCmdID = m_cbLogonMode  #2B 子命令码
#############CMD_Head###################
#CMD_GP_LogonAccounts
PlazaVersion = 0x06090302 #4B 广场版本 逆向找到 
dwNum = 0x0100007F  # 
MachineID = MachineID #0x44B 机器序列
PassWord = PassWord #0x44B 登录密码
cbNeeValidateMBCard = 0x00 #密保校验
&#39;&#39;&#39;-----------------Packet_struct--------------------------------------------&#39;&#39;&#39;
  
global SENDBUFF
SENDBUFF = create_string_buffer(wPacketSize)
buff = create_string_buffer(wPacketSize)
  
pack_into ( "B", buff, 0, cbVersion )   #固定值
pack_into ( "B", buff, 1, cbCheckCode ) #校验码计算正确即可
pack_into ( "H", buff, 2, wPacketSize ) #固定值
pack_into ( "HH",buff, 4, wMainCmdID, wSubCmdID ) #不同登录类型不同固定值
  
CMD_GP_LogonAccounts_Size = wPacketSize - 4 - 4  - 4  #cmd_info 、cmd_command 、m_dwSendXorKey
PlazaVersion_offset = 8
  
pack_into ("I", buff, PlazaVersion_offset, PlazaVersion )
pack_into ("I", buff, PlazaVersion_offset + 4, dwNum )
  
MachineID_offset = PlazaVersion_offset + DWORD_SIZE + DWORD_SIZE  #PlazaVersion 和 dwNum
a2u (buff, MachineID, MachineID_offset  )
if wSubCmdID == LOGON_BY_GAME_ID:
    pack_into ("I", buff, MachineID_offset + 0x42, GameID )
    a2u (buff, PassWord, MachineID_offset + 0x42 + 4 )
if wSubCmdID == LOGON_BY_ACCOUNTS:
    a2u (buff, PassWord, MachineID_offset + 0x42 )
    a2u (buff, Accounts, MachineID_offset  + 0x42 + 0x42 )
    pack_into ("B", buff, MachineID_offset + 0x42 + 0x42 + 0x40, cbNeeValidateMBCard )
  
wDataSize = wPacketSize - 4 #前面把m_dwSendXorKey 也算上了
&#39;&#39;&#39;
i = 0
while i < wDataSize:
    print hex(i),
    print hex(ord(buff[i]))
  
    i += 1
exit()
&#39;&#39;&#39;
   
EncryptBuffer(buff, wDataSize)
  
SendLogonPacket(ADDR,SENDBUFF) #accounts登录时返回数据大小 257 用户名密码机器码正确, 12机器码更换   68用户密码错误 78机器码不正确
Copy after login

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template