第七届强网拟态RE WP
easyre
发现有多种花指令,对angr不太熟,感觉通过ida_python没法直接解出,故开始了苦逼的硬逆之旅
通过在strlen下断点,可以定位到输入的位置

下硬件断点,发现是8个字节一组的分组加密,猜测是tea算法中的某一个,接下来就是验证了
接着trace与调试,看到了一些特征

还有一个 shr 11没截下来,故猜测是xtea,接着调试可以得到是66轮
然后密钥呢

观察算法,实际上我们只要让v0,v1都等于0,让sum分别等于0,1,2,3就可以分别得到v0,v1,v2,v3
然后输入数据调试验证发现出题人没有魔改,还是很善良的ww。
接着尝试获取密文,总之还是没看到逻辑,但是看到了cmp

动调试了下发现确实是这里,故下个条件断点主动更改寄存器并将所有值打出来
1 2 3 4 5 6 7 8 9 10 11 12 | import ida_dbg# 获取 R8D 寄存器的值r8d_value = ida_dbg.get_reg_val("R8D")print(f"R8D value: 0x{r8d_value:X}")# 使用 SetRegVal 设置 EDX 为 R8D 的值ida_dbg.set_reg_val("EDX", r8d_value)# 验证 EDX 是否已更改edx_value = ida_dbg.get_reg_val("EDX")print(f"New EDX value: 0x{edx_value:X}") |
然后解发现不对,试了下attach,啊发现有反调试我滴妈,一度陷入绝望
上网搜了下发现https://github.com/x64dbg/ScyllaHide/
尝试使用了下还真绕过了似乎
接着按照以上步骤再来一次 即可写出解密脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include <stdio.h>#include <stdint.h> /* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */ void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9; for (i = 0; i < num_rounds; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); sum += delta; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]); printf("Round %d: v0 = %08X, v1 = %08X, sum = %08X\n", i + 1, v0, v1, sum); } v[0] = v0; v[1] = v1;} void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds; for (i = 0; i < num_rounds; i++) { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]); sum -= delta; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); // printf("Round %d: v0 = %08X, v1 = %08X, sum = %08X\n", num_rounds - i, v0, v1, sum); } v[0] = v0; v[1] = v1;}int main() { uint32_t v[7][2] = { {0x9851e3a1, 0x49765686}, {0x812b6b6f, 0x9612cecf}, {0x3c3570a2, 0xf15c6231}, {0xaa6b77fa, 0xbe056d9e}, {0xf8a424e8, 0x0b3a23db}, {0x03cc2016, 0xa92bb5ad}, {0x1d789f34, 0x9ef9b92e} }; uint32_t v1[2] = {0x1e1e1e1e,0x1e1e1e1e}; uint32_t const k[4] = {0xef6fd9db, 0xd2c273d3, 0x6f97e412, 0x72bfd624}; unsigned int r = 0x66; // num_rounds建议取值为32 // printf("\n开始加密...\n"); // encipher(r, v1, k); // printf("加密后的数据:%08X %08X\n", v1[0], v1[1]); printf("\n开始解密...\n"); for(int i = 0;i<7;i++){ decipher(r, v[i], k); printf("解密后的数据:%08X %08X\n", v[i][0], v[i][1]); } return 0;} |
至于开始的单字节加密,把全部塞进去跑了下得到了个映射表,解密后映射回来即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | enc = [ 0xD9, 0xD3, 0xDE, 0xD8, 0xC4, 0xCA, 0xE0, 0xDE,0xCD,0X0C,0XE0,0Xcd,0Xda,0Xff,0X0e,0x0e, 0xc6, 0xe0, 0xd8, 0x0f, 0x0f, 0xdb,0xe0, 0xff, 0xcb,0xe0,0x0f,0x0e,0x0e,0xc9,0xd2,0xe0, 0xdb ,0xda ,0x0f, 0xdd , 0xd9, 0xe0 ,0xde, 0xd1,0xdb,0xe0,0xde,0xd1,0xcb,0xd6,0xe0,0xdb, 0xda,0xdd,0xca,0xd8,0xd8,0xda,0xcd,0xc2]print(len(enc))my_dict = { 0x0f: '0', 0x0e: '1', 0x0d: '2', 0x0c: '3', 0x0b: '4', 0x0a: '5', 0x09: '6', 0x08: '7', 0x07: '8', 0x06: '9', 0xde: 'a', 0xdd: 'b', 0xdc: 'c', 0xdb: 'd', 0xda: 'e', 0xd9: 'f', 0xd8: 'g', 0xd7: 'h', 0xd6: 'i', 0xd5: 'j', 0xd4: 'k', 0xd3: 'l', 0xd2: 'm', 0xd1: 'n', 0xd0: 'o', 0xcf: 'p', 0xce: 'q', 0xcd: 'r', 0xcc: 's', 0xcb: 't', 0xca: 'u', 0xc9: 'v', 0xc8: 'w', 0xc7: 'x', 0xc6: 'y', 0xc5: 'z', 0xfe: 'A', 0xfd: 'B', 0xfc: 'C', 0xfb: 'D', 0xfa: 'E', 0xf9: 'F', 0xf8: 'G', 0xf7: 'H', 0xf6: 'I', 0xf5: 'J', 0xf4: 'K', 0xf3: 'L', 0xf2: 'M', 0xf1: 'N', 0xf0: 'O', 0xef: 'P', 0xee: 'Q', 0xed: 'R', 0xec: 'S', 0xeb: 'T', 0x1E: '!', 0x1D: '"', 0x1C: '#', 0x1B: '$', 0x1A: '%', 0x19: '&', 0x18: "'", 0x17: '(', 0x16: ')', 0x15: '*', 0x14: '+', 0x13: ',', 0x12: '-', 0x11: '.', 0x10: '/', 0x05: ':', 0x04: ';', 0x03: '<', 0x02: '=', 0x01: '>', 0x00: '?', 0xFF: '@', 0xE4: '[', 0xE3: '\\', 0xE2: ']', 0xE1: '^', 0xE0: '_', 0xDF: '`', 0xC4: '{', 0xC3: '|', 0xC2: '}', 0xC1: '~', 0xEA: 'U', 0xE9: 'V', 0xE8: 'W', 0xE7: 'X', 0xE6: 'Y', 0xE5: 'Z', 0xFC: 'C', 0xFB: 'D', 0xFA: 'E', 0xF9: 'F', 0xF8: 'G', 0xF7: 'H', 0xF6: 'I', 0xF5: 'J', 0xF4: 'K', 0xF3: 'L'}flag = ''for i in range(len(enc)): print(hex(enc[i])) try: flag += my_dict[enc[i]%256] except: continue print(flag) |
flag{u_ar3_re@11y_g00d_@t_011vm_de0bf_and_anti_debugger}
babyre
和学长一起做的题,熬夜脑子真是浆糊,这题把我俩套到两点多
首先是一个AES没加密,接着是一个对输入的“二进制化”,最后是一个校验,用z3解就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import z3from Crypto.Cipher import AES# cipher_text = [[z3.BitVec(f"c{i}{j}", 1) for j in range(12)] for i in range(16)]cipher_text = [[0 for j in range(12)] for i in range(16)]s = z3.Solver()solves = [[] for i in range(16)]for i in range(16): count = 0 for c in range(256): for j, bit in enumerate(f"{c:08b}"): cipher_text[i][j] = int(bit) for j, bit in enumerate(f"{i:04b}"): cipher_text[i][j+8] = int(bit) # v1 = cipher_text[i][9] & cipher_text[i][8] & cipher_text[i][7] & (1-cipher_text[i][5]) & (1-cipher_text[i][4]) & cipher_text[i][3] & ((cipher_text[i][2] | cipher_text[i][1] | (1-cipher_text[i][0]))) & (1-cipher_text[i][6]) & (1-cipher_text[i][10]) | cipher_text[i][9] & cipher_text[i][7] & cipher_text[i][5] & (1-cipher_text[i][3]) & (1-cipher_text[i][2]) & cipher_text[i][0] & (1-cipher_text[i][1]) & (1-cipher_text[i][4]) & (1-cipher_text[i][6]) & (1-cipher_text[i][8]) & (1-cipher_text[i][10]) | cipher_text[i][10] & (1-cipher_text[i][8]) & (1-cipher_text[i][7]) & (1-cipher_text[i][6]) & cipher_text[i][5] & cipher_text[i][4] & (cipher_text[i][2] & cipher_text[i][1] & cipher_text[i][0]) & (1-cipher_text[i][3]) & (1-cipher_text[i][9]) # v2 = cipher_text[i][11] & cipher_text[i][10] & cipher_text[i][8] & cipher_text[i][7] & cipher_text[i][6] & cipher_text[i][5] & cipher_text[i][4] & (1-cipher_text[i][2]) & (cipher_text[i][1] & cipher_text[i][0]) & (1-cipher_text[i][3]) & (1-cipher_text[i][9]) | (1-cipher_text[i][10]) & (1-cipher_text[i][9]) & cipher_text[i][8] & cipher_text[i][7] & cipher_text[i][6] & cipher_text[i][4] & cipher_text[i][3] & cipher_text[i][1] & (1-cipher_text[i][0]) & (1-cipher_text[i][2]) & (1-cipher_text[i][5]) & (1-cipher_text[i][11]) | cipher_text[i][11] & (1-cipher_text[i][9]) & cipher_text[i][8] & cipher_text[i][6] & cipher_text[i][4] & cipher_text[i][3] & cipher_text[i][2] & cipher_text[i][0] & (1-cipher_text[i][1]) & (1-cipher_text[i][5]) & (1-cipher_text[i][7]) & (1-cipher_text[i][10]) | cipher_text[i][11] & cipher_text[i][9] & cipher_text[i][8] & cipher_text[i][6] & cipher_text[i][5] & cipher_text[i][3] & cipher_text[i][2] & (1-cipher_text[i][1]) & (1-cipher_text[i][4]) & (1-cipher_text[i][7]) & (1-cipher_text[i][10]) | (v1 | cipher_text[i][10] & cipher_text[i][9] & (1-cipher_text[i][7]) & cipher_text[i][6] & (1-cipher_text[i][4]) & cipher_text[i][3] & cipher_text[i][2] & cipher_text[i][0] & (1-cipher_text[i][1]) & (1-cipher_text[i][5]) & (1-cipher_text[i][8])) & (1-cipher_text[i][11]) # v3 = cipher_text[i][11] & cipher_text[i][10] & (1-cipher_text[i][8]) & (1-cipher_text[i][7]) & cipher_text[i][6] & (1-cipher_text[i][4]) & (1-cipher_text[i][3]) & (1-cipher_text[i][2]) & (cipher_text[i][1] & cipher_text[i][0]) & (1-cipher_text[i][5]) & (1-cipher_text[i][9]) | (1-cipher_text[i][10]) & (1-cipher_text[i][9]) & (1-cipher_text[i][8]) & (1-cipher_text[i][7]) & cipher_text[i][6] & (1-cipher_text[i][4]) & cipher_text[i][3] & ((cipher_text[i][2] | cipher_text[i][1] | (1-cipher_text[i][0]))) & (1-cipher_text[i][5]) & (1-cipher_text[i][11]) | cipher_text[i][11] & cipher_text[i][10] & cipher_text[i][9] & (1-cipher_text[i][7]) & (1-cipher_text[i][6]) & cipher_text[i][5] & cipher_text[i][4] & (1-cipher_text[i][2]) & cipher_text[i][1] & (1-cipher_text[i][0]) & (1-cipher_text[i][3]) & (1-cipher_text[i][8]) | cipher_text[i][11] & cipher_text[i][9] & (1-cipher_text[i][7]) & (1-cipher_text[i][6]) & cipher_text[i][5] & ((cipher_text[i][4] | cipher_text[i][3] | cipher_text[i][2] | cipher_text[i][1] | (1-cipher_text[i][0]))) & (1-cipher_text[i][8]) & (1-cipher_text[i][10]) | cipher_text[i][11] & (1-cipher_text[i][9]) & (1-cipher_text[i][8]) & cipher_text[i][7] & cipher_text[i][6] & cipher_text[i][5] & cipher_text[i][4] & (1-cipher_text[i][2]) & cipher_text[i][0] & (1-cipher_text[i][1]) & (1-cipher_text[i][3]) & (1-cipher_text[i][10]) | v2 # if ( (cipher_text[i][10] & cipher_text[i][8] & cipher_text[i][6] & cipher_text[i][4] & (1-cipher_text[i][2]) & cipher_text[i][1] & (1-cipher_text[i][0]) & (1-cipher_text[i][3]) & (1-cipher_text[i][5]) & (1-cipher_text[i][7]) & (1-cipher_text[i][9]) & (1-cipher_text[i][11]) | cipher_text[i][11] & cipher_text[i][10] & cipher_text[i][9] & cipher_text[i][8] & (1-cipher_text[i][6]) & (1-cipher_text[i][5]) & cipher_text[i][4] & (1-cipher_text[i][2]) & cipher_text[i][1] & (1-cipher_text[i][0]) & (1-cipher_text[i][3]) & (1-cipher_text[i][7]) | v3 | cipher_text[i][10] & cipher_text[i][9] & cipher_text[i][8] & cipher_text[i][6] & cipher_text[i][4] & ((cipher_text[i][3] | cipher_text[i][2] | cipher_text[i][1] | (1-cipher_text[i][0]))) & (1-cipher_text[i][5]) & (1-cipher_text[i][7]) & (1-cipher_text[i][11])) == 1 ): v15 = cipher_text[i][1] v14 = cipher_text[i][2] v13 = cipher_text[i][3] v12 = cipher_text[i][4] v11 = cipher_text[i][5] v10 = cipher_text[i][6] v9 = cipher_text[i][7] v8 = cipher_text[i][8] v7 = cipher_text[i][9] v6 = cipher_text[i][10] v5 = cipher_text[i][11] v1 = v7 & v8 & v9 & (v11 == 0) & (v12 == 0) & v13 & ((v14 | cipher_text[i][1] | cipher_text[i][0]) == 0) & (v10 == 0) & (v6 == 0) | v7 & v9 & v11 & (v13 == 0) & (v14 == 0) & cipher_text[i][0] & (cipher_text[i][1] == 0) & (v12 == 0) & (v10 == 0) & (v8 == 0) & (v6 == 0) | v6 & (v8 == 0) & (v9 == 0) & (v10 == 0) & v11 & v12 & (v14 & v15 & cipher_text[i][0]) & (v13 == 0) & (v7 == 0) v2 = v5 & v6 & v8 & v9 & v10 & v11 & v12 & (v14 == 0) & (v15 & cipher_text[i][0]) & (v13 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & v8 & v9 & v10 & v12 & v13 & v15 & (cipher_text[i][0] == 0) & (v14 == 0) & (v11 == 0) & (v5 == 0) | v5 & (v7 == 0) & v8 & v10 & v12 & v13 & v14 & cipher_text[i][0] & (cipher_text[i][1] == 0) & (v11 == 0) & (v9 == 0) & (v6 == 0) | v5 & v7 & v8 & v10 & v11 & v13 & v14 & (v15 == 0) & (v12 == 0) & (v9 == 0) & (v6 == 0) | (v1 | v6 & v7 & (v9 == 0) & v10 & (v12 == 0) & v13 & v14 & cipher_text[i][0] & (cipher_text[i][1] == 0) & (v11 == 0) & (v8 == 0)) & (v5 == 0) v3 = v5 & v6 & (v8 == 0) & (v9 == 0) & v10 & (v12 == 0) & (v13 == 0) & (v14 == 0) & (v15 & cipher_text[i][0]) & (v11 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (v8 == 0) & (v9 == 0) & v10 & (v12 == 0) & v13 & ((v14 | cipher_text[i][1] | cipher_text[i][0]) == 0) & (v11 == 0) & (v5 == 0) | v5 & v6 & v7 & (v9 == 0) & (v10 == 0) & v11 & v12 & (v14 == 0) & v15 & (cipher_text[i][0] == 0) & (v13 == 0) & (v8 == 0) | v5 & v7 & (v9 == 0) & (v10 == 0) & v11 & ((v12 | v13 | v14 | cipher_text[i][1] | cipher_text[i][0]) == 0) & (v8 == 0) & (v6 == 0) | v5 & (v7 == 0) & (v8 == 0) & v9 & v10 & v11 & v12 & (v14 == 0) & cipher_text[i][0] & (cipher_text[i][1] == 0) & (v13 == 0) & (v6 == 0) | v2 if ( (v6 & v8 & v10 & v12 & (v14 == 0) & v15 & (cipher_text[i][0] == 0) & (v13 == 0) & (v11 == 0) & (v9 == 0) & (v7 == 0) & (v5 == 0) | v5 & v6 & v7 & v8 & (v10 == 0) & (v11 == 0) & v12 & (v14 == 0) & v15 & (cipher_text[i][0] == 0) & (v13 == 0) & (v9 == 0) | v3 | v6 & v7 & v8 & v10 & v12 & ((v13 | v14 | cipher_text[i][1] | cipher_text[i][0]) == 0) & (v11 == 0) & (v9 == 0) & (v5 == 0)) == 1 ): print(i, c) solves[i].append(c) count += 1 # print(i, count) # for j, bit in enumerate(f"{i:04b}"): # s.add(cipher_text[i][j+8] == int(bit))key = bytes.fromhex('3577402ECCA44A3F9AB72182F9B01F35')aes = AES.new(key, AES.MODE_ECB)from itertools import productfor s in product(*solves): plain_text = aes.decrypt(bytes(s)) print(plain_text.hex())# if s.check() == z3.sat:# m = s.model()# for i in range(16):# for j in range(12):# print(m[cipher_text[i][j]], end="")# print()# else:# print("unsat") |
pacman
这题早上起床看了一会,以前没做过游戏题,中间找到win的逻辑尝试patch赢了游戏,但是没啥发现,接着看到game.data,猜测肯定会有对data的加载过程,尝试去找,只找到了对game.record的加载过程,最终没定位到(),赛后尝试复现。
首先比赛时发现用frida调用直接寄,猜测做了反调试
不太了解windows的反调试机制,这里用插件AntiDebugSeeker成功定位到了反调试的位置

