avatar

南宁杯re-SMC.exe

写在前面

之前做了一下这个比赛 pwn,这道题其实当时也看了一下,感觉逻辑比较复杂然后时间有点来不急就没再看了,之后逛先知社区发现有人写了一篇动态逆向这道题的文章,看了一下写的很详细,学习一下。

文章地址

idea

先运行一下看看程序的大体逻辑,可以发现是一个经典的验证类型的程序。

然后去 ida 里面看看这个验证程序怎么实现的,flag 为 29 位的字符串最后一位是 ‘}’ ,然后进行前8位的校验。 v7是一个计数器,前 8 位每次与预设值验证相等的时候技术器会加 1 ,当 v7 等于 8 的时候就会进入下一轮的 check。本轮的 check 可以简化为 A ^ B == C ,我们想要的是 input1,那么看一下汇编代码。

1
2
3
4
5
6
7
.text:00401268                 movsx   ebp, byte ptr [eax]
.text:0040126B mov ebx, dword_40803C[ebx*4]
.text:00401272 xor ebx, ebp
.text:00401274 movsx ebp, byte ptr [edx+eax]
.text:00401278 cmp ebx, ebp
.text:0040127A jnz short loc_401280
.text:0040127C inc [esp+14h+var_4]

可以看一下核心过程,xor ebx,ebp 是将 exb ebp 异或的结果赋值给 ebx,对应 if 的判断,那么要想得到 input1 把 ebp 寄存器的值和 ebx 寄存器的值异或一下就行了。 A ^ B == C <—> C ^ B == A

1
2
.text:00401272                 xor     ebx, ebp
.text:00401278 cmp ebx, ebp

在 od 中这个地址下一个断点 00401272 观察寄存器的值,然后先写一个脚本验证一下。

1
2
3
4
5
6
7
8
9
10
ebp = [0x6d,0x77,0x77,0x5f,0x63,0x60,0x74,0x77]
ebx = [0xa,0xf,0x19,0x31,0x00,0x14,0x12,0xc]
flag = []
for i in range(8):
flag.append(chr(ebp[i] ^ ebx[i]))

print "".join(flag)

❯ python ll.py
gxnnctf{

可以看到思路确实这样的~,那么进入下一个 check。道理和上一轮一样,但是逻辑简单了不少:v3 的值已经全部给出来了,那么我们继续。

当然,如果这里写成了其它逻辑的话我们也可以去 od 中动态调试。

1
2
3
4
5
6
7
8
9
a = [61,11,95,8,67]

for i in range(5):
flag.append(chr(a[i] ^ 110))

print "".join(flag)

❯ python ll.py
Se1f-

进入下一轮 check ,这轮的 check 比较复杂,如果静态去逆的话工程量非常大… 动态去逆的话工程量会小的不是一点半点儿。

这边还有一个坑,这边有两个计数器,一个是 9 一个是 12 。如果一切 ok 进入下一轮的 check 是计数器 v8 == 12,来回顾一下:flag 总共 29位,目前得到的 flag 是 gxnnctf{Se1f- 这 13 个字符。最后一位是 } 。那么我们还需要计算出 29 - 14 = 15 个字符,先进入下一轮 check 看看计算出的 flag 是多少位的。

6位的,那么本轮的计算出来的字符应该是多少位的呢? 15 - 6 = 9。但是为什么会输出 12 位字符呢?应该是被加密了,联想一下常用编码的特性,应该不难想到 base64编码。

那么关注一下本轮的核心验证逻辑,*((_BYTE *)&v11 + v9) == v15[v9] 再看看汇编,关心一下 寄存器 dl 的值就好。

1
2
3
4
5
.text:00401127                 mov     dl, byte ptr [esp+eax+34h+var_20]
.text:0040112B mov bl, [esp+eax+34h+var_10]
.text:0040112F cmp dl, bl
.text:00401131 jnz short loc_401134
.text:00401133 inc ecx

ok,没问题,进入下一轮 check~ 核心验证逻辑是

可以简化一下,如下。其实不用动态调,这个值就是 v3 的值。

1
2
3
4
5
6
if ( *(char *)(result + a1) + 2 == *((char *)&v3) )


.data:004080C4 dword_4080C4 dd 66326561h ; DATA XREF: sub_401000+3↑r
.data:004080C8 word_4080C8 dw 2367h ; DATA XREF: sub_401000+8↑r
.data:004080CA byte_4080CA db 0
y
1
2
3
4
❯ python ll.py
gxnnctf{
gxnnctf{Se1f-
gxnnctf{Se1f-_c0de!

总结一下,gxnnctf{Se1f-M0difying_c0de!},然后去验证。

Author: CarlStar
Link: http://yoursite.com/2019/01/22/smc/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment