mirror of
https://github.com/Vita3K/unicorn.git
synced 2024-11-23 13:29:40 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
065fd60d4c
@ -7,10 +7,10 @@ Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows
|
||||
|
||||
Unicorn requires few dependent packages as followings
|
||||
|
||||
- For Mac OS X, "pkg-config" is needed.
|
||||
Brew users can install "pkg-config" with:
|
||||
- For Mac OS X, "pkg-config" and "glib" are needed.
|
||||
Brew users can install "pkg-config" and "glib" with:
|
||||
|
||||
$ brew install pkg-config
|
||||
$ brew install pkg-config glib
|
||||
|
||||
- For Linux, glib2-dev is needed.
|
||||
Ubuntu/Debian users can install this with:
|
||||
|
@ -13,6 +13,7 @@ X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], e
|
||||
X86_CODE64 = b"\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"
|
||||
X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
||||
X86_CODE64_SYSCALL = '\x0f\x05' # SYSCALL
|
||||
X86_CODE16 = '\x00\x00' # add byte ptr [bx + si], al
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x1000000
|
||||
@ -437,6 +438,36 @@ def test_x86_64_syscall():
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_x86_16():
|
||||
print("Emulate x86 16-bit code")
|
||||
try:
|
||||
# Initialize emulator in X86-16bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_16)
|
||||
|
||||
# map 8KB memory for this emulation
|
||||
mu.mem_map(0, 8 * 1024)
|
||||
|
||||
# set CPU registers
|
||||
mu.reg_write(UC_X86_REG_EAX, 7)
|
||||
mu.reg_write(UC_X86_REG_EBX, 5)
|
||||
mu.reg_write(UC_X86_REG_ESI, 6)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(0, X86_CODE16)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(0, len(X86_CODE16))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
tmp = mu.mem_read(11, 1)
|
||||
print("[0x%x] = 0x%x" %(11, tmp[0]))
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_i386()
|
||||
print("=" * 20)
|
||||
@ -451,3 +482,5 @@ if __name__ == '__main__':
|
||||
test_x86_64()
|
||||
print("=" * 20)
|
||||
test_x86_64_syscall()
|
||||
print("=" * 20)
|
||||
test_x86_16()
|
||||
|
@ -390,9 +390,9 @@ uc_err uc_hook_del(uch handle, uch *h2);
|
||||
|
||||
@handle: handle returned by uc_open()
|
||||
@address: starting address of the new memory region to be mapped in.
|
||||
This address will be round down to 8KB boundary
|
||||
@size: size of the new memory region to be mapped in. This will be round up to
|
||||
the next 8KB boundary.
|
||||
This address must be aligned to 4KB, or this will return with UC_ERR_MAP error.
|
||||
@size: size of the new memory region to be mapped in.
|
||||
This size must be multiple of 4KB, or this will return with UC_ERR_MAP error.
|
||||
|
||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||
for detailed error).
|
||||
|
@ -19169,9 +19169,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
||||
int num_insns;
|
||||
int max_insns;
|
||||
int insn_bytes;
|
||||
int is_slot;
|
||||
int is_slot = 0;
|
||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||
TCGArg *save_opparam_ptr;
|
||||
TCGArg *save_opparam_ptr = NULL;
|
||||
|
||||
if (search_pc)
|
||||
qemu_log("search pc %d\n", search_pc);
|
||||
|
32
regress/fpu_mem_write.py
Executable file
32
regress/fpu_mem_write.py
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/python
|
||||
from unicorn import *
|
||||
from unicorn.x86_const import *
|
||||
|
||||
ESP = 0x2000
|
||||
PAGE_SIZE = 1 * 1024 * 1024
|
||||
|
||||
# fstcw [esp]
|
||||
# pop ecx
|
||||
CODE = b'\x9B\xD9\x3C\x24\x59'
|
||||
|
||||
def mem_reader(addr, size):
|
||||
tmp = mu.mem_read(addr, size)
|
||||
|
||||
for i in tmp:
|
||||
print(" 0x%x" % i),
|
||||
print("")
|
||||
|
||||
def hook_mem_write(uc, access, address, size, value, user_data):
|
||||
print("mem WRITE: 0x%x, data size = %u, data value = 0x%x" % (address, size, value))
|
||||
return True
|
||||
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
mu.mem_map(0, PAGE_SIZE)
|
||||
mu.mem_write(0, CODE)
|
||||
mu.reg_write(UC_X86_REG_ESP, ESP)
|
||||
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write)
|
||||
|
||||
mu.emu_start(0x0, 0, 0, 2)
|
||||
esp = mu.reg_read(UC_X86_REG_ESP)
|
||||
print("value at ESP [0x%X]: " % esp)
|
||||
mem_reader(esp, 10)
|
2
regress/memmap_segfault2.py
Normal file → Executable file
2
regress/memmap_segfault2.py
Normal file → Executable file
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from unicorn import *
|
||||
uc = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
uc.mem_map(0x0000, 0x2000)
|
||||
|
@ -15,6 +15,8 @@ if test -e $DIR/sample_x86; then
|
||||
$DIR/sample_x86 -32
|
||||
echo "=========================="
|
||||
$DIR/sample_x86 -64
|
||||
echo "=========================="
|
||||
$DIR/sample_x86 -16
|
||||
fi
|
||||
if test -e $DIR/sample_arm; then
|
||||
echo "=========================="
|
||||
|
@ -24,7 +24,8 @@
|
||||
|
||||
//#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" //\xc3"
|
||||
#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
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x1000000
|
||||
@ -672,6 +673,58 @@ static void test_x86_64(void)
|
||||
uc_close(&handle);
|
||||
}
|
||||
|
||||
static void test_x86_16(void)
|
||||
{
|
||||
uch handle;
|
||||
uc_err err;
|
||||
uint8_t tmp;
|
||||
|
||||
int32_t eax = 7;
|
||||
int32_t ebx = 5;
|
||||
int32_t esi = 6;
|
||||
|
||||
printf("Emulate x86 16-bit code\n");
|
||||
|
||||
// Initialize emulator in X86-16bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_16, &handle);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// map 8KB memory for this emulation
|
||||
uc_mem_map(handle, 0, 8 * 1024);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
if (uc_mem_write(handle, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) {
|
||||
printf("Failed to write emulation code to memory, quit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(handle, UC_X86_REG_EAX, &eax);
|
||||
uc_reg_write(handle, UC_X86_REG_EBX, &ebx);
|
||||
uc_reg_write(handle, UC_X86_REG_ESI, &esi);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(handle, 0, sizeof(X86_CODE16) - 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");
|
||||
|
||||
// read from memory
|
||||
if (!uc_mem_read(handle, 11, &tmp, 1))
|
||||
printf(">>> Read 1 bytes from [0x%x] = 0x%x\n", 11, tmp);
|
||||
else
|
||||
printf(">>> Failed to read 1 bytes from [0x%x]\n", 11);
|
||||
|
||||
uc_close(&handle);
|
||||
}
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
if (argc == 2) {
|
||||
@ -689,6 +742,10 @@ int main(int argc, char **argv, char **envp)
|
||||
test_x86_64();
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "-16")) {
|
||||
test_x86_16();
|
||||
}
|
||||
|
||||
// test memleak
|
||||
if (!strcmp(argv[1], "-0")) {
|
||||
while(1) {
|
||||
@ -697,7 +754,7 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("Syntax: %s <-32|-64>\n", argv[0]);
|
||||
printf("Syntax: %s <-16|-32|-64>\n", argv[0]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
17
uc.c
17
uc.c
@ -535,7 +535,6 @@ UNICORN_EXPORT
|
||||
uc_err uc_mem_map(uch handle, uint64_t address, size_t size)
|
||||
{
|
||||
struct uc_struct* uc = (struct uc_struct *)handle;
|
||||
size_t s;
|
||||
|
||||
if (handle == 0)
|
||||
// invalid handle
|
||||
@ -545,11 +544,17 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size)
|
||||
// invalid memory mapping
|
||||
return UC_ERR_MAP;
|
||||
|
||||
// align to 8KB boundary
|
||||
map_begin[map_count] = address & (~ (8*1024 - 1));
|
||||
s = (size + 8*1024 - 1) & (~ (8*1024 - 1));
|
||||
map_end[map_count] = s + map_begin[map_count];
|
||||
uc->memory_map(uc, map_begin[map_count], s);
|
||||
// address must be aligned to 4KB
|
||||
if ((address & (4*1024 - 1)) != 0)
|
||||
return UC_ERR_MAP;
|
||||
|
||||
// size must be multiple of 4KB
|
||||
if ((size & (4*1024 - 1)) != 0)
|
||||
return UC_ERR_MAP;
|
||||
|
||||
map_begin[map_count] = address;
|
||||
map_end[map_count] = size + map_begin[map_count];
|
||||
uc->memory_map(uc, map_begin[map_count], size);
|
||||
map_count++;
|
||||
|
||||
return UC_ERR_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user