Skip to content

Commit

Permalink
Replace function_arg with new fcall api
Browse files Browse the repository at this point in the history
  • Loading branch information
elicn committed Feb 27, 2021
1 parent 34c7c09 commit 2579e21
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 70 deletions.
22 changes: 11 additions & 11 deletions examples/hello_mips32el_linux_function_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@
import sys

sys.path.append("..")
from qiling import *
from qiling.const import *
from qiling import Qiling
from qiling.os.const import STRING
from qiling.const import QL_INTERCEPT

def my_puts_onenter(ql):
addr = ql.os.function_arg[0]
print("puts(%s)" % ql.mem.string(addr))
return 2
def my_puts_onenter(ql: Qiling):
params = ql.os.resolve_fcall_params({'s': STRING})

def my_puts(ql):
addr = ql.os.function_arg[0]
print("puts(%s)" % ql.mem.string(addr))
print(f'puts("{params["s"]}")')
return 2

def my_puts_onexit(ql):
print("puts exit")
def my_puts_onexit(ql: Qiling):
print(f'after puts')
return 2

if __name__ == "__main__":
ql = Qiling(["rootfs/mips32el_linux/bin/mips32el_double_hello"], "rootfs/mips32el_linux", output="debug")

ql.set_api('puts', my_puts_onenter, QL_INTERCEPT.ENTER)
ql.set_api('puts', my_puts_onexit, QL_INTERCEPT.EXIT)

ql.run()
12 changes: 7 additions & 5 deletions examples/hello_x8664_linux_customapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
#
import sys
sys.path.append("..")
from qiling import *
from qiling.const import *

def my_puts(ql):
addr = ql.os.function_arg[0]
print("puts(%s)" % ql.mem.string(addr))
from qiling import Qiling
from qiling.os.const import STRING

def my_puts(ql: Qiling):
params = ql.os.resolve_fcall_params({'s': STRING})

print(f'puts("{params["s"]}")')

if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/x8664_hello"], "rootfs/x8664_linux", output="debug")
Expand Down
44 changes: 25 additions & 19 deletions examples/netgear_6220_mips32el_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
#
# This firmware will more or less alive now.


from qiling import *
from qiling.os.posix import syscall
from qiling.const import *
from colorama import Back
import struct
import sys
sys.path.append("..")

from qiling import Qiling
from qiling.const import QL_INTERCEPT
from qiling.os.posix import syscall
from qiling.os.const import UINT, POINTER

def my_syscall_write(ql, write_fd, write_buf, write_count, *rest):
if write_fd == 2 and ql.os.fd[2].__class__.__name__ == 'ql_pipe':
Expand All @@ -28,11 +28,18 @@ def my_syscall_write(ql, write_fd, write_buf, write_count, *rest):
return syscall.ql_syscall_write(ql, write_fd, write_buf, write_count, *rest)


def my_bind(ql, *args, **kw):
bind_fd = ql.os.function_arg[0]
bind_addr = ql.os.function_arg[1]
bind_addrlen = ql.os.function_arg[2]
print(Back.GREEN + "Hijack bind(%d, %d, %d)" % (bind_fd, bind_addr, bind_addrlen) + Back.RESET)
def my_bind(ql: Qiling):
params = ql.os.resolve_fcall_params({
'fd': UINT,
'addr': POINTER,
'addrlen': UINT
})

bind_fd = params['fd']
bind_addr = params['addr']
bind_addrlen = params['addrlen']

print(Back.GREEN + f'Hijack bind({bind_fd}, {bind_addr:#x}, {bind_addrlen})' + Back.RESET)
# read from memory (start_address, len)
data = ql.mem.read(bind_addr, bind_addrlen)
# custom unpack (your own ql.unpack) of a C struct from memory
Expand All @@ -41,25 +48,24 @@ def my_bind(ql, *args, **kw):
# little-endian short -> format_string -> https://docs.python.org/3/library/struct.html#format-strings
port, host = struct.unpack(">HI", data[2:8])
# big-endian unsigned short, unsigned int -> format_string
print(Back.RED+"[*] Socket Infos:"+Back.RESET+"\nFamily: %d\nPort: %d (no root: +8000)\nHost-interface?: %d\n" % (sin_family, port, host))
print(Back.RED + f'[*] Socket Infos:' + Back.RESET)
print(f'''
Family: {sin_family}
Port: {port} (no root: +8000)
Host-interface?: {host}
''')
return 0 # from syscall.ql_syscall_bind(ql, bind_fd, bind_addr, bind_addrlen)

def my_netgear(path, rootfs):
ql = Qiling(
path,
rootfs,
output = "debug",
profile = "netgear_6220.ql"
)
ql = Qiling(path, rootfs, output="debug", profile="netgear_6220.ql")

ql.root = False
ql.multithread = False
ql.root = False
ql.multithread = False
ql.add_fs_mapper('/proc', '/proc')
ql.set_syscall(4004, my_syscall_write)
ql.set_api('bind', my_bind, QL_INTERCEPT.ENTER) # intercepting the bind call on enter
ql.run()


if __name__ == "__main__":
my_netgear(["rootfs/netgear_r6220/bin/mini_httpd",
"-d", "/www",
Expand Down
16 changes: 0 additions & 16 deletions qiling/os/posix/posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
from qiling.os.macos.syscall import *
from qiling.os.freebsd.syscall import *

from qiling.os.linux.function_hook import FunctionArgv, ARMFunctionArg, MIPS32FunctionArg, ARM64FunctionArg, X86FunctionArg, X64FunctionArg

SYSCALL_PREF: str = f'ql_syscall_'

class QlOsPosix(QlOs):
Expand Down Expand Up @@ -154,14 +152,6 @@ def __syscall_args_x8664():
QL_ARCH.X8664: __syscall_args_x8664
}[self.ql.archtype]

self.__fcall_args: FunctionArgv = {
QL_ARCH.ARM64: ARM64FunctionArg,
QL_ARCH.ARM : ARMFunctionArg,
QL_ARCH.MIPS : MIPS32FunctionArg,
QL_ARCH.X86 : X86FunctionArg,
QL_ARCH.X8664: X64FunctionArg
}[self.ql.archtype](self.ql)

self.fd = QlFileDes([0] * 256)

if self.ql.ostype in QL_OS_POSIX:
Expand All @@ -188,12 +178,6 @@ def set_syscall(self, target: Union[int, str], handler: Callable, intercept: QL_
# if self.ql.ostype in (QL_OS.WINDOWS, QL_OS.UEFI):
# self.set_api(target_syscall, intercept_function)

# TODO: replace by fcall.cc
# ql.func_arg - get syscall for all posix series
@property
def function_arg(self) -> FunctionArgv:
return self.__fcall_args

@staticmethod
def getNameFromErrorCode(ret: int) -> str:
"""Return the hex representation of a return value and if possible
Expand Down
42 changes: 23 additions & 19 deletions tests/test_elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#

import sys, unittest, subprocess, string, random, os

from unicorn import UcError, UC_ERR_READ_UNMAPPED, UC_ERR_FETCH_UNMAPPED
import sys, unittest, string, random, os

sys.path.append("..")
from qiling import *
from qiling.const import *
from qiling import Qiling
from qiling.const import QL_OS, QL_OUTPUT, QL_INTERCEPT
from qiling.exception import *
from qiling.os.const import STRING
from qiling.os.posix import syscall
from qiling.os.mapper import QlFsMappedObject
from qiling.os.posix.stat import Fstat
Expand Down Expand Up @@ -61,11 +60,12 @@ def stop(ql, *args, **kw):

del ql

PARAMS_PUTS = {'s': STRING}

def test_elf_linux_x8664(self):
def my_puts(ql):
addr = ql.os.function_arg[0]
print("puts(%s)" % ql.mem.string(addr))
def my_puts(ql: Qiling):
params = ql.os.resolve_fcall_params(ELFTest.PARAMS_PUTS)
print(f'puts("{params["s"]}")')
reg = ql.reg.read("rax")
print("reg : 0x%x" % reg)
ql.reg.rax = reg
Expand Down Expand Up @@ -105,10 +105,10 @@ def write_onexit(ql, arg1, arg2, arg3, *args):

def test_elf_hijackapi_linux_x8664(self):

def my_puts_enter(ql):
addr = ql.os.function_arg[0]
self.test_enter_str = ql.mem.string(addr)
def my_puts_enter(ql: Qiling):
params = ql.os.resolve_fcall_params(ELFTest.PARAMS_PUTS)
self.test_enter_str = params["s"]

def my_puts_exit(ql):
self.test_exit_rdi = ql.reg.rdi

Expand Down Expand Up @@ -274,11 +274,12 @@ def test_syscall_ftruncate(ql, ftrunc_fd, ftrunc_length, *args):

def test_elf_linux_arm(self):
def my_puts(ql):
addr = ql.os.function_arg[0]
print("puts(%s)" % ql.mem.string(addr))
params = ql.os.resolve_fcall_params(ELFTest.PARAMS_PUTS)
print(f'puts("{params["s"]}")')

all_mem = ql.mem.save()
ql.mem.restore(all_mem)

ql = Qiling(["../examples/rootfs/arm_linux/bin/arm_hello"], "../examples/rootfs/arm_linux", output = "debug", profile='profiles/append_test.ql')
ql.set_api('puts', my_puts)
ql.run()
Expand Down Expand Up @@ -426,10 +427,13 @@ def random_generator(size=6, chars=string.ascii_uppercase + string.digits):


def test_elf_onEnter_mips32el(self):
def my_puts_onenter(ql):
addr = ql.os.function_arg[0]
print("puts(%s)" % ql.mem.string(addr))
self.my_puts_onenter_addr = addr
def my_puts_onenter(ql: Qiling):
params = ql.os.resolve_fcall_params(ELFTest.PARAMS_PUTS)
print(f'puts("{params["s"]}")')

params = ql.os.fcall.readParams(ELFTest.PARAMS_PUTS.values())
self.my_puts_onenter_addr = params[0]

return 2

ql = Qiling(["../examples/rootfs/mips32el_linux/bin/mips32el_double_hello"], "../examples/rootfs/mips32el_linux")
Expand Down

0 comments on commit 2579e21

Please sign in to comment.