C statements:
syscall(__NR_write, fd, buffer, len) where __NR_write is equal to 1 on x86_64 architecture and fd is stdoutsyscall(__NR_getuid) where __NR_getuid is equal to 102 on x86_64 architecture
syscall(__NR_ptrace, req, pid, addr, data) where __NR_ptrace is equal to 101 on x86_64 architecture
Python statements:
$ cat syscall.py#!/usr/bin/env python
# proof of concept how to call syscall from python
# with write(2), ptrace(2) and getuid(2) example
from ctypes.util import find_library
from ctypes import *
import platform, sys
if sys.maxint == 0x7fffffffffffffff and platform.architecture()[0][:2] == '64':
target_x64 = True
else:
target_x64 = False
syscalls = {}
syscalls['__NR_write'] = (4, 1)[target_x64]
syscalls['__NR_ptrace'] = (26, 101)[target_x64]
syscalls['__NR_getuid'] = (24, 102)[target_x64]
libc = cdll.LoadLibrary(find_library('c'))
def ctypes_bind(funcname, restype=None, argtypes=[]):
f = getattr(libc, funcname)
f.restype = restype
f.argtypes = argtypes
return f
def write(msg):
syscall = ctypes_bind('syscall', c_int, [c_int, c_int, c_char_p, c_int])
syscall(syscalls['__NR_write'], 1, msg, len(msg))
def getuid():
syscall = ctypes_bind('syscall', c_int, [])
syscall(syscalls['__NR_getuid'])
(
PTRACE_TRACEME,
PTRACE_PEEKEXT,
PTRACE_PEEKDATA,
PTRACE_USR,
PTRACE_POKEEXT,
PTRACE_POKEDATA,
PTRACE_POKEUSR,
PTRACE_CONT,
PTRACE_KILL,
PTRACE_SINGLESTEP
) = range(0, 10)
PTRACE_ATTACH = 16
PTRACE_DETACH = 17
PTRACE_SYSCALL = 24
def ptrace(req, pid, addr, data):
syscall = ctypes_bind('syscall', c_long, [c_int, c_int, c_void_p, c_void_p])
syscall(syscalls['__NR_ptrace'], req, pid, addr, data)
def traceme():
ptrace(PTRACE_TRACEME, 0, 0, 0)
if __name__ == '__main__':
write("sbz write syscall lulz for the fnu\n")
print getuid()
On runtime in ipython:
In [1]: from syscall import *
In [2]: write("lulz\n")
lulz
In [3]: getuid()
1010
Like this, we can emulate the syscall function of ruby Kernel module.
0 comments:
Post a Comment