qiling
qiling copied to clipboard
Signal handler is not triggered
*Describe the bug Qiling does not support the emulation of signal for ARM binaries
Sample Code
ql = Qiling(["test_binary"], "qiling/examples/rootfs/arm_linux", output = "debug")
ql.run()
Expected behavior When the instruction reads/writes to a memory address, which is not mapped or illegal. The signal number SIGSEGV should be raised. I register the signal handler for this signal number. The expected behavior is that the binary should raise a signal number, which will be captured by the signal handler. Then the code inside the signal handler should be executed. However, qiling (or unicorn) directly raises the exception, indicating there is a memory error.
Screenshots
main
[+] [arm.py:82] [+] Enable ARM VFP
[+] [utils.py:24] [+] Set init_kernel_get_tls
[+] [elf.py:243] [+] load 0x10000 - 0x16000
[+] [elf.py:243] [+] load 0x25000 - 0x27000
[+] [elf.py:267] [+] mem_start: 0x10000 mem_end: 0x27000
[+] [elf.py:312] [+] mmap_address is : 0x774bf000
[+] [core_hooks.py:58] [+] Received Interupt: 2 Hooked Interupt: 2
[+] [syscall.py:61] settls(0x26628)
[+] [core_hooks.py:58] [+] Received Interupt: 2 Hooked Interupt: 2
[+] [unistd.py:524] set_tid_address(266e0) = 26453
[+] [core_hooks.py:58] [+] Received Interupt: 2 Hooked Interupt: 2
[+] [signal.py:44] rt_sigprocmask(0x1, 0x7ff3cd84, 0x0, 0x8) = 0
[+] [core_hooks.py:58] [+] Received Interupt: 2 Hooked Interupt: 2
[+] [signal.py:32] rt_sigaction(0x4, 0x7ff3cd70, = 0x7ff3cd84) = 0
[+] [core_hooks.py:58] [+] Received Interupt: 2 Hooked Interupt: 2
[+] [signal.py:32] rt_sigaction(0xb, 0x7ff3cd70, = 0x7ff3cd84) = 0
[+] [core_hooks.py:58] [+] Received Interupt: 2 Hooked Interupt: 2
[+] [signal.py:32] rt_sigaction(0x7, 0x7ff3cd70, = 0x7ff3cd84) = 0
[x] [os.py:95]
[x] [os.py:101] r0 : 0x0
[x] [os.py:101] r1 : 0x0
[x] [os.py:101] r2 : 0x0
[x] [os.py:101] r3 : 0x0
[x] [os.py:101] r4 : 0x0
[x] [os.py:101] r5 : 0x0
[x] [os.py:101] r6 : 0x0
[x] [os.py:101] r7 : 0x0
[x] [os.py:101] r8 : 0x0
[x] [os.py:101] r9 : 0x0
[x] [os.py:101] r10 : 0x0
[x] [os.py:101] r11 : 0x7ff3cee4
[x] [os.py:101] r12 : 0x0
[x] [os.py:101] sp : 0x7ff3cee0
[x] [os.py:101] lr : 0x102b0
[x] [os.py:101] pc : 0x102b0
[x] [os.py:101] cpsr : 0x600001d3
[x] [os.py:101] c1_c0_2 : 0xf00000
[x] [os.py:101] c13_c0_3 : 0x26628
[x] [os.py:101] fpexc : 0x40000000
[x] [os.py:103]
[x] [os.py:104] PC = 0x102b0
[x] [os.py:108] (/mnt/muhui/ins_emu/arm32_batch0/testcases/6534800+0x102b0)
[=] [memory.py:133] [+] Start End Perm. Path
[=] [memory.py:139] [+] 00010000 - 00016000 - r-x /mnt/muhui/ins_emu/arm32_batch0/testcases/6534800 (/mnt/muhui/ins_emu/arm32_batch0/testcases/6534800)
[=] [memory.py:139] [+] 00025000 - 00027000 - rw- /mnt/muhui/ins_emu/arm32_batch0/testcases/6534800 (/mnt/muhui/ins_emu/arm32_batch0/testcases/6534800)
[=] [memory.py:139] [+] 00027000 - 00029000 - rwx [hook_mem]
[=] [memory.py:139] [+] 7ff0d000 - 7ff3d000 - rwx [stack]
[=] [memory.py:139] [+] ffff0000 - ffff1000 - rwx [arm_tls]
[x] [os.py:115] ['0xab', '0xf', '0x2f', '0x27', '0x0', '0xf0', '0x20', '0xe3']
[=] [os.py:117]
[=] [utils.py:265] 0x000102b0 {/mnt/muhui/ins_emu/arm32_batch0/testcases/6534800 + 0x0002b0} ab 0f 2f 27 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 00 f0 20 e3 strhs r0, [pc, -fp, lsr #31]!
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
Traceback (most recent call last):
File "run_batch.py", line 37, in <module>
run_one_testcase("/mnt/muhui/ins_emu/arm32_batch0/testcases/6534800","qlog")
File "run_batch.py", line 13, in run_one_testcase
ql.run(timeout=100000)
File "/home/jmh/.local/lib/python3.6/site-packages/qiling/core.py", line 765, in run
self.os.run()
File "/home/jmh/.local/lib/python3.6/site-packages/qiling/os/linux/linux.py", line 145, in run
self.ql.emu_start(self.ql.loader.elf_entry, self.exit_point, self.ql.timeout, self.ql.count)
File "/home/jmh/.local/lib/python3.6/site-packages/qiling/core.py", line 994, in emu_start
self.uc.emu_start(begin, end, timeout, count)
File "/home/jmh/.local/lib/python3.6/site-packages/unicorn/unicorn.py", line 318, in emu_start
raise UcError(status)
unicorn.unicorn.UcError: Write to write-protected memory (UC_ERR_WRITE_PROT)
Additional context I personally think this should be a bug rather than the specific design as qiling claims it is an emulator. Feel free if you need any further information.
The return msg from is
unicorn.unicorn.UcError: Write to write-protected memory (UC_ERR_WRITE_PROT)
I guess this is more clear compare to just raise a SIGSEGV.
Is this a binary with intention to write to protected memory ?
I admit this is more clear compared with a SIGSEGV. However, this is not what the users expected and is different from the binaries' logic.
If there is no signal handler registered for this signal number. I think this is the right behavior. Qiling exit and print the debugging information.
However, I have already registered the signal handler. In this case, even Qiling prints the msg like Write to write-protected memory
, The program should not exit, and the code inside the handler should be executed.
PR are welcome :)
@valour01 can you share the sample binary?
@TheZ3ro As more than 10 months are passed and I can not find the sample binary. This problem is not triggered by a particular binary. The question is that Qiling does not support the signal handler. Any binary that can trigger signals (e.g., illegal instruction, write into write-protected memory, etc) can trigger this problem.
There is a rework in the memory module, feel free to try and if problem still exits feel free to open new issue.
There is a rework in the memory module, feel free to try and if problem still exits feel free to open new issue.