Introduction
根据题目程序存在后门,某个参数可以触发该程序执行后门操作。这个程序是个exe程序,但在win10和win7虚拟机上均无法运行,最后在Win XP上按照提示下载了缺失的MSVCP100D.dll后终于得以成功运行。
Analysis
一开始在hopper中反编译程序,虽然程序逻辑结构很清楚,但是代码可读性真是一言难尽……还是老老实实打开IDA吧。
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
| signed int __cdecl wmain(int a1, int a2) { char v3; char v4; char v5; char Source[4]; char v7; __int16 i; char Dest[2]; char Dst; char v11[25]; char v12[483]; __int16 v13; LPSTR lpMultiByteStr; int cbMultiByte;
cbMultiByte = WideCharToMultiByte(1u, 0, *(LPCWSTR *)(a2 + 4), -1, 0, 0, 0, 0); lpMultiByteStr = (LPSTR)sub_4011F0(cbMultiByte); WideCharToMultiByte(1u, 0, *(LPCWSTR *)(a2 + 4), -1, lpMultiByteStr, cbMultiByte, 0, 0); v13 = *(_WORD *)lpMultiByteStr; if ( v13 < 0 ) return -1; v13 ^= 0x6443u; strcpy(Dest, "0"); memset(&Dst, 0, 0x1FEu); for ( i = 0; i < v13; ++i ) Dest[i] = 65; *(_DWORD *)Source = 2147108114; v7 = 0; strcpy(&Dest[v13], Source); qmemcpy(&v5, &unk_4021FC, 0x1Au); strcpy(&v11[v13], &v5); qmemcpy(&v3, &unk_402168, 0x91u); v4 = 0; strcpy(&v12[v13], &v3); sub_401000(Dest); return 0; }
|
首先看下这个主函数。应该是接收键盘输入的内容,经过转换然后赋给v13,注意v13申明的是int 16,再将v13与0x6443异或。然后向Dest数组里填充v13数值个的ASCII值65也就是’A’。
再将2147108114即0x7ffa4512这个地址传到了Dest[v13]。而0x7ffa4512这个地址在windows上是一个万能的jmp esp(几乎所有的平台上这个地址都是jmp esp)。所以可以通过这个地址上的jmp esp指令控制程序跳转到某一个函数的地址上去执行设定好的函数。
再往下走,这个函数最后调用Dest是将其作为sub_401000函数的参数,再去找一下这个函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| int __cdecl sub_401000(char *Source) { char Dest[2]; int v3; int v4; int v5; int v6; int v7; int v8; int v9; __int16 v10;
strcpy(Dest, "0"); v3 = 0; v4 = 0; v5 = 0; v6 = 0; v7 = 0; v8 = 0; v9 = 0; v10 = 0; strcpy(Dest, Source); return 0; }
|
果然在这个函数里发现了溢出漏洞,在strcpy(Dest, Source)语句这里。在主函数中Source申明的是char Source[4],而Dest申明的是char Dest[2],strcpy函数把一个长字符赋给里一个短字符,典型的溢出漏洞。
根据Dest的大小,需要0x20的padding加上4个字节的返回地址,一共0x24字节。这样程序执行的时候会将0x7ffa4512覆盖到Dest最后4字节也就是strcpy函数的返回地址,从而控制程序跳转触发后门。
所以我们需要控制的是v13的值为0x24即可,再注意一下机器的大小端问题以及题目要求的给出参数小写SHA256值,直接给出EXP:
1 2 3 4 5 6 7
| import hashlib
value = chr(0x24 ^ 0x43) value += chr(0 ^ 0x64)
print "value: " + value print "flag: PCTF{" + hashlib.sha256(value).hexdigest() + "}"
|
执行之后就可以得到出发后门的参数以及flag:
后门程序在Win XP中复现成功,弹出了计算器: