2016-08-19 38 views
0

我想监视函数操作码的汇编指令。我通过从内存中的函数中减去一个存根地址来获得函数大小的字节数。我目前只在寻找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; 
} 
+1

我还是不明白你要完成什么。我的理解是,函数中的操作码在运行时不会改变,为什么他们需要监视?你是*基准*还是*分析*一些代码? –

+0

我打算在以后增加更多mov的突变。 http://pastebin.com/G8WnSCDY – SamLaren

回答

1

为什么没有mov指令显示?

如果你在调试模式下,你需要知道你正在传递一个错误的地址到GetCurrentDate(PVOID),那意味着你是从一个错误的地址读取字节,还有另外一些错误,解决这个问题遵循这些步骤:

首先,从字节生成的代码:

mov eax, x  // code bytes: 8B 45 08 
mov result, eax // code bytes: 89 45 FC 

0x8B和0x89上是你应该看看你的附加组件内(INT,INT)函数的值。

其次,让你添加的第一个字节的地址(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函数的字节,因此当你发现一个字节equivalente到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指令,因为编译器创建了它们,你会感到惊讶。

Amrane Abdelkader。

+0

在包含mov al,0xc3或C3的函数中,扫描0xc3字节失败,因为modr/m,SIB或位移字节。或'C3F ...'。 x86是一个可变长度的指令集。无论如何,因为大部分建议都是有帮助的,OP似乎完全失去了循环遍历函数的字节。 –

+0

感谢您的反馈,我会建议一个更好的机制(扫描函数的所有opecode),但这个(只扫描0xC3)将在这个简单的例子中完成这项工作。 –

0

GetCurrentByte()每次调用它时都会查看第一个字节。看第一个字节size次对你没有帮助。

+0

将指令大小递增currentByte移动到下一个字节? – SamLaren

+0

你的意思是递增'PBYTE pCurrentByte'?是。 –

+0

@SamLaren您需要对当前指令进行部分解码才能找到下一个指令。 –