MD5: FC76A2EFBD7D07A89A2DD343B9328E26
SHA1: EDAA95DB7406E5076A2AA8B30BA6B3E7547CD7B4
CRC32: 1374F4F7
很久很久之前某次CTF的PWN。。。题目在附件。
首先分析.exe文件
前面可以看到程序创建了socket服务
黄色选中的call为‘程序功能区’
进入call后,程序先问候一下用户,并设EBX为0:
然后等待用户输入:
清场:
在输入的字符串中查找\x0D,\x0A这两个字符。【这两个查找的目的我不确定,,留作日后任务:
检测输入字符串前九位是否与”USERNAME ”相同,如果不同,跳转至loc_45212c9(即为检测输入字符串是否是”LOGIN ”函数处):
清场:
检查字符串长度,如果字符串长度超过0X7F,只取前0X7F位:
按格式输出一个字符串。需要注意的是此处【mov dword_4532A6C, 1(此处即为我们需要覆盖的关键内存点)】:
接下来是检测输入是否以”LOGIN ”开头的函数,紧挨着这一函数的是校验输入是否以”GETFLAG”开头的函数。(因服务端并未向客户端请求数据,所以此处将校验失败,并在最后返回到本个CALL最开始的部分等待用户输入):
上图中可以看到,输入”LOGIN password”后,【mov dword_4532A6C, 2】,将关键位置设置为2。
并且有:
cmp byte_4532A70, bl //4532A70是我们
jnz short loc_4521306
即如果没有输入”USERNAME ”,则将报错。
如果均为正确输入,则有
call sub_4521000
在结束这些操作后,检验4532a6c处的值,如果其值为0x4452534e,则send flag.txt里的内容。
跟进4521000,先清场,然后检验字符长度,如果超过0X100,则报错:
用几个API生成IP地址的字符串表示,并压入栈
计算长度,将字符串send出去:
然后在下面,出现了一个格式化字符串漏洞:
静态分析结束,拖进OD
直接进入关键点,配置输入,服务端输出如下:
栈内如下:
还可以看到栈内下面不远处就是我们的USERNAME
构造一下输入:
“USERNAME a\x6c\x2a\x53\x04xxxx\x6e\x2a\x53\x04”
//此处目测是出了一点问题,应该是从’2’开始字节对齐的。所以字符串前只加一个’a’
“LOGIN%x%x%x%x%x%x%x%x%x%x%x%x%x%x%21169x%n%61700x%n”
其中第一段%x用于为%n找到写在USERNAME里的地址,之所以使用两个%n是因为只写一个的话数太大,要打很多空格,会很慢。
溢出完成。