我正在为Windows x86平台开发简单的调试器,只是为了测试。我已经实现了几乎所有我需要的功能,除了代码反汇编。我决定使用udis86库,但这对我来说并不重要。
在 0x86 - 0x64 架构中,任何指令最多只能有 15 个字节的长度,我怎么才能从例如 0x4000bcda 开始得到大约 10 条指令?
我有以下代码。
void disassembly(HANDLE hProcess, DWORD address)
{
BYTE buffer[15];
SIZE_T bytes_read;
GetProcessMemory(hProcess, (LPBYTE) address, buffer, sizeof(buffer), &bytes_read);
}
当GetProcessMemory函数没有失败时,缓冲区应该被数据填满。
但我不能假设缓冲区包含固定数量的指令。它可能是一个,两个或其他什么。
也许你有什么想法应该如何实现?
这是我目前的解决方案。
SIZE_T bytes_read;
BYTE buffer[4096];
if (!ReadProcessMemory(hProcess, (LPBYTE)address, buffer, sizeof(buffer), &bytes_read)) {
std::cout << "Cannot read process memory -> dissasembly." << std::endl;
return;
}
printf("Address : %#010x\n", address);
std::cout << "Disassembled code: " << std::endl;
ud_t ud_obj;
ud_init(&ud_obj);
ud_set_input_buffer(&ud_obj, buffer, sizeof(buffer));
ud_set_mode(&ud_obj, 64);
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
int counter = 0;
int instructionAmount = 10;
while (ud_disassemble(&ud_obj)) {
printf("\t%s\n", ud_insn_asm(&ud_obj));
counter++;
if (counter == instructionAmount) {
break;
}
}
基本上是可行的,但在我看来,这不是一个好的解决方案,可能会导致错误。
你说每条指令的最大字节数是15,你要读10条指令,所以15×10=150。 这就是你在调用ReadProcessMemory时应该读取多少内存。
但是指令不会消耗这么多的内存,一旦你把这些内存读到你的本地缓冲区,你就必须从buffer[0]开始读取每条指令,对它进行解码,得到它的长度,索引到下一条指令,对指令进行解码,一直到解码的指令数达到10条为止。 你解码的所有指令的总长度代表你的10条指令在缓冲区的最后一个字节。
你每次迭代都要增加指令计数器和一个独立的字节数计数器。