Skip to content

Commit d2b4867

Browse files
committed
Adjust test and example
1 parent 327f475 commit d2b4867

File tree

2 files changed

+87
-57
lines changed

2 files changed

+87
-57
lines changed

examples/hello_arm_uboot.py

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,68 +8,82 @@
88

99
from qiling.core import Qiling
1010
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
11-
from qiling.os.const import STRING
11+
from qiling.os.const import STRING, SIZE_T, POINTER
1212

1313

14-
def get_kaimendaji_password():
15-
def my_getenv(ql: Qiling):
16-
env = {
17-
"ID" : b"000000000000000",
18-
"ethaddr" : b"11:22:33:44:55:66"
19-
}
14+
def my_getenv(ql: Qiling):
15+
env = {
16+
"ID" : b"000000000000000",
17+
"ethaddr" : b"11:22:33:44:55:66"
18+
}
2019

21-
params = ql.os.resolve_fcall_params({'key': STRING})
22-
value = env.get(params["key"], b"")
20+
params = ql.os.resolve_fcall_params({'key': STRING})
21+
value = env.get(params["key"], b"")
2322

24-
value_addr = ql.os.heap.alloc(len(value))
25-
ql.mem.write(value_addr, value)
23+
value_addr = ql.os.heap.alloc(len(value))
24+
ql.mem.write(value_addr, value)
2625

27-
ql.arch.regs.r0 = value_addr
28-
ql.arch.regs.arch_pc = ql.arch.regs.lr
26+
ql.arch.regs.r0 = value_addr
27+
ql.arch.regs.arch_pc = ql.arch.regs.lr
2928

30-
def get_password(ql: Qiling):
31-
password_raw = ql.mem.read(ql.arch.regs.r0, ql.arch.regs.r2)
3229

33-
password = ''
34-
for item in password_raw:
35-
if 0 <= item <= 9:
36-
password += chr(item + 48)
37-
else:
38-
password += chr(item + 87)
30+
def get_password(ql: Qiling):
31+
# we land on a memcmp call, where the real password is being compared to
32+
# the one provided by the user. we can follow the arguments to read the
33+
# real password
3934

40-
print("The password is: %s" % password)
35+
params = ql.os.resolve_fcall_params({
36+
'ptr1': POINTER, # points to real password
37+
'ptr2': POINTER, # points to user provided password
38+
'size': SIZE_T # comparison length
39+
})
4140

42-
def partial_run_init(ql: Qiling):
43-
# argv prepare
44-
ql.arch.regs.arch_sp -= 0x30
45-
arg0_ptr = ql.arch.regs.arch_sp
46-
ql.mem.write(arg0_ptr, b"kaimendaji")
41+
ptr1 = params['ptr1']
42+
size = params['size']
4743

48-
ql.arch.regs.arch_sp -= 0x10
49-
arg1_ptr = ql.arch.regs.arch_sp
50-
ql.mem.write(arg1_ptr, b"000000") # arbitrary password
44+
password_raw = ql.mem.read(ptr1, size)
5145

52-
ql.arch.regs.arch_sp -= 0x20
53-
argv_ptr = ql.arch.regs.arch_sp
54-
ql.mem.write_ptr(argv_ptr, arg0_ptr)
55-
ql.mem.write_ptr(argv_ptr + ql.arch.pointersize, arg1_ptr)
46+
def __hex_digit(ch: int) -> str:
47+
off = ord('0') if ch in range(10) else ord('a') - 10
5648

57-
ql.arch.regs.r2 = 2
58-
ql.arch.regs.r3 = argv_ptr
49+
return chr(ch + off)
5950

60-
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
61-
uboot_code = f.read()
51+
# should be: "013f1f"
52+
password = "".join(__hex_digit(ch) for ch in password_raw)
6253

63-
ql = Qiling(code=uboot_code[0x40:], archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="uboot_bin.ql", verbose=QL_VERBOSE.OFF)
54+
print(f'The password is: {password}')
6455

65-
image_base_addr = ql.loader.load_address
66-
ql.hook_address(my_getenv, image_base_addr + 0x13AC0)
67-
ql.hook_address(get_password, image_base_addr + 0x48634)
6856

