第七届强网拟态RE WP

easyre

发现有多种花指令,对angr不太熟,感觉通过ida_python没法直接解出,故开始了苦逼的硬逆之旅

通过在strlen下断点,可以定位到输入的位置

image-20241019215021520

下硬件断点,发现是8个字节一组的分组加密,猜测是tea算法中的某一个,接下来就是验证了

接着trace与调试,看到了一些特征

image-20241019215031399

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

然后密钥呢

image-20241019215044804

观察算法,实际上我们只要让v0,v1都等于0,让sum分别等于0,1,2,3就可以分别得到v0,v1,v2,v3

然后输入数据调试验证发现出题人没有魔改,还是很善良的ww。

接着尝试获取密文,总之还是没看到逻辑,但是看到了cmp

image-20241019215055395

动调试了下发现确实是这里,故下个条件断点主动更改寄存器并将所有值打出来

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 z3
from 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 product
for 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成功定位到了反调试的位置

image-20241020224712919

将jnz patch 为jmp绕过

image-20241020235728446

接着这里如果马后炮的话直接去康康对应的函数就行,但是今天面对这种题目确实一直找不到切入点,故考虑能否通过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脚本

image-20241020235706574

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

image-20241020234843657

这里用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_bytes
 
 
def 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 + key
 
def 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_byte
 
 
def 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_byte
 
 
result = [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] * 41
 
for 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

上传的附件 main.zip
challenge.zip
babyre.zip

最新回复:
Editor 2024-10-21 18:39:53
实例以附件形式提供一下
z2zccc 2024-10-21 23:20:37
Editor 实例以附件形式提供一下
已添加附件