Created
February 2, 2016 15:24
-
-
Save w4kfu/2be8798265d39dd76edf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
from capstone import * | |
# PACKETS FROM https://www.reddit.com/r/REGames/comments/3tlmi2/reverseengineering_realm_onlines_game_protocol/ | |
packet_00 = [ | |
0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDC, 0xED, 0xA3, 0x5F, | |
0x85, 0x48, 0x8F, 0xA9, 0x83, 0x13, 0xFA, 0xE4, 0x21, 0x48, 0x9D, 0xE4, | |
0x3E, 0x46, 0xB2, 0xDC, 0xF6, 0xC1, 0x26, 0x20, 0x34, 0x7E, 0x8C, 0x5B, | |
0xEB, 0xBD, 0xA3, 0x59, 0x30, 0x5E, 0xF3, 0x59, 0x30, 0xBD, 0xD6, 0x77, | |
0xD5, 0xB4, 0xC8, 0xAD, 0x30, 0xBD, 0xA3, 0x5E, 0x31, 0xBD, 0xA3, 0x59, | |
0x61, 0x04, 0x9F, 0x39, 0x1D, 0x60, 0xF3, 0x59, 0x30, 0xBD, 0x2C, 0x78, | |
0x8F, 0x1B, 0xFE, 0xB1, 0x8D, 0x80, 0xA3, 0x59, 0x30, 0xBD, 0xA3, 0x59, | |
0x30, 0xBD, 0xA3, 0x59, 0x30, 0xBD, 0xA3, 0x59, 0x13, 0x45, 0xBB, 0x94, | |
0x1F, 0x3D, 0xA4, 0x59, 0x30, 0xBD, 0xA3, 0x59, 0x30, 0xBD, 0xA3, 0x59, | |
0x33, 0xDB, 0xA3, 0x80, 0x30, 0xF3, 0xA3, 0x59, 0x30, 0xBD, 0xA3, 0x59, | |
0x30, 0xBD, 0x00, 0x00, 0x00, 0x19, 0x00, 0x8B | |
] | |
packet_01 = [ | |
0xD0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF7, 0xF9, 0xBF, 0x58, | |
0x6A, 0x54, 0xAA, 0x9D, 0x68, 0x1F, 0x15, 0x0E, 0xFE, 0xCB, 0x5F, 0xDD, | |
0x15, 0xC9, 0xBE, 0xD8, 0x07, 0x54, 0xDC, 0x44, 0x3A, 0x5D, 0xBE, 0x4D, | |
0x15, 0xCE, 0xBF, 0x4D, 0x15, 0xC9, 0xEF, 0x53, 0x0C, 0xEE, 0x52, 0x4D, | |
0x15, 0xC9, 0xC3, 0x4E, 0x15, 0xC9, 0xBE, 0x7E, 0x5B, 0xCD, 0xF1, 0xAB, | |
0x19, 0xC0, 0xE3, 0xE1, 0x15, 0xC9, 0xBE, 0x52, 0x16, 0xC9, 0xBE, 0x4D, | |
0x46, 0x0F, 0xC6, 0x80, 0x73, 0xD1, 0x61, 0xDD, 0x15, 0xC9, 0xBE, 0xD0, | |
0x0E, 0xCD, 0x3A, 0x8A, 0x0C, 0xEE, 0x52, 0x4D, 0x15, 0xC9, 0xC3, 0x4E, | |
0x15, 0xC9, 0xBE, 0x7E, 0x5B, 0xD5, 0xF1, 0xAB, 0x21, 0x6C, 0x4E, 0x4D, | |
0x15, 0xC9, 0x41, 0x46, 0x1A, 0x45, 0xE0, 0xD0, 0xDB, 0xD9, 0x41, 0x36, | |
0x1A, 0x3D, 0xC5, 0x80, 0x33, 0x4C, 0x84, 0x51, 0xF5, 0xC2, 0xF9, 0x6B, | |
0x89, 0xD8, 0x77, 0x5D, 0x15, 0xC9, 0xBE, 0x07, 0xAD, 0xC9, 0xBE, 0x4D, | |
0xFD, 0xC9, 0xBE, 0x4D, 0x15, 0x28, 0x1C, 0xA8, 0x6D, 0x26, 0x81, 0x4D, | |
0xC7, 0xD4, 0x44, 0x61, 0x04, 0x49, 0xBF, 0x4D, 0x1D, 0xC9, 0xBE, 0x4D, | |
0x15, 0xC9, 0xBE, 0x4B, 0x17, 0xC9, 0xBE, 0x4D, 0x15, 0xC9, 0xBE, 0x4D, | |
0x15, 0xC9, 0xBE, 0x4D, 0x15, 0xC9, 0xBE, 0x4D, 0x1D, 0xD4, 0xBE, 0x62, | |
0x15, 0xEB, 0xBE, 0x80, 0x15, 0x0C, 0xBE, 0x9B, 0x15, 0x27, 0xBE, 0xCD, | |
0x15, 0xCA, 0x43, 0x4D, 0x16, 0xC9, 0x00, 0x00, 0x00, 0x4C, 0x65, 0x61 | |
] | |
packet_03 = [ | |
0x20, 0x00, 0x00, 0x00, 0xE0, 0x4B, 0x3C, 0xF9, 0x35, 0xE3, 0x4E, 0x43, | |
0xFD, 0xF8, 0xE4, 0xB6, 0x88, 0x37, 0x9E, 0x72, 0x3D, 0x20, 0xDD, 0x81, | |
0xA1, 0xA1, 0xC9, 0x7F, 0xCD, 0x9E, 0xE0, 0xF2, 0x05, 0xCE, 0x5B, 0x95, | |
0x74, 0xC2, 0x28, 0x3D | |
] | |
packet_00 = ''.join([chr(x) for x in packet_00]) | |
packet_01 = ''.join([chr(x) for x in packet_01]) | |
packet_03 = ''.join([chr(x) for x in packet_03]) | |
def hexdump(src, length=16): | |
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)]) | |
lines = [] | |
for c in xrange(0, len(src), length): | |
chars = src[c:c+length] | |
hex = ' '.join(["%02x" % ord(x) for x in chars]) | |
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.') for x in chars]) | |
lines.append("%04x %-*s %s\n" % (c, length*3, hex, printable)) | |
return ''.join(lines).rstrip('\n') | |
def disas(code, addr=0x00): | |
md = Cs(CS_ARCH_X86, CS_MODE_32) | |
for i in md.disasm(code, addr): | |
print "0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str) | |
def subti(buf, length): | |
""" | |
03210F17 90 NOP | |
03210F18 83C6 06 ADD ESI,6 | |
03210F1B 8BDE MOV EBX,ESI | |
03210F1D 66:8B43 FE MOV AX,WORD PTR DS:[EBX-2] | |
03210F21 83E9 06 SUB ECX,6 | |
03210F24 C1E9 02 SHR ECX,2 | |
03210F27 2803 SUB BYTE PTR DS:[EBX],AL | |
03210F29 8003 39 ADD BYTE PTR DS:[EBX],39 | |
03210F2C 0063 01 ADD BYTE PTR DS:[EBX+1],AH | |
03210F2F 806B 01 46 SUB BYTE PTR DS:[EBX+1],46 | |
03210F33 0043 02 ADD BYTE PTR DS:[EBX+2],AL | |
03210F36 806B 02 0C SUB BYTE PTR DS:[EBX+2],0C | |
03210F3A 2863 03 SUB BYTE PTR DS:[EBX+3],AH | |
03210F3D 8043 03 30 ADD BYTE PTR DS:[EBX+3],30 | |
03210F41 83C3 04 ADD EBX,4 | |
03210F44 ^ E2 E1 LOOPD SHORT 03210F27 | |
""" | |
out = "" | |
k_sub_00 = struct.unpack("<B", buf[0:1])[0] | |
k_sub_01 = struct.unpack("<B", buf[1:2])[0] | |
for i in xrange(0, (len(buf) - 2) - ((len(buf) - 2) % 4), 4): | |
out += chr(((ord(buf[i + 2: i + 2 + 1]) - k_sub_00) + 0x39) & 0xFF) # SUB K_00 ; ADD CONST | |
out += chr(((ord(buf[i + 2 + 1: i + 2 + 2]) + k_sub_01) - 0x46) & 0xFF) # ADD K_01 ; SUB CONST | |
out += chr(((ord(buf[i + 2 + 2: i + 2 + 3]) + k_sub_00) - 0x0C) & 0xFF) # ADD K_00 ; SUB CONST | |
out += chr(((ord(buf[i + 2 + 3: i + 2 + 4]) - k_sub_01) + 0x30) & 0xFF) # SUB K_01 ; ADD CONST | |
return out | |
def extract_sc(buf): | |
""" | |
/!\ Relocations stuff not handled | |
Header packet (after substitution): | |
+ 0x00 FLAG_RELOC_TYPE [BYTE] | |
+ 0x01 NB_BLOCK_CODE [BYTE] // BLOCK OF 16 BYTES | |
+ 0x02 CODE [BYTE] * NB_BLOCK_CODE * 16 | |
""" | |
code_length = struct.unpack("<B", buf[1:1 + 1])[0] * 0x10 | |
disas(buf[2: 2 + code_length]) | |
# METHOD FROM DISASSEMBLY CODE IN PACKET_00 | |
def decrypt_packet(buf, k_00, k_01): | |
length = struct.unpack("<I", buf[0:4])[0] | |
crc_packet = struct.unpack("<I", buf[-4:])[0] | |
buf = buf[4:-4] | |
out = "" | |
crc_computed = 0 | |
for i in xrange(0, (len(buf) / 4)): | |
k_00 = ((k_00 * k_01) + 1) & 0xFFFFFFFF | |
val = struct.unpack("<I", buf[i * 4:((i + 1) * 4)])[0] | |
val = (val ^ k_00) & 0xFFFFFFFF | |
crc_computed ^= val | |
out += struct.pack("<I", val) | |
if crc_computed != crc_packet: | |
print "[WARNING] Wrong CRC packet" | |
return out, k_00 | |
def handle_packet(packet): | |
""" | |
Header packet: | |
+ 0x00: LENGTH [DWORD] | |
+ 0x04: FLAG_SUBSTI [DWORD] | |
""" | |
length, sflag = struct.unpack("<II", packet[0:8]) | |
print "[+] length : 0x%08X" % length | |
print "[+] sflag : 0x%08X" % sflag | |
if sflag == 0x04: | |
b = subti(packet[0x08:0x08 + length], length) | |
extract_sc(b) | |
# PACKET_00 => kind of shellcode to decrypt further packets | |
handle_packet(packet_00) | |
# PACKET_01 => kind of shellcode to encrypt further packets | |
handle_packet(packet_01) | |
# 0x3B1888E3 STORED AT OFFSET 0x50 IN FIRST PACKET SHELLCODE | |
# 0x180EF STORED AT OFFSET 0x54 IN FIRST PACKET SHELLCODE | |
b, k_00 = decrypt_packet(packet_03, 0x3B1888E3, 0x180EF) | |
print hexdump(b) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment