Snapshot & Partial Execution
Snapshot & Partial Execution
Partial Execution (Skip-Ahead Pattern)
Save state at a point, then restore and resume from a later address — useful for skipping long sleeps, initialization, or irrelevant code paths.
1from qiling import Qiling
2from qiling.const import QL_VERBOSE
3
4def dump(ql, *args, **kw):
5 ql.save(reg=False, cpu_context=True, snapshot="/tmp/snapshot.bin")
6 ql.emu_stop()
7
8# Pass 1: run until just before sleep(), save state
9ql = Qiling(["examples/rootfs/x8664_linux/bin/sleep_hello"], "examples/rootfs/x8664_linux", verbose=QL_VERBOSE.DEFAULT)
10X64BASE = int(ql.profile.get("OS64", "load_address"), 16)
11ql.hook_address(dump, X64BASE + 0x1094)
12ql.run()
13
14# Pass 2: restore saved state, run from after sleep()
15ql = Qiling(["examples/rootfs/x8664_linux/bin/sleep_hello"], "examples/rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG)
16X64BASE = int(ql.profile.get("OS64", "load_address"), 16)
17ql.restore(snapshot="/tmp/snapshot.bin")
18ql.run(begin=X64BASE + 0x109e, end=X64BASE + 0x10bc)
Full State Save/Restore
1# Save everything to a dict
2ql_all = ql.save()
3
4# Restore from dict
5ql.restore(ql_all)
Save options (all default to True except cpu_ctx):
1ql.save(mem=True, reg=True, fd=True, cpu_ctx=False)
Save to file:
1ql.save(snapshot="/tmp/snapshot.bin")
2ql.restore(snapshot="/tmp/snapshot.bin")
CPU Context Save/Restore
Wraps Unicorn’s uc_context_save / uc_context_restore:
1# Save all CPU registers
2all_registers_context = ql.arch.regs.context_save()
3
4# Restore all CPU registers
5ql.arch.regs.context_restore(all_registers_context)
Register Save/Restore
1# Save all registers to a dict
2all_registers = ql.arch.regs.save()
3
4# Modify a register in the saved state
5all_registers["eip"] = 0xaabbccdd
6
7# Restore registers from dict
8ql.arch.regs.restore(all_registers)
Memory Save/Restore
1all_mem = ql.mem.save()
2ql.mem.restore(all_mem)
File Descriptor Save/Restore
1all_fd = ql.fd.save()
2ql.fd.restore(all_fd)