unicorn-engine / unicorn

Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
http://www.unicorn-engine.org
GNU General Public License v2.0
7.33k stars 1.31k forks source link

Unicorn2 crashes but Unocorn1 ok #1915

Open kycgni opened 6 months ago

kycgni commented 6 months ago

In the simulation of the shellcode, I found that directly modifying the lower bits of cr7 would cause random crashes in Unicorn2, but Unicorn1 does not have this issue. Below is a code snippet that reproduces the problem. `static void test_i386(void) { uc_engine *uc; uc_err err; uc_hook trace1, trace2;

BYTE x86Code[] = {
    0xB8, 0x01, 0x00, 0x00, 0x00,  //mov eax,0x7b
    0x0F, 0x23, 0x38,              //mov dr7,eax
    0xB8, 0x00, 0x00, 0x00, 0x7B,  //mov eax,0x7b
    0x0F, 0x23, 0x38,              //mov dr7,eax   
};

int r_esp = ADDRESS + 0x200000; // ESP register

printf("Emulate i386 code\n");

// Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
if (err) {
    printf("Failed on uc_open() with error returned: %u\n", err);
    return;
}

// map 2MB memory for this emulation
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);

// write machine code to be emulated to memory
if (uc_mem_write(uc, ADDRESS, x86Code,
                 sizeof(x86Code) - 1)) {
    printf("Failed to write emulation code to memory, quit!\n");
    return;
}

// initialize machine registers
uc_reg_write(uc, UC_X86_REG_ESP, &r_esp);

// tracing all instructions by having @begin > @end
uc_hook_add(uc, &trace1, UC_HOOK_CODE, hook_code, NULL, 1, 0);

// handle interrupt ourself
uc_hook_add(uc, &trace2, UC_HOOK_INTR, hook_intr, NULL, 1, 0);

printf("\n>>> Start tracing this Linux code\n");

// emulate machine code in infinite time
// err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0,
// 12); <--- emulate only 12 instructions
err =
    uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(x86Code) - 1, 0, 0);
if (err) {
    printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
           uc_strerror(err));
}

printf("\n>>> Emulation done.\n");

uc_close(uc);

}`

kycgni commented 6 months ago

If only the following code is simulated, it works fine BYTE x86Code[] = { 0xB8, 0x01, 0x00, 0x00, 0x00, //mov eax,0x01000000 0x0F, 0x23, 0x38, //mov dr7,eax //0xB8, 0x00, 0x00, 0x00, 0x7B, //mov eax,0x7b //0x0F, 0x23, 0x38, //mov dr7,eax };