Я пытаюсь отслеживать инструкции по сборке кода операции. Я получаю размер функции в байтах, вычитая адрес заглушки из функций в памяти. В настоящее время я только ищу инструкцию MOV. Когда я отображаю currentByte, он выводит только Ú, у которого есть шестнадцатеричное значение 0xDA, которое является FIADD в сборке http://ref.x86asm.net/coder32.html#xDA Почему не отображается инструкция mov?
#include <iostream>
#include <Windows.h>
#include <ctime>
#include <vector>
#define PUSH 0x50
#define POP 0x58
#define MOV 0xB8
#define NOP 0x90
#define ADD 0x01
#define AND 0x21
#define XOR 0x31
#define OR 0x09
#define SBB 0x19
#define SUB 0x29
using namespace std;
int add(int x, int y)
{
int result;
__asm
{
mov eax, x
add eax, y
mov result, eax
xor eax, eax
}
return result;
}
void stub() { return; }
DWORD GetFunctionSize(DWORD* functionStartAddress, DWORD* stub)
{
DWORD dwOldProtect;
DWORD *func, *stubAddr;
func = (DWORD*)functionStartAddress;
stubAddr = (DWORD*)stub;
DWORD size = func - stubAddr;
VirtualProtect(func, size, PAGE_EXECUTE_READWRITE, &dwOldProtect);
return size;
}
void GetCurrentByte(PVOID function)
{
vector<PBYTE> currByte;
PBYTE pCurrentByte = (PBYTE)function;
if (*pCurrentByte == MOV)
{
cout << "MOV instr.\n";
}
cout << *pCurrentByte;
currByte.push_back(pCurrentByte);
}
int main()
{
DWORD size = GetFunctionSize((DWORD*)&add, (DWORD*)&stub);
for (int i = 0; i < size; i++)
{
GetCurrentByte(add);
}
system("pause");
return 0;
}
Почему не отображается инструкция mov?
Если вы находитесь в режиме отладки, вам нужно знать, что вы передаете неправильный адрес в GetCurrentDate (PVOID), это означает, что вы читаете байты с неправильного адреса, и есть еще несколько ошибок, чтобы решить эту проблему, выполните следующие действия:
Во-первых, байты кода, сгенерированные из:
mov eax, x // code bytes: 8B 45 08
mov result, eax // code bytes: 89 45 FC
0x8B и 0x89 — это значения, которые вы должны искать в своей функции add (int, int).
во-вторых, чтобы получить адрес первого байта вашей функции add (int, int), я предлагаю использовать эту функцию:
#define ASM_CALL 0x000000E8
#define ASM_JMP 0x000000E9
#define ASM_CALL_SIZE 0x00000001
#define ASM_CALL_FULL_SIZE 0x00000005
DWORD GetFuncAddress(DWORD funcAddress)
{
BYTE calledAddress = *(BYTE*)funcAddress;
while (calledAddress == ASM_CALL || calledAddress == ASM_JMP) {
funcAddress = funcAddress + *(DWORD*)(funcAddress + ASM_CALL_SIZE) + ASM_CALL_FULL_SIZE;
calledAddress = *(BYTE*)funcAddress;
}
return funcAddress; // The address of the first byte of the function.
}
в-третьих, я предлагаю оптимизацию внутри вашего GetFunctionSize (DOWRD), так как вы знаете, что ваша функция добавления заканчивается одним возвратом:
return result; // code bytes: C3
почему бы просто не бросить цикл в байтах функции add, поэтому, когда вы найдете байт, эквивалентный 0xC3, вы получите точный размер вашей функции (в байтах), этот код прояснит ситуацию:
#define ASM_RET 0xC3
SIZE_T GetFunctionSize(DWORD functionAddress)
{
SIZE_T funcSize = 0;
// Loop thru func's bytes, and breaks when return byte found.
while (*((PBYTE)functionAddress++) != RET)
funcSize++;
return funcSize;
}
в-четвертых, функция GetCurrentByte (PVOID) нуждается в некотором обслуживании, поэтому я предлагаю:
#define ASM_MOV1 0x8B
#define ASM_MOV2 0x89
VOID GetCurrentByte(DWORD functionAddress, UINT &index)
{
BYTE tempByte = *((PBYTE)functionAddress + index);
// search for bytes which contains a mov instruction:
if (tempByte == ASM_MOV1 || tempByte == ASM_MOV2)
cout << "MOV instr found at : " << hex << ((DWORD)functionAddress + index) << endl;
}
наконец, полный код будет выглядеть так:
#include <iostream>
#include <Windows.h>#define ASM_RET 0xC3
#define ASM_MOV1 0x8B
#define ASM_MOV2 0x89
#define ASM_CALL 0xE8
#define ASM_JMP 0xE9
#define ASM_CALL_SIZE 0x01
#define ASM_CALL_FULL_SIZE 0x05
using namespace std;
INT add(INT x, INT y)
{
int result;
__asm
{
mov eax, x
add eax, y
mov result, eax
xor eax, eax
}
return result;
}
DWORD GetFuncAddress(DWORD funcAddress)
{
BYTE calledAddress = *(BYTE*)funcAddress;
while (calledAddress == ASM_CALL || calledAddress == ASM_JMP) {
funcAddress = funcAddress + *(DWORD*)(funcAddress + ASM_CALL_SIZE) + ASM_CALL_FULL_SIZE;
calledAddress = *(BYTE*)funcAddress;
}
return funcAddress;
}
SIZE_T GetFunctionSize(DWORD functionAddress)
{
SIZE_T funcSize = 0;
while (*((PBYTE)functionAddress++) != ASM_RET)
{
funcSize++;
}
return funcSize;
}VOID GetCurrentByte(DWORD functionAddress, UINT &index)
{
BYTE tempByte = *((PBYTE)functionAddress + index);
if (tempByte == ASM_MOV1 || tempByte == ASM_MOV2)
cout << "MOV instr found at : " << hex << ((DWORD)functionAddress + index) << endl;
}INT main()
{
DWORD funcAddress = GetFuncAddress((DWORD)add); // Get func address.
SIZE_T size = GetFunctionSize(funcAddress); // Get func size (bytes).
for (UINT i = 0; i < size; i++) // loop thru the function memory block.
{
GetCurrentByte(funcAddress, i);
}system("pause");
return 0;
}
Не удивляйтесь, если вы нашли много инструкций MOV в своей функции, потому что компилятор создал их.
Амран Абделькадер.
GetCurrentByte()
смотрит на первый байт каждый раз, когда вы его вызываете. Глядя на первый байт size
времена не помогают