Skip to content

Commit 81c2a39

Browse files
committed
minimizing blob changes
1 parent d3cc47d commit 81c2a39

File tree

6 files changed

+56
-50
lines changed

6 files changed

+56
-50
lines changed

examples/blob_raw.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[BLOB_RAW]
1+
[CODE]
22
load_address = 0x10000000
3-
image_size = 0xbc
4-
image_name = example_raw.bin
3+
entry_point = 0x10000008
4+
ram_size = 0xa00000

examples/hello_arm_blob_raw.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from qiling import Qiling
77
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
88
from qiling.extensions.coverage import utils as cov_utils
9+
from qiling.loader.loader import Image
910

1011
BASE_ADDRESS = 0x10000000
1112
CHECKSUM_FUNC_ADDR = BASE_ADDRESS + 0x8
@@ -29,6 +30,7 @@ def checksum_function(input_data_buffer: bytes):
2930
for i in range(input_data_len):
3031
expected_checksum_python += input_data_buffer[i]
3132
expected_checksum_python &= 0xFF # Ensure it's a single byte
33+
return expected_checksum_python
3234

3335
def unmapped_handler(ql, type, addr, size, value):
3436

@@ -37,18 +39,24 @@ def unmapped_handler(ql, type, addr, size, value):
3739
def emulate_checksum_function(input_data_buffer: bytes):
3840
print(f"\n--- Testing with input: {input_data_buffer.hex()} ---")
3941

40-
ql = Qiling(archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
42+
with open("rootfs/blob/example_raw.bin", "rb") as f:
43+
raw_code = f.read()
44+
45+
ql = Qiling(code=raw_code, archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
46+
47+
# monkeypatch - Correcting the loader image name, used for coverage collection
48+
# Remove all images with name 'blob_code' that were created by the blob loader
49+
ql.loader.images = [img for img in ql.loader.images if img.path != 'blob_code']
50+
# Add image back with correct info
51+
ql.loader.images.append(Image(ql.loader.load_address, ql.loader.load_address + ql.os.code_ram_size, 'example_raw.bin'))
52+
4153

4254
input_data_len = len(input_data_buffer)
4355

44-
# Map memory for the binary, data and stack
45-
ql.mem.map(BASE_ADDRESS, 0x10000)
56+
# Map memory for the data and stack
4657
ql.mem.map(STACK_ADDR, 0x2000)
4758
ql.mem.map(DATA_ADDR, ql.mem.align_up(input_data_len + 0x100)) # Map enough space for data
4859

49-
# Write the binary into memory
50-
ql.mem.write(BASE_ADDRESS, open("rootfs/blob/example_raw.bin", "rb").read())
51-
5260
# Write input data
5361
ql.mem.write(DATA_ADDR, input_data_buffer)
5462

@@ -70,12 +78,14 @@ def emulate_checksum_function(input_data_buffer: bytes):
7078
# Start emulation
7179
print(f"Starting emulation at PC: {hex(ql.arch.regs.pc)}")
7280
try:
73-
ql.run(begin=CHECKSUM_FUNC_ADDR, end=END_ADDRESS)
81+
with cov_utils.collect_coverage(ql, 'drcov', 'output.cov'):
82+
ql.run(begin=CHECKSUM_FUNC_ADDR, end=END_ADDRESS)
7483
except Exception as e:
7584
print(f"Emulation error: {e}")
7685

7786
print(f"Emulated checksum: {hex(ql.arch.regs.r0)}")
7887

7988
if __name__ == "__main__":
8089
data = b"\x01\x02\x03\x04\x05" # Example input data
81-
emulate_checksum_function(data)
90+
emulate_checksum_function(data)
91+
print(hex(checksum_function(data)))

qiling/loader/blob.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,38 @@
99
from qiling import Qiling
1010
from qiling.loader.loader import QlLoader, Image
1111
from qiling.os.memory import QlMemoryHeap
12+
import configparser
1213

1314

1415
class QlLoaderBLOB(QlLoader):
1516
def __init__(self, ql: Qiling):
1617
super().__init__(ql)
1718

19+
self.load_address = 0
20+
1821
def run(self):
19-
if self.ql.os.profile.has_section("BLOB_RAW"):
20-
# For raw binary blobs, user will handle memory mapping
21-
self.load_address = int(self.ql.os.profile.get("BLOB_RAW", "load_address"), 16)
22-
image_size = int(self.ql.os.profile.get("BLOB_RAW", "image_size"), 16)
23-
image_name = self.ql.os.profile.get("BLOB_RAW", "image_name", fallback="blob.raw")
24-
self.images.append(Image(self.load_address, self.load_address+image_size, image_name)) # used to collect coverage
25-
else:
26-
self.load_address = self.ql.os.load_address
27-
self.entry_point = self.ql.os.entry_point
28-
29-
code_begins = self.load_address
30-
code_size = self.ql.os.code_ram_size
31-
code_ends = code_begins + code_size
32-
33-
self.ql.mem.map(code_begins, code_size, info="[code]")
34-
self.ql.mem.write(code_begins, self.ql.code)
35-
36-
# allow image-related functionalities
37-
self.images.append(Image(code_begins, code_ends, 'blob_code'))
38-
39-
# FIXME: heap starts above end of ram??
40-
# FIXME: heap should be allocated by OS, not loader
41-
heap_base = code_ends
22+
self.load_address = self.ql.os.load_address
23+
self.entry_point = self.ql.os.entry_point
24+
25+
code_begins = self.load_address
26+
code_size = self.ql.os.code_ram_size
27+
code_ends = code_begins + code_size
28+
29+
self.ql.mem.map(code_begins, code_size, info="[code]")
30+
self.ql.mem.write(code_begins, self.ql.code)
31+
32+
# allow image-related functionalities
33+
self.images.append(Image(code_begins, code_ends, 'blob_code'))
34+
35+
# FIXME: heap starts above end of ram??
36+
# FIXME: heap should be allocated by OS, not loader
37+
heap_base = code_ends
38+
# if heap_size is defined, create the heap
39+
try:
4240
heap_size = int(self.ql.os.profile.get("CODE", "heap_size"), 16)
4341
self.ql.os.heap = QlMemoryHeap(self.ql, heap_base, heap_base + heap_size)
42+
except (configparser.NoSectionError, configparser.NoOptionError):
43+
pass # heap_size is not required
4444

45-
# FIXME: stack pointer should be a configurable profile setting
46-
self.ql.arch.regs.arch_sp = code_ends - 0x1000
45+
# FIXME: stack pointer should be a configurable profile setting
46+
self.ql.arch.regs.arch_sp = code_ends - 0x1000

qiling/os/blob/blob.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
#
33
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44
#
5-
# Added support for raw binary blob emulation
6-
# Kelly Patterson - Cisco Talos
7-
# Copyright (C) 2025 Cisco Systems Inc
85

96
from qiling import Qiling
107
from qiling.cc import QlCC, intel, arm, mips, riscv, ppc
@@ -47,10 +44,10 @@ def run(self):
4744
if self.ql.entry_point is not None:
4845
self.entry_point = self.ql.entry_point
4946

47+
self.exit_point = self.load_address + len(self.ql.code)
48+
5049
# if exit point was set explicitly, override the default one
5150
if self.ql.exit_point is not None:
5251
self.exit_point = self.ql.exit_point
53-
elif self.ql.code is not None: # self.ql.code might not always be provided
54-
self.exit_point = self.load_address + len(self.ql.code)
5552

5653
self.ql.emu_start(self.entry_point, self.exit_point, self.ql.timeout, self.ql.count)

tests/profiles/blob_raw.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[BLOB_RAW]
1+
[CODE]
22
load_address = 0x10000000
3-
image_size = 0xbc
4-
image_name = example_raw.bin
3+
entry_point = 0x10000008
4+
ram_size = 0xa00000

tests/test_blob.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,17 @@ def run_checksum_emu(input_data_buffer: bytes) -> int:
9797
DATA_ADDR = 0xa0000000
9898
STACK_ADDR = 0xb0000000
9999

100-
ql = Qiling(archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="profiles/blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
100+
with open("../examples/rootfs/blob/example_raw.bin", "rb") as f:
101+
raw_code = f.read()
102+
103+
ql = Qiling(code=raw_code, archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="profiles/blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
101104

102105
input_data_len = len(input_data_buffer)
103106

104-
# Map memory for the binary, data and stack
105-
ql.mem.map(BASE_ADDRESS, 0x10000)
107+
# Map memory for data and stack
106108
ql.mem.map(STACK_ADDR, 0x2000)
107109
ql.mem.map(DATA_ADDR, ql.mem.align_up(input_data_len + 0x100))
108110

109-
# Write the binary into memory
110-
ql.mem.write(BASE_ADDRESS, open("../examples/rootfs/blob/example_raw.bin", "rb").read())
111-
112111
# Write input data
113112
ql.mem.write(DATA_ADDR, input_data_buffer)
114113

0 commit comments

Comments
 (0)