mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
minimizing blob changes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
[BLOB_RAW]
|
||||
[CODE]
|
||||
load_address = 0x10000000
|
||||
image_size = 0xbc
|
||||
image_name = example_raw.bin
|
||||
entry_point = 0x10000008
|
||||
ram_size = 0xa00000
|
||||
@@ -6,6 +6,7 @@
|
||||
from qiling import Qiling
|
||||
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
|
||||
from qiling.extensions.coverage import utils as cov_utils
|
||||
from qiling.loader.loader import Image
|
||||
|
||||
BASE_ADDRESS = 0x10000000
|
||||
CHECKSUM_FUNC_ADDR = BASE_ADDRESS + 0x8
|
||||
@@ -29,6 +30,7 @@ def checksum_function(input_data_buffer: bytes):
|
||||
for i in range(input_data_len):
|
||||
expected_checksum_python += input_data_buffer[i]
|
||||
expected_checksum_python &= 0xFF # Ensure it's a single byte
|
||||
return expected_checksum_python
|
||||
|
||||
def unmapped_handler(ql, type, addr, size, value):
|
||||
|
||||
@@ -37,18 +39,24 @@ def unmapped_handler(ql, type, addr, size, value):
|
||||
def emulate_checksum_function(input_data_buffer: bytes):
|
||||
print(f"\n--- Testing with input: {input_data_buffer.hex()} ---")
|
||||
|
||||
ql = Qiling(archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
|
||||
with open("rootfs/blob/example_raw.bin", "rb") as f:
|
||||
raw_code = f.read()
|
||||
|
||||
ql = Qiling(code=raw_code, archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
|
||||
|
||||
# monkeypatch - Correcting the loader image name, used for coverage collection
|
||||
# Remove all images with name 'blob_code' that were created by the blob loader
|
||||
ql.loader.images = [img for img in ql.loader.images if img.path != 'blob_code']
|
||||
# Add image back with correct info
|
||||
ql.loader.images.append(Image(ql.loader.load_address, ql.loader.load_address + ql.os.code_ram_size, 'example_raw.bin'))
|
||||
|
||||
|
||||
input_data_len = len(input_data_buffer)
|
||||
|
||||
# Map memory for the binary, data and stack
|
||||
ql.mem.map(BASE_ADDRESS, 0x10000)
|
||||
# Map memory for the data and stack
|
||||
ql.mem.map(STACK_ADDR, 0x2000)
|
||||
ql.mem.map(DATA_ADDR, ql.mem.align_up(input_data_len + 0x100)) # Map enough space for data
|
||||
|
||||
# Write the binary into memory
|
||||
ql.mem.write(BASE_ADDRESS, open("rootfs/blob/example_raw.bin", "rb").read())
|
||||
|
||||
# Write input data
|
||||
ql.mem.write(DATA_ADDR, input_data_buffer)
|
||||
|
||||
@@ -70,7 +78,8 @@ def emulate_checksum_function(input_data_buffer: bytes):
|
||||
# Start emulation
|
||||
print(f"Starting emulation at PC: {hex(ql.arch.regs.pc)}")
|
||||
try:
|
||||
ql.run(begin=CHECKSUM_FUNC_ADDR, end=END_ADDRESS)
|
||||
with cov_utils.collect_coverage(ql, 'drcov', 'output.cov'):
|
||||
ql.run(begin=CHECKSUM_FUNC_ADDR, end=END_ADDRESS)
|
||||
except Exception as e:
|
||||
print(f"Emulation error: {e}")
|
||||
|
||||
@@ -78,4 +87,5 @@ def emulate_checksum_function(input_data_buffer: bytes):
|
||||
|
||||
if __name__ == "__main__":
|
||||
data = b"\x01\x02\x03\x04\x05" # Example input data
|
||||
emulate_checksum_function(data)
|
||||
emulate_checksum_function(data)
|
||||
print(hex(checksum_function(data)))
|
||||
+21
-21
@@ -9,38 +9,38 @@
|
||||
from qiling import Qiling
|
||||
from qiling.loader.loader import QlLoader, Image
|
||||
from qiling.os.memory import QlMemoryHeap
|
||||
import configparser
|
||||
|
||||
|
||||
class QlLoaderBLOB(QlLoader):
|
||||
def __init__(self, ql: Qiling):
|
||||
super().__init__(ql)
|
||||
|
||||
self.load_address = 0
|
||||
|
||||
def run(self):
|
||||
if self.ql.os.profile.has_section("BLOB_RAW"):
|
||||
# For raw binary blobs, user will handle memory mapping
|
||||
self.load_address = int(self.ql.os.profile.get("BLOB_RAW", "load_address"), 16)
|
||||
image_size = int(self.ql.os.profile.get("BLOB_RAW", "image_size"), 16)
|
||||
image_name = self.ql.os.profile.get("BLOB_RAW", "image_name", fallback="blob.raw")
|
||||
self.images.append(Image(self.load_address, self.load_address+image_size, image_name)) # used to collect coverage
|
||||
else:
|
||||
self.load_address = self.ql.os.load_address
|
||||
self.entry_point = self.ql.os.entry_point
|
||||
self.load_address = self.ql.os.load_address
|
||||
self.entry_point = self.ql.os.entry_point
|
||||
|
||||
code_begins = self.load_address
|
||||
code_size = self.ql.os.code_ram_size
|
||||
code_ends = code_begins + code_size
|
||||
code_begins = self.load_address
|
||||
code_size = self.ql.os.code_ram_size
|
||||
code_ends = code_begins + code_size
|
||||
|
||||
self.ql.mem.map(code_begins, code_size, info="[code]")
|
||||
self.ql.mem.write(code_begins, self.ql.code)
|
||||
self.ql.mem.map(code_begins, code_size, info="[code]")
|
||||
self.ql.mem.write(code_begins, self.ql.code)
|
||||
|
||||
# allow image-related functionalities
|
||||
self.images.append(Image(code_begins, code_ends, 'blob_code'))
|
||||
# allow image-related functionalities
|
||||
self.images.append(Image(code_begins, code_ends, 'blob_code'))
|
||||
|
||||
# FIXME: heap starts above end of ram??
|
||||
# FIXME: heap should be allocated by OS, not loader
|
||||
heap_base = code_ends
|
||||
# FIXME: heap starts above end of ram??
|
||||
# FIXME: heap should be allocated by OS, not loader
|
||||
heap_base = code_ends
|
||||
# if heap_size is defined, create the heap
|
||||
try:
|
||||
heap_size = int(self.ql.os.profile.get("CODE", "heap_size"), 16)
|
||||
self.ql.os.heap = QlMemoryHeap(self.ql, heap_base, heap_base + heap_size)
|
||||
except (configparser.NoSectionError, configparser.NoOptionError):
|
||||
pass # heap_size is not required
|
||||
|
||||
# FIXME: stack pointer should be a configurable profile setting
|
||||
self.ql.arch.regs.arch_sp = code_ends - 0x1000
|
||||
# FIXME: stack pointer should be a configurable profile setting
|
||||
self.ql.arch.regs.arch_sp = code_ends - 0x1000
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
#
|
||||
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
|
||||
#
|
||||
# Added support for raw binary blob emulation
|
||||
# Kelly Patterson - Cisco Talos
|
||||
# Copyright (C) 2025 Cisco Systems Inc
|
||||
|
||||
from qiling import Qiling
|
||||
from qiling.cc import QlCC, intel, arm, mips, riscv, ppc
|
||||
@@ -47,10 +44,10 @@ class QlOsBlob(QlOs):
|
||||
if self.ql.entry_point is not None:
|
||||
self.entry_point = self.ql.entry_point
|
||||
|
||||
self.exit_point = self.load_address + len(self.ql.code)
|
||||
|
||||
# if exit point was set explicitly, override the default one
|
||||
if self.ql.exit_point is not None:
|
||||
self.exit_point = self.ql.exit_point
|
||||
elif self.ql.code is not None: # self.ql.code might not always be provided
|
||||
self.exit_point = self.load_address + len(self.ql.code)
|
||||
|
||||
self.ql.emu_start(self.entry_point, self.exit_point, self.ql.timeout, self.ql.count)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[BLOB_RAW]
|
||||
[CODE]
|
||||
load_address = 0x10000000
|
||||
image_size = 0xbc
|
||||
image_name = example_raw.bin
|
||||
entry_point = 0x10000008
|
||||
ram_size = 0xa00000
|
||||
+5
-6
@@ -97,18 +97,17 @@ class BlobTest(unittest.TestCase):
|
||||
DATA_ADDR = 0xa0000000
|
||||
STACK_ADDR = 0xb0000000
|
||||
|
||||
ql = Qiling(archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="profiles/blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
|
||||
with open("../examples/rootfs/blob/example_raw.bin", "rb") as f:
|
||||
raw_code = f.read()
|
||||
|
||||
ql = Qiling(code=raw_code, archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="profiles/blob_raw.ql", verbose=QL_VERBOSE.DEBUG, thumb=True)
|
||||
|
||||
input_data_len = len(input_data_buffer)
|
||||
|
||||
# Map memory for the binary, data and stack
|
||||
ql.mem.map(BASE_ADDRESS, 0x10000)
|
||||
# Map memory for data and stack
|
||||
ql.mem.map(STACK_ADDR, 0x2000)
|
||||
ql.mem.map(DATA_ADDR, ql.mem.align_up(input_data_len + 0x100))
|
||||
|
||||
# Write the binary into memory
|
||||
ql.mem.write(BASE_ADDRESS, open("../examples/rootfs/blob/example_raw.bin", "rb").read())
|
||||
|
||||
# Write input data
|
||||
ql.mem.write(DATA_ADDR, input_data_buffer)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user