Skip to content

Commit a86099d

Browse files
committed
Merge branch 'dev' of github.com:xwings/qiling into dev
2 parents 5d3e74e + d68c750 commit a86099d

File tree

8 files changed

+252
-0
lines changed

8 files changed

+252
-0
lines changed

examples/hello_arm_uboot.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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.core import Qiling
10+
from qiling.const import QL_VERBOSE
11+
from qiling.os.const import STRING
12+
13+
def get_kaimendaji_password():
14+
def my_getenv(ql, *args, **kwargs):
15+
env = {"ID": b"000000000000000", "ethaddr": b"11:22:33:44:55:66"}
16+
params = ql.os.resolve_fcall_params({'key': STRING})
17+
value = env.get(params["key"], b"")
18+
19+
value_addr = ql.os.heap.alloc(len(value))
20+
ql.mem.write(value_addr, value)
21+
22+
ql.reg.r0 = value_addr
23+
ql.reg.arch_pc = ql.reg.lr
24+
25+
def get_password(ql, *args, **kwargs):
26+
password_raw = ql.mem.read(ql.reg.r0, ql.reg.r2)
27+
28+
password = ''
29+
for item in password_raw:
30+
if 0 <= item <= 9:
31+
password += chr(item + 48)
32+
else:
33+
password += chr(item + 87)
34+
35+
print("The password is: %s" % password)
36+
37+
def partial_run_init(ql):
38+
# argv prepare
39+
ql.reg.arch_sp -= 0x30
40+
arg0_ptr = ql.reg.arch_sp
41+
ql.mem.write(arg0_ptr, b"kaimendaji")
42+
43+
ql.reg.arch_sp -= 0x10
44+
arg1_ptr = ql.reg.arch_sp
45+
ql.mem.write(arg1_ptr, b"000000") # arbitrary password
46+
47+
ql.reg.arch_sp -= 0x20
48+
argv_ptr = ql.reg.arch_sp
49+
ql.mem.write(argv_ptr, ql.pack(arg0_ptr))
50+
ql.mem.write(argv_ptr + ql.pointersize, ql.pack(arg1_ptr))
51+
52+
ql.reg.r2 = 2
53+
ql.reg.r3 = argv_ptr
54+
55+
56+
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
57+
uboot_code = f.read()
58+
59+
ql = Qiling(code=uboot_code[0x40:], archtype="arm", ostype="blob", profile="uboot_bin.ql", verbose=QL_VERBOSE.OFF)
60+
61+
image_base_addr = ql.loader.load_address
62+
ql.hook_address(my_getenv, image_base_addr + 0x13AC0)
63+
ql.hook_address(get_password, image_base_addr + 0x48634)
64+
65+
partial_run_init(ql)
66+
67+
ql.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
68+
69+
if __name__ == "__main__":
70+
get_kaimendaji_password()

examples/uboot_bin.ql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[CODE]
2+
ram_size = 0xa00000
3+
entry_point = 0x80800000
4+
heap_size = 0x300000
5+
6+
7+
[LOG]
8+
# log directory output
9+
# usage: dir = qlog
10+
dir =
11+
# split log file, use with multithread
12+
split = False
13+
14+
15+
[MISC]
16+
# append string into different logs
17+
# maily for multiple times Ql run with one file
18+
# usage: append = test1
19+
append =
20+
current_path = /

qiling/const.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class QL_OS(IntEnum):
3333
EVM = 207
3434
QNX = 208
3535
MCU = 209
36+
BLOB = 210
3637

3738
class QL_VERBOSE(IntEnum):
3839
OFF = 0
@@ -89,6 +90,7 @@ def __reverse_enum(e: Type[Enum]) -> Mapping[str, Any]:
8990
QL_OS.DOS : "DOS",
9091
QL_OS.EVM : "EVM",
9192
QL_OS.MCU : "MCU",
93+
QL_OS.BLOB : "BLOB"
9294
}
9395

