2016-08-19 39 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您需要對當前指令進行部分解碼才能找到下一個指令。 –