Skip to content

Instantly share code, notes, and snippets.

@cseagle
Created February 7, 2023 02:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cseagle/7d76181e26d581b605391bccdba75fad to your computer and use it in GitHub Desktop.
Save cseagle/7d76181e26d581b605391bccdba75fad to your computer and use it in GitHub Desktop.
Emulate 16-bit code
>>> Execution begins --- cs:ip is 0x13c8:0x1d (0x13c9d)
>>> Tracing basic block at 0x13c9d, block size = 0xf
--- cs:ip is 0x13c8:0x1d (0x13c9d)
>>> Tracing instruction at 0x13c9d, instruction size = 0x3
--- cs:ip is 0x13c8:0x3c9d (0x1791d)
>>> Tracing instruction at 0x13ca0, instruction size = 0x4
--- cs:ip is 0x13c8:0x3ca0 (0x17920)
>>> Tracing instruction at 0x13ca4, instruction size = 0x2
--- cs:ip is 0x13c8:0x3ca4 (0x17924)
>>> Tracing instruction at 0x13ca6, instruction size = 0x4
--- cs:ip is 0x13c8:0x3ca6 (0x17926)
>>> Tracing instruction at 0x13caa, instruction size = 0x2
--- cs:ip is 0x13c8:0x3caa (0x1792a)
>>> Tracing basic block at 0x13cac, block size = 0x6
--- cs:ip is 0x13c8:0x2c (0x13cac)
>>> Tracing instruction at 0x13cac, instruction size = 0x3
--- cs:ip is 0x13c8:0x3cac (0x1792c)
>>> Tracing instruction at 0x13caf, instruction size = 0x1
--- cs:ip is 0x13c8:0x3caf (0x1792f)
>>> Tracing instruction at 0x13cb0, instruction size = 0x2
--- cs:ip is 0x13c8:0x3cb0 (0x17930)
>>> Tracing basic block at 0x13cb2, block size = 0x4
--- cs:ip is 0x13c8:0x32 (0x13cb2)
>>> Tracing instruction at 0x13cb2, instruction size = 0x4
--- cs:ip is 0x13c8:0x3cb2 (0x17932)
>>> Tracing basic block at 0x13cb6, block size = 0x1
--- cs:ip is 0x13c8:0x36 (0x13cb6)
>>> Tracing instruction at 0x13cb6, instruction size = 0x1
--- cs:ip is 0x13c8:0x3cb6 (0x17936)
>>> Tracing basic block at 0x13cb7, block size = 0x2
--- cs:ip is 0x13c8:0x37 (0x13cb7)
>>> Tracing instruction at 0x13cb7, instruction size = 0x2
--- cs:ip is 0x13c8:0x3cb7 (0x17937)
>>> Tracing basic block at 0x13ccb, block size = 0x40
--- cs:ip is 0x13c8:0x4b (0x13ccb)
>>> Tracing instruction at 0x13ccb, instruction size = 0x2
--- cs:ip is 0x13c8:0x3ccb (0x1794b)
>>> Tracing instruction at 0x13ccd, instruction size = 0x2
--- cs:ip is 0x13c8:0x3ccd (0x1794d)
>>> Tracing instruction at 0x13ccf, instruction size = 0x2
--- cs:ip is 0x13c8:0x3ccf (0x1794f)
>>> Tracing instruction at 0x13cd1, instruction size = 0x1
--- cs:ip is 0x13c8:0x3cd1 (0x17951)
>>> Tracing instruction at 0x13cd2, instruction size = 0x4
--- cs:ip is 0x13c8:0x3cd2 (0x17952)
>>> Tracing instruction at 0x13cd6, instruction size = 0x3
--- cs:ip is 0x13c8:0x3cd6 (0x17956)
>>> Tracing instruction at 0x13cd9, instruction size = 0x3
--- cs:ip is 0x13c8:0x3cd9 (0x17959)
>>> Tracing instruction at 0x13cdc, instruction size = 0x3
--- cs:ip is 0x13c8:0x3cdc (0x1795c)
>>> Tracing instruction at 0x13cdf, instruction size = 0x4
--- cs:ip is 0x13c8:0x3cdf (0x1795f)
>>> Tracing instruction at 0x13ce3, instruction size = 0x3
--- cs:ip is 0x13c8:0x3ce3 (0x17963)
>>> Tracing instruction at 0x13ce6, instruction size = 0x1
--- cs:ip is 0x13c8:0x3ce6 (0x17966)
>>> Tracing instruction at 0x13ce7, instruction size = 0x4
--- cs:ip is 0x13c8:0x3ce7 (0x17967)
>>> Tracing instruction at 0x13ceb, instruction size = 0x2
--- cs:ip is 0x13c8:0x3ceb (0x1796b)
>>> Tracing instruction at 0x13ced, instruction size = 0x1
--- cs:ip is 0x13c8:0x3ced (0x1796d)
>>> Tracing instruction at 0x13cee, instruction size = 0x4
--- cs:ip is 0x13c8:0x3cee (0x1796e)
>>> Tracing instruction at 0x13cf2, instruction size = 0x4
--- cs:ip is 0x13c8:0x3cf2 (0x17972)
>>> Tracing instruction at 0x13cf6, instruction size = 0x5
--- cs:ip is 0x13c8:0x3cf6 (0x17976)
>>> Tracing instruction at 0x13cfb, instruction size = 0x2
--- cs:ip is 0x13c8:0x3cfb (0x1797b)
>>> Tracing instruction at 0x13cfd, instruction size = 0x4
--- cs:ip is 0x13c8:0x3cfd (0x1797d)
>>> Tracing instruction at 0x13d01, instruction size = 0x2
--- cs:ip is 0x13c8:0x3d01 (0x17981)
>>> Tracing instruction at 0x13d03, instruction size = 0x2
--- cs:ip is 0x13c8:0x3d03 (0x17983)
>>> Tracing instruction at 0x13d05, instruction size = 0x2
--- cs:ip is 0x13c8:0x3d05 (0x17985)
>>> Tracing instruction at 0x13d07, instruction size = 0x2
--- cs:ip is 0x13c8:0x3d07 (0x17987)
>>> Tracing instruction at 0x13d09, instruction size = 0x2
--- cs:ip is 0x13c8:0x3d09 (0x17989)
Failed on uc_emu_start() with error returned 21: Unhandled CPU exception (UC_ERR_EXCEPTION)
>>> Emulation done. Below is the CPU context
>>> CS = 0x13c8
>>> IP = 0x8b
#include <unicorn/unicorn.h>
#include <string.h>
// callback for tracing basic blocks
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
unsigned short ip;
unsigned short cs;
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
address, size);
uc_reg_read(uc, UC_X86_REG_IP, &ip);
uc_reg_read(uc, UC_X86_REG_CS, &cs);
printf(" --- cs:ip is 0x%x:0x%x (0x%x)\n", cs, ip, 16 * cs + ip);
}
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
void *user_data)
{
unsigned short ip;
unsigned short cs;
printf(" >>> Tracing instruction at 0x%" PRIx64
", instruction size = 0x%x\n",
address, size);
uc_reg_read(uc, UC_X86_REG_IP, &ip);
uc_reg_read(uc, UC_X86_REG_CS, &cs);
printf(" --- cs:ip is 0x%x:0x%x (0x%x)\n", cs, ip, 16 * cs + ip);
}
// callback for SYSCALL instruction (X86).
static void hook_syscall(uc_engine *uc, void *user_data)
{
uint32_t eax;
uc_reg_read(uc, UC_X86_REG_IP, &eax);
printf("syscall eax=0x%x\n", eax);
}
static void test_x86_16(const char *input, uint32_t loadaddr)
{
uc_engine *uc;
uc_err err;
uint32_t tmp;
uc_hook trace1, trace2;
FILE *f;
f = fopen(input, "rb");
if (f == NULL) {
return;
}
uint32_t sz;
fseek(f, 0, SEEK_END);
sz = ftell(f);
fseek(f, 0, SEEK_SET);
char *b = (char*)malloc(sz);
fread(b, 1, sz, f);
fclose(f);
uint16_t r_cs = 0x13c8;
uint16_t r_ip = 0x1d;
printf("Emulate 16-bit code\n");
// Initialize emulator in X86-16bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u\n", err);
return;
}
// map 1MB memory for this emulation
uc_mem_map(uc, 0, 1024 * 1024, UC_PROT_ALL);
// write machine code to be emulated to memory
if (uc_mem_write(uc, loadaddr, b, sz)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
// initialize machine registers
uc_reg_write(uc, UC_X86_REG_CS, &r_cs);
uc_reg_write(uc, UC_X86_REG_IP, &r_ip);
// tracing all basic blocks with customized callback
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
// tracing all instruction by having @begin > @end
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
uc_reg_read(uc, UC_X86_REG_IP, &r_ip);
uc_reg_read(uc, UC_X86_REG_CS, &r_cs);
printf(">>> Execution begins --- cs:ip is 0x%x:0x%x (0x%x)\n", r_cs, r_ip, 16 * r_cs + r_ip);
// emulate machine code in infinite time
err = uc_emu_start(uc, 0x13C9D, 0x10000 + sz, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n", err,
uc_strerror(err));
}
// now print out some registers
printf(">>> Emulation done. Below is the CPU context\n");
uc_reg_read(uc, UC_X86_REG_CS, &r_cs);
uc_reg_read(uc, UC_X86_REG_IP, &r_ip);
printf(">>> CS = 0x%x\n", r_cs);
printf(">>> IP = 0x%x\n", r_ip);
uc_close(uc);
}
int main(int argc, char **argv, char **envp)
{
test_x86_16(argv[1], 0x10000);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment