2016-08-19 2 views
0

함수 opcode의 어셈블리 명령어를 모니터하려고합니다. 메모리의 함수에서 스텁 주소를 빼서 함수 크기를 바이트 단위로 얻습니다. 현재 mov 명령 만 찾고 있습니다. currentByte를 표시 할 때 조립체에서 FIADD 인 0xDA의 16 진수 값을 가진 Ú 만 출력합니다. http://ref.x86asm.net/coder32.html#xDA mov 명령이 표시되지 않는 이유는 무엇입니까?opcode 모니터링

#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

나는 아직도 당신이 달성하고자하는 것을 이해하지 못합니다. 필자가 알고있는 점은 함수의 opcode가 런타임 중에 변경되지 않는다는 것입니다. 따라서 모니터링이 필요한 이유는 무엇입니까? * 벤치마킹 * 또는 * 프로파일 링 * 일부 코드입니까? –

+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) 기능을 찾아야한다 값됩니다. 셋째

#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) 내부 최적화를 제안한다

둘째, 추가 기능의 첫 번째 바이트의 주소 (INT, INT) 함수는 내가이 기능을 사용하는 것이 좋습니다를 얻을 수

return result; // code bytes: C3 

가 왜 그냥 루프, 추가 기능의 바이트를 던져 당신이 0xC3에 바이트 equivalente을 찾을 때, 당신이 정확한 크기로 끝날 것입니다 : 당신은 당신의 추가 기능이 하나의 복귀로 끝나는 것을 알고 (바이트 단위로)이 코드는 일을 명확하게합니다 :

#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

modr/m, SIB 또는 변위 바이트로'mov al, 0xc3' 또는'C3'을 포함하는 함수에서'0xc3' 바이트에 대한 검색이 실패합니다.또는 '0F C3 ...'. x86은 가변 길이 명령어 세트입니다. 어쨌든 대부분의 조언이 도움이되고 OP가 함수의 바이트를 루핑하는 것에 대해 완전히 잃어버린 것처럼 보입니다. –

+0

귀하의 의견을 보내 주셔서 감사합니다, 더 나은 메커니즘 (함수의 모든 opecode 스캔)하지만이 하나의 (단지 0xC3에 대한 검색)이 간단한 예제에서 일을 할 것이 좋습니다 것이 좋습니다. –

0

GetCurrentByte()는 첫 번째 바이트에 당신이 그것을 호출 할 때마다 보인다. 첫 번째 바이트를 보면 size 번은 도움이되지 않습니다.

+0

명령어 크기만큼 currentByte를 증가 시키면 다음 바이트로 이동하겠습니까? – SamLaren

+0

'PBYTE pCurrentByte'를 증가시키는 것을 의미합니까? 예. –

+0

@SamLaren 다음 명령을 찾으려면 현재 명령을 부분적으로 디코딩해야합니다. –