69-
partial_run_init(ql)
57+
def partial_run_init(ql: Qiling):
58+
# argv prepare
59+
ql.arch.regs.arch_sp -= 0x30
60+
arg0_ptr = ql.arch.regs.arch_sp
61+
ql.mem.write(arg0_ptr, b"kaimendaji")
62+
63+
ql.arch.regs.arch_sp -= 0x10
64+
arg1_ptr = ql.arch.regs.arch_sp
65+
ql.mem.write(arg1_ptr, b"000000") # arbitrary password
7066

71-
ql.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
67+
ql.arch.regs.arch_sp -= 0x20
68+
argv_ptr = ql.arch.regs.arch_sp
69+
ql.mem.write_ptr(argv_ptr, arg0_ptr)
70+
ql.mem.write_ptr(argv_ptr + ql.arch.pointersize, arg1_ptr)
71+
72+
ql.arch.regs.r2 = 2
73+
ql.arch.regs.r3 = argv_ptr
7274

7375

7476
if __name__ == "__main__":
75-
get_kaimendaji_password()
77+
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
78+
uboot_code = f.read()
79+
80+
ql = Qiling(code=uboot_code[0x40:], archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="uboot_bin.ql", verbose=QL_VERBOSE.DEBUG)
81+
82+
imgbase = ql.loader.images[0].base
83+
84+
ql.hook_address(my_getenv, imgbase + 0x13AC0)
85+
ql.hook_address(get_password, imgbase + 0x48634)
86+
87+
partial_run_init(ql)
88+
89+
ql.run(imgbase + 0x486B4, imgbase + 0x48718)

tests/test_blob.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@
1010

1111
from qiling.core import Qiling
1212
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
13-
from qiling.os.const import STRING
13+
from qiling.os.const import STRING, POINTER, SIZE_T
1414

1515

1616
class BlobTest(unittest.TestCase):
1717
def test_uboot_arm(self):
18-
def my_getenv(ql, *args, **kwargs):
19-
env = {"ID": b"000000000000000", "ethaddr": b"11:22:33:44:55:66"}
18+
def my_getenv(ql: Qiling):
19+
env = {
20+
"ID": b"000000000000000",
21+
"ethaddr": b"11:22:33:44:55:66"
22+
}
23+
2024
params = ql.os.resolve_fcall_params({'key': STRING})
2125
value = env.get(params["key"], b"")
2226

@@ -26,12 +30,23 @@ def my_getenv(ql, *args, **kwargs):
2630
ql.arch.regs.r0 = value_addr
2731
ql.arch.regs.arch_pc = ql.arch.regs.lr
2832

29-
def check_password(ql, *args, **kwargs):
30-
passwd_output = ql.mem.read(ql.arch.regs.r0, ql.arch.regs.r2)
31-
passwd_input = ql.mem.read(ql.arch.regs.r1, ql.arch.regs.r2)
32-
self.assertEqual(passwd_output, passwd_input)
33+
def check_password(ql: Qiling):
34+
params = ql.os.resolve_fcall_params({
35+
'ptr1': POINTER, # points to real password
36+
'ptr2': POINTER, # points to user provided password
37+
'size': SIZE_T # comparison length
38+
})
39+
40+
ptr1 = params['ptr1']
41+
ptr2 = params['ptr2']
42+
size = params['size']
43+
44+
real_password = ql.mem.read(ptr1, size)
45+
user_password = ql.mem.read(ptr2, size)
3346

34-
def partial_run_init(ql):
47+
self.assertSequenceEqual(real_password, user_password, seq_type=bytearray)
48+
49+
def partial_run_init(ql: Qiling):
3550
# argv prepare
3651
ql.arch.regs.arch_sp -= 0x30
3752
arg0_ptr = ql.arch.regs.arch_sp
@@ -56,13 +71,14 @@ def partial_run_init(ql):
5671

5772
ql = Qiling(code=uboot_code[0x40:], archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="profiles/uboot_bin.ql", verbose=QL_VERBOSE.DEBUG)
5873

59-
image_base_addr = ql.loader.load_address
60-
ql.hook_address(my_getenv, image_base_addr + 0x13AC0)
61-
ql.hook_address(check_password, image_base_addr + 0x48634)
74+
imgbase = ql.loader.images[0].base
75+
76+
ql.hook_address(my_getenv, imgbase + 0x13AC0)
77+
ql.hook_address(check_password, imgbase + 0x48634)
6278

6379
partial_run_init(ql)
6480

65-
ql.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
81+
ql.run(imgbase + 0x486B4, imgbase + 0x48718)
6682

6783
del ql
6884

0 commit comments

Comments
 (0)