REVERSE-COMPETITION-CCSSSC-2025
- donntyousee
- HappyLock
- kernel_traffic
donntyousee
elf64,ida反编译不太行,有花指令,直接调汇编
读输入
读输入前有条打印”plz input your flag”,肯定是在.init_array,确实有很多
先不管,往下看,类似一个函数指针数组,通过偏移调用函数
大概是rc4,但是不知道走哪个数组
调试发现确实是rc4,直接异或回去发现不对
strace一下发现有个ptrace,猜测是反调试
.init_array->sub_4053A5->sub_529980
直接改掉这块跳转
再走rc4,然后异或回去即可
inp = list(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")inp_enc = [0x20, 0xCD, 0x47, 0xBA, 0x4B, 0x04, 0x09, 0xE7, 0x8D, 0x1A,0x40, 0x43, 0xC1, 0xD6, 0x5F, 0xFE, 0xF0, 0x16, 0x44, 0x4A,0xB2, 0x6B, 0xE2, 0xF0, 0x9D, 0x92, 0x30, 0xD1, 0x51, 0x0E,0xC1, 0xFF, 0x23, 0xC9, 0x7A, 0xFF, 0x9C, 0x76, 0xA1, 0x4B,0x36, 0x59, 0x8F, 0xD3, 0xF1, 0xB4, 0x2D, 0x31, 0x6F, 0x78]enc = [0x25, 0xCD, 0x54, 0xAF, 0x51, 0x1C, 0x58, 0xD3, 0xA8, 0x4B,0x4F, 0x56, 0xEC, 0x83, 0x5D, 0xD4, 0xF6, 0x47, 0x4A, 0x6F,0xE0, 0x73, 0xB0, 0xA5, 0xA8, 0xC3, 0x17, 0x81, 0x5E, 0x2B,0xF4, 0xF6, 0x71, 0xEA, 0x2F, 0xFF, 0xA8, 0x63, 0x99, 0x57]for i in range(len(enc)):enc[i] ^= inp[i] ^ inp_enc[i]print(bytes(enc))# dart{y0UD0ntL4cKg0oD3y34T0F1nDTh3B4aUtY}
HappyLock
画完手势后会走Utils.cmp(s)校验,flag就是这个s
反射调用cmp方法
交叉引用找到DexClassLoader
从r2路径加载dex文件
hook出r2路径
function hook() {Java.perform(function () {// 获取 DexClassLoader 类var DexClassLoader = Java.use('dalvik.system.DexClassLoader');// hook DexClassLoader 构造方法DexClassLoader.$init.overload('java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.ClassLoader').implementation = function (param1, param2, param3, param4) {// 在这里可以访问到构造函数的参数console.log('r2 (param1): ' + param1); // param1 对应的是 $r2 的值// 调用原始的构造函数return this.$init(param1, param2, param3, param4);};});
}
hook()
但是它加载完就删了,内存里肯定有
gg修改器dump出内存来
再反编译,根据jadx提示改下checksum
cmp就是个循环异或
解密即可
enc=[118, 17, 2, 80, 9, 125, 6, 22, 113, 66, 0, 81, 94, 41, 87, 20, 122, 65, 88, 5, 94, 41, 7, 19, 118, 22, 3, 2, 90, 41, 87, 71, 117, 68, 4, 7, 95, 116, 4, 67]
key=list(b"CrackMe!CrackMe!")
for i in range(len(enc)):enc[i]^=key[i%len(key)]
print(bytes(enc))
# 5cc3b0c720a25d25939f5db25dba1d2f66ed49ab
kernel_traffic
首先是生成会话密钥,也就是rc4密钥,两个大数分别是模数n和私钥d,公钥e为65537
把流量里两块0x80大小的数据用私钥解密然后异或就能得到会话密钥
n = int("00b7db0b385f4cfb85bf9af7c1c8298ec4d691c8341b8a09d3e0f1685f1e9e8198b03426855ee144c38c10b623ae2f1f671b9aee7a8a7a49fc46154c5d57d1827c28bdf1aeb7cbf259ee1564dd24fcaa66f1e95db6652bbd8f4b1ef1a7bd698085609b8d50a714162bedc8f9478807984fa257ba6647d0a18cb5595bcd789cb8b7", 16)
e = 0x10001
d = int("18260d333a5142382f128bb848322d2e6d80786b5fb2a1d7d293e2c19ba3f621b803218c230a339dfba7b644b97c3703b3fc859652d9fd1dc596c690fc17e8ab6d2de44fcddc6d7af84fc50175347cebf1aeb4c920036fab4a20b4ba44b72f69d45e6ed40111bff5d1186087dc40d31c22bec7bdd6c39e079c518a2a385ecb01", 16)def getint(bufhex: str):tmp = bytes.fromhex(bufhex)[::-1]tmp = int(tmp.hex(), 16)return tmprandomenc = getint("676273984e2bca8ac3a86fad9f1f9765dede291b81dd0877e464881ddf1ee5dd8cd573387b0c3fe2c33b29f9dd22cc3962e76008f936911c96dc2b458cbb3b5a0cbf941d56b9b8ef536321e4d06ebcc6eb26458385fd64392492a41bcc7370f0a2209ea92ae8513ad31191a92fc44ca65fbf68757450a21ba9c9527454e3cd44")
randompla = pow(randomenc, d, n)
print(hex(randompla))
# 0x14b225e8fdd58d9aad84e8f691d93435serverenc = getint("ac180aeccc63af3bc278d4200b8caf22f4932366722e1be39fd165d0e56dab6d42cd95ea2458e1906a4c16422d374c5d488bca352f03485dd40cc7a7096df5ca7c20e3db6290797f418e3a84fb3b76e640ffe15913f4e73b9ab2cbd2deada3fda8e61a5dcd88f86bed46e6a5a44fc1fd40029d42b7311cb72b00555e401a2881")
serverpla = pow(serverenc, d, n)
print(hex(serverpla))
# 0xad6badbb35592b2d6d2d6d7138af4bc5randompla = list(bytes.fromhex(hex(randompla)[2:])[::-1])
print(randompla)
# [53, 52, 217, 145, 246, 232, 132, 173, 154, 141, 213, 253, 232, 37, 178, 20]
serverpla = list(bytes.fromhex(hex(serverpla)[2:])[::-1])
print(serverpla)
# [197, 75, 175, 56, 113, 109, 45, 109, 45, 43, 89, 53, 187, 173, 107, 173]rc4key = randompla.copy()
for i in range(len(rc4key)):rc4key[i] ^= (serverpla[i]*17) & 0xFF
rc4key = bytes(rc4key)
从内核读数据,先做rc4加密,再做基于表的替换,每轮的表根据时间戳设置
解密
data = bytes.fromhex("c9a435670c000000a92066b352dd8b65a0840fbac9a435670c000000d21c608abafe1fa3ed22ee1bcaa435670c0000005cd8e734e9ff3ddc88f82ff6cba435670c0000000f2c1f33a63872e89d85419dcda435670c0000009c4c416a6c33912c5d2dbea3cda435670c0000003405e1f86f204cb3233cee47cfa435670c000000babf35d58fb039f34ac0bc68d0a435670c00000069c3563248492fa3dd39c300d1a435670c0000009660928ac69bd2c5ed38c575d3a435670c0000008068f321bb9f3ad2db1733fcd4a435670c000000d0d76861912565a75fab99ead4a435670c000000d5e4f21427976a29b28d2465d5a435670c000000b8dc14e8f9e098ee0eae689cd5a435670c0000008d0a397c810b8e6387dc5317d5a435670c0000001a972a6c158c1bda02fc43ded5a435670c000000297eaa03818999b004297ca8d5a435670c000000c66c97a36a413d0fe38a57c5d8a435670c0000001809619ecdf37f837d44f986d8a435670c0000003b52e6a439e9f1ee97daa235d9a435670c000000a44507aa2e755b35675722fcdba435670c00000012d4da0167e78a3cd8080e4edda435670c00000083202fb19c2937cb9e3015e1dda435670c000000a34e094fd2e4cc0fc0d52e08e0a435670c000000c5323082d0db41cc22eaf37ee0a435670c000000c2fe09cd87dd6b8dc540b11fe1a435670c0000009f34dc29085976f1f1f4804ce1a435670c0000005928e0ea62033a917bbe2439e1a435670c00000025e8f3be3759dae1dddf5760e1a435670c000000a1985a4755ed3b39af887410e1a435670c000000b6dd7db5d3da879d6fcce465e1a435670c000000907194e5ccf0ab56d9cee5fce1a435670c000000a0d42f568286477b5000a21ee3a435670c000000fab0826bcd5e77a70d11ca95e3a435670c0000003c0b8f780746b6c870b8eb3de6a435670c000000a25ad5f8ab74414f116791afe8a435670c00000031b2eed379afb67f9aa962bfe8a435670c000000802421958e372da29ca75ae7eba435670c000000ed3db7f76f2b1fc8ace9dccbeba435670c00000012b5a5a2a5a161c619319de9eba435670c000000aefd55c6cdbef465b24dca78eba435670c000000daf9a0aef390e56d2c59da48f0a435670c000000a7e1347f096846f5b8f08c8bf1a435670c0000004754a89602a3902d44f2d151f1a435670c00000092a034c0c522c297349f7cfff3a435670c00000019a5598acb6abf72ab62e79cf4a435670c000000ebcca8b0c020566761d8484bf5a435670c000000bc65b1fd58a6c24a2bcdb23cf5a435670c000000dee8f9c766cb33cb771f8babf6a435670c000000547c2274e7be1e8a492d2566f6a435670c0000005c60476d6f22c523af08e883f6a435670c00000029ea7e1ccd945a6fec3f1bbff6a435670c000000816f99fc399b312a76a61b97")libc = ctypes.cdll.LoadLibrary("./libc.so.6")def rev_tb(rdm, buf):tb = [i for i in range(256)]libc.srand(rdm)for j in range(255, -1, -1):v2 = libc.rand()v5 = tb[j]tb[j] = tb[v2 % (j + 1)]tb[v2 % (j + 1)] = v5res = []for i in buf:res.append(tb.index(i))return resgrps = len(data) // 20rc4 = ARC4.new(rc4key)for grp in range(grps):rdm = struct.unpack("<I", data[grp*20+0:grp*20+4])[0]lgh = struct.unpack("<I", data[grp*20+4:grp*20+8])[0]assert(lgh == 0x0C)enc = list(data[grp*20+8:grp*20+20])enc = rev_tb(rdm, enc)print(f"\"{rc4.decrypt(bytes(enc)).hex()}\",")
前8字节是左shift,切大小写的,后4字节是键码,找个表映射回去即可(写的比较乱😓
import structscan_code_to_ascii = {0x00: 'Null', # 无效的扫描码0x01: 'ESC', # Esc0x02: '1', # 10x03: '2', # 20x04: '3', # 30x05: '4', # 40x06: '5', # 50x07: '6', # 60x08: '7', # 70x09: '8', # 80x0A: '9', # 90x0B: '0', # 00x0C: '-', # -0x0D: '=', # =0x0E: 'Backspace', # Backspace0x0F: 'Tab', # Tab0x10: 'Q', # Q0x11: 'W', # W0x12: 'E', # E0x13: 'R', # R0x14: 'T', # T0x15: 'Y', # Y0x16: 'U', # U0x17: 'I', # I0x18: 'O', # O0x19: 'P', # P0x1A: '[', # [0x1B: ']', # ]0x1C: 'Enter', # Enter0x1D: 'Left Ctrl', # Left Ctrl0x1E: 'A', # A0x1F: 'S', # S0x20: 'D', # D0x21: 'F', # F0x22: 'G', # G0x23: 'H', # H0x24: 'J', # J0x25: 'K', # K0x26: 'L', # L0x27: ';', # ;0x28: "'", # '0x29: '`', # `0x2A: 'Left Shift', # Left Shift0x2B: '\\', # \0x2C: 'Z', # Z0x2D: 'X', # X0x2E: 'C', # C0x2F: 'V', # V0x30: 'B', # B0x31: 'N', # N0x32: 'M', # M0x33: ',', # ,0x34: '.', # .0x35: '/', # /0x36: 'Right Shift', # Right Shift0x37: '*', # NumPad *0x38: 'Left Alt', # Left Alt0x39: 'Space', # Space0x3A: 'Caps Lock', # Caps Lock0x3B: 'F1', # F10x3C: 'F2', # F20x3D: 'F3', # F30x3E: 'F4', # F40x3F: 'F5', # F50x40: 'F6', # F60x41: 'F7', # F70x42: 'F8', # F80x43: 'F9', # F90x44: 'F10', # F100x57: 'F11', # F110x58: 'F12', # F120xE0: 'Right Ctrl', # Right Ctrl0xE1: 'Print Screen', # Print Screen0xE2: 'Scroll Lock', # Scroll Lock0xE3: 'Pause', # Pause0xE4: 'Insert', # Insert0xE5: 'Home', # Home0xE6: 'Page Up', # Page Up0xE7: 'Delete', # Delete0xE8: 'End', # End0xE9: 'Page Down', # Page Down0xEA: 'Up Arrow', # Up Arrow0xEB: 'Left Arrow', # Left Arrow0xEC: 'Down Arrow', # Down Arrow0xED: 'Right Arrow', # Right Arrow
}def scan_code_to_ascii_code(scan_code):return scan_code_to_ascii.get(scan_code, 'Unknown')scan_codes = ["000000000000000021000000","000000000000000026000000","00000000000000001e000000","000000000000000022000000","00000000000000002a000000","01000000000000001a000000","000000000000000025000000","000000000000000004000000","000000000000000013000000","000000000000000031000000","000000000000000012000000","000000000000000026000000","00000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000000c000000","00000000000000002a000000","010000000000000014000000","000000000000000013000000","000000000000000005000000","000000000000000021000000","000000000000000021000000","000000000000000017000000","00000000000000002e000000","00000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000000c000000","00000000000000002a000000","010000000000000022000000","000000000000000005000000","000000000000000032000000","000000000000000012000000","00000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000000c000000","00000000000000002a000000","01000000000000002a000000","010000000000000023000000","000000000000000005000000","000000000000000023000000","00000000000000001e000000","00000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000002a000000","01000000000000001b000000"]s = []for scan_code in scan_codes:scan_code_bytes = bytes.fromhex(scan_code)ls = struct.unpack("<Q", scan_code_bytes[:8])[0]val = struct.unpack("<I", scan_code_bytes[8:])[0]s.append(ls)s.append(val)flag = ""islow = Truefor i in range(0, len(s), 2):ls = s[i+0]val = s[i+1]if ls == 0 and val == 0x2A:islow = ~islowcontinueif ls == 1 and val == 0x2A:continueif ls == 1 and val == 0x1A:flag += "{"continueif ls == 1 and val == 0x1B:flag += "}"continueif ls == 1 and val == 0x0C:flag += "_"continuech = scan_code_to_ascii_code(val)if ch.isalpha():if islow:if ls == 1:flag += chelse:flag += chr(ord(ch)+32)else:if ls == 1:flag += chr(ord(ch)+32)else:flag += chelif ch.isdigit():flag += chprint(flag)
# flag{k3rnel_Tr4ffic_G4me_H4ha}