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

@ -77,7 +77,7 @@ static inline void uc_common_init(struct uc_struct* uc)
uc->readonly_mem = memory_region_set_readonly; uc->readonly_mem = memory_region_set_readonly;
uc->target_page_size = TARGET_PAGE_SIZE; uc->target_page_size = TARGET_PAGE_SIZE;
uc->target_page_align = TARGET_PAGE_SIZE - 1; uc->target_page_align = TARGET_PAGE_SIZE - 1;
if (!uc->release) if (!uc->release)
uc->release = release_common; uc->release = release_common;

View file

@ -160,7 +160,7 @@ int main(int argc, char **argv, char **envp)
uint32_t eax = 0x40002C; uint32_t eax = 0x40002C;
uc_reg_write(handle, UC_X86_REG_EAX, &eax); uc_reg_write(handle, UC_X86_REG_EAX, &eax);
//resume execution at the mov dword [eax], 0x87654321 //resume execution at the mov dword [eax], 0x87654321
//to test an aligned write as well //to test an aligned write as well
err = uc_emu_start(handle, 0x400015, 0x400000 + sizeof(PROGRAM), 0, 2); err = uc_emu_start(handle, 0x400015, 0x400000 + sizeof(PROGRAM), 0, 2);
if (err) { if (err) {
printf("Expected failure on uc_emu_start() with error returned %u: %s\n", printf("Expected failure on uc_emu_start() with error returned %u: %s\n",

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
srand(time(NULL));
for (i = 0; i < 1024; i++) {
buf1[i] = rand();
buf2[i] = rand();
}
printf("# Memory protect test\n"); //don't really care about quality of randomness
srand(time(NULL));
for (i = 0; i < 1024; i++) {
buf1[i] = rand();
buf2[i] = rand();
}
// Initialize emulator in X86-32bit mode printf("# Memory protect test\n");
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
if (err) {
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1;
}
else {
printf("ok %d - uc_open() success\n", log_num++);
}
uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC); // Initialize emulator in X86-32bit mode
uc_mem_map(handle, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE); err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
uc_mem_map(handle, 0x300000, 0x2000, UC_PROT_READ); if (err) {
uc_mem_map(handle, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1;
} else {
printf("ok %d - uc_open() success\n", log_num++);
}
esp = 0xf00000 + 0x1000; 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, 0x300000, 0x2000, UC_PROT_READ);
uc_mem_map(handle, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
// Setup stack pointer esp = 0xf00000 + 0x1000;
if (uc_reg_write(handle, UC_X86_REG_ESP, &esp)) {
printf("not ok %d - Failed to set esp. quit!\n", log_num++);
return 2;
}
else {
printf("ok %d - ESP set\n", log_num++);
}
// fill in sections that shouldn't get touched // Setup stack pointer
if (uc_mem_write(handle, 0x1ff000, (uint8_t*)buf1, 4096)) { if (uc_reg_write(handle, UC_X86_REG_ESP, &esp)) {
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); printf("not ok %d - Failed to set esp. quit!\n", log_num++);
return 3; return 2;
} } else {
else { printf("ok %d - ESP set\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)) { // fill in sections that shouldn't get touched
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); if (uc_mem_write(handle, 0x1ff000, (uint8_t*)buf1, 4096)) {
return 4; printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
} return 3;
else { } else {
printf("ok %d - Random buffer 2 written to memory\n", log_num++); printf("ok %d - Random buffer 1 written to memory\n", log_num++);
} }
// write machine code to be emulated to memory if (uc_mem_write(handle, 0x301000, (uint8_t*)buf2, 4096)) {
if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) { printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); return 4;
return 5; } else {
} printf("ok %d - Random buffer 2 written to memory\n", log_num++);
else { }
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) { // write machine code to be emulated to memory
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) {
return 6; printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
} return 5;
else { } else {
printf("ok %d - UC_HOOK_CODE installed\n", log_num++); printf("ok %d - Program written to memory\n", log_num++);
} }
// intercept memory write events if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != 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_CODE handler\n", log_num++);
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 6;
return 7; } else {
} printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
else { }
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
}
// intercept invalid memory events // intercept memory write 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_WRITE, hook_mem_write, 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_WRITE handler\n", log_num++);
return 8; return 7;
} } else {
else { printf("ok %d - UC_HOOK_MEM_WRITE 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 // intercept invalid memory events
printf("# BEGIN execution\n"); if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
err = uc_emu_start(handle, 0x100000, 0x400000, 0, 0); printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++);
if (err != UC_ERR_OK) { return 8;
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); } else {
return 9; printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
} }
else {
printf("ok %d - uc_emu_start complete\n", log_num++);
}
printf("# END execution\n");
// get ending EIP // emulate machine code until told to stop by hook_code
if (uc_reg_read(handle, UC_X86_REG_EIP, &eip)) { printf("# BEGIN execution\n");
printf("not ok %d - Failed to read eip.\n", log_num++); err = uc_emu_start(handle, 0x100000, 0x400000, 0, 0);
} if (err != UC_ERR_OK) {
else { printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
printf("ok %d - Ending EIP 0x%x\n", log_num++, eip); return 9;
} } else {
printf("ok %d - uc_emu_start complete\n", log_num++);
}
printf("# END execution\n");
//make sure that random blocks didn't get nuked // get ending EIP
// fill in sections that shouldn't get touched if (uc_reg_read(handle, UC_X86_REG_EIP, &eip)) {
if (uc_mem_read(handle, 0x1ff000, (uint8_t*)readbuf, 4096)) { printf("not ok %d - Failed to read eip.\n", log_num++);
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); } else {
} printf("ok %d - Ending EIP 0x%x\n", log_num++, eip);
else { }
printf("ok %d - Random buffer 1 read from memory\n", log_num++);
if (memcmp(buf1, readbuf, 4096)) {
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++);
}
}
if (uc_mem_read(handle, 0x301000, (uint8_t*)readbuf, 4096)) { //make sure that random blocks didn't get nuked
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); // fill in sections that shouldn't get touched
} if (uc_mem_read(handle, 0x1ff000, (uint8_t*)readbuf, 4096)) {
else { printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
printf("ok %d - Random buffer 2 read from memory\n", log_num++); } else {
if (memcmp(buf2, readbuf, 4096)) { printf("ok %d - Random buffer 1 read from memory\n", log_num++);
printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++); if (memcmp(buf1, readbuf, 4096)) {
} printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
else { } else {
printf("ok %d - Random buffer 2 contents are correct\n", log_num++); printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
} }
} }
if (uc_close(&handle) == UC_ERR_OK) { if (uc_mem_read(handle, 0x301000, (uint8_t*)readbuf, 4096)) {
printf("ok %d - uc_close complete\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("not ok %d - uc_close complete\n", log_num++); if (memcmp(buf2, readbuf, 4096)) {
} 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++);
}
}
return 0; if (uc_close(&handle) == UC_ERR_OK) {
printf("ok %d - uc_close complete\n", log_num++);
} else {
printf("not ok %d - uc_close complete\n", log_num++);
}
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
srand(time(NULL));
for (i = 0; i < 1024; i++) {
buf1[i] = rand();
buf2[i] = rand();
}
printf("# Memory protect test\n"); //don't really care about quality of randomness
srand(time(NULL));
for (i = 0; i < 1024; i++) {
buf1[i] = rand();
buf2[i] = rand();
}
// Initialize emulator in X86-32bit mode printf("# Memory protect test\n");
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
if (err) {
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1;
}
else {
printf("ok %d - uc_open() success\n", log_num++);
}
uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); // Initialize emulator in X86-32bit mode
uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); if (err) {
uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1;
} else {
printf("ok %d - uc_open() success\n", log_num++);
}
// fill in sections that shouldn't get touched uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) { uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
return 2; uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);
}
else {
printf("ok %d - Random buffer 1 written to memory\n", log_num++);
}
if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) { // fill in sections that shouldn't get touched
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) {
return 3; printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
} return 2;
else { } else {
printf("ok %d - Random buffer 2 written to memory\n", log_num++); printf("ok %d - Random buffer 1 written to memory\n", log_num++);
} }
// write machine code to be emulated to memory if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) {
if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); return 3;
return 4; } else {
} printf("ok %d - Random buffer 2 written to memory\n", log_num++);
else { }
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) { // write machine code to be emulated to memory
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
return 5; printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
} return 4;
else { } else {
printf("ok %d - UC_HOOK_CODE installed\n", log_num++); printf("ok %d - Program written to memory\n", log_num++);
} }
// intercept memory write events if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != 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_CODE handler\n", log_num++);
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 5;
return 6; } else {
} printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
else { }
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
}
// intercept invalid memory events // intercept memory write 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_WRITE, hook_mem_write, 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_WRITE handler\n", log_num++);
return 7; return 6;
} } else {
else { printf("ok %d - UC_HOOK_MEM_WRITE 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 // intercept invalid memory events
printf("# BEGIN execution\n"); if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++);
if (err != UC_ERR_OK) { return 7;
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); } else {
return 8; printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
} }
else {
printf("ok %d - uc_emu_start complete\n", log_num++);
}
printf("# END execution\n");
//read from the remapped memory // emulate machine code until told to stop by hook_code
testval = 0x42424242; printf("# BEGIN execution\n");
for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) { err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
uint32_t val; if (err != UC_ERR_OK) {
if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != 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 - Failed uc_mem_read for address 0x%x\n", log_num++, addr); return 8;
} } else {
else { printf("ok %d - uc_emu_start complete\n", log_num++);
printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr); }
} printf("# END execution\n");
if (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++);
}
testval += 0x02020202;
}
//account for the two mods made by the machine code //read from the remapped memory
buf1[512] = 0x47474747; testval = 0x42424242;
buf2[512] = 0x48484848; for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
uint32_t val;
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);
} else {
printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr);
}
if (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++);
}
testval += 0x02020202;
}
//make sure that random blocks didn't get nuked //account for the two mods made by the machine code
// fill in sections that shouldn't get touched buf1[512] = 0x47474747;
if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) { buf2[512] = 0x48484848;
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
}
else {
printf("ok %d - Random buffer 1 read from memory\n", log_num++);
if (memcmp(buf1, readbuf, 4096)) {
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++);
}
}
if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) { //make sure that random blocks didn't get nuked
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); // fill in sections that shouldn't get touched
} if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) {
else { printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
printf("ok %d - Random buffer 2 read from memory\n", log_num++); } else {
if (memcmp(buf2, readbuf, 4096)) { printf("ok %d - Random buffer 1 read from memory\n", log_num++);
printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++); if (memcmp(buf1, readbuf, 4096)) {
} printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
else { } else {
printf("ok %d - Random buffer 2 contents are correct\n", log_num++); printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
} }
} }
if (uc_close(&handle) == UC_ERR_OK) { if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) {
printf("ok %d - uc_close complete\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("not ok %d - uc_close complete\n", log_num++); if (memcmp(buf2, readbuf, 4096)) {
} 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++);
}
}
return 0; if (uc_close(&handle) == UC_ERR_OK) {
printf("ok %d - uc_close complete\n", log_num++);
} else {
printf("not ok %d - uc_close complete\n", log_num++);
}
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
srand(time(NULL));
for (i = 0; i < 1024; i++) {
buf1[i] = rand();
buf2[i] = rand();
}
printf("# Memory unmapping test\n"); //don't really care about quality of randomness
srand(time(NULL));
for (i = 0; i < 1024; i++) {
buf1[i] = rand();
buf2[i] = rand();
}
// Initialize emulator in X86-32bit mode printf("# Memory unmapping test\n");
err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
if (err) {
printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1;
}
else {
printf("ok %d - uc_open() success\n", log_num++);
}
uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC); // Initialize emulator in X86-32bit mode
uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle);
uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); if (err) {
uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE); printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
return 1;
} else {
printf("ok %d - uc_open() success\n", log_num++);
}
// fill in sections that shouldn't get touched uc_mem_map(handle, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) { uc_mem_map(handle, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++); uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
return 2; uc_mem_map(handle, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);
}
else {
printf("ok %d - Random buffer 1 written to memory\n", log_num++);
}
if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) { // fill in sections that shouldn't get touched
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++); if (uc_mem_write(handle, 0x3ff000, (uint8_t*)buf1, 4096)) {
return 3; printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
} return 2;
else { } else {
printf("ok %d - Random buffer 2 written to memory\n", log_num++); printf("ok %d - Random buffer 1 written to memory\n", log_num++);
} }
// write machine code to be emulated to memory if (uc_mem_write(handle, 0x401000, (uint8_t*)buf2, 4096)) {
if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) { printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++); return 3;
return 4; } else {
} printf("ok %d - Random buffer 2 written to memory\n", log_num++);
else { }
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) { // write machine code to be emulated to memory
printf("not ok %d - Failed to install UC_HOOK_CODE handler\n", log_num++); if (uc_mem_write(handle, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
return 5; printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
} return 4;
else { } else {
printf("ok %d - UC_HOOK_CODE installed\n", log_num++); printf("ok %d - Program written to memory\n", log_num++);
} }
// intercept memory write events if (uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != 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_CODE handler\n", log_num++);
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE handler\n", log_num++); return 5;
return 6; } else {
} printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
else { }
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
}
// intercept invalid memory events // intercept memory write 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_WRITE, hook_mem_write, 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_WRITE handler\n", log_num++);
return 7; return 6;
} } else {
else { printf("ok %d - UC_HOOK_MEM_WRITE 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 // intercept invalid memory events
printf("# BEGIN execution\n"); if (uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL) != UC_ERR_OK) {
err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0); printf("not ok %d - Failed to install UC_HOOK_MEM_INVALID handler\n", log_num++);
if (err != UC_ERR_OK) { return 7;
printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err)); } else {
return 8; printf("ok %d - UC_HOOK_MEM_INVALID installed\n", log_num++);
} }
else {
printf("ok %d - uc_emu_start complete\n", log_num++);
}
printf("# END execution\n");
//read from the remapped memory // emulate machine code until told to stop by hook_code
testval = 0x42424242; printf("# BEGIN execution\n");
for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) { err = uc_emu_start(handle, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
uint32_t val; if (err != UC_ERR_OK) {
if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != 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 - Failed uc_mem_read for address 0x%x\n", log_num++, addr); return 8;
} } else {
else { printf("ok %d - uc_emu_start complete\n", log_num++);
printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr); }
} printf("# END execution\n");
if (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++);
}
testval += 0x02020202;
}
//make sure that random blocks didn't get nuked //read from the remapped memory
// fill in sections that shouldn't get touched testval = 0x42424242;
if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) { for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++); uint32_t val;
} if (uc_mem_read(handle, addr, (uint8_t*)&val, sizeof(val)) != UC_ERR_OK) {
else { printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr);
printf("ok %d - Random buffer 1 read from memory\n", log_num++); } else {
if (memcmp(buf1, readbuf, 4096)) { printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr);
printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++); }
} if (val != testval) {
else { printf("not ok %d - Read 0x%x, expected 0x%x\n", log_num++, val, testval);
printf("ok %d - Random buffer 1 contents are correct\n", log_num++); } else {
} printf("ok %d - Correct value retrieved\n", log_num++);
} }
testval += 0x02020202;
}
if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) { //make sure that random blocks didn't get nuked
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++); // fill in sections that shouldn't get touched
} if (uc_mem_read(handle, 0x3ff000, (uint8_t*)readbuf, 4096)) {
else { printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
printf("ok %d - Random buffer 2 read from memory\n", log_num++); } else {
if (memcmp(buf2, readbuf, 4096)) { printf("ok %d - Random buffer 1 read from memory\n", log_num++);
printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++); if (memcmp(buf1, readbuf, 4096)) {
} printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
else { } else {
printf("ok %d - Random buffer 2 contents are correct\n", log_num++); printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
} }
} }
if (uc_close(&handle) == UC_ERR_OK) { if (uc_mem_read(handle, 0x401000, (uint8_t*)readbuf, 4096)) {
printf("ok %d - uc_close complete\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("not ok %d - uc_close complete\n", log_num++); if (memcmp(buf2, readbuf, 4096)) {
} 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++);
}
}
return 0; if (uc_close(&handle) == UC_ERR_OK) {
printf("ok %d - uc_close complete\n", log_num++);
} else {
printf("not ok %d - uc_close complete\n", log_num++);
}
return 0;
} }

21
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)
{ {
@ -709,7 +709,7 @@ static bool split_region(uch handle, MemoryRegion *mr, uint64_t address, size_t
perms = mr->perms; perms = mr->perms;
begin = mr->addr; begin = mr->addr;
end = mr->end; end = mr->end;
if (uc_mem_unmap(handle, mr->addr, int128_get64(mr->size)) != UC_ERR_OK) if (uc_mem_unmap(handle, mr->addr, int128_get64(mr->size)) != UC_ERR_OK)
goto error; goto error;
@ -784,7 +784,7 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms)
// check for only valid permissions // check for only valid permissions
if ((perms & ~UC_PROT_ALL) != 0) if ((perms & ~UC_PROT_ALL) != 0)
return UC_ERR_INVAL; return UC_ERR_INVAL;
//check that user's entire requested block is mapped //check that user's entire requested block is mapped
if (!check_mem_area(uc, address, size)) if (!check_mem_area(uc, address, size))
return UC_ERR_NOMEM; return UC_ERR_NOMEM;
@ -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) {