cleaning & indentation

This commit is contained in:
Nguyen Anh Quynh 2015-09-03 18:16:49 +08:00
parent b8d4240240
commit 9f9d57e84f
6 changed files with 633 additions and 694 deletions

View file

@ -1,23 +1,22 @@
/* /*
Executable memory regions demo / unit test
Executable memory regions demo / unit test Copyright(c) 2015 Chris Eagle
Copyright(c) 2015 Chris Eagle This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or This program is distributed in the hope that it will be useful,
modify it under the terms of the GNU General Public License but WITHOUT ANY WARRANTY; without even the implied warranty of
version 2 as published by the Free Software Foundation. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful, You should have received a copy of the GNU General Public License
but WITHOUT ANY WARRANTY; without even the implied warranty of along with this program; if not, write to the Free Software
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
#include <inttypes.h> #include <inttypes.h>
@ -30,47 +29,47 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <unicorn/unicorn.h> #include <unicorn/unicorn.h>
unsigned char PROGRAM[] = unsigned char PROGRAM[] =
"\xeb\x45\x5e\x81\xe6\x00\xf0\xff\xff\x40\x40\x40\x40\x40\x40\x40" "\xeb\x45\x5e\x81\xe6\x00\xf0\xff\xff\x40\x40\x40\x40\x40\x40\x40"
"\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40" "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
"\x40\x40\x40\x40\x40\x40\x40\x89\xf7\x81\xc7\x00\x00\x10\x00\xb9" "\x40\x40\x40\x40\x40\x40\x40\x89\xf7\x81\xc7\x00\x00\x10\x00\xb9"
"\x4c\x00\x00\x00\x81\xff\x00\x00\x40\x00\x75\x01\xf4\xf3\xa4\x81" "\x4c\x00\x00\x00\x81\xff\x00\x00\x40\x00\x75\x01\xf4\xf3\xa4\x81"
"\xe7\x00\xf0\xff\xff\xff\xe7\xe8\xb6\xff\xff\xff"; "\xe7\x00\xf0\xff\xff\xff\xe7\xe8\xb6\xff\xff\xff";
// total size: 76 bytes // total size: 76 bytes
/* /*
bits 32 bits 32
; assumes r-x section at 0x100000 ; assumes r-x section at 0x100000
; assumes rw- section at 0x200000 ; assumes rw- section at 0x200000
; assumes r-- section at 0x300000 ; assumes r-- section at 0x300000
; also needs an initialized stack ; also needs an initialized stack
start: start:
jmp bottom jmp bottom
top: top:
pop esi pop esi
and esi, ~0xfff and esi, ~0xfff
times 30 inc eax times 30 inc eax
mov edi, esi mov edi, esi
add edi, 0x100000 add edi, 0x100000
mov ecx, end - start mov ecx, end - start
rep movsb rep movsb
and edi, ~0xfff and edi, ~0xfff
cmp edi, 0x400000 cmp edi, 0x400000
jnz next_block jnz next_block
hlt hlt
next_block: next_block:
jmp edi jmp edi
bottom: bottom:
call top call top
end: end:
*/ */
int test_num = 0; int test_num = 0;
uint32_t tests[] = { uint32_t tests[] = {
0x41414141, 0x41414141,
0x43434343, 0x43434343,
0x45454545 0x45454545
}; };
static int log_num = 1; static int log_num = 1;
@ -81,216 +80,200 @@ static int log_num = 1;
// callback for tracing instruction // callback for tracing instruction
static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data)
{ {
uint8_t opcode; uint8_t opcode;
if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) {
printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) {
} printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
// printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr); }
switch (opcode) {
case 0xf4: //hlt // printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
printf("# Handling HLT\n"); switch (opcode) {
if (uc_emu_stop(handle) != UC_ERR_OK) { case 0xf4: //hlt
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("# Handling HLT\n");
_exit(-1); if (uc_emu_stop(handle) != UC_ERR_OK) {
} printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
else { _exit(-1);
printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++); } else {
} printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
break; }
default: //all others break;
// printf("# Handling OTHER\n"); default: //all others
break; // printf("# Handling OTHER\n");
} break;
}
} }
// callback for tracing memory access (READ or WRITE) // callback for tracing memory access (READ or WRITE)
static void hook_mem_write(uch handle, uc_mem_type type, static void hook_mem_write(uch handle, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data) uint64_t addr, int size, int64_t value, void *user_data)
{ {
printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
} }
// callback for tracing invalid memory access (READ or WRITE) // callback for tracing invalid memory access (READ or WRITE)
static bool hook_mem_invalid(uch handle, uc_mem_type type, static bool hook_mem_invalid(uch handle, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data) uint64_t addr, int size, int64_t value, void *user_data)
{ {
switch(type) { switch(type) {
default: default:
printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr); printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
return false; return false;
case UC_MEM_EXEC_PROT: case UC_MEM_EXEC_PROT:
printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr); printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
//make page executable //make page executable
if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) { if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) {
printf("not ok %d - uc_mem_protect fail for address: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_protect fail for address: 0x%" PRIx64 "\n", log_num++, addr);
} } else {
else { printf("ok %d - uc_mem_protect success at 0x%" PRIx64 "\n", log_num++, addr);
printf("ok %d - uc_mem_protect success at 0x%" PRIx64 "\n", log_num++, addr); }
} return true;
return true; case UC_MEM_WRITE_PROT:
case UC_MEM_WRITE_PROT: printf("# write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
printf("# write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) {
printf("not ok %d - uc_mem_protect fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_protect fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} } else {
else { printf("ok %d - uc_mem_protect success\n", log_num++);
printf("ok %d - uc_mem_protect success\n", log_num++); }
} return true;
return true; }
}
} }
int main(int argc, char **argv, char **envp) int main(int argc, char **argv, char **envp)
{ {
uch handle, trace1, trace2; uch handle, trace1, trace2;
uc_err err; uc_err err;
uint32_t esp, eip; uint32_t esp, eip;
int32_t buf1[1024], buf2[1024], readbuf[1024]; int32_t buf1[1024], buf2[1024], readbuf[1024];
int i; int i;
//don't really care about quality of randomness //don't really care about quality of randomness
srand(time(NULL)); srand(time(NULL));
for (i = 0; i < 1024; i++) { for (i = 0; i < 1024; i++) {
buf1[i] = rand(); buf1[i] = rand();
buf2[i] = rand(); buf2[i] = rand();
} }
printf("# Memory protect test\n"); printf("# Memory protect test\n");
// Initialize emulator in X86-32bit mode // Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
if (err) { if (err) {
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err); printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1; return 1;
} } else {
else { printf("ok %d - uc_open() success\n", log_num++);
printf("ok %d - uc_open() success\n", log_num++); }
}
uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC); uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC);
uc_mem_map(handle, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE);
uc_mem_map(handle, 0x300000, 0x2000, UC_PROT_READ); uc_mem_map(handle, 0x300000, 0x2000, UC_PROT_READ);
uc_mem_map(handle, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
esp = 0xf00000 + 0x1000; esp = 0xf00000 + 0x1000;
// Setup stack pointer // Setup stack pointer
if (uc_reg_write(handle, UC_X86_REG_ESP, &esp)) { if (uc_reg_write(handle, UC_X86_REG_ESP, &esp)) {
printf("not ok %d - Failed to set esp. quit!\n", log_num++); printf("not ok %d - Failed to set esp. quit!\n", log_num++);
return 2; return 2;
} } else {
else { printf("ok %d - ESP set\n", log_num++);
printf("ok %d - ESP set\n", log_num++); }
}
// fill in sections that shouldn't get touched // fill in sections that shouldn't get touched
if (uc_mem_write(handle, 0x1ff000, (uint8_t*)buf1, 4096)) { if (uc_mem_write(handle, 0x1ff000, (uint8_t*)buf1, 4096)) {
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
return 3; return 3;
} } else {
else { printf("ok %d - Random buffer 1 written to memory\n", log_num++);
printf("ok %d - Random buffer 1 written to memory\n", log_num++); }
}
if (uc_mem_write(handle, 0x301000, (uint8_t*)buf2, 4096)) { if (uc_mem_write(handle, 0x301000, (uint8_t*)buf2, 4096)) {
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
return 4; return 4;
} } else {
else { printf("ok %d - Random buffer 2 written to memory\n", log_num++);
printf("ok %d - Random buffer 2 written to memory\n", log_num++); }
}
// write machine code to be emulated to memory // write machine code to be emulated to memory
if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) { if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) {
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
return 5; return 5;
} } else {
else { printf("ok %d - Program written to memory\n", log_num++);
printf("ok %d - Program written to memory\n", log_num++); }
}
if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
return 6; return 6;
} } else {
else { printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
printf("ok %d - UC_HOOK_CODE installed\n", log_num++); }
}
// intercept memory write events // intercept memory write events
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
return 7; return 7;
} } else {
else { printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++); }
}
// intercept invalid memory events // intercept invalid memory events
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++);
return 8; return 8;
} } else {
else { printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++); }
}
// emulate machine code until told to stop by hook_code // emulate machine code until told to stop by hook_code
printf("# BEGIN execution\n"); printf("# BEGIN execution\n");
err = uc_emu_start(handle, 0x100000, 0x400000, 0, 0); err = uc_emu_start(handle, 0x100000, 0x400000, 0, 0);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
return 9; return 9;
} } else {
else { printf("ok %d - uc_emu_start complete\n", log_num++);
printf("ok %d - uc_emu_start complete\n", log_num++); }
} printf("# END execution\n");
printf("# END execution\n");
// get ending EIP // get ending EIP
if (uc_reg_read(handle, UC_X86_REG_EIP, &eip)) { if (uc_reg_read(handle, UC_X86_REG_EIP, &eip)) {
printf("not ok %d - Failed to read eip.\n", log_num++); printf("not ok %d - Failed to read eip.\n", log_num++);
} } else {
else { printf("ok %d - Ending EIP 0x%x\n", log_num++, eip);
printf("ok %d - Ending EIP 0x%x\n", log_num++, eip); }
}
//make sure that random blocks didn't get nuked //make sure that random blocks didn't get nuked
// fill in sections that shouldn't get touched // fill in sections that shouldn't get touched
if (uc_mem_read(handle, 0x1ff000, (uint8_t*)readbuf, 4096)) { if (uc_mem_read(handle, 0x1ff000, (uint8_t*)readbuf, 4096)) {
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
} } else {
else { printf("ok %d - Random buffer 1 read from memory\n", log_num++);
printf("ok %d - Random buffer 1 read from memory\n", log_num++); if (memcmp(buf1, readbuf, 4096)) {
if (memcmp(buf1, readbuf, 4096)) { printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++); } else {
} printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
else { }
printf("ok %d - Random buffer 1 contents are correct\n", log_num++); }
}
}
if (uc_mem_read(handle, 0x301000, (uint8_t*)readbuf, 4096)) { if (uc_mem_read(handle, 0x301000, (uint8_t*)readbuf, 4096)) {
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
} } else {
else { printf("ok %d - Random buffer 2 read from memory\n", log_num++);
printf("ok %d - Random buffer 2 read from memory\n", log_num++); if (memcmp(buf2, readbuf, 4096)) {
if (memcmp(buf2, readbuf, 4096)) { printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++);
printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++); } else {
} printf("ok %d - Random buffer 2 contents are correct\n", log_num++);
else { }
printf("ok %d - Random buffer 2 contents are correct\n", log_num++); }
}
}
if (uc_close(&handle) == UC_ERR_OK) { if (uc_close(&handle) == UC_ERR_OK) {
printf("ok %d - uc_close complete\n", log_num++); printf("ok %d - uc_close complete\n", log_num++);
} } else {
else { printf("not ok %d - uc_close complete\n", log_num++);
printf("not ok %d - uc_close complete\n", log_num++); }
}
return 0; return 0;
} }

View file

@ -1,23 +1,22 @@
/* /*
uc_mem_protect demo / unit test
uc_mem_protect demo / unit test Copyright(c) 2015 Chris Eagle
Copyright(c) 2015 Chris Eagle This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or This program is distributed in the hope that it will be useful,
modify it under the terms of the GNU General Public License but WITHOUT ANY WARRANTY; without even the implied warranty of
version 2 as published by the Free Software Foundation. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful, You should have received a copy of the GNU General Public License
but WITHOUT ANY WARRANTY; without even the implied warranty of along with this program; if not, write to the Free Software
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
#include <inttypes.h> #include <inttypes.h>
@ -30,23 +29,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <unicorn/unicorn.h> #include <unicorn/unicorn.h>
unsigned char PROGRAM[] = unsigned char PROGRAM[] =
"\xc7\x05\x00\x00\x20\x00\x41\x41\x41\x41\x90\xc7\x05\x00\x00\x20" "\xc7\x05\x00\x00\x20\x00\x41\x41\x41\x41\x90\xc7\x05\x00\x00\x20"
"\x00\x42\x42\x42\x42\xc7\x05\x00\x00\x30\x00\x43\x43\x43\x43\x90" "\x00\x42\x42\x42\x42\xc7\x05\x00\x00\x30\x00\x43\x43\x43\x43\x90"
"\xc7\x05\x00\x00\x30\x00\x44\x44\x44\x44\xc7\x05\x00\x00\x40\x00" "\xc7\x05\x00\x00\x30\x00\x44\x44\x44\x44\xc7\x05\x00\x00\x40\x00"
"\x45\x45\x45\x45\x90\xc7\x05\x00\x00\x40\x00\x46\x46\x46\x46\xc7" "\x45\x45\x45\x45\x90\xc7\x05\x00\x00\x40\x00\x46\x46\x46\x46\xc7"
"\x05\x00\xf8\x3f\x00\x47\x47\x47\x47\xc7\x05\x00\x18\x40\x00\x48" "\x05\x00\xf8\x3f\x00\x47\x47\x47\x47\xc7\x05\x00\x18\x40\x00\x48"
"\x48\x48\x48\xf4"; "\x48\x48\x48\xf4";
// total size: 84 bytes // total size: 84 bytes
/* /*
bits 32 bits 32
; assumes code section at 0x100000 ; assumes code section at 0x100000
; assumes data section at 0x200000, initially rw ; assumes data section at 0x200000, initially rw
; assumes data section at 0x300000, initially rw ; assumes data section at 0x300000, initially rw
; assumes data section at 0x400000, initially rw ; assumes data section at 0x400000, initially rw
; with installed hooks unmaps or maps on each nop ; with installed hooks unmaps or maps on each nop
mov dword [0x200000], 0x41414141 mov dword [0x200000], 0x41414141
nop ; mark it RO nop ; mark it RO
@ -63,13 +62,13 @@ bits 32
mov dword [0x401800], 0x48484848 ; make sure surrounding areas remained RW mov dword [0x401800], 0x48484848 ; make sure surrounding areas remained RW
hlt ; tell hook function we are done hlt ; tell hook function we are done
*/ */
int test_num = 0; int test_num = 0;
uint32_t tests[] = { uint32_t tests[] = {
0x41414141, 0x41414141,
0x43434343, 0x43434343,
0x45454545 0x45454545
}; };
static int log_num = 1; static int log_num = 1;
@ -80,244 +79,223 @@ static int log_num = 1;
// callback for tracing instruction // callback for tracing instruction
static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data)
{ {
uint8_t opcode; uint8_t opcode;
uint32_t testval; uint32_t testval;
if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) { if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) {
printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} }
printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr); printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
switch (opcode) { switch (opcode) {
case 0x90: //nop case 0x90: //nop
printf("# Handling NOP\n"); printf("# Handling NOP\n");
if (uc_mem_read(handle, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { if (uc_mem_read(handle, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) {
printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
} } else {
else { printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); printf("# uc_mem_read for test %d\n", test_num);
printf("# uc_mem_read for test %d\n", test_num);
if (testval == tests[test_num]) { if (testval == tests[test_num]) {
printf("ok %d - passed test %d\n", log_num++, test_num); printf("ok %d - passed test %d\n", log_num++, test_num);
} else {
printf("not ok %d - failed test %d\n", log_num++, test_num);
printf("# Expected: 0x%x\n",tests[test_num]);
printf("# Received: 0x%x\n", testval);
}
} }
else { if (uc_mem_protect(handle, 0x200000 + test_num * 0x100000, 0x1000, UC_PROT_READ) != UC_ERR_OK) {
printf("not ok %d - failed test %d\n", log_num++, test_num); printf("not ok %d - uc_mem_protect fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
printf("# Expected: 0x%x\n",tests[test_num]); } else {
printf("# Received: 0x%x\n", testval); printf("ok %d - uc_mem_protect success\n", log_num++);
} }
} test_num++;
if (uc_mem_protect(handle, 0x200000 + test_num * 0x100000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { break;
printf("not ok %d - uc_mem_protect fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); case 0xf4: //hlt
} printf("# Handling HLT\n");
else { if (uc_emu_stop(handle) != UC_ERR_OK) {
printf("ok %d - uc_mem_protect success\n", log_num++); printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} _exit(-1);
test_num++; } else {
break; printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
case 0xf4: //hlt }
printf("# Handling HLT\n"); break;
if (uc_emu_stop(handle) != UC_ERR_OK) { default: //all others
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("# Handling OTHER\n");
_exit(-1); break;
} }
else {
printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
}
break;
default: //all others
printf("# Handling OTHER\n");
break;
}
} }
// callback for tracing memory access (READ or WRITE) // callback for tracing memory access (READ or WRITE)
static void hook_mem_write(uch handle, uc_mem_type type, static void hook_mem_write(uch handle, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data) uint64_t addr, int size, int64_t value, void *user_data)
{ {
printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
} }
// callback for tracing invalid memory access (READ or WRITE) // callback for tracing invalid memory access (READ or WRITE)
static bool hook_mem_invalid(uch handle, uc_mem_type type, static bool hook_mem_invalid(uch handle, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data) uint64_t addr, int size, int64_t value, void *user_data)
{ {
uint32_t testval; uint32_t testval;
switch(type) { switch(type) {
default: default:
printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr); printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
return false; return false;
case UC_MEM_WRITE_PROT: case UC_MEM_WRITE_PROT:
printf("# write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); printf("# write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
if (uc_mem_read(handle, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { if (uc_mem_read(handle, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) {
printf("not ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr);
} } else {
else { printf("ok %d - uc_mem_read success after mem_protect at test %d\n", log_num++, test_num - 1);
printf("ok %d - uc_mem_read success after mem_protect at test %d\n", log_num++, test_num - 1); }
}
if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { if (uc_mem_protect(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) {
printf("not ok %d - uc_mem_protect fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_protect fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} } else {
else { printf("ok %d - uc_mem_protect success\n", log_num++);
printf("ok %d - uc_mem_protect success\n", log_num++); }
} return true;
return true; }
}
} }
int main(int argc, char **argv, char **envp) int main(int argc, char **argv, char **envp)
{ {
uch handle, trace1, trace2; uch handle, trace1, trace2;
uc_err err; uc_err err;
uint32_t addr, testval; uint32_t addr, testval;
int32_t buf1[1024], buf2[1024], readbuf[1024]; int32_t buf1[1024], buf2[1024], readbuf[1024];
int i; int i;
//don't really care about quality of randomness //don't really care about quality of randomness
srand(time(NULL)); srand(time(NULL));
for (i = 0; i < 1024; i++) { for (i = 0; i < 1024; i++) {
buf1[i] = rand(); buf1[i] = rand();
buf2[i] = rand(); buf2[i] = rand();
} }
printf("# Memory protect test\n"); printf("# Memory protect test\n");
// Initialize emulator in X86-32bit mode // Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
if (err) { if (err) {
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err); printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1; return 1;
} } else {
else { printf("ok %d - uc_open() success\n", log_num++);
printf("ok %d - uc_open() success\n", log_num++); }
}
uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);
// fill in sections that shouldn't get touched // fill in sections that shouldn't get touched
if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) { if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) {
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
return 2; return 2;
} } else {
else { printf("ok %d - Random buffer 1 written to memory\n", log_num++);
printf("ok %d - Random buffer 1 written to memory\n", log_num++); }
}
if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) { if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) {
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
return 3; return 3;
} } else {
else { printf("ok %d - Random buffer 2 written to memory\n", log_num++);
printf("ok %d - Random buffer 2 written to memory\n", log_num++); }
}
// write machine code to be emulated to memory // write machine code to be emulated to memory
if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
return 4; return 4;
} } else {
else { printf("ok %d - Program written to memory\n", log_num++);
printf("ok %d - Program written to memory\n", log_num++); }
}
if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
return 5; return 5;
} } else {
else { printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
printf("ok %d - UC_HOOK_CODE installed\n", log_num++); }
}
// intercept memory write events // intercept memory write events
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
return 6; return 6;
} } else {
else { printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++); }
}
// intercept invalid memory events // intercept invalid memory events
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++);
return 7; return 7;
} } else {
else { printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++); }
}
// emulate machine code until told to stop by hook_code // emulate machine code until told to stop by hook_code
printf("# BEGIN execution\n"); printf("# BEGIN execution\n");
err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
return 8; return 8;
} } else {
else { printf("ok %d - uc_emu_start complete\n", log_num++);
printf("ok %d - uc_emu_start complete\n", log_num++); }
} printf("# END execution\n");
printf("# END execution\n");
//read from the remapped memory //read from the remapped memory
testval = 0x42424242; testval = 0x42424242;
for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) { for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
uint32_t val; uint32_t val;
if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) { if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) {
printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr); printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr);
} } else {
else { printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr);
printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr); }
} if (val != testval) {
if (val != testval) { printf("not ok %d - Read 0x%x, expected 0x%x\n", log_num++, val, testval);
printf("not ok %d - Read 0x%x, expected 0x%x\n", log_num++, val, testval); } else {
} printf("ok %d - Correct value retrieved\n", log_num++);
else { }
printf("ok %d - Correct value retrieved\n", log_num++); testval += 0x02020202;
} }
testval += 0x02020202;
}
//account for the two mods made by the machine code //account for the two mods made by the machine code
buf1[512] = 0x47474747; buf1[512] = 0x47474747;
buf2[512] = 0x48484848; buf2[512] = 0x48484848;
//make sure that random blocks didn't get nuked //make sure that random blocks didn't get nuked
// fill in sections that shouldn't get touched // fill in sections that shouldn't get touched
if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) { if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) {
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
} } else {
else { printf("ok %d - Random buffer 1 read from memory\n", log_num++);
printf("ok %d - Random buffer 1 read from memory\n", log_num++); if (memcmp(buf1, readbuf, 4096)) {
if (memcmp(buf1, readbuf, 4096)) { printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++); } else {
} printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
else { }
printf("ok %d - Random buffer 1 contents are correct\n", log_num++); }
}
}
if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) { if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) {
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
} } else {
else { printf("ok %d - Random buffer 2 read from memory\n", log_num++);
printf("ok %d - Random buffer 2 read from memory\n", log_num++); if (memcmp(buf2, readbuf, 4096)) {
if (memcmp(buf2, readbuf, 4096)) { printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++);
printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++); } else {
} printf("ok %d - Random buffer 2 contents are correct\n", log_num++);
else { }
printf("ok %d - Random buffer 2 contents are correct\n", log_num++); }
}
}
if (uc_close(&handle) == UC_ERR_OK) { if (uc_close(&handle) == UC_ERR_OK) {
printf("ok %d - uc_close complete\n", log_num++); printf("ok %d - uc_close complete\n", log_num++);
} } else {
else { printf("not ok %d - uc_close complete\n", log_num++);
printf("not ok %d - uc_close complete\n", log_num++); }
}
return 0; return 0;
} }

