Skip to content

Commit 0dfa357

Browse files
authored
Merge pull request #1050 from kabeor/dev
add QNX set_api() support
2 parents c6a0264 + f6ba871 commit 0dfa357

File tree

5 files changed

+109
-8
lines changed

5 files changed

+109
-8
lines changed

.github/workflows/build-ci.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ jobs:
7878
wget https://github.com/qilingframework/rootfs/archive/refs/heads/master.zip
7979
unzip master.zip && mv rootfs-master rootfs
8080
cd ../qiling
81-
rm -rf engine
82-
wget https://github.com/qilingframework/engine/archive/refs/heads/main.zip
83-
unzip main.zip && mv engine-main engine
8481
cd ../examples/rootfs/x86_linux/kernel && unzip -P infected m0hamed_rootkit.ko.zip
8582
cd ../../../../
8683
pip3 install -e .[evm]
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
import sys
7+
sys.path.append("..")
8+
9+
from qiling import Qiling
10+
from qiling.const import QL_INTERCEPT, QL_CALL_BLOCK, QL_VERBOSE
11+
from qiling.os.const import STRING
12+
13+
def my_puts_onenter(ql: Qiling):
14+
params = ql.os.resolve_fcall_params({'s': STRING})
15+
16+
print(f'puts("{params["s"]}")')
17+
return QL_CALL_BLOCK
18+
19+
def my_printf_onenter(ql: Qiling):
20+
params = ql.os.resolve_fcall_params({'s': STRING})
21+
22+
print(f'printf("{params["s"]}")')
23+
return QL_CALL_BLOCK
24+
25+
def my_puts_onexit(ql: Qiling):
26+
print(f'after puts')
27+
return QL_CALL_BLOCK
28+
29+
if __name__ == "__main__":
30+
ql = Qiling(["rootfs/arm_qnx/bin/hello_static"], "rootfs/arm_qnx")
31+
ql.set_api('puts', my_puts_onenter, QL_INTERCEPT.ENTER)
32+
ql.set_api('printf', my_printf_onenter, QL_INTERCEPT.ENTER)
33+
ql.set_api('puts', my_puts_onexit, QL_INTERCEPT.EXIT)
34+
ql.run()

qiling/os/qnx/message.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def ql_qnx_msg_io_connect(ql:Qiling, coid, smsg, sparts, rmsg, rparts, *args, **
9898
else:
9999
# TODO: Can we throw this exception here?
100100
# raise NotImplementedError(f'msg_io_connect(_IO_CONNECT_COMBINE) for type 0x{x_type:x} not implemented')
101-
ql.log.warn(f'msg_io_connect(_IO_CONNECT_COMBINE) for type 0x{x_type:x} not implemented')
101+
ql.log.warning(f'msg_io_connect(_IO_CONNECT_COMBINE) for type 0x{x_type:x} not implemented')
102102
elif subtype == 2: # == _IO_CONNECT_OPEN
103103
ql.log.debug(f'open(path = {path}, openflags = 0x{ioflag:x}, openmode = 0x{real_mode:x})')
104104
ql.os.connections[coid].fd = ql_syscall_open(ql, ql.unpack32(ql.mem.read(smsg + 8, 4)), ioflag, real_mode)
@@ -127,7 +127,7 @@ def ql_qnx_msg_io_connect(ql:Qiling, coid, smsg, sparts, rmsg, rparts, *args, **
127127
elif os.path.isfile(real_path):
128128
umask = file_stats['_S_IFREG']
129129
else:
130-
ql.log.warn("msg_io_connect(): type of {real_path} not handled properly?")
130+
ql.log.warning("msg_io_connect(): type of {real_path} not handled properly?")
131131
umask = 0
132132
# struct _io_connect_link_reply in lib/c/public/sys/iomsg.h
133133
ql.mem.write(iov_base, pack("<IIBBHIHH", 0, file_type, eflag, 0, 0, umask, 0, 0))
@@ -190,7 +190,7 @@ def ql_qnx_msg_mem_ctrl(ql:Qiling, coid, smsg, sparts, rmsg, rparts, *args, **kw
190190
if not subtype in mem_ctrl_subtypes:
191191
raise NotImplementedError(f'MEM_CTRL subtype {subtype} not implemented')
192192

193-
ql.log.warn(f'msg_mem_ctrl(subtype = {mem_ctrl_subtypes[subtype]}, flags = 0x{flags:x}, addr = 0x{addr:x}, len = 0x{len:x}) not implemented')
193+
ql.log.warning(f'msg_mem_ctrl(subtype = {mem_ctrl_subtypes[subtype]}, flags = 0x{flags:x}, addr = 0x{addr:x}, len = 0x{len:x}) not implemented')
194194
# TODO: implement mem_ctrl
195195
return -1
196196

qiling/os/qnx/qnx.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,34 @@
33
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44
#
55

6+
from typing import Callable
67
import os
78
from unicorn import UcError
89

910
from qiling.os.posix.posix import QlOsPosix
1011
from qiling.os.qnx.const import NTO_SIDE_CHANNEL, SYSMGR_PID, SYSMGR_CHID, SYSMGR_COID
1112
from qiling.os.qnx.helpers import QnxConn
1213
from qiling.os.qnx.structs import _thread_local_storage
13-
from qiling.const import QL_ARCH
14+
from qiling.os.fcall import QlFunctionCall
15+
from qiling.cc import QlCC, intel, arm, mips, riscv
16+
from qiling.const import QL_ARCH, QL_INTERCEPT
1417

1518
class QlOsQnx(QlOsPosix):
1619
def __init__(self, ql):
1720
super(QlOsQnx, self).__init__(ql)
1821
self.load()
22+
23+
cc: QlCC = {
24+
QL_ARCH.X86 : intel.cdecl,
25+
QL_ARCH.X8664 : intel.amd64,
26+
QL_ARCH.ARM : arm.aarch32,
27+
QL_ARCH.ARM64 : arm.aarch64,
28+
QL_ARCH.MIPS : mips.mipso32,
29+
QL_ARCH.RISCV : riscv.riscv,
30+
QL_ARCH.RISCV64: riscv.riscv,
31+
}[ql.archtype](ql)
32+
33+
self.fcall = QlFunctionCall(ql, cc)
1934

2035
# use counters to get free Ids
2136
self.channel_id = 1
@@ -44,6 +59,10 @@ def hook_syscall(self, intno= None, int = None):
4459
return self.load_syscall()
4560

4661

62+
def add_function_hook(self, fn: str, cb: Callable, intercept: QL_INTERCEPT):
63+
self.ql.os.function_hook.add_function_hook(fn, cb, intercept)
64+
65+
4766
def hook_sigtrap(self, intno= None, int = None):
4867
self.ql.log.info("Trap Found")
4968
self.emu_error()

tests/test_qnx.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from qiling import *
1010
from qiling.exception import *
1111
from qiling.const import QL_VERBOSE
12+
from qiling.const import QL_INTERCEPT, QL_CALL_BLOCK, QL_VERBOSE
13+
from qiling.os.const import STRING
1214

1315
class QNXTest(unittest.TestCase):
1416
def test_arm_qnx_static(self):
@@ -20,7 +22,56 @@ def test_arm_qnx_static(self):
2022

2123
def test_arm_qnx_sqrt(self):
2224
ql = Qiling(["../examples/rootfs/arm_qnx/bin/hello_sqrt"], "../examples/rootfs/arm_qnx", verbose=QL_VERBOSE.DEBUG)
23-
ql.run()
25+
ql.run()
26+
27+
def test_set_api_arm_qnx_sqrt(self):
28+
self.set_api_puts_onenter = False
29+
self.set_api_puts_onexit = False
30+
self.set_api_printf_onenter = False
31+
self.set_api_printf_onexit = False
32+
33+
def my_puts_onenter(ql: Qiling):
34+
params = ql.os.resolve_fcall_params({'s': STRING})
35+
36+
print(f'puts("{params["s"]}")')
37+
self.set_api_puts_onenter = True
38+
return QL_CALL_BLOCK
39+
40+
def my_puts_onexit(ql: Qiling):
41+
print(f'after puts')
42+
self.set_api_puts_onexit = True
43+
return QL_CALL_BLOCK
44+
45+
def my_printf_onenter(ql: Qiling):
46+
params = ql.os.resolve_fcall_params({'s': STRING})
47+
48+
print(f'printf("{params["s"]}")')
49+
self.set_api_printf_onenter = True
50+
return QL_CALL_BLOCK
51+
52+
def my_printf_onexit(ql: Qiling):
53+
print(f'after printf')
54+
self.set_api_printf_onexit = True
55+
return QL_CALL_BLOCK
56+
57+
ql = Qiling(["../examples/rootfs/arm_qnx/bin/hello_sqrt"], "../examples/rootfs/arm_qnx", verbose=QL_VERBOSE.DEBUG)
58+
ql.set_api('puts', my_puts_onenter, QL_INTERCEPT.ENTER)
59+
ql.set_api('printf', my_printf_onenter, QL_INTERCEPT.ENTER)
60+
61+
# ql.set_api('puts', my_puts_onexit, QL_INTERCEPT.EXIT)
62+
ql.set_api('printf', my_printf_onexit, QL_INTERCEPT.EXIT)
63+
64+
ql.run()
65+
66+
self.assertEqual(False, self.set_api_puts_onenter)
67+
self.assertEqual(False, self.set_api_puts_onexit)
68+
self.assertEqual(True, self.set_api_printf_onenter)
69+
self.assertEqual(True, self.set_api_printf_onexit)
70+
71+
del self.set_api_puts_onenter
72+
del self.set_api_puts_onexit
73+
del self.set_api_printf_onenter
74+
del self.set_api_printf_onexit
2475

2576
if __name__ == "__main__":
2677
unittest.main()

0 commit comments

Comments
 (0)