将jnz patch 为jmp绕过

接着这里如果马后炮的话直接去康康对应的函数就行,但是今天面对这种题目确实一直找不到切入点,故考虑能否通过frida hook的方式通过对读写文件的api的监控来达到寻找切入点的目的,思考了下可能以下的步骤会有帮助:
首先查看程序加载后加载了哪些dll,查看下各个加载的dll,将其中的open,read,write等函数都hook上,最好再将exit函数hook上,可以一定程度上防止反调试,当然如果其反调试是对逻辑的改变则一点没用。
得到以下hook脚本
// Hook CreateFileA function
Interceptor.attach(Module.getExportByName("kernel32.dll", "CreateFileA"), {
onEnter: function(args) {
var fileName = Memory.readCString(args[0]);
console.log("[CreateFileA] Called with file name: " + fileName);
},
onLeave: function(retval) {
console.log("[CreateFileA] Returned handle: " + retval);
}
});
// Hook CreateFileW function
Interceptor.attach(Module.getExportByName("kernel32.dll", "CreateFileW"), {
onEnter: function(args) {
var fileName = Memory.readUtf16String(args[0]);
console.log("[CreateFileW] Called with file name: " + fileName);
},
onLeave: function(retval) {
console.log("[CreateFileW] Returned handle: " + retval);
}
});
// Hook ReadFile function
Interceptor.attach(Module.getExportByName("kernel32.dll", "ReadFile"), {
onEnter: function(args) {
this.handle = args[0];
this.buffer = args[1];
this.bytesToRead = args[2].toInt32();
console.log("[ReadFile] Reading " + this.bytesToRead + " bytes from handle: " + this.handle);
},
onLeave: function(retval) {
if (retval.toInt32() != 0) {
var data = Memory.readByteArray(this.buffer, this.bytesToRead);
console.log("[ReadFile] Data: " + hexdump(data, {
offset: 0,
length: this.bytesToRead,
header: false,
ansi: false
}));
} else {
console.log("[ReadFile] Failed to read file.");
}
}
});
// Hook ReadFileEx function
Interceptor.attach(Module.getExportByName("kernel32.dll", "ReadFileEx"), {
onEnter: function(args) {
this.handle = args[0];
this.buffer = args[1];
this.bytesToRead = args[2].toInt32();
console.log("[ReadFileEx] Reading " + this.bytesToRead + " bytes from handle: " + this.handle);
},
onLeave: function(retval) {
if (retval.toInt32() != 0) {
var data = Memory.readByteArray(this.buffer, this.bytesToRead);
console.log("[ReadFileEx] Data: " + hexdump(data, {
offset: 0,
length: this.bytesToRead,
header: false,
ansi: false
}));
} else {
console.log("[ReadFileEx] Failed to read file.");
}
}
});
// Hook WriteFile function
// Interceptor.attach(Module.getExportByName("kernel32.dll", "WriteFile"), {
// onEnter: function(args) {
// this.handle = args[0];
// this.buffer = args[1];
// this.bytesToWrite = args[2].toInt32();
// console.log("[WriteFile] Writing " + this.bytesToWrite + " bytes to handle: " + this.handle);
// var data = Memory.readByteArray(this.buffer, this.bytesToWrite);
// console.log("[WriteFile] Data to write: " + hexdump(data, {
// offset: 0,
// length: this.bytesToWrite,
// header: false,
// ansi: false
// }));
// },
// onLeave: function(retval) {
// if (retval.toInt32() != 0) {
// console.log("[WriteFile] Write successful.");
// } else {
// console.log("[WriteFile] Write failed.");
// }
// }
// });
// Hook CreateFileMapping function
Interceptor.attach(Module.getExportByName("kernel32.dll", "CreateFileMappingA"), {
onEnter: function(args) {
this.handle = args[0];
var fileSizeHigh = args[2].toInt32();
var fileSizeLow = args[3].toInt32();
console.log("[CreateFileMappingA] Mapping file handle: " + this.handle + " with size: " + (fileSizeHigh << 32 | fileSizeLow));
},
onLeave: function(retval) {
console.log("[CreateFileMappingA] Returned mapping handle: " + retval);
}
});
// Hook MapViewOfFile function
Interceptor.attach(Module.getExportByName("kernel32.dll", "MapViewOfFile"), {
onEnter: function(args) {
this.fileMappingHandle = args[0];
this.offsetHigh = args[2].toInt32();
this.offsetLow = args[3].toInt32();
this.numberOfBytesToMap = args[4].toInt32();
console.log("[MapViewOfFile] Mapping view of file handle: " + this.fileMappingHandle +
" at offset: " + (this.offsetHigh << 32 | this.offsetLow) +
" with size: " + this.numberOfBytesToMap);
},
onLeave: function(retval) {
console.log("[MapViewOfFile] Mapped view address: " + retval);
}
});
// Hook CloseHandle function
Interceptor.attach(Module.getExportByName("kernel32.dll", "CloseHandle"), {
onEnter: function(args) {
console.log("[CloseHandle] Closing handle: " + args[0]);
},
onLeave: function(retval) {
if (retval.toInt32() != 0) {
console.log("[CloseHandle] Handle closed successfully.");
} else {
console.log("[CloseHandle] Failed to close handle.");
}
}
});
// Hook fopen function (from msvcrt.dll)
Interceptor.attach(Module.getExportByName("msvcrt.dll", "fopen"), {
onEnter: function(args) {
var filename = Memory.readCString(args[0]); // 读取文件名参数
var mode = Memory.readCString(args[1]); // 读取打开模式
console.log("[fopen] Called with filename: " + filename + ", mode: " + mode);
},
onLeave: function(retval) {
console.log("[fopen] Returned FILE* handle: " + retval);
}
});
// Hook fread function (from msvcrt.dll)
Interceptor.attach(Module.getExportByName("msvcrt.dll", "fread"), {
onEnter: function(args) {
this.buffer = args[0];
this.size = args[1].toInt32();
this.count = args[2].toInt32();
this.stream = args[3];
console.log("[fread] Called to read " + (this.size * this.count) + " bytes from FILE* handle: " + this.stream);
},
onLeave: function(retval) {
console.log("[fread] Read " + retval.toInt32() + " items");
// 如果需要,可以在这里读取缓冲区内容,例如:
var data = Memory.readByteArray(this.buffer, this.size * this.count);
console.log(hexdump(data, {
offset: 0,
length: this.size * this.count,
header: false,
ansi: false
}));
}
});
// Hook fwrite function (from msvcrt.dll)
Interceptor.attach(Module.getExportByName("msvcrt.dll", "fwrite"), {
onEnter: function(args) {
this.buffer = args[0];
this.size = args[1].toInt32();
this.count = args[2].toInt32();
this.stream = args[3];
console.log("[fwrite] Called to write " + (this.size * this.count) + " bytes to FILE* handle: " + this.stream);
// 读取要写入的缓冲区内容
var data = Memory.readByteArray(this.buffer, this.size * this.count);
console.log("[fwrite] Data to write: " + hexdump(data, {
offset: 0,
length: this.size * this.count,
header: false,
ansi: false
}));
},
onLeave: function(retval) {
console.log("[fwrite] Written " + retval.toInt32() + " items");
}
});
// Hook fclose function (from msvcrt.dll)
Interceptor.attach(Module.getExportByName("msvcrt.dll", "fclose"), {
onEnter: function(args) {
var stream = args[0]; // 读取 FILE* 句柄
console.log("[fclose] Called to close FILE* handle: " + stream);
},
onLeave: function(retval) {
console.log("[fclose] File closed successfully.");
}
});
// Hook ucrtbase_fopen (from ucrtbased.dll)
Interceptor.attach(Module.getExportByName("ucrtbased.dll", "fopen"), {
onEnter: function(args) {
var filename = Memory.readCString(args[0]); // 读取文件名参数
var mode = Memory.readCString(args[1]); // 读取打开模式
console.log("[ucrtbased_fopen] Called with filename: " + filename + ", mode: " + mode);
},
onLeave: function(retval) {
console.log("[ucrtbased_fopen] Returned FILE* handle: " + retval);
}
});
// Hook ucrtbase_fread (from ucrtbased.dll)
Interceptor.attach(Module.getExportByName("ucrtbased.dll", "fread"), {
onEnter: function(args) {
this.buffer = args[0];
this.size = args[1].toInt32();
this.count = args[2].toInt32();
this.stream = args[3];
console.log("[ucrtbased_fread] Called to read " + (this.size * this.count) + " bytes from FILE* handle: " + this.stream);
},
onLeave: function(retval) {
console.log("[ucrtbased_fread] Read " + retval.toInt32() + " items");
// 读取缓冲区内容
var data = Memory.readByteArray(this.buffer, this.size * this.count);
console.log("[ucrtbased_fread] Data: " + hexdump(data, {
offset: 0,
length: this.size * this.count,
header: false,
ansi: false
}));
}
});
// Hook ucrtbase_fwrite (from ucrtbased.dll)
Interceptor.attach(Module.getExportByName("ucrtbased.dll", "fwrite"), {
onEnter: function(args) {
this.buffer = args[0];
this.size = args[1].toInt32();
this.count = args[2].toInt32();
this.stream = args[3];
console.log("[ucrtbased_fwrite] Called to write " + (this.size * this.count) + " bytes to FILE* handle: " + this.stream);
// 读取要写入的缓冲区内容
var data = Memory.readByteArray(this.buffer, this.size * this.count);
console.log("[ucrtbased_fwrite] Data to write: " + hexdump(data, {
offset: 0,
length: this.size * this.count,
header: false,
ansi: false
}));
},
onLeave: function(retval) {
console.log("[ucrtbased_fwrite] Written " + retval.toInt32() + " items");
}
});
// Hook ucrtbase_fclose (from ucrtbased.dll)
Interceptor.attach(Module.getExportByName("ucrtbased.dll", "fclose"), {
onEnter: function(args) {
var stream = args[0]; // 获取 FILE* 句柄
console.log("[ucrtbased_fclose] Called to close FILE* handle: " + stream);
},
onLeave: function(retval) {
console.log("[ucrtbased_fclose] File closed successfully.");
}
});
// 获取标准C库中的 exit 函数(通常在 msvcrt.dll 或 ucrtbased.dll 中)
var exitFunc = Module.getExportByName("msvcrt.dll", "exit");
// 使用 Interceptor.replace 来替换 exit 函数
Interceptor.replace(exitFunc, new NativeCallback(function(code) {
console.log("[Hooked exit] Program attempted to exit with code: " + code);
// 不执行实际的退出操作,可以在这里写替代逻辑
console.log("[Hooked exit] Preventing program from exiting.");
// 在这里可以自定义逻辑,程序将不会退出
}, 'void', ['int']));
// 获取标准C库中的 exit 函数(通常在 msvcrt.dll 或 ucrtbased.dll 中)
var exitFunc2 = Module.getExportByName("ucrtbased.dll", "exit");
// 使用 Interceptor.replace 来替换 exit 函数
Interceptor.replace(exitFunc2, new NativeCallback(function(code) {
console.log("[Hooked exit] Program attempted to exit with code: " + code);
// 不执行实际的退出操作,可以在这里写替代逻辑
console.log("[Hooked exit] Preventing program from exiting.");
// 在这里可以自定义逻辑,程序将不会退出
}, 'void', ['int']));
可以看到,hook到了对应的ps脚本