View file

@ -1,23 +1,23 @@
/* /*
uc_mem_unmap demo / unit test uc_mem_unmap demo / unit test
Copyright(c) 2015 Chris Eagle Copyright(c) 2015 Chris Eagle
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
#include <inttypes.h> #include <inttypes.h>
@ -30,19 +30,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <unicorn/unicorn.h> #include <unicorn/unicorn.h>
unsigned char PROGRAM[] = unsigned char PROGRAM[] =
"\xc7\x05\x00\x00\x20\x00\x41\x41\x41\x41\x90\xc7\x05\x00\x00\x20" "\xc7\x05\x00\x00\x20\x00\x41\x41\x41\x41\x90\xc7\x05\x00\x00\x20"
"\x00\x42\x42\x42\x42\xc7\x05\x00\x00\x30\x00\x43\x43\x43\x43\x90" "\x00\x42\x42\x42\x42\xc7\x05\x00\x00\x30\x00\x43\x43\x43\x43\x90"
"\xc7\x05\x00\x00\x30\x00\x44\x44\x44\x44\xc7\x05\x00\x00\x40\x00" "\xc7\x05\x00\x00\x30\x00\x44\x44\x44\x44\xc7\x05\x00\x00\x40\x00"
"\x45\x45\x45\x45\x90\xc7\x05\x00\x00\x40\x00\x46\x46\x46\x46\xf4"; "\x45\x45\x45\x45\x90\xc7\x05\x00\x00\x40\x00\x46\x46\x46\x46\xf4";
// total size: 64 bytes // total size: 64 bytes
/* /*
; assumes code section at 0x100000 ; assumes code section at 0x100000
; assumes data section at 0x200000, initially rw ; assumes data section at 0x200000, initially rw
; assumes data section at 0x300000, initially rw ; assumes data section at 0x300000, initially rw
; assumes data section at 0x400000, initially rw ; assumes data section at 0x400000, initially rw
; with installed hooks unmaps or maps on each nop ; with installed hooks unmaps or maps on each nop
mov dword [0x200000], 0x41414141 mov dword [0x200000], 0x41414141
nop ; unmap it nop ; unmap it
@ -57,13 +57,13 @@ unsigned char PROGRAM[] =
mov dword [0x400000], 0x46464646 mov dword [0x400000], 0x46464646
hlt ; tell hook function we are done hlt ; tell hook function we are done
*/ */
int test_num = 0; int test_num = 0;
uint32_t tests[] = { uint32_t tests[] = {
0x41414141, 0x41414141,
0x43434343, 0x43434343,
0x45454545 0x45454545
}; };
static int log_num = 1; static int log_num = 1;
@ -74,240 +74,219 @@ static int log_num = 1;
// callback for tracing instruction // callback for tracing instruction
static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data) static void hook_code(uch handle, uint64_t addr, uint32_t size, void *user_data)
{ {
uint8_t opcode; uint8_t opcode;
uint32_t testval; uint32_t testval;
if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) { if (uc_mem_read(handle, addr, &opcode, 1) != UC_ERR_OK) {
printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} }
printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr); printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
switch (opcode) { switch (opcode) {
case 0x90: //nop case 0x90: //nop
printf("# Handling NOP\n"); printf("# Handling NOP\n");
if (uc_mem_read(handle, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { if (uc_mem_read(handle, 0x200000 + test_num * 0x100000, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) {
printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
} } else {
else { printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); printf("# uc_mem_read for test %d\n", test_num);
printf("# uc_mem_read for test %d\n", test_num);
if (testval == tests[test_num]) { if (testval == tests[test_num]) {
printf("ok %d - passed test %d\n", log_num++, test_num); printf("ok %d - passed test %d\n", log_num++, test_num);
} else {
printf("not ok %d - failed test %d\n", log_num++, test_num);
printf("# Expected: 0x%x\n",tests[test_num]);
printf("# Received: 0x%x\n", testval);
}
} }
else { if (uc_mem_unmap(handle, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) {
printf("not ok %d - failed test %d\n", log_num++, test_num); printf("not ok %d - uc_mem_unmap fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
printf("# Expected: 0x%x\n",tests[test_num]); } else {
printf("# Received: 0x%x\n", testval); printf("ok %d - uc_mem_unmap success\n", log_num++);
} }
} test_num++;
if (uc_mem_unmap(handle, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) { break;
printf("not ok %d - uc_mem_unmap fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000); case 0xf4: //hlt
} printf("# Handling HLT\n");
else { if (uc_emu_stop(handle) != UC_ERR_OK) {
printf("ok %d - uc_mem_unmap success\n", log_num++); printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} _exit(-1);
test_num++; } else {
break; printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
case 0xf4: //hlt }
printf("# Handling HLT\n"); break;
if (uc_emu_stop(handle) != UC_ERR_OK) { default: //all others
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("# Handling OTHER\n");
_exit(-1); break;
} }
else {
printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
}
break;
default: //all others
printf("# Handling OTHER\n");
break;
}
} }
// callback for tracing memory access (READ or WRITE) // callback for tracing memory access (READ or WRITE)
static void hook_mem_write(uch handle, uc_mem_type type, static void hook_mem_write(uch handle, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data) uint64_t addr, int size, int64_t value, void *user_data)
{ {
printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); printf("# write to memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
} }
// callback for tracing invalid memory access (READ or WRITE) // callback for tracing invalid memory access (READ or WRITE)
static bool hook_mem_invalid(uch handle, uc_mem_type type, static bool hook_mem_invalid(uch handle, uc_mem_type type,
uint64_t addr, int size, int64_t value, void *user_data) uint64_t addr, int size, int64_t value, void *user_data)
{ {
uint32_t testval; uint32_t testval;
switch(type) { switch(type) {
default: default:
printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr); printf("not ok %d - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
return false; return false;
case UC_MEM_WRITE: case UC_MEM_WRITE:
printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
if (uc_mem_read(handle, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) { if (uc_mem_read(handle, addr, (uint8_t*)&testval, sizeof(testval)) != UC_ERR_OK) {
printf("ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr); printf("ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr);
} } else {
else { printf("not ok %d - uc_mem_read success after unmap at test %d\n", log_num++, test_num - 1);
printf("not ok %d - uc_mem_read success after unmap at test %d\n", log_num++, test_num - 1); }
}
if (uc_mem_map(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) { if (uc_mem_map(handle, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) {
printf("not ok %d - uc_mem_map fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr); printf("not ok %d - uc_mem_map fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
} } else {
else { printf("ok %d - uc_mem_map success\n", log_num++);
printf("ok %d - uc_mem_map success\n", log_num++); }
} return true;
return true; }
}
} }
int main(int argc, char **argv, char **envp) int main(int argc, char **argv, char **envp)
{ {
uch handle, trace1, trace2; uch handle, trace1, trace2;
uc_err err; uc_err err;
uint32_t addr, testval; uint32_t addr, testval;
int32_t buf1[1024], buf2[1024], readbuf[1024]; int32_t buf1[1024], buf2[1024], readbuf[1024];
int i; int i;
//don't really care about quality of randomness //don't really care about quality of randomness
srand(time(NULL)); srand(time(NULL));
for (i = 0; i < 1024; i++) { for (i = 0; i < 1024; i++) {
buf1[i] = rand(); buf1[i] = rand();
buf2[i] = rand(); buf2[i] = rand();
} }
printf("# Memory unmapping test\n"); printf("# Memory unmapping test\n");
// Initialize emulator in X86-32bit mode // Initialize emulator in X86-32bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
if (err) { if (err) {
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err); printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1; return 1;
} } else {
else { printf("ok %d - uc_open() success\n", log_num++);
printf("ok %d - uc_open() success\n", log_num++); }
}
uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);
// fill in sections that shouldn't get touched // fill in sections that shouldn't get touched
if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) { if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) {
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
return 2; return 2;
} } else {
else { printf("ok %d - Random buffer 1 written to memory\n", log_num++);
printf("ok %d - Random buffer 1 written to memory\n", log_num++); }
}
if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) { if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) {
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
return 3; return 3;
} } else {
else { printf("ok %d - Random buffer 2 written to memory\n", log_num++);
printf("ok %d - Random buffer 2 written to memory\n", log_num++); }
}
// write machine code to be emulated to memory // write machine code to be emulated to memory
if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
return 4; return 4;
} } else {
else { printf("ok %d - Program written to memory\n", log_num++);
printf("ok %d - Program written to memory\n", log_num++); }
}
if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) { if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++);
return 5; return 5;
} } else {
else { printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
printf("ok %d - UC_HOOK_CODE installed\n", log_num++); }
}
// intercept memory write events // intercept memory write events
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) { if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++);
return 6; return 6;
} } else {
else { printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++); }
}
// intercept invalid memory events // intercept invalid memory events
if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) { if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++); printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++);
return 7; return 7;
} } else {
else { printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++); }
}
// emulate machine code until told to stop by hook_code // emulate machine code until told to stop by hook_code
printf("# BEGIN execution\n"); printf("# BEGIN execution\n");
err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
if (err != UC_ERR_OK) { if (err != UC_ERR_OK) {
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
return 8; return 8;
} } else {
else { printf("ok %d - uc_emu_start complete\n", log_num++);
printf("ok %d - uc_emu_start complete\n", log_num++); }
} printf("# END execution\n");
printf("# END execution\n");
//read from the remapped memory //read from the remapped memory
testval = 0x42424242; testval = 0x42424242;
for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) { for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
uint32_t val; uint32_t val;
if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) { if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) {
printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr); printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr);
} } else {
else { printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr);
printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr); }
} if (val != testval) {
if (val != testval) { printf("not ok %d - Read 0x%x, expected 0x%x\n", log_num++, val, testval);
printf("not ok %d - Read 0x%x, expected 0x%x\n", log_num++, val, testval); } else {
} printf("ok %d - Correct value retrieved\n", log_num++);
else { }
printf("ok %d - Correct value retrieved\n", log_num++); testval += 0x02020202;
} }
testval += 0x02020202;
}
//make sure that random blocks didn't get nuked //make sure that random blocks didn't get nuked
// fill in sections that shouldn't get touched // fill in sections that shouldn't get touched
if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) { if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) {
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
} } else {
else { printf("ok %d - Random buffer 1 read from memory\n", log_num++);
printf("ok %d - Random buffer 1 read from memory\n", log_num++); if (memcmp(buf1, readbuf, 4096)) {
if (memcmp(buf1, readbuf, 4096)) { printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++); } else {
} printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
else { }
printf("ok %d - Random buffer 1 contents are correct\n", log_num++); }
}
}
if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) { if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) {
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
} } else {
else { printf("ok %d - Random buffer 2 read from memory\n", log_num++);
printf("ok %d - Random buffer 2 read from memory\n", log_num++); if (memcmp(buf2, readbuf, 4096)) {
if (memcmp(buf2, readbuf, 4096)) { printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++);
printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++); } else {
} printf("ok %d - Random buffer 2 contents are correct\n", log_num++);
else { }
printf("ok %d - Random buffer 2 contents are correct\n", log_num++); }
}
}
if (uc_close(&handle) == UC_ERR_OK) { if (uc_close(&handle) == UC_ERR_OK) {
printf("ok %d - uc_close complete\n", log_num++); printf("ok %d - uc_close complete\n", log_num++);
} } else {
else { printf("not ok %d - uc_close complete\n", log_num++);
printf("not ok %d - uc_close complete\n", log_num++); }
}
return 0; return 0;
} }

17
uc.c
View file

@ -670,14 +670,14 @@ static uint8_t *copy_region(uch handle, MemoryRegion *mr)
} }
/* /*
Split the given MemoryRegion at the indicated address for the indicated size Split the given MemoryRegion at the indicated address for the indicated size
this may result in the create of up to 3 spanning sections. If the delete this may result in the create of up to 3 spanning sections. If the delete
parameter is true, the no new section will be created to replace the indicate parameter is true, the no new section will be created to replace the indicate
range. This functions exists to support uc_mem_protect and uc_mem_unmap. range. This functions exists to support uc_mem_protect and uc_mem_unmap.
This is a static function and callers have already done some preliminary This is a static function and callers have already done some preliminary
parameter validation. parameter validation.
*/ */
//TODO: investigate whether qemu region manipulation functions already offer this capability //TODO: investigate whether qemu region manipulation functions already offer this capability
static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, size_t size, bool do_delete) static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, size_t size, bool do_delete)
{ {
@ -860,8 +860,7 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size)
break; break;
} }
} }
} } else {
else {
//ouch, we are going to need to subdivide blocks //ouch, we are going to need to subdivide blocks
size_t count = 0, len; size_t count = 0, len;
while(count < size) { while(count < size) {