Closed javacommons closed 8 months ago
I modified the above code like this:
#include <unicorn/unicorn.h>
#include <assert.h>
#include <stdio.h>
#include <iostream>
#define OK(x) {uc_err __err; if ((__err = x)) { fprintf(stderr, "%s", uc_strerror(__err)); assert(false); } }
int host_function(uc_engine* uc, void* user_data) {
std::cout << "host_function(begin)" << std::endl;
uint64_t arg1, arg2;
uc_reg_read(uc, UC_X86_REG_RDI, &arg1);
uc_reg_read(uc, UC_X86_REG_RSI, &arg2);
uint64_t result = arg1 + arg2;
std::cout << "arg1:" << arg1 << std::endl;
std::cout << "arg2:" << arg2 << std::endl;
std::cout << "result:" << result << std::endl;
uc_reg_write(uc, UC_X86_REG_RAX, &result);
std::cout << "host_function(end)" << std::endl;
return 0;
}
int main() {
uc_engine* uc;
uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
if (err != UC_ERR_OK) {
printf("uc_open() failed with error: %s\n", uc_strerror(err));
return -1;
}
uint64_t code_address = 0x1000;
#if 0x0
// https://disasm.pro/
mov rsi, 5
mov rdi, 3
mov eax, 1
int 0x80
ret
#endif
char code[] = "\x48\xC7\xC6\x05\x00\x00\x00\x48\xC7\xC7\x03\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80\xC3";
OK(uc_mem_map(uc, code_address, 0x1000/*sizeof(code)*/, UC_PROT_ALL));
OK(uc_mem_write(uc, code_address, code, sizeof(code)));
uc_hook hook;
OK(uc_hook_add(uc, &hook, UC_HOOK_INTR | UC_HOOK_MEM_UNMAPPED, (void*)host_function, NULL, code_address, code_address + sizeof(code)));
OK(uc_reg_write(uc, UC_X86_REG_RSP, &code_address));
OK(uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0));
uint64_t result;
OK(uc_reg_read(uc, UC_X86_REG_RAX, &result));
printf("Emulation result: %lu\n", result);
uc_close(uc);
return 0;
}
Then, I got a different error:
$ g++ host-calc.cpp -lunicorn -static && ./a.exe
host_function(begin)
arg1:3
arg2:5
result:8
host_function(end)
Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)Assertion failed: false, file host-calc.cpp, line 51
If I changed the source code to ignore uc_emu_start()'s error, the result is just like I expected. Can I just ignore uc_emu_start()'s error?
OK(uc_reg_write(uc, UC_X86_REG_RSP, &code_address));
#if 0x0 // ignore uc_emu_start()'s error
OK(uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0));
#else
uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0);
#endif
$ g++ host-calc.cpp -lunicorn -static && ./a.exe
host_function(begin)
arg1:3
arg2:5
result:8
host_function(end)
host_function(begin)
arg1:3
arg2:5
result:8
host_function(end)
Emulation result: 8
Final source code:
When DEBUG is not defined:
$ g++ host-calc.cpp -lunicorn -static && ./a.exe
host_function(begin)
arg1:30
arg2:50
result:80
host_function(end)
host_function(begin)
arg1:3
arg2:5
result:8
host_function(end)
Emulation result: 8
When DEBUG is defined:
$ g++ host-calc.cpp -DDEBUG -lunicorn -static && ./a.exe
host_function(begin)
arg1:30
arg2:50
result:80
host_function(end)
host_function(begin)
arg1:3
arg2:5
result:8
host_function(end)
Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)Assertion failed: false, file host-calc.cpp, line 50
#include <unicorn/unicorn.h>
#include <assert.h>
#include <stdio.h>
#include <iostream>
#define OK(x) {uc_err __err; if ((__err = x)) { fprintf(stderr, "%s", uc_strerror(__err)); assert(false); } }
int host_function(uc_engine* uc, void* user_data) {
std::cout << "host_function(begin)" << std::endl;
uint64_t arg1, arg2;
uc_reg_read(uc, UC_X86_REG_RDI, &arg1);
uc_reg_read(uc, UC_X86_REG_RSI, &arg2);
uint64_t result = arg1 + arg2;
std::cout << "arg1:" << arg1 << std::endl;
std::cout << "arg2:" << arg2 << std::endl;
std::cout << "result:" << result << std::endl;
uc_reg_write(uc, UC_X86_REG_RAX, &result);
std::cout << "host_function(end)" << std::endl;
return 0;
}
int main() {
uc_engine* uc;
uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
if (err != UC_ERR_OK) {
printf("uc_open() failed with error: %s\n", uc_strerror(err));
return -1;
}
uint64_t code_address = 0x1000;
#if 0x0
// https://disasm.pro/
mov rsi, 50
mov rdi, 30
mov eax, 1
int 0x80
mov rsi, 5
mov rdi, 3
mov eax, 1
int 0x80
ret
#endif
char code[] = "\x48\xC7\xC6\x32\x00\x00\x00\x48\xC7\xC7\x1E\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80\x48\xC7\xC6\x05\x00\x00\x00\x48\xC7\xC7\x03\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80\xC3";
OK(uc_mem_map(uc, code_address, 0x1000/*sizeof(code)*/, UC_PROT_ALL));
OK(uc_mem_write(uc, code_address, code, sizeof(code)));
uc_hook hook;
OK(uc_hook_add(uc, &hook, UC_HOOK_INTR,
(void*)host_function, NULL, code_address, code_address + sizeof(code)));
OK(uc_reg_write(uc, UC_X86_REG_RSP, &code_address));
#ifdef DEBUG // abort on uc_emu_start()'s error
OK(uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0));
#else // ignore uc_emu_start()'s error
uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0);
#endif
uint64_t result;
OK(uc_reg_read(uc, UC_X86_REG_RAX, &result));
printf("Emulation result: %llu\n", result);
uc_close(uc);
return 0;
}
Finally I could solve the problem (I'm closing this issue):
$ g++ host-calc.cpp -lunicorn -static && ./a.exe
host_function(begin)
arg1:30
arg2:50
result:80
host_function(end)
host_function(begin)
arg1:3
arg2:5
result:8
host_function(end)
Emulation result: 8
// https://disasm.pro/
mov rsi, 50
mov rdi, 30
mov eax, 1
int 0x80
mov rsi, 5
mov rdi, 3
mov eax, 1
int 0x80
ret // <--unnecessary (was the cause of the problem)
#include <unicorn/unicorn.h>
#include <assert.h>
#include <stdio.h>
#include <iostream>
#define OK(x) {uc_err __err; if ((__err = x)) { fprintf(stderr, "%s", uc_strerror(__err)); assert(false); } }
int host_function(uc_engine* uc, void* user_data) {
std::cout << "host_function(begin)" << std::endl;
uint64_t arg1, arg2;
uc_reg_read(uc, UC_X86_REG_RDI, &arg1);
uc_reg_read(uc, UC_X86_REG_RSI, &arg2);
uint64_t result = arg1 + arg2;
std::cout << "arg1:" << arg1 << std::endl;
std::cout << "arg2:" << arg2 << std::endl;
std::cout << "result:" << result << std::endl;
uc_reg_write(uc, UC_X86_REG_RAX, &result);
std::cout << "host_function(end)" << std::endl;
return 0;
}
int main() {
uc_engine* uc;
uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
if (err != UC_ERR_OK) {
printf("uc_open() failed with error: %s\n", uc_strerror(err));
return -1;
}
uint64_t code_address = 0x1000;
#if 0x0
// https://disasm.pro/
mov rsi, 50
mov rdi, 30
mov eax, 1
int 0x80
mov rsi, 5
mov rdi, 3
mov eax, 1
int 0x80
#endif
char code[] = "\x48\xC7\xC6\x32\x00\x00\x00\x48\xC7\xC7\x1E\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80\x48\xC7\xC6\x05\x00\x00\x00\x48\xC7\xC7\x03\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80";
OK(uc_mem_map(uc, code_address, 0x1000/*sizeof(code)*/, UC_PROT_ALL));
OK(uc_mem_write(uc, code_address, code, sizeof(code) - 1));
uc_hook hook;
OK(uc_hook_add(uc, &hook, UC_HOOK_INTR,
(void*)host_function, NULL, code_address, code_address + sizeof(code) - 1));
OK(uc_reg_write(uc, UC_X86_REG_RSP, &code_address));
OK(uc_emu_start(uc, code_address, code_address + sizeof(code) - 1, 0, 0));
uint64_t result;
OK(uc_reg_read(uc, UC_X86_REG_RAX, &result));
printf("Emulation result: %lu\n", result);
uc_close(uc);
return 0;
}
host_function
is not called in the following example.