Skip to content
This repository has been archived by the owner on Nov 29, 2021. It is now read-only.

Unicorn stops emulation when PC = 0x00 #16

Open
bspdev opened this issue Apr 8, 2021 · 8 comments
Open

Unicorn stops emulation when PC = 0x00 #16

bspdev opened this issue Apr 8, 2021 · 8 comments

Comments

@bspdev
Copy link

bspdev commented Apr 8, 2021

Hello,

I recently opened an issue in the Unicorn repository (unicorn-engine#1383), but I believe my problem comes from the AFLplusplus implementation.

My problem is that when I emulate ARM code, unicorn stops when the address 0 is reached.
I tried calling directly to unicorn with uc_emu_start(uc, start_addr, 0, 0, 0) and I got the same behavior, but then calling uc_emu_start(uc, start_addr, 0x12345678, 0, 0) it did NOT stopped at 0x0.

My guess is that uc_afl_emu_start() is eventually passing 0 as third parameter (until) and that's why the emulation stopped. However, I tried to identify that code in the source without success. I see that uc_afl_emu_start() executes uc->vm_start(uc), which if I am not mistaken, is in qemu/cpus.c:44.

I naively expected to find a call like uc_emu_start(uc, addr, 0, xx, xx).
I would like to ask you, how can I prevent AFLplusplus to stop emulation at address 0?
My new guess is that addr_end within struct uc_struct is zero. If that's the case, I can't find a way to modify that variable from the outside since its definition is not exposed.

Thank you in advance and congratulations for the great work done on this project, it is really impressive and useful.

@domenukk
Copy link
Member

domenukk commented May 6, 2021

Hey @bspdev, thank you for your detailed report!
can you check if 8a217c5 fixes this issue? Thanks :)

@bspdev
Copy link
Author

bspdev commented May 6, 2021

Hi @domenukk !

Thank you very much again for your effort.

I have tried it, but unfortunately the problem remains, although in a different way from my original post. The emulator still does not execute any instructions. However, instead of simply terminating, it hangs in an infinite loop.

I will try to code a minimum working example so you can experience what happens to me.

Due to time constraints, I can't get my hands on the code myself to solve the problem in an elegant way... However, in case it helps, I'm using locally this little workaround:

diff --git a/qemu/cpus.c b/qemu/cpus.c
--- a/qemu/cpus.c
+++ b/qemu/cpus.c
@@ -43,6 +43,10 @@ static void qemu_tcg_cpu_loop(struct uc_struct *uc);
 
 int vm_start(struct uc_struct* uc)
 {
+
+    // XXX patch uc->addr_end to avoid stopping at address 0x0000
+    if (!uc->addr_end) uc->addr_end = -1;
+
     if (resume_all_vcpus(uc)) {
         return -1;
     }

It is strange because 8a217c5 does not solve it despite being the same idea of setting uc->addr_end.

@domenukk
Copy link
Member

domenukk commented May 6, 2021

What arch are you emulating?
If aarch64, try the latest version.
In my understanding, setting addr_end to an address in the list should have the s name effect as setting it to -1/max_int.
Odd.

@bspdev
Copy link
Author

bspdev commented May 6, 2021

Yeah...
The binary I am emulating is ARM 32 bits.
I will come here in a few days hopefully with a reproducible example.

Cheers

@domenukk
Copy link
Member

domenukk commented May 6, 2021

Next try, 1f10035 - now it definitely shouldn't have issues with end_addr...

@bspdev
Copy link
Author

bspdev commented May 7, 2021

Hi @domenukk

I tried 1f10035, but the issue still remains. I have modified the arm sample present in this repo to get an example to show the bug. Here is the patch:

diff --git a/samples/sample_arm.c b/samples/sample_arm.c
index 1e142c13..2b15fe64 100644
--- a/samples/sample_arm.c
+++ b/samples/sample_arm.c
@@ -12,7 +12,7 @@
 #define THUMB_CODE "\x83\xb0" // sub    sp, #0xc
 
 // memory address where emulation starts
-#define ADDRESS 0x10000
+#define ADDRESS 0x0000
 
 static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
 {
@@ -30,6 +30,7 @@ static void test_arm(void)
     uc_err err;
     uc_hook trace1, trace2;
 
+    int pc = ADDRESS;    // PC register
     int r0 = 0x1234;     // R0 register
     int r2 = 0x6789;     // R1 register
     int r3 = 0x3333;     // R2 register
@@ -52,6 +53,7 @@ static void test_arm(void)
     uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1);
 
     // initialize machine registers
+    uc_reg_write(uc, UC_ARM_REG_PC, &pc); // for uc_afl_emu_start()
     uc_reg_write(uc, UC_ARM_REG_R0, &r0);
     uc_reg_write(uc, UC_ARM_REG_R2, &r2);
     uc_reg_write(uc, UC_ARM_REG_R3, &r3);
@@ -64,7 +66,19 @@ static void test_arm(void)
 
     // emulate machine code in infinite time (last param = 0), or when
     // finishing all the code.
-    err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
+    // err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
+
+    // ---------- BUG: When address is 0x0000 ---------- //
+
+    // XXX Instruction not executed
+    err = uc_emu_start(uc, ADDRESS, 0, 1, 0);
+
+    // XXX loop
+    //err = uc_afl_emu_start(uc);
+
+    // XXX loop
+    // err = uc_emu_start(uc, ADDRESS, 0, 0, 0);
+
     if (err) {
         printf("Failed on uc_emu_start() with error returned: %u\n", err);
     }

What I am experiencing is that uc_emu_start() with 0 in the third parameter just don't execute any instruction, which is a similar behaviour of what happened in the first message of this github issue. There is something important to mention, though.
I'm not entirely sure but I recall that back then there was no infinite loop in any case. Now, if I either call uc_emu_start(uc, ADDRESS, 0, 0, 0) or uc_afl_emu_start(uc) it hangs.

Please, ask me any further information if you need it. I can put here a small Dockerfile to reproduce exactly the environment I am using for this. For AFLplusplus, I am cloning branch 3.12c commit 2dac4e785.

Thanks again for your time.
Cheers

@bspdev
Copy link
Author

bspdev commented May 7, 2021

I forgot to mention that all these cases are "solved" with the workaround of qemu/cpus.c, which is quite confusing...

@domenukk
Copy link
Member

domenukk commented May 9, 2021

I'm a bit confused, imho it should work now (and not loop infinitely)... The patch in cpus.c seems too ad-hoc: how would you actually stop execution at 0x0? :)
I mean, we could set -1 as addr in the afl emulation, but that should have exactly the same effect, as far as I can tell...

dmitryya pushed a commit to dmitryya/unicornafl that referenced this issue May 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants