import Unicorn2
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from unicorn import *
|
||||
from unicorn.arm_const import *
|
||||
|
||||
import regress
|
||||
|
||||
class APSRAccess(regress.RegressTest):
|
||||
|
||||
def runTest(self):
|
||||
code = (
|
||||
b'\x00\x00\xa0\xe1' + # 0: mov r0, r0
|
||||
b'\x08\x10\x9f\xe5' + # 4: ldr r1, [pc, #8]
|
||||
b'\x01\xf0\x28\xe1' + # 8: 01 f0 28 e1 msr apsr_nzcvq, r1
|
||||
b'\x00\x00\xa0\xe1' + # c: mov r0, r0
|
||||
b'\x00\x00\xa0\xe1' + # 10: mov r0, r0
|
||||
b'\x00\x00\x00\xff') # 14: data for inst @4
|
||||
|
||||
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
|
||||
uc.mem_map(0x1000, 0x1000)
|
||||
uc.mem_write(0x1000, code) # bxeq lr; mov r0, r0
|
||||
|
||||
uc.reg_write(UC_ARM_REG_APSR, 0)
|
||||
uc.emu_start(0x1000, 0x100c)
|
||||
|
||||
self.assertEqual(uc.reg_read(UC_ARM_REG_APSR), 0xf8000000)
|
||||
self.assertEqual(uc.reg_read(UC_ARM_REG_APSR_NZCV), 0xf0000000)
|
||||
|
||||
if __name__ == '__main__':
|
||||
regress.main()
|
||||
52
tests/regress/arm_memcpy_neon.py
Normal file
52
tests/regress/arm_memcpy_neon.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from unicorn import *
|
||||
from unicorn.arm_const import *
|
||||
|
||||
# .text:0001F894 ADD PC, PC, R3
|
||||
# .text:0001F898 ; ---------------------------------------------------------------------------
|
||||
# .text:0001F898 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F89C VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8A0 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F8A4 VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8A8 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F8AC VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8B0 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F8B4 VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8B8 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F8BC VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8C0 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F8C4 VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8C8 VLD1.8 {D0}, [R1]!
|
||||
# .text:0001F8CC VST1.8 {D0}, [R12]!
|
||||
# .text:0001F8D0 TST R2, #4
|
||||
# .text:0001F8D4 LDRNE R3, [R1],#4
|
||||
# .text:0001F8D8 STRNE R3, [R12],#4
|
||||
# .text:0001F8DC MOVS R2, R2,LSL#31
|
||||
# .text:0001F8E0 LDRHCS R3, [R1],#2
|
||||
# .text:0001F8E4 LDRBNE R1, [R1]
|
||||
# .text:0001F8E8 STRHCS R3, [R12],#2
|
||||
# .text:0001F8EC STRBNE R1, [R12]
|
||||
shellcode = [0x3, 0xf0, 0x8f, 0xe0, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0x4, 0x0, 0x12, 0xe3, 0x4, 0x30, 0x91, 0x14, 0x4, 0x30, 0x8c, 0x14, 0x82, 0x2f, 0xb0, 0xe1, 0xb2, 0x30, 0xd1, 0x20, 0x0, 0x10, 0xd1, 0x15, 0xb2, 0x30, 0xcc, 0x20, 0x0, 0x10, 0xcc, 0x15]
|
||||
base = 0x1F894
|
||||
from_address = 0x1000
|
||||
to_address = 0x2000
|
||||
cplen = 8
|
||||
bs = b"c8"*cplen
|
||||
|
||||
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
|
||||
uc.mem_map(from_address, 0x1000)
|
||||
uc.mem_map(to_address, 0x1000)
|
||||
uc.mem_map(0x1F000, 0x1000)
|
||||
uc.mem_write(from_address, bs)
|
||||
uc.mem_write(base, bytes(shellcode))
|
||||
uc.reg_write(UC_ARM_REG_R12, to_address)
|
||||
uc.reg_write(UC_ARM_REG_R1, from_address)
|
||||
uc.reg_write(UC_ARM_REG_R2, cplen)
|
||||
uc.reg_write(UC_ARM_REG_R3, 0x24)
|
||||
# enable_vfp
|
||||
uc.reg_write(UC_ARM_REG_C1_C0_2, uc.reg_read(UC_ARM_REG_C1_C0_2) | (0xf << 20))
|
||||
uc.reg_write(UC_ARM_REG_FPEXC, 0x40000000)
|
||||
|
||||
uc.emu_start(base, base+len(shellcode))
|
||||
fr = uc.mem_read(from_address, len(bs))
|
||||
to = uc.mem_read(to_address, len(bs))
|
||||
print(f"memcpy result:\nfrom: {bytes(fr)}\nto: {bytes(to)}")
|
||||
15
tests/regress/arm_wfi_first_insn_of_tb.py
Normal file
15
tests/regress/arm_wfi_first_insn_of_tb.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from unicorn import *
|
||||
from unicorn.arm_const import *
|
||||
|
||||
# ADD R0, R10, R0;
|
||||
# B L0;
|
||||
# L0:
|
||||
# ADD R0, R10, R0; <--- we stop at here, the first instruction of the next TB.
|
||||
|
||||
code = b'\x00\x00\x8a\xe0\xff\xff\xff\xea\x00\x00\x8a\xe0'
|
||||
address = 0x1000
|
||||
|
||||
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
|
||||
mu.mem_map(address, 0x1000)
|
||||
mu.mem_write(address, code)
|
||||
mu.emu_start(address, address + len(code) - 4)
|
||||
@@ -1,39 +0,0 @@
|
||||
import regress
|
||||
from unicorn import Uc, UC_ARCH_X86, UC_MODE_64, UC_HOOK_CODE
|
||||
|
||||
CODE = b"\x90" * 3
|
||||
CODE_ADDR = 0x1000
|
||||
|
||||
|
||||
class HookCounter(object):
|
||||
"""Counts number of hook calls."""
|
||||
|
||||
def __init__(self):
|
||||
self.hook_calls = 0
|
||||
|
||||
def bad_code_hook(self, uc, address, size, data):
|
||||
self.hook_calls += 1
|
||||
raise ValueError("Something went wrong")
|
||||
|
||||
def good_code_hook(self, uc, address, size, data):
|
||||
self.hook_calls += 1
|
||||
|
||||
|
||||
class TestExceptionInHook(regress.RegressTest):
|
||||
|
||||
def test_exception_in_hook(self):
|
||||
uc = Uc(UC_ARCH_X86, UC_MODE_64)
|
||||
uc.mem_map(CODE_ADDR, 0x1000)
|
||||
uc.mem_write(CODE_ADDR, CODE)
|
||||
|
||||
counter = HookCounter()
|
||||
uc.hook_add(UC_HOOK_CODE, counter.bad_code_hook, begin=CODE_ADDR, end=CODE_ADDR + len(CODE))
|
||||
uc.hook_add(UC_HOOK_CODE, counter.good_code_hook, begin=CODE_ADDR, end=CODE_ADDR + len(CODE))
|
||||
|
||||
self.assertRaises(ValueError, uc.emu_start, CODE_ADDR, CODE_ADDR + len(CODE))
|
||||
# Make sure hooks calls finish before raising (hook_calls == 2)
|
||||
self.assertEqual(counter.hook_calls, 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
regress.main()
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
uint64_t starts[] = {0x10000000, 0x110004000ll};
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
int i;
|
||||
// Initialize emulator in X86-64bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < (sizeof(starts) / sizeof(uint64_t)); i++) {
|
||||
uc_mem_map(uc, starts[i], 4096, UC_PROT_ALL);
|
||||
}
|
||||
|
||||
uint32_t count;
|
||||
uc_mem_region *regions;
|
||||
int err_count = 0;
|
||||
err = uc_mem_regions(uc, ®ions, &count);
|
||||
if (err == UC_ERR_OK) {
|
||||
for (i = 0; i < count; i++) {
|
||||
fprintf(stderr, "region %d: 0x%"PRIx64"-0x%"PRIx64" (%d)\n", i, regions[i].begin, regions[i].end - 1, regions[i].perms);
|
||||
if (regions[i].begin != starts[i]) {
|
||||
err_count++;
|
||||
fprintf(stderr, " ERROR: region start does not match requested start address, expected 0x%"PRIx64", found 0x%"PRIx64"\n",
|
||||
starts[i], regions[i].begin);
|
||||
}
|
||||
}
|
||||
uc_free(regions);
|
||||
}
|
||||
|
||||
uc_close(uc);
|
||||
return err_count;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("not ok - Failed on uc_open() with error returned: %u\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL);
|
||||
if (err) {
|
||||
printf("not ok - Failed on uc_mem_map() with error returned: %u\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uc_mem_map(uc, 0x4000, 0x1000, UC_PROT_ALL);
|
||||
if (err) {
|
||||
printf("not ok - Failed on uc_mem_map() with error returned: %u\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = uc_mem_unmap(uc, 0x4000, 0x1000);
|
||||
if (err) {
|
||||
printf("not ok - Failed on uc_mem_unmap() with error returned: %u\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = uc_mem_unmap(uc, 0x4000, 0x1000);
|
||||
if (!err) {
|
||||
printf("not ok - second unmap succeeded\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Tests OK\n");
|
||||
uc_close(uc);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
Executable memory regions demo / unit test
|
||||
|
||||
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 distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
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
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
unsigned char PROGRAM[] =
|
||||
"\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\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"
|
||||
"\xe7\x00\xf0\xff\xff\xff\xe7\xe8\xb6\xff\xff\xff";
|
||||
// total size: 76 bytes
|
||||
|
||||
/*
|
||||
bits 32
|
||||
|
||||
; assumes r-x section at 0x100000
|
||||
; assumes rw- section at 0x200000
|
||||
; assumes r-- section at 0x300000
|
||||
; also needs an initialized stack
|
||||
|
||||
start:
|
||||
jmp bottom
|
||||
top:
|
||||
pop esi
|
||||
and esi, ~0xfff
|
||||
times 30 inc eax
|
||||
mov edi, esi
|
||||
add edi, 0x100000
|
||||
mov ecx, end - start
|
||||
rep movsb
|
||||
and edi, ~0xfff
|
||||
cmp edi, 0x400000
|
||||
jnz next_block
|
||||
hlt
|
||||
next_block:
|
||||
jmp edi
|
||||
bottom:
|
||||
call top
|
||||
end:
|
||||
*/
|
||||
|
||||
int test_num = 0;
|
||||
uint32_t tests[] = {
|
||||
0x41414141,
|
||||
0x43434343,
|
||||
0x45454545
|
||||
};
|
||||
|
||||
static int log_num = 1;
|
||||
|
||||
#define CODE_SECTION 0x100000
|
||||
#define CODE_SIZE 0x1000
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
||||
if (uc_mem_read(uc, 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("# Handling HLT\n");
|
||||
if (uc_emu_stop(uc) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
_exit(-1);
|
||||
} 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)
|
||||
static void hook_mem_write(uc_engine *uc, uc_mem_type type,
|
||||
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);
|
||||
}
|
||||
|
||||
// callback for tracing invalid memory access (READ or WRITE)
|
||||
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
||||
uint64_t addr, int size, int64_t value, void *user_data)
|
||||
{
|
||||
switch(type) {
|
||||
default:
|
||||
printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
||||
return false;
|
||||
case UC_MEM_FETCH_PROT:
|
||||
printf("# Fetch from non-executable memory at 0x%"PRIx64 "\n", addr);
|
||||
|
||||
//make page executable
|
||||
if (uc_mem_protect(uc, 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);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_protect success at 0x%" PRIx64 "\n", log_num++, addr);
|
||||
}
|
||||
return true;
|
||||
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);
|
||||
|
||||
if (uc_mem_protect(uc, 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);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_protect success\n", log_num++);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_hook trace1, trace2;
|
||||
uc_err err;
|
||||
uint32_t esp, eip;
|
||||
int32_t buf1[1024], buf2[1024], readbuf[1024];
|
||||
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");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
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(uc, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC);
|
||||
uc_mem_map(uc, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x300000, 0x2000, UC_PROT_READ);
|
||||
uc_mem_map(uc, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
|
||||
esp = 0xf00000 + 0x1000;
|
||||
|
||||
// Setup stack pointer
|
||||
if (uc_reg_write(uc, 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
|
||||
if (uc_mem_write(uc, 0x1ff000, buf1, sizeof(buf1))) {
|
||||
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
|
||||
return 3;
|
||||
} else {
|
||||
printf("ok %d - Random buffer 1 written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_mem_write(uc, 0x301000, buf2, sizeof(buf2))) {
|
||||
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
|
||||
return 4;
|
||||
} else {
|
||||
printf("ok %d - Random buffer 2 written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(uc, 0x100000, PROGRAM, sizeof(PROGRAM))) {
|
||||
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
|
||||
return 5;
|
||||
} else {
|
||||
printf("ok %d - Program written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++);
|
||||
return 6;
|
||||
} else {
|
||||
printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
|
||||
}
|
||||
|
||||
// intercept memory write events
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++);
|
||||
return 7;
|
||||
} else {
|
||||
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
|
||||
}
|
||||
|
||||
// intercept invalid memory events
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
|
||||
return 8;
|
||||
} else {
|
||||
printf("ok %d - memory invalid handler installed\n", log_num++);
|
||||
}
|
||||
|
||||
// emulate machine code until told to stop by hook_code
|
||||
printf("# BEGIN execution\n");
|
||||
err = uc_emu_start(uc, 0x100000, 0x400000, 0, 0);
|
||||
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));
|
||||
return 9;
|
||||
} else {
|
||||
printf("ok %d - uc_emu_start complete\n", log_num++);
|
||||
}
|
||||
printf("# END execution\n");
|
||||
|
||||
// get ending EIP
|
||||
if (uc_reg_read(uc, UC_X86_REG_EIP, &eip)) {
|
||||
printf("not ok %d - Failed to read eip.\n", log_num++);
|
||||
} else {
|
||||
printf("ok %d - Ending EIP 0x%x\n", log_num++, eip);
|
||||
}
|
||||
|
||||
//make sure that random blocks didn't get nuked
|
||||
// fill in sections that shouldn't get touched
|
||||
if (uc_mem_read(uc, 0x1ff000, readbuf, sizeof(readbuf))) {
|
||||
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(uc, 0x301000, readbuf, sizeof(readbuf))) {
|
||||
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
|
||||
} else {
|
||||
printf("ok %d - Random buffer 2 read from memory\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++);
|
||||
}
|
||||
}
|
||||
|
||||
if (uc_close(uc) == 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;
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
|
||||
uint64_t baseranges[] = {0,0,0,0};
|
||||
int step =0;
|
||||
|
||||
uint64_t urnd(){
|
||||
uint64_t rnd = rand();
|
||||
rnd = rnd << 32;
|
||||
rnd += rand();
|
||||
return rnd;
|
||||
}
|
||||
uint64_t get_addr(){
|
||||
uint64_t base = ((uint64_t)urnd())%4;
|
||||
uint64_t addr= baseranges[base] + urnd()%(4096*10);
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint64_t get_aligned_addr(){
|
||||
uint64_t addr = get_addr();
|
||||
return addr - (addr % 4096);
|
||||
}
|
||||
|
||||
uint64_t get_len(){
|
||||
uint64_t len = (urnd() % (4096*5))+1;
|
||||
return len;
|
||||
}
|
||||
|
||||
uint64_t get_aligned_len(){
|
||||
uint64_t len = get_len();
|
||||
len = len - (len %4096);
|
||||
len = ((len == 0) ? 4096 : len);
|
||||
return len;
|
||||
}
|
||||
|
||||
void perform_map_step(uc_engine *uc){
|
||||
uint64_t addr = get_aligned_addr();
|
||||
uint64_t len = get_aligned_len();
|
||||
printf("map(uc,0x%"PRIx64",0x%"PRIx64"); //%d\n", addr, len, step);
|
||||
uc_mem_map(uc, addr, len, UC_PROT_READ | UC_PROT_WRITE);
|
||||
}
|
||||
|
||||
void perform_unmap_step(uc_engine *uc){
|
||||
uint64_t addr = get_aligned_addr();
|
||||
uint64_t len = get_aligned_len();
|
||||
printf("unmap(uc,0x%"PRIx64",0x%"PRIx64"); //%d\n", addr, len, step);
|
||||
uc_mem_unmap(uc, addr, len);
|
||||
}
|
||||
|
||||
void perform_write_step(uc_engine *uc){
|
||||
char buff[4096*4];
|
||||
memset((void *)buff, 0, 4096*4);
|
||||
uint64_t addr = get_addr();
|
||||
uint64_t len = get_len()%(4096*3);
|
||||
printf("write(uc,0x%"PRIx64",0x%"PRIx64"); //%d\n", addr, len, step);
|
||||
uc_mem_write(uc, addr, buff, len);
|
||||
}
|
||||
|
||||
void perform_read_step(uc_engine *uc){
|
||||
char buff[4096*4];
|
||||
uint64_t addr = get_addr();
|
||||
uint64_t len = get_len()%(4096*4);
|
||||
printf("read(uc,0x%"PRIx64",0x%"PRIx64"); //%d\n", addr, len, step);
|
||||
uc_mem_read(uc, addr, buff, len);
|
||||
}
|
||||
|
||||
void perform_fuzz_step(uc_engine *uc){
|
||||
switch( ((uint32_t)rand())%4 ){
|
||||
case 0: perform_map_step(uc); break;
|
||||
case 1: perform_unmap_step(uc); break;
|
||||
case 2: perform_read_step(uc); break;
|
||||
case 3: perform_write_step(uc); break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
if(argc<2){
|
||||
printf("usage: mem_fuzz $seed\n");
|
||||
return 1;
|
||||
}
|
||||
int seed = atoi(argv[1]);
|
||||
int i = 0;
|
||||
|
||||
//don't really care about quality of randomness
|
||||
srand(seed);
|
||||
printf("running with seed %d\n",seed);
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i = 0; i < 2048; i++){
|
||||
step++;
|
||||
perform_fuzz_step(uc);
|
||||
}
|
||||
// fill in sections that shouldn't get touched
|
||||
|
||||
if (uc_close(uc) != UC_ERR_OK) {
|
||||
printf("Failed on uc_close\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#include <unicorn/unicorn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
uc_engine *u;
|
||||
uc_err err;
|
||||
|
||||
printf("mem_map_0x100000000.c \n");
|
||||
|
||||
if ((err = uc_open(UC_ARCH_X86, UC_MODE_32, &u)) != UC_ERR_OK) {
|
||||
printf("uc_open() failed: %s\n", uc_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = uc_mem_map(u, 0x100000000, 0x002c0000, UC_PROT_ALL)) != UC_ERR_OK) {
|
||||
printf("uc_mem_map() failed: %s\n", uc_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
if ((err = uc_mem_map(u, 0x0018D000, 0x00006000, UC_PROT_ALL)) != UC_ERR_OK) {
|
||||
printf("uc_mem_map() failed: %s\n", uc_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = uc_close(u)) != UC_ERR_OK) {
|
||||
printf("uc_close() failed: %s\n", uc_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Success.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <unicorn/unicorn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
uc_engine *u;
|
||||
uc_err err;
|
||||
if ((err = uc_open(UC_ARCH_X86, UC_MODE_32, &u)) != UC_ERR_OK) {
|
||||
printf("uc_open() failed: %s\n", uc_strerror(err));
|
||||
}
|
||||
printf("Trying large map.\n");
|
||||
if ((err = uc_mem_map(u, 0x60802000, (unsigned) 0x28bd211200004000, UC_PROT_ALL)) != UC_ERR_OK) {
|
||||
printf("uc_mem_map() failed: %s\n", uc_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
printf("Success.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
#define ADDRESS1 0x10000000
|
||||
#define ADDRESS2 0x20000000
|
||||
#define SIZE (80 * 1024 * 1024)
|
||||
|
||||
static void VM_exec()
|
||||
{
|
||||
int c;
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
|
||||
// Initialize emulator in X86-64bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if(err)
|
||||
{
|
||||
printf("Failed on uc_open() with error returned: %s\n", uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
repeat:
|
||||
err = uc_mem_map(uc, ADDRESS1, SIZE, UC_PROT_ALL);
|
||||
if(err != UC_ERR_OK)
|
||||
{
|
||||
printf("Failed to map memory %s\n", uc_strerror(err));
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = uc_mem_map(uc, ADDRESS2, SIZE, UC_PROT_ALL);
|
||||
if(err != UC_ERR_OK)
|
||||
{
|
||||
printf("Failed to map memory %s\n", uc_strerror(err));
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = uc_mem_unmap(uc, ADDRESS1, SIZE);
|
||||
if(err != UC_ERR_OK)
|
||||
{
|
||||
printf("Failed to unmap memory %s\n", uc_strerror(err));
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = uc_mem_unmap(uc, ADDRESS2, SIZE);
|
||||
if(err != UC_ERR_OK)
|
||||
{
|
||||
printf("Failed to unmap memory %s\n", uc_strerror(err));
|
||||
goto err;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
c = getchar(); //pause here and analyse memory usage before exiting with a program like VMMap;
|
||||
if(c != 'e')
|
||||
goto repeat;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
VM_exec();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
uc_mem_protect demo / unit test
|
||||
|
||||
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 distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
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
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
unsigned char PROGRAM[] =
|
||||
"\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"
|
||||
"\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"
|
||||
"\x05\x00\xf8\x3f\x00\x47\x47\x47\x47\xc7\x05\x00\x18\x40\x00\x48"
|
||||
"\x48\x48\x48\xf4";
|
||||
// total size: 84 bytes
|
||||
|
||||
/*
|
||||
bits 32
|
||||
|
||||
; assumes code section at 0x100000
|
||||
; assumes data section at 0x200000, initially rw
|
||||
; assumes data section at 0x300000, initially rw
|
||||
; assumes data section at 0x400000, initially rw
|
||||
|
||||
; with installed hooks unmaps or maps on each nop
|
||||
|
||||
mov dword [0x200000], 0x41414141
|
||||
nop ; mark it RO
|
||||
mov dword [0x200000], 0x42424242
|
||||
|
||||
mov dword [0x300000], 0x43434343
|
||||
nop ; mark it RO
|
||||
mov dword [0x300000], 0x44444444
|
||||
|
||||
mov dword [0x400000], 0x45454545
|
||||
nop ; mark it RO
|
||||
mov dword [0x400000], 0x46464646
|
||||
mov dword [0x3ff800], 0x47474747 ; make sure surrounding areas remained RW
|
||||
mov dword [0x401800], 0x48484848 ; make sure surrounding areas remained RW
|
||||
|
||||
hlt ; tell hook function we are done
|
||||
*/
|
||||
|
||||
int test_num = 0;
|
||||
uint32_t tests[] = {
|
||||
0x41414141,
|
||||
0x43434343,
|
||||
0x45454545
|
||||
};
|
||||
|
||||
static int log_num = 1;
|
||||
|
||||
#define CODE_SECTION 0x100000
|
||||
#define CODE_SIZE 0x1000
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint32_t testval;
|
||||
if (uc_mem_read(uc, 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 0x90: //nop
|
||||
printf("# Handling NOP\n");
|
||||
if (uc_mem_read(uc, 0x200000 + test_num * 0x100000, &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);
|
||||
} else {
|
||||
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);
|
||||
|
||||
if (testval == tests[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);
|
||||
}
|
||||
}
|
||||
if (uc_mem_protect(uc, 0x200000 + test_num * 0x100000, 0x1000, UC_PROT_READ) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_mem_protect fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_protect success\n", log_num++);
|
||||
}
|
||||
test_num++;
|
||||
break;
|
||||
case 0xf4: //hlt
|
||||
printf("# Handling HLT\n");
|
||||
if (uc_emu_stop(uc) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
_exit(-1);
|
||||
} 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)
|
||||
static void hook_mem_write(uc_engine *uc, uc_mem_type type,
|
||||
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);
|
||||
}
|
||||
|
||||
// callback for tracing invalid memory access (READ or WRITE)
|
||||
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
||||
uint64_t addr, int size, int64_t value, void *user_data)
|
||||
{
|
||||
uint32_t testval;
|
||||
switch(type) {
|
||||
default:
|
||||
printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
||||
return false;
|
||||
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);
|
||||
|
||||
if (uc_mem_read(uc, addr, &testval, sizeof(testval)) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_read success after mem_protect at test %d\n", log_num++, test_num - 1);
|
||||
}
|
||||
|
||||
if (uc_mem_protect(uc, 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);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_protect success\n", log_num++);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_hook trace1, trace2;
|
||||
uc_err err;
|
||||
uint32_t addr, testval;
|
||||
int32_t buf1[1024], buf2[1024], readbuf[1024];
|
||||
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");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
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(uc, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
|
||||
uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
|
||||
// fill in sections that shouldn't get touched
|
||||
if (uc_mem_write(uc, 0x3ff000, buf1, sizeof(buf1))) {
|
||||
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
|
||||
return 2;
|
||||
} else {
|
||||
printf("ok %d - Random buffer 1 written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_mem_write(uc, 0x401000, buf2, sizeof(buf2))) {
|
||||
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
|
||||
return 3;
|
||||
} else {
|
||||
printf("ok %d - Random buffer 2 written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(uc, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
|
||||
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
|
||||
return 4;
|
||||
} else {
|
||||
printf("ok %d - Program written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++);
|
||||
return 5;
|
||||
} else {
|
||||
printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
|
||||
}
|
||||
|
||||
// intercept memory write events
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++);
|
||||
return 6;
|
||||
} else {
|
||||
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
|
||||
}
|
||||
|
||||
// intercept invalid memory events
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_PROT, hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
|
||||
return 7;
|
||||
} else {
|
||||
printf("ok %d - memory invalid handler installed\n", log_num++);
|
||||
}
|
||||
|
||||
// emulate machine code until told to stop by hook_code
|
||||
printf("# BEGIN execution\n");
|
||||
err = uc_emu_start(uc, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
|
||||
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));
|
||||
return 8;
|
||||
} else {
|
||||
printf("ok %d - uc_emu_start complete\n", log_num++);
|
||||
}
|
||||
printf("# END execution\n");
|
||||
|
||||
//read from the remapped memory
|
||||
testval = 0x42424242;
|
||||
for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
|
||||
uint32_t val;
|
||||
if (uc_mem_read(uc, addr, &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;
|
||||
}
|
||||
|
||||
//account for the two mods made by the machine code
|
||||
buf1[512] = 0x47474747;
|
||||
buf2[512] = 0x48484848;
|
||||
|
||||
//make sure that random blocks didn't get nuked
|
||||
// fill in sections that shouldn't get touched
|
||||
if (uc_mem_read(uc, 0x3ff000, readbuf, sizeof(readbuf))) {
|
||||
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(uc, 0x401000, readbuf, sizeof(readbuf))) {
|
||||
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
|
||||
} else {
|
||||
printf("ok %d - Random buffer 2 read from memory\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++);
|
||||
}
|
||||
}
|
||||
|
||||
if (uc_close(uc) == 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;
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
|
||||
uc_mem_unmap demo / unit test
|
||||
|
||||
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 distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
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
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
unsigned char PROGRAM[] =
|
||||
"\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"
|
||||
"\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";
|
||||
// total size: 64 bytes
|
||||
|
||||
/*
|
||||
; assumes code section at 0x100000
|
||||
; assumes data section at 0x200000, initially rw
|
||||
; assumes data section at 0x300000, initially rw
|
||||
; assumes data section at 0x400000, initially rw
|
||||
|
||||
; with installed hooks unmaps or maps on each nop
|
||||
|
||||
mov dword [0x200000], 0x41414141
|
||||
nop ; unmap it
|
||||
mov dword [0x200000], 0x42424242
|
||||
|
||||
mov dword [0x300000], 0x43434343
|
||||
nop ; unmap it
|
||||
mov dword [0x300000], 0x44444444
|
||||
|
||||
mov dword [0x400000], 0x45454545
|
||||
nop ; unmap it
|
||||
mov dword [0x400000], 0x46464646
|
||||
|
||||
hlt ; tell hook function we are done
|
||||
*/
|
||||
|
||||
int test_num = 0;
|
||||
uint32_t tests[] = {
|
||||
0x41414141,
|
||||
0x43434343,
|
||||
0x45454545
|
||||
};
|
||||
|
||||
static int log_num = 1;
|
||||
|
||||
#define CODE_SECTION 0x100000
|
||||
#define CODE_SIZE 0x1000
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint32_t testval;
|
||||
if (uc_mem_read(uc, 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 0x90: //nop
|
||||
printf("# Handling NOP\n");
|
||||
if (uc_mem_read(uc, 0x200000 + test_num * 0x100000, &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);
|
||||
} else {
|
||||
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);
|
||||
|
||||
if (testval == tests[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);
|
||||
}
|
||||
}
|
||||
if (uc_mem_unmap(uc, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_mem_unmap fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_unmap success\n", log_num++);
|
||||
}
|
||||
test_num++;
|
||||
break;
|
||||
case 0xf4: //hlt
|
||||
printf("# Handling HLT\n");
|
||||
if (uc_emu_stop(uc) != UC_ERR_OK) {
|
||||
printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
_exit(-1);
|
||||
} 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)
|
||||
static void hook_mem_write(uc_engine *uc, uc_mem_type type,
|
||||
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);
|
||||
}
|
||||
|
||||
// callback for tracing invalid memory access (READ or WRITE)
|
||||
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
|
||||
uint64_t addr, int size, int64_t value, void *user_data)
|
||||
{
|
||||
uint32_t testval;
|
||||
switch(type) {
|
||||
default:
|
||||
printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
|
||||
return false;
|
||||
case UC_MEM_WRITE_UNMAPPED:
|
||||
printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);
|
||||
|
||||
if (uc_mem_read(uc, addr, &testval, sizeof(testval)) != UC_ERR_OK) {
|
||||
printf("ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr);
|
||||
} else {
|
||||
printf("not ok %d - uc_mem_read success after unmap at test %d\n", log_num++, test_num - 1);
|
||||
}
|
||||
|
||||
if (uc_mem_map(uc, 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);
|
||||
} else {
|
||||
printf("ok %d - uc_mem_map success\n", log_num++);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_hook trace1, trace2;
|
||||
uc_err err;
|
||||
uint32_t addr, testval;
|
||||
int32_t buf1[1024], buf2[1024], readbuf[1024];
|
||||
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");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
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(uc, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
|
||||
uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
uc_mem_map(uc, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);
|
||||
|
||||
// fill in sections that shouldn't get touched
|
||||
if (uc_mem_write(uc, 0x3ff000, buf1, sizeof(buf1))) {
|
||||
printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
|
||||
return 2;
|
||||
} else {
|
||||
printf("ok %d - Random buffer 1 written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_mem_write(uc, 0x401000, buf2, sizeof(buf1))) {
|
||||
printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
|
||||
return 3;
|
||||
} else {
|
||||
printf("ok %d - Random buffer 2 written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(uc, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
|
||||
printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
|
||||
return 4;
|
||||
} else {
|
||||
printf("ok %d - Program written to memory\n", log_num++);
|
||||
}
|
||||
|
||||
if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++);
|
||||
return 5;
|
||||
} else {
|
||||
printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
|
||||
}
|
||||
|
||||
// intercept memory write events
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++);
|
||||
return 6;
|
||||
} else {
|
||||
printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
|
||||
}
|
||||
|
||||
// intercept invalid memory events
|
||||
if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
|
||||
printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
|
||||
return 7;
|
||||
} else {
|
||||
printf("ok %d - memory invalid handler installed\n", log_num++);
|
||||
}
|
||||
|
||||
// emulate machine code until told to stop by hook_code
|
||||
printf("# BEGIN execution\n");
|
||||
err = uc_emu_start(uc, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
|
||||
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));
|
||||
return 8;
|
||||
} else {
|
||||
printf("ok %d - uc_emu_start complete\n", log_num++);
|
||||
}
|
||||
printf("# END execution\n");
|
||||
|
||||
//read from the remapped memory
|
||||
testval = 0x42424242;
|
||||
for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
|
||||
uint32_t val;
|
||||
if (uc_mem_read(uc, addr, &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
|
||||
// fill in sections that shouldn't get touched
|
||||
if (uc_mem_read(uc, 0x3ff000, readbuf, sizeof(readbuf))) {
|
||||
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(uc, 0x401000, readbuf, sizeof(readbuf))) {
|
||||
printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
|
||||
} else {
|
||||
printf("ok %d - Random buffer 2 read from memory\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++);
|
||||
}
|
||||
}
|
||||
|
||||
if (uc_close(uc) == 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;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate ARM code */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3
|
||||
#define THUMB_CODE "\x83\xb0" // sub sp, #0xc
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_arm(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int r0 = 0x1234; // R0 register
|
||||
int r2 = 0x6789; // R1 register
|
||||
int r3 = 0x3333; // R2 register
|
||||
int r1; // R1 register
|
||||
|
||||
printf("Emulate ARM code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_write(uc, UC_ARM_REG_R2, &r2);
|
||||
uc_reg_write(uc, UC_ARM_REG_R3, &r3);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_read(uc, UC_ARM_REG_R1, &r1);
|
||||
printf(">>> R0 = 0x%x\n", r0);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_thumb(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int sp = 0x1234; // R0 register
|
||||
|
||||
printf("Emulate THUMB code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_ARM_REG_SP, &sp);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_ARM_REG_SP, &sp);
|
||||
printf(">>> SP = 0x%x\n", sp);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// test memleak
|
||||
while(1) {
|
||||
test_arm();
|
||||
printf("==========================\n");
|
||||
test_thumb();
|
||||
}
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate ARM64 code */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define ARM_CODE "\xab\x01\x0f\x8b" // add x11, x13, x15
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_arm64(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int64_t x11 = 0x1234; // X11 register
|
||||
int64_t x13 = 0x6789; // X13 register
|
||||
int64_t x15 = 0x3333; // X15 register
|
||||
|
||||
printf("Emulate ARM64 code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_ARM64_REG_X11, &x11);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X13, &x13);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X15, &x15);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_ARM64_REG_X11, &x11);
|
||||
printf(">>> X11 = 0x%" PRIx64 "\n", x11);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
test_arm64();
|
||||
}
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Loi Anh Tuan, 2015 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate m68k code */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
// code to be emulated
|
||||
#define M68K_CODE "\x76\xed" // movq #-19, %d3
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_m68k(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_hook trace1, trace2;
|
||||
uc_err err;
|
||||
|
||||
int d0 = 0x0000; // d0 data register
|
||||
int d1 = 0x0000; // d1 data register
|
||||
int d2 = 0x0000; // d2 data register
|
||||
int d3 = 0x0000; // d3 data register
|
||||
int d4 = 0x0000; // d4 data register
|
||||
int d5 = 0x0000; // d5 data register
|
||||
int d6 = 0x0000; // d6 data register
|
||||
int d7 = 0x0000; // d7 data register
|
||||
|
||||
int a0 = 0x0000; // a0 address register
|
||||
int a1 = 0x0000; // a1 address register
|
||||
int a2 = 0x0000; // a2 address register
|
||||
int a3 = 0x0000; // a3 address register
|
||||
int a4 = 0x0000; // a4 address register
|
||||
int a5 = 0x0000; // a5 address register
|
||||
int a6 = 0x0000; // a6 address register
|
||||
int a7 = 0x0000; // a6 address register
|
||||
|
||||
int pc = 0x0000; // program counter
|
||||
int sr = 0x0000; // status register
|
||||
|
||||
printf("Emulate M68K code\n");
|
||||
|
||||
// Initialize emulator in M68K mode
|
||||
err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, M68K_CODE, sizeof(M68K_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_M68K_REG_D0, &d0);
|
||||
uc_reg_write(uc, UC_M68K_REG_D1, &d1);
|
||||
uc_reg_write(uc, UC_M68K_REG_D2, &d2);
|
||||
uc_reg_write(uc, UC_M68K_REG_D3, &d3);
|
||||
uc_reg_write(uc, UC_M68K_REG_D4, &d4);
|
||||
uc_reg_write(uc, UC_M68K_REG_D5, &d5);
|
||||
uc_reg_write(uc, UC_M68K_REG_D6, &d6);
|
||||
uc_reg_write(uc, UC_M68K_REG_D7, &d7);
|
||||
|
||||
uc_reg_write(uc, UC_M68K_REG_A0, &a0);
|
||||
uc_reg_write(uc, UC_M68K_REG_A1, &a1);
|
||||
uc_reg_write(uc, UC_M68K_REG_A2, &a2);
|
||||
uc_reg_write(uc, UC_M68K_REG_A3, &a3);
|
||||
uc_reg_write(uc, UC_M68K_REG_A4, &a4);
|
||||
uc_reg_write(uc, UC_M68K_REG_A5, &a5);
|
||||
uc_reg_write(uc, UC_M68K_REG_A6, &a6);
|
||||
uc_reg_write(uc, UC_M68K_REG_A7, &a7);
|
||||
|
||||
uc_reg_write(uc, UC_M68K_REG_PC, &pc);
|
||||
uc_reg_write(uc, UC_M68K_REG_SR, &sr);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instruction
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_M68K_REG_D0, &d0);
|
||||
uc_reg_read(uc, UC_M68K_REG_D1, &d1);
|
||||
uc_reg_read(uc, UC_M68K_REG_D2, &d2);
|
||||
uc_reg_read(uc, UC_M68K_REG_D3, &d3);
|
||||
uc_reg_read(uc, UC_M68K_REG_D4, &d4);
|
||||
uc_reg_read(uc, UC_M68K_REG_D5, &d5);
|
||||
uc_reg_read(uc, UC_M68K_REG_D6, &d6);
|
||||
uc_reg_read(uc, UC_M68K_REG_D7, &d7);
|
||||
|
||||
uc_reg_read(uc, UC_M68K_REG_A0, &a0);
|
||||
uc_reg_read(uc, UC_M68K_REG_A1, &a1);
|
||||
uc_reg_read(uc, UC_M68K_REG_A2, &a2);
|
||||
uc_reg_read(uc, UC_M68K_REG_A3, &a3);
|
||||
uc_reg_read(uc, UC_M68K_REG_A4, &a4);
|
||||
uc_reg_read(uc, UC_M68K_REG_A5, &a5);
|
||||
uc_reg_read(uc, UC_M68K_REG_A6, &a6);
|
||||
uc_reg_read(uc, UC_M68K_REG_A7, &a7);
|
||||
|
||||
uc_reg_read(uc, UC_M68K_REG_PC, &pc);
|
||||
uc_reg_read(uc, UC_M68K_REG_SR, &sr);
|
||||
|
||||
printf(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n", a0, d0);
|
||||
printf(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n", a1, d1);
|
||||
printf(">>> A2 = 0x%x\t\t>>> D2 = 0x%x\n", a2, d2);
|
||||
printf(">>> A3 = 0x%x\t\t>>> D3 = 0x%x\n", a3, d3);
|
||||
printf(">>> A4 = 0x%x\t\t>>> D4 = 0x%x\n", a4, d4);
|
||||
printf(">>> A5 = 0x%x\t\t>>> D5 = 0x%x\n", a5, d5);
|
||||
printf(">>> A6 = 0x%x\t\t>>> D6 = 0x%x\n", a6, d6);
|
||||
printf(">>> A7 = 0x%x\t\t>>> D7 = 0x%x\n", a7, d7);
|
||||
printf(">>> PC = 0x%x\n", pc);
|
||||
printf(">>> SR = 0x%x\n", sr);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// test memleak
|
||||
while(1) {
|
||||
test_m68k();
|
||||
}
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate Mips code (big endian) */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define MIPS_CODE_EB "\x34\x21\x34\x56" // ori $at, $at, 0x3456;
|
||||
#define MIPS_CODE_EL "\x56\x34\x21\x34" // ori $at, $at, 0x3456;
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_mips_eb(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int r1 = 0x6789; // R1 register
|
||||
|
||||
printf("Emulate MIPS code (big-endian)\n");
|
||||
|
||||
// Initialize emulator in MIPS mode
|
||||
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_MIPS_REG_1, &r1);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err));
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_MIPS_REG_1, &r1);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_mips_el(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int r1 = 0x6789; // R1 register
|
||||
|
||||
printf("===========================\n");
|
||||
printf("Emulate MIPS code (little-endian)\n");
|
||||
|
||||
// Initialize emulator in MIPS mode
|
||||
err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_MIPS_REG_1, &r1);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err));
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_MIPS_REG_1, &r1);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// test memleak
|
||||
while(1) {
|
||||
test_mips_eb();
|
||||
test_mips_el();
|
||||
}
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate Sparc code */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define SPARC_CODE "\x86\x00\x40\x02" // add %g1, %g2, %g3;
|
||||
//#define SPARC_CODE "\xbb\x70\x00\x00" // illegal code
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_sparc(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int g1 = 0x1230; // G1 register
|
||||
int g2 = 0x6789; // G2 register
|
||||
int g3 = 0x5555; // G3 register
|
||||
|
||||
printf("Emulate SPARC code\n");
|
||||
|
||||
// Initialize emulator in Sparc mode
|
||||
err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, SPARC_CODE, sizeof(SPARC_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_SPARC_REG_G1, &g1);
|
||||
uc_reg_write(uc, UC_SPARC_REG_G2, &g2);
|
||||
uc_reg_write(uc, UC_SPARC_REG_G3, &g3);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instructions with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_SPARC_REG_G3, &g3);
|
||||
printf(">>> G3 = 0x%x\n", g3);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// test memleak
|
||||
while(1) {
|
||||
test_sparc();
|
||||
}
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh & Dang Hoang Vu, 2015 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate X86 code */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
// common includes
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx
|
||||
#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop
|
||||
// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41"
|
||||
//#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx;
|
||||
#define X86_CODE32_LOOP "\x41\x4a\xeb\xfe" // INC ecx; DEC edx; JMP self-loop
|
||||
#define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx
|
||||
#define X86_CODE32_MEM_READ "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx
|
||||
|
||||
#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx
|
||||
#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
||||
|
||||
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash
|
||||
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
|
||||
#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59"
|
||||
#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al
|
||||
#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x1000000
|
||||
|
||||
// callback for tracing basic blocks
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
int eflags;
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
|
||||
uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
|
||||
printf(">>> --- EFLAGS is 0x%x\n", eflags);
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// uc_emu_stop(uc);
|
||||
}
|
||||
|
||||
// callback for tracing instruction
|
||||
static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
uint64_t rip;
|
||||
|
||||
uc_reg_read(uc, UC_X86_REG_RIP, &rip);
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
printf(">>> RIP is 0x%"PRIx64 "\n", rip);
|
||||
|
||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||
// if (address == 0x1000009)
|
||||
// uc_emu_stop(uc);
|
||||
}
|
||||
|
||||
static void hook_mem64(uc_engine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t value, void *user_data)
|
||||
{
|
||||
switch(type) {
|
||||
default: break;
|
||||
case UC_MEM_READ:
|
||||
printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n",
|
||||
address, size);
|
||||
break;
|
||||
case UC_MEM_WRITE:
|
||||
printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
||||
address, size, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_i386(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uint32_t tmp;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
int r_edx = 0x7890; // EDX register
|
||||
|
||||
printf("Emulate i386 code\n");
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instruction by having @begin > @end
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
|
||||
// read from memory
|
||||
if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp)))
|
||||
printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp);
|
||||
else
|
||||
printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_x86_64(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2, trace3, trace4;
|
||||
|
||||
int64_t rax = 0x71f3029efd49d41d;
|
||||
int64_t rbx = 0xd87b45277f133ddb;
|
||||
int64_t rcx = 0xab40d1ffd8afc461;
|
||||
int64_t rdx = 0x919317b4a733f01;
|
||||
int64_t rsi = 0x4c24e753a17ea358;
|
||||
int64_t rdi = 0xe509a57d2571ce96;
|
||||
int64_t r8 = 0xea5b108cc2b9ab1f;
|
||||
int64_t r9 = 0x19ec097c8eb618c1;
|
||||
int64_t r10 = 0xec45774f00c5f682;
|
||||
int64_t r11 = 0xe17e9dbec8c074aa;
|
||||
int64_t r12 = 0x80f86a8dc0f6d457;
|
||||
int64_t r13 = 0x48288ca5671c5492;
|
||||
int64_t r14 = 0x595f72f6e4017f6e;
|
||||
int64_t r15 = 0x1efd97aea331cccc;
|
||||
|
||||
int64_t rsp = ADDRESS + 0x200000;
|
||||
|
||||
|
||||
printf("Emulate x86_64 code\n");
|
||||
|
||||
// Initialize emulator in X86-64bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(uc, ADDRESS, X86_CODE64, sizeof(X86_CODE64) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_X86_REG_RSP, &rsp);
|
||||
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_write(uc, UC_X86_REG_RBX, &rbx);
|
||||
uc_reg_write(uc, UC_X86_REG_RCX, &rcx);
|
||||
uc_reg_write(uc, UC_X86_REG_RDX, &rdx);
|
||||
uc_reg_write(uc, UC_X86_REG_RSI, &rsi);
|
||||
uc_reg_write(uc, UC_X86_REG_RDI, &rdi);
|
||||
uc_reg_write(uc, UC_X86_REG_R8, &r8);
|
||||
uc_reg_write(uc, UC_X86_REG_R9, &r9);
|
||||
uc_reg_write(uc, UC_X86_REG_R10, &r10);
|
||||
uc_reg_write(uc, UC_X86_REG_R11, &r11);
|
||||
uc_reg_write(uc, UC_X86_REG_R12, &r12);
|
||||
uc_reg_write(uc, UC_X86_REG_R13, &r13);
|
||||
uc_reg_write(uc, UC_X86_REG_R14, &r14);
|
||||
uc_reg_write(uc, UC_X86_REG_R15, &r15);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all instructions in the range [ADDRESS, ADDRESS+20]
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)ADDRESS, (uint64_t)(ADDRESS+20));
|
||||
|
||||
// tracing all memory WRITE access (with @begin > @end)
|
||||
uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// tracing all memory READ access (with @begin > @end)
|
||||
uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned %u: %s\n",
|
||||
err, uc_strerror(err));
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_X86_REG_RAX, &rax);
|
||||
uc_reg_read(uc, UC_X86_REG_RBX, &rbx);
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &rdx);
|
||||
uc_reg_read(uc, UC_X86_REG_RSI, &rsi);
|
||||
uc_reg_read(uc, UC_X86_REG_RDI, &rdi);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &r8);
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &r9);
|
||||
uc_reg_read(uc, UC_X86_REG_R10, &r10);
|
||||
uc_reg_read(uc, UC_X86_REG_R11, &r11);
|
||||
uc_reg_read(uc, UC_X86_REG_R12, &r12);
|
||||
uc_reg_read(uc, UC_X86_REG_R13, &r13);
|
||||
uc_reg_read(uc, UC_X86_REG_R14, &r14);
|
||||
uc_reg_read(uc, UC_X86_REG_R15, &r15);
|
||||
|
||||
printf(">>> RAX = 0x%" PRIx64 "\n", rax);
|
||||
printf(">>> RBX = 0x%" PRIx64 "\n", rbx);
|
||||
printf(">>> RCX = 0x%" PRIx64 "\n", rcx);
|
||||
printf(">>> RDX = 0x%" PRIx64 "\n", rdx);
|
||||
printf(">>> RSI = 0x%" PRIx64 "\n", rsi);
|
||||
printf(">>> RDI = 0x%" PRIx64 "\n", rdi);
|
||||
printf(">>> R8 = 0x%" PRIx64 "\n", r8);
|
||||
printf(">>> R9 = 0x%" PRIx64 "\n", r9);
|
||||
printf(">>> R10 = 0x%" PRIx64 "\n", r10);
|
||||
printf(">>> R11 = 0x%" PRIx64 "\n", r11);
|
||||
printf(">>> R12 = 0x%" PRIx64 "\n", r12);
|
||||
printf(">>> R13 = 0x%" PRIx64 "\n", r13);
|
||||
printf(">>> R14 = 0x%" PRIx64 "\n", r14);
|
||||
printf(">>> R15 = 0x%" PRIx64 "\n", r15);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
test_i386();
|
||||
test_x86_64();
|
||||
}
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
13
tests/regress/mips_cp1.py
Normal file
13
tests/regress/mips_cp1.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from unicorn import *
|
||||
from unicorn.mips_const import *
|
||||
|
||||
|
||||
|
||||
# .text:00416CB0 cfc1 $v1, FCSR
|
||||
shellcode = [0x44, 0x43, 0xF8, 0x00]
|
||||
base = 0x416CB0
|
||||
|
||||
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN)
|
||||
uc.mem_map(0x416000, 0x1000)
|
||||
uc.mem_write(base, bytes(shellcode))
|
||||
uc.emu_start(base, base + len(shellcode))
|
||||
21
tests/regress/x86_ld_crash.py
Executable file
21
tests/regress/x86_ld_crash.py
Executable file
File diff suppressed because one or more lines are too long
21
tests/regress/x86_set_ip.py
Normal file
21
tests/regress/x86_set_ip.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from unicorn import *
|
||||
from unicorn.x86_const import *
|
||||
|
||||
count = 0
|
||||
|
||||
def cb(uc, addr, sz, data):
|
||||
global count
|
||||
count += 1
|
||||
print(f"addr: {hex(addr)} count: {count}")
|
||||
if count == 5:
|
||||
uc.emu_stop()
|
||||
else:
|
||||
uc.reg_write(UC_X86_REG_RIP, 0x2000)
|
||||
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_64)
|
||||
|
||||
mu.mem_map(0x1000, 0x4000)
|
||||
mu.mem_write(0x1000, b"\x90" * 5)
|
||||
mu.mem_write(0x2000, b"\x90" * 5)
|
||||
mu.hook_add(UC_HOOK_CODE, cb)
|
||||
mu.emu_start(0x1000, 0x2000+1, 0, 0)
|
||||
Reference in New Issue
Block a user