completed the test
The issue noticed before only occurs while we are in the hook_code (eflags is not correctly updated after the execution of the SHL instruction using CL). Once the emulation has finished executing the code the value of eflags is correct.
This commit is contained in:
@ -1,55 +1,96 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <Windows.h>
|
||||||
|
# define printf OutputDebugStringA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||||
{
|
{
|
||||||
uint32_t eax = 0, eflags = 0;
|
uint32_t eax = 0, ebx = 0, eflags = 0;
|
||||||
uc_reg_read(uc, UC_X86_REG_EAX, &eax);
|
uc_reg_read(uc, UC_X86_REG_EAX, &eax);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EBX, &ebx);
|
||||||
uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
|
uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
|
||||||
printf("eip=%08x - eax=%08x - eflags=%08X\n", (uint32_t)address, eax, eflags);
|
sprintf(buffer, "eip=%08x - eax=%08x - ebx=%08x - eflags=%08X\n", (uint32_t)address, eax, ebx, eflags);
|
||||||
|
printf(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char code32_prob[] = {
|
const char code32_prob[] = {
|
||||||
0xB8, 0x3C, 0x00, 0x00, 0x00, //0x100000: mov eax, 3Ch
|
0xBB, 0x3C, 0x00, 0x00, 0x00, //0x100000: mov ebx, 3Ch
|
||||||
0xB1, 0x02, //0x100005: mov cl, 2
|
0xB1, 0x02, //0x100005: mov cl, 2
|
||||||
0xD3, 0xE0, //0x100007: shl eax, cl <- do not set PF
|
0xD3, 0xE3, //0x100007: shl ebx, cl
|
||||||
0x33, 0xC0 //0x100009: xor eax, eax
|
0x9F, //0x100009: lahf
|
||||||
|
0xCC //0x10000A: int3
|
||||||
};
|
};
|
||||||
|
|
||||||
const char code32_ok[] = {
|
const char code32_ok[] = {
|
||||||
0xB8, 0x3C, 0x00, 0x00, 0x00, //0x100000: mov eax, 3Ch
|
0xBB, 0x3C, 0x00, 0x00, 0x00, //0x100000: mov ebx, 3Ch
|
||||||
0xC1, 0xE0, 0x02, //0x100005: shl eax, 2 <- set PF correctly
|
0xC1, 0xE3, 0x02, //0x100005: shl ebx, 2
|
||||||
0x33, 0xC0 //0x100007: xor eax, eax
|
0x9F, //0x100008: lahf
|
||||||
|
0xCC //0x100009: int3
|
||||||
};
|
};
|
||||||
|
|
||||||
const char code16_prob[] = {
|
const char code16_prob[] = {
|
||||||
0x66, 0xB8, 0x3C, 0x00, //0x100000: mov ax, 3Ch
|
0x66, 0xBB, 0x3C, 0x00, //0x100000: mov bx, 3Ch
|
||||||
0xB1, 0x02, //0x100004: mov cl, 2
|
0xB1, 0x02, //0x100004: mov cl, 2
|
||||||
0x66, 0xD3, 0xE0, //0x100006: shl ax, cl
|
0x66, 0xD3, 0xE3, //0x100006: shl bx, cl
|
||||||
0x33, 0xC0 //0x100009: xor eax, eax
|
0x9F, //0x100009: lahf
|
||||||
|
0xCC //0x10000A: int3
|
||||||
};
|
};
|
||||||
|
|
||||||
const char code16_ok[] = {
|
const char code16_ok[] = {
|
||||||
0x66, 0xB8, 0x3C, 0x00, //0x100000: mov ax, 3Ch
|
0x66, 0xBB, 0x3C, 0x00, //0x100000: mov bx, 3Ch
|
||||||
0x66, 0xC1, 0xE0, 0x02, //0x100004: shl ax, 2
|
0x66, 0xC1, 0xE3, 0x02, //0x100004: shl bx, 2
|
||||||
0x33, 0xC0 //0x100008: xor eax, eax
|
0x9F, //0x100008: lahf
|
||||||
|
0xCC //0x10000A: int3
|
||||||
};
|
};
|
||||||
|
|
||||||
const char code8_prob[] = {
|
const char code8_prob[] = {
|
||||||
0xB0, 0x3C, //0x100000: mov al, 3Ch
|
0xB3, 0x3C, //0x100000: mov bl, 3Ch
|
||||||
0xB1, 0x02, //0x100002: mov cl, 2
|
0xB1, 0x02, //0x100002: mov cl, 2
|
||||||
0xD2, 0xE0, //0x100004: shl al, 2
|
0xD2, 0xE3, //0x100004: shl bl, 2
|
||||||
0x33, 0xC0 //0x100006: xor eax, eax
|
0x9F, //0x100006: lahf
|
||||||
|
0xCC //0x100007: int3
|
||||||
};
|
};
|
||||||
|
|
||||||
const char code8_ok[] = {
|
const char code8_ok[] = {
|
||||||
0xB0, 0x3C, //0x100000: mov al, 3Ch
|
0xB3, 0x3C, //0x100000: mov bl, 3Ch
|
||||||
0xC0, 0xE0, 0x02, //0x100002: shl al, 2
|
0xC0, 0xE3, 0x02, //0x100002: shl bl, 2
|
||||||
0x33, 0xC0 //0x100005: xor eax, eax
|
0x9F, //0x100005: lahf
|
||||||
|
0xCC //0x100006: int3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char code_SHL_JP_CL[] = {
|
||||||
|
0xB4, 0x00, //0x100000: mov ah, 0
|
||||||
|
0x9E, //0x100002: sahf
|
||||||
|
0xB8, 0x3C, 0x00, 0x00, 0x00, //0x100003: mov eax, 3Ch
|
||||||
|
0xB1, 0x02, //0x100008: mov cl, 2
|
||||||
|
0xD3, 0xE0, //0x10000A: shl eax, cl
|
||||||
|
0x7A, 0x07, //0x10000C: jp +7
|
||||||
|
0xB8, 0x00, 0x00, 0x00, 0x00, //0x10000E: mov eax, 0
|
||||||
|
0xEB, 0x05, //0x100014: jmp +5
|
||||||
|
0xB8, 0x01, 0x00, 0x00, 0x00, //0x100016: mov eax, 1
|
||||||
|
0xCC //0x10001B: int3
|
||||||
|
};
|
||||||
|
|
||||||
|
const char code_SHL_JP_NOCL[] = {
|
||||||
|
0xB4, 0x00, //0x100000: mov ah, 0
|
||||||
|
0x9E, //0x100002: sahf
|
||||||
|
0xB8, 0x3C, 0x00, 0x00, 0x00, //0x100003: mov eax, 3Ch
|
||||||
|
0xC1, 0xE0, 0x02, //0x100008: shl eax, 2
|
||||||
|
0x7A, 0x07, //0x10000B: jp +7
|
||||||
|
0xB8, 0x00, 0x00, 0x00, 0x00, //0x10000D: mov eax, 0
|
||||||
|
0xEB, 0x05, //0x100014:
|
||||||
|
0xB8, 0x01, 0x00, 0x00, 0x00, //0x100016: mov eax, 1
|
||||||
|
0xCC //0x100017: int3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define ADDR_START 0x100000
|
#define ADDR_START 0x100000
|
||||||
|
|
||||||
#define TEST(X) if((X) != UC_ERR_OK) { \
|
#define TEST(X) if((X) != UC_ERR_OK) { \
|
||||||
@ -59,6 +100,7 @@ const char code8_ok[] = {
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
uint32_t eflags = 0, eax = 0;
|
||||||
uc_engine * uc = NULL;
|
uc_engine * uc = NULL;
|
||||||
|
|
||||||
TEST(uc_open(UC_ARCH_X86, UC_MODE_32, &uc));
|
TEST(uc_open(UC_ARCH_X86, UC_MODE_32, &uc));
|
||||||
@ -67,47 +109,55 @@ int main()
|
|||||||
TEST(uc_hook_add(uc, &trace_hook_code, UC_HOOK_CODE, hook_code, NULL, 1, 0));
|
TEST(uc_hook_add(uc, &trace_hook_code, UC_HOOK_CODE, hook_code, NULL, 1, 0));
|
||||||
TEST(uc_mem_map(uc, ADDR_START, 0x1000, UC_PROT_READ | UC_PROT_EXEC));
|
TEST(uc_mem_map(uc, ADDR_START, 0x1000, UC_PROT_READ | UC_PROT_EXEC));
|
||||||
|
|
||||||
|
#define RUN_CODE(CODE) { \
|
||||||
|
TEST(uc_mem_write(uc, ADDR_START, CODE, sizeof(CODE))); \
|
||||||
|
printf("running " #CODE "...\n"); \
|
||||||
|
eflags = 0; \
|
||||||
|
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags); \
|
||||||
|
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(CODE) - 1, 0, 0)); \
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); \
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EAX, &eax); \
|
||||||
|
sprintf(buffer, "after uc_emu_start: eflags=%08X - ah=%08X - %s\n", eflags, (eax>>8) & 0xFF, eflags & 4 ? "success" : "failed"); \
|
||||||
|
printf(buffer); \
|
||||||
|
}
|
||||||
|
|
||||||
//32 bits
|
//32 bits
|
||||||
TEST(uc_mem_write(uc, ADDR_START, code32_prob, sizeof(code32_prob)));
|
RUN_CODE(code32_prob);
|
||||||
printf("running code_prob\n");
|
RUN_CODE(code32_ok);
|
||||||
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code32_prob) - 1, 0, 4));
|
|
||||||
|
|
||||||
uint32_t eflags = 0;
|
|
||||||
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
|
||||||
|
|
||||||
TEST(uc_mem_write(uc, ADDR_START, code32_ok, sizeof(code32_ok)));
|
|
||||||
printf("running code_ok\n");
|
|
||||||
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code32_ok) - 1, 0, 3));
|
|
||||||
|
|
||||||
//16 bits
|
//16 bits
|
||||||
eflags = 0;
|
RUN_CODE(code16_prob);
|
||||||
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
RUN_CODE(code16_ok);
|
||||||
|
|
||||||
TEST(uc_mem_write(uc, ADDR_START, code16_prob, sizeof(code16_prob)));
|
|
||||||
printf("running code16_prob\n");
|
|
||||||
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code16_prob) - 1, 0, 4));
|
|
||||||
|
|
||||||
eflags = 0;
|
|
||||||
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
|
||||||
|
|
||||||
TEST(uc_mem_write(uc, ADDR_START, code16_ok, sizeof(code16_ok)));
|
|
||||||
printf("running code16_ok\n");
|
|
||||||
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code16_ok) - 1, 0, 3));
|
|
||||||
|
|
||||||
//8 bits
|
//8 bits
|
||||||
|
RUN_CODE(code8_prob);
|
||||||
|
RUN_CODE(code8_ok);
|
||||||
|
|
||||||
|
//test with JP-CL
|
||||||
eflags = 0;
|
eflags = 0;
|
||||||
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
||||||
|
|
||||||
TEST(uc_mem_write(uc, ADDR_START, code8_prob, sizeof(code8_prob)));
|
TEST(uc_mem_write(uc, ADDR_START, code_SHL_JP_CL, sizeof(code_SHL_JP_CL)));
|
||||||
printf("running code8_prob\n");
|
printf("running code_SHL_JP_CL ...\n");
|
||||||
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code8_prob) - 1, 0, 4));
|
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code_SHL_JP_CL) - 1, 0, 0));
|
||||||
|
|
||||||
|
eax = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EAX, &eax);
|
||||||
|
if (eax == 1) printf("success\n");
|
||||||
|
else printf("failed\n");
|
||||||
|
|
||||||
|
//test with JP-NOCL
|
||||||
eflags = 0;
|
eflags = 0;
|
||||||
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags);
|
||||||
|
|
||||||
TEST(uc_mem_write(uc, ADDR_START, code8_ok, sizeof(code8_ok)));
|
TEST(uc_mem_write(uc, ADDR_START, code_SHL_JP_NOCL, sizeof(code_SHL_JP_NOCL)));
|
||||||
printf("running code8_ok\n");
|
printf("running code_SHL_JP_NOCL ...\n");
|
||||||
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code8_ok) - 1, 0, 3));
|
TEST(uc_emu_start(uc, ADDR_START, ADDR_START + sizeof(code_SHL_JP_NOCL) - 1, 0, 0));
|
||||||
|
|
||||||
|
eax = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_EAX, &eax);
|
||||||
|
if (eax == 1) printf("success\n");
|
||||||
|
else printf("failed\n");
|
||||||
|
|
||||||
TEST(uc_close(uc));
|
TEST(uc_close(uc));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user