9496
arch_os_map = {

qiling/loader/blob.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
from qiling import Qiling
7+
from qiling.loader.loader import QlLoader
8+
from qiling.os.memory import QlMemoryHeap
9+
10+
class QlLoaderBLOB(QlLoader):
11+
def __init__(self, ql: Qiling):
12+
super().__init__(ql)
13+
14+
self.load_address = 0
15+
16+
def run(self):
17+
self.load_address = self.ql.os.entry_point # for consistency
18+
19+
self.ql.mem.map(self.ql.os.entry_point, self.ql.os.code_ram_size, info="[code]")
20+
self.ql.mem.write(self.ql.os.entry_point, self.ql.code)
21+
22+
heap_address = self.ql.os.entry_point + self.ql.os.code_ram_size
23+
heap_size = int(self.ql.os.profile.get("CODE", "heap_size"), 16)
24+
self.ql.os.heap = QlMemoryHeap(self.ql, heap_address, heap_address + heap_size)
25+
26+
self.ql.reg.arch_sp = heap_address - 0x1000
27+
28+
return

qiling/os/blob/blob.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
from qiling import Qiling
7+
from qiling.cc import QlCC, intel, arm, mips
8+
from qiling.const import QL_ARCH
9+
from qiling.os.fcall import QlFunctionCall
10+
from qiling.os.os import QlOs
11+
12+
class QlOsBlob(QlOs):
13+
""" QlOsBlob for bare barines.
14+
15+
For bare binary such as u-boot, it's ready to be mapped and executed directly,
16+
where there is(may be) no concept of os? Currently, some functionalities such as
17+
resolve_fcall_params(), heap or add_fs_mapper() are based on os. To keep the
18+
consistence of api usage, QlOsBlob is introduced and placed at its loader temporarily.
19+
"""
20+
def __init__(self, ql: Qiling):
21+
super(QlOsBlob, self).__init__(ql)
22+
23+
self.ql = ql
24+
25+
cc: QlCC = {
26+
QL_ARCH.X86 : intel.cdecl,
27+
QL_ARCH.X8664 : intel.amd64,
28+
QL_ARCH.ARM : arm.aarch32,
29+
QL_ARCH.ARM64 : arm.aarch64,
30+
QL_ARCH.MIPS : mips.mipso32
31+
}[ql.archtype](ql)
32+
33+
self.fcall = QlFunctionCall(ql, cc)
34+
35+
def run(self):
36+
if self.ql.entry_point:
37+
self.entry_point = self.ql.entry_point
38+
39+
self.exit_point = self.ql.loader.load_address + len(self.ql.code)
40+
if self.ql.exit_point:
41+
self.exit_point = self.ql.exit_point
42+
43+
self.ql.emu_start(self.entry_point, self.exit_point, self.ql.timeout, self.ql.count)

tests/profiles/uboot_bin.ql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[CODE]
2+
ram_size = 0xa00000
3+
entry_point = 0x80800000
4+
heap_size = 0x300000
5+
6+
7+
[LOG]
8+
# log directory output
9+
# usage: dir = qlog
10+
dir =
11+
# split log file, use with multithread
12+
split = False
13+
14+
15+
[MISC]
16+
# append string into different logs
17+
# maily for multiple times Ql run with one file
18+
# usage: append = test1
19+
append =
20+
current_path = /

tests/test_blob.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
import sys, unittest
7+
sys.path.append("..")
8+
9+
from qiling.core import Qiling
10+
from qiling.const import QL_VERBOSE
11+
from qiling.os.const import STRING
12+
13+
class BlobTest(unittest.TestCase):
14+
def test_uboot_arm(self):
15+
def my_getenv(ql, *args, **kwargs):
16+
env = {"ID": b"000000000000000", "ethaddr": b"11:22:33:44:55:66"}
17+
params = ql.os.resolve_fcall_params({'key': STRING})
18+
value = env.get(params["key"], b"")
19+
20+
value_addr = ql.os.heap.alloc(len(value))
21+
ql.mem.write(value_addr, value)
22+
23+
ql.reg.r0 = value_addr
24+
ql.reg.arch_pc = ql.reg.lr
25+
26+
def check_password(ql, *args, **kwargs):
27+
passwd_output = ql.mem.read(ql.reg.r0, ql.reg.r2)
28+
passwd_input = ql.mem.read(ql.reg.r1, ql.reg.r2)
29+
self.assertEqual(passwd_output, passwd_input)
30+
31+
def partial_run_init(ql):
32+
# argv prepare
33+
ql.reg.arch_sp -= 0x30
34+
arg0_ptr = ql.reg.arch_sp
35+
ql.mem.write(arg0_ptr, b"kaimendaji")
36+
37+
ql.reg.arch_sp -= 0x10
38+
arg1_ptr = ql.reg.arch_sp
39+
ql.mem.write(arg1_ptr, b"013f1f")
40+
41+
ql.reg.arch_sp -= 0x20
42+
argv_ptr = ql.reg.arch_sp
43+
ql.mem.write(argv_ptr, ql.pack(arg0_ptr))
44+
ql.mem.write(argv_ptr + ql.pointersize, ql.pack(arg1_ptr))
45+
46+
ql.reg.r2 = 2
47+
ql.reg.r3 = argv_ptr
48+
49+
print("ARM uboot bin")
50+
51+
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
52+
uboot_code = f.read()
53+
54+
ql = Qiling(code=uboot_code[0x40:], archtype="arm", ostype="blob", profile="profiles/uboot_bin.ql", verbose=QL_VERBOSE.DEBUG)
55+
56+
image_base_addr = ql.loader.load_address
57+
ql.hook_address(my_getenv, image_base_addr + 0x13AC0)
58+
ql.hook_address(check_password, image_base_addr + 0x48634)
59+
60+
partial_run_init(ql)
61+
62+
ql.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
63+
64+
del ql
65+
66+
67+
if __name__ == "__main__":
68+
unittest.main()

tests/test_onlinux.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ python3 ./test_qnx.py &&
1515
python3 ./test_android.py &&
1616
python3 ./test_mcu.py &&
1717
python3 ./test_evm.py &&
18+
python3 ./test_blob.py &&
1819
echo "Done Test"

0 commit comments

Comments
 (0)