并且可以打印出堆栈帮忙定位

这里用attch,因为spawn的话好像不太方便注入
接着dump下来ps脚本解混淆即可解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | def enc(plaintext_bytes, key_bytes): # Initialize S and KSA S = list(range(256)) j = 0 for i in range(256): j = (j + S[i] + key_bytes[i % len(key_bytes)]) % 256 S[i], S[j] = S[j], S[i] # PRGA and encryption i = j = 0 ciphertext_bytes = [] for k in range(len(plaintext_bytes)): i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] t = (S[i] + S[j]) % 256 ciphertext_bytes.append(plaintext_bytes[k] ^ S[t]) return ciphertext_bytesdef enc1(input_byte): key = [0x70, 0x6f, 0x77, 0x65, 0x72] encrypted_text = [] for _ in range(len(input_byte)): encrypted_text = enc(input_byte, key) key = enc(key, encrypted_text) return encrypted_text + keydef enc2(input_byte): key = [0x70, 0x30, 0x77, 0x65, 0x72] for k in range(len(input_byte)): input_byte[k] = (input_byte[k] + key[k % len(key)]) return input_bytedef enc3(input_byte): key = [0x70, 0x30, 0x77, 0x33, 0x72] for k in range(len(input_byte)): input_byte[k] = (input_byte[k] * key[k % len(key)]) return input_byteresult = [38304, 8928, 43673, 25957, 67260, 47152, 16656, 62832, 19480, 66690, 40432, 15072, 63427, 28558, 54606, 47712, 18240, 68187, 18256, 63954, 48384, 14784, 60690, 21724, 53238, 64176, 9888, 54859, 23050, 58368, 46032, 15648, 64260, 17899, 52782, 51968, 12336, 69377, 27844, 43206, 63616]ans = []payload = [0] * 41for i in range(41): for j in range(0, 0x100): payload[i] = j res = enc2(enc2(enc3(enc2(enc2(enc2(payload)))))) if res[i] == result[i]: ans.append(j)print(len(ans))encrypted_text = ans[:36]key = ans[36:]print(key)key = enc(key, encrypted_text)ans = enc(encrypted_text, key)for a in ans: print(chr(a), end='') |
flag是73412036-7d8c-437b-9026-0c2ca1b7f79d
脚本参考DJB Team师傅发的wp