-
Notifications
You must be signed in to change notification settings - Fork 742
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix issue where restoring a snapshot created with reg=True throws an …
…exception When restoring a snapshot created with reg=True a unicorn cpu exception can be thrown when restoring the GS register. It looks like for at least 32bit mode on X86 processors unicorn will validate memory structures pointed to by loaded GS reg. If the memory is not loaded the validation will surely fail, and thus the exception. The fix is then to load the memory maps first, before loading the registers. Note, this validation does not happen when restoring via cpu_context. Included is a test case which will have errors if this fix is not applied.
- Loading branch information
Showing
3 changed files
with
61 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework | ||
# | ||
|
||
import os, sys, unittest | ||
|
||
sys.path.append("..") | ||
from qiling import * | ||
from qiling.const import QL_VERBOSE | ||
|
||
class SnapshotRestoreTest(unittest.TestCase): | ||
|
||
def _test_snapshot_restore_common(self, reg=False, ctx=False): | ||
rootfs = "../examples/rootfs/x86_linux" | ||
cmdline = ["../examples/rootfs/x86_linux/bin/x86_hello"] | ||
snapshot = os.path.join(rootfs, 'snapshot_restore_reg_ctx.snapshot') | ||
|
||
ql = Qiling(cmdline, rootfs, verbose=QL_VERBOSE.DEBUG) | ||
|
||
X86BASE = int(ql.profile.get("OS32", "load_address"), 16) | ||
hook_address = X86BASE + 0x542 # call printf | ||
|
||
def dump(ql): | ||
nonlocal snapshot | ||
nonlocal reg | ||
nonlocal ctx | ||
ql.save(reg=reg, cpu_context=ctx, os_context=True, loader=True, snapshot=snapshot) | ||
ql.emu_stop() | ||
ql.hook_address(dump, hook_address) | ||
|
||
ql.run() | ||
|
||
# make sure that the ending PC is the same as the hook address because dump stops the emulater | ||
assert ql.reg.arch_pc == hook_address, f"0x{ql.reg.arch_pc:x} != 0x{hook_address:x}" | ||
del ql | ||
|
||
ql = Qiling(cmdline, rootfs, verbose=QL_VERBOSE.DEBUG) | ||
ql.restore(snapshot=snapshot) | ||
|
||
# ensure that the starting PC is same as the PC we stopped on when taking the snapshot | ||
assert ql.reg.arch_pc == hook_address, f"0x{ql.reg.arch_pc:x} != 0x{hook_address:x}" | ||
|
||
ql.run(begin=hook_address) | ||
del ql | ||
|
||
def test_snapshot_restore_reg(self): | ||
self._test_snapshot_restore_common(reg=True, ctx=False) | ||
|
||
def test_snapshot_restore_ctx(self): | ||
self._test_snapshot_restore_common(reg=False, ctx=True) | ||
|
||
def test_snapshot_restore_reg_ctx(self): | ||
self._test_snapshot_restore_common(reg=True, ctx=True) | ||
|
||
if __name__ == "__main__": | ||
unittest.main() |