介绍
题目链接 https://ctf.bugku.com/challenges/detail/id/412.html
该题目动态生成核心的校验代码,因此动态调试比较容易。
write up
大概分析
main 函数中得到输入,给变量addr 分配内存并由 sub_1185函数写入数据。然后执行addr处指令(函数),addr处函数返回0,则成功。
因此,核心是拿到addr处函数。
__int64 __fastcall main(int a1, char **a2, char **a3)
{char s[136]; // [rsp+0h] [rbp-90h] BYREFvoid *addr; // [rsp+88h] [rbp-8h]puts(::s);printf("Enter the license key: ");fgets(s, 128, stdin);s[strcspn(s, "\n")] = 0;addr = mmap(0LL, 0xE2uLL, 7, 33, -1, 0LL);sub_1185((__int64)addr, 0, 0, 1);if ( ((unsigned int (__fastcall *)(char *))addr)(s) )puts("\x1B[1m\x1B[31m[-] Nope, wrong.\x1B[0m");elseputs("\x1B[1m\x1B[32m[+] Well done, that's it!\x1B[0m");munmap(addr, 0xE2uLL);return 0LL;
}
动态调试
gdb下断点到调用addr处第一条指令,使用 x/27i $rip
查看函数指令:
0x7ffff7fbc000: lea -0x7(%rip),%rsi # 0x7ffff7fbc000 │
0x7ffff7fbc007: xor %rcx,%rcx │
0x7ffff7fbc00a: jmp 0x7ffff7fbc00f │
0x7ffff7fbc00c: inc %rcx │
0x7ffff7fbc00f: mov (%rdi,%rcx,1),%al │
0x7ffff7fbc012: test %al,%al │
0x7ffff7fbc014: jne 0x7ffff7fbc00c │
0x7ffff7fbc016: cmp $0x2f,%rcx │ 判断字符串长度是否为0x2f
0x7ffff7fbc01a: jne 0x7ffff7fbc04d │
0x7ffff7fbc01c: xor %rdx,%rdx │ rdx = 0
0x7ffff7fbc01f: xor %rax,%rax │ rax = 0
0x7ffff7fbc022: mov 0x55(%rsi,%rdx,1),%al │ al = rsi + rdx + 0x55
0x7ffff7fbc026: mov 0x84(%rax,%rsi,1),%al │ al = rax + rsi + 0x84
0x7ffff7fbc02d: mov (%rdi,%rdx,1),%bl │ bl = rdi + rdx
0x7ffff7fbc030: xor %bl,%al │ al = al ^ bl
0x7ffff7fbc032: mov 0xb3(%rdx,%rsi,1),%bl │ bl = rdx + rsi + 0xb3
0x7ffff7fbc039: cmp %bl,%al │ bl == al? input_string[i]^ target_rsi_0x84[ target_string_rsi_0x55[i] ] = target_rsi_0xb3[i]
0x7ffff7fbc03b: jne 0x7ffff7fbc04d │ 不相等 return 1
0x7ffff7fbc03d: dec %rcx │ rcx --
0x7ffff7fbc040: inc %rdx │ rdx ++
0x7ffff7fbc043: test %rcx,%rcx │ rcx == 0 ?
0x7ffff7fbc046: jne 0x7ffff7fbc022 │ 继续循环
0x7ffff7fbc048: xor %rax,%rax │
0x7ffff7fbc04b: jmp 0x7ffff7fbc054 │
0x7ffff7fbc04d: mov $0x1,%eax │
0x7ffff7fbc052: jmp 0x7ffff7fbc054 │
0x7ffff7fbc054: ret
逆向算法
校验算法大概是
for(i=0; i<=0x2f; ++i){if (input_string[i]^ target_rsi_0x84[ target_string_rsi_0x55[i] ] != target_rsi_0xb3[i]) return 1;
}
return 0;
查看 rsi + 0x55 处数据:
(gdb) x/47x 0x7ffff7fbc000+0x55 │
0x7ffff7fbc055: 0x0b 0x20 0x04 0x08 0x29 0x1c 0x15 0x11 │
0x7ffff7fbc05d: 0x16 0x18 0x07 0x1e 0x1f 0x26 0x01 0x25 │
0x7ffff7fbc065: 0x23 0x1a 0x06 0x21 0x1d 0x12 0x0f 0x14 │
0x7ffff7fbc06d: 0x09 0x05 0x0d 0x2b 0x0a 0x28 0x10 0x03 │
0x7ffff7fbc075: 0x0c 0x22 0x2c 0x27 0x24 0x02 0x2e 0x19 │
0x7ffff7fbc07d: 0x17 0x2d 0x13 0x1b 0x2a 0x00 0x0e
同理查看 rsi+0x84 处数据:
(gdb) x/47x 0x7ffff7fbc000+0x84
0x7ffff7fbc084: 0xa2 0x20 0x50 0x04 0xdc 0x48 0x85 0x84
0x7ffff7fbc08c: 0x09 0x47 0xa9 0x30 0x24 0x53 0x81 0xd7
0x7ffff7fbc094: 0x6c 0xde 0xa7 0x8a 0x3b 0x3e 0x02 0xf9
0x7ffff7fbc09c: 0x19 0x14 0xac 0xda 0xbf 0x25 0x36 0x9a
0x7ffff7fbc0a4: 0x69 0x39 0xc8 0x9f 0xc6 0xef 0xaf 0x66
0x7ffff7fbc0ac: 0x9b 0x02 0x35 0xd9 0x2b 0xf2 0xdc
rsi+0xb3处数据:
(gdb) x/47x 0x7ffff7fbc000+0xb3
0x7ffff7fbc0b3: 0x43 0x01 0xb9 0x65 0x6e 0xd2 0x5f 0xaa
0x7ffff7fbc0bb: 0x67 0x6a 0xff 0x66 0xca 0xfb 0x61 0xa7
0x7ffff7fbc0c3: 0xb2 0xfa 0xca 0x7a 0x67 0xe5 0xfa 0x72
0x7ffff7fbc0cb: 0x02 0x09 0x1a 0x9a 0x84 0xaa 0x59 0x51
0x7ffff7fbc0d3: 0x7c 0x9d 0x06 0x54 0x92 0x14 0x93 0x5f
0x7ffff7fbc0db: 0xd4 0xc6 0xcc 0x95 0x77 0xf3 0xfc
写脚本:
# target_string_rsi_0x55
arr1 = [0x0b,0x20 , 0x04 , 0x08 , 0x29 , 0x1c , 0x15 , 0x11, 0x16 , 0x18 , 0x07 , 0x1e , 0x1f , 0x26,0x01 , 0x25, 0x23 , 0x1a , 0x06 , 0x21,0x1d , 0x12 , 0x0f , 0x14
, 0x09 , 0x05 , 0x0d , 0x2b,0x0a , 0x28 , 0x10 , 0x03 , 0x0c , 0x22 , 0x2c,0x27 , 0x24 , 0x02 , 0x2e, 0x19, 0x17, 0x2d, 0x13, 0x1b, 0x2a, 0x00, 0x0e]# target_rsi_0x84
arr2 = [0xa2,0x20,0x50,0x04 , 0xdc,0x48 , 0x85,0x84, 0x09 , 0x47 , 0xa9,0x30,0x24 , 0x53 , 0x81 , 0xd7, 0x6c , 0xde , 0xa7 , 0x8a , 0x3b , 0x3e , 0x02 , 0xf9,
0x19 , 0x14,0xac , 0xda , 0xbf , 0x25 , 0x36 , 0x9a,0x69 , 0x39 , 0xc8 , 0x9f , 0xc6 , 0xef , 0xaf , 0x66, 0x9b, 0x02, 0x35, 0xd9, 0x2b, 0xf2, 0xdc, 0x43]# target_rsi_0xb3
arr3 = [0x43,0x01,0xb9,0x65,0x6e,0xd2,0x5f,0xaa , 0x67,0x6a,0xff,0x66,0xca,0xfb,0x61,0xa7 , 0xb2,0xfa,0xca,0x7a,0x67,0xe5,0xfa,0x72,
0x02,0x09,0x1a,0x9a,0x84,0xaa,0x59,0x51,0x7c,0x9d,0x06,0x54,0x92,0x14,0x93, 0x5f, 0xd4, 0xc6 , 0xcc , 0x95 , 0x77 , 0xf3 , 0xfc ]print((arr1))
print((arr2))
print((arr3))for i in range(0x2f):index = arr1[i]# print(index)print(chr(arr2[index] ^ arr3[i]), end="")