1. 程式人生 > >用C/C++提取可執行程式碼

用C/C++提取可執行程式碼

使用C/C++語言,結合內聯彙編,可以方便的提取可執行程式碼。下面一個例子,掌握了這種方法,很容易舉一反三。

例程:

先用內聯彙編設計出一個顯示對話方塊的函式MsgBox,然後通過C/C++指標把這個函式的實體地址程式碼取出並列印。

程式使用了2個函式,MsgBox()用於顯示對話方塊和提取對話方塊的機器程式碼、PrintMsgboxCode()列印MsgBox()函式中內聯彙編的機器程式碼。

//下面程式設計實現

#include <windows.h>

#include <iostream>

using namespace std;

#include<stdio.h>

#define PROC_BEGIN_asm _emit 0x90   _asm _emit 0x90/

  _asm _emit 0x90   _asm _emit 0x90/

_asm _emit 0x90   _asm _emit 0x90/

_asm _emit 0x90   _asm _emit 0x90

#define PROC_END PROC_BEGIN

#define BEGIN_STRLEN 0x08

#define END_STRLEN 0x08

#define MAX_Sc_Len 0x400

//資訊顯示對話方塊函式

void MsgBox(){

//獲取MessageBoxA在記憶體中的地址

HINSTANCE hLibMsg=LoadLibrary("user32.dll");

DWORD dwMessageBoxAddress=(DWORD)GetProcAddress(hLibMsg,"MessageBoxA");

_asm{

PROC_BEGIN

push MB_ICONINFORMATION or MB_OK

call Func1

_emit'T'

_emit 'e'

_emit's'

_emit 't'

_emit0

Func1:

call Func2

_emit'H'

_emit'e'

_emit'l'

_emit'l'

_emit'o'

_emit0

Func2:

push NULL

call DWORD PTR [dwMessageBoxAddress]

}

}

//列印資訊顯示對話方塊函式的機器程式碼

void PrintMsgBoxCode(){

char buffer[MAX_Sc_Len];

char *pSc_addr;

int i,k;

int Sc_Len;//實際程式碼的長度

char *fnbgn_str="/x90/x90/x90/x90/x90/x90/x90/x90/x90";//標記開始位置的字串

char *fnend_str="/x90/x90/x90/x90/x90/x90/x90/x90/x90";//標記結束位置的字串

pSc_addr=(char*)MsgBox;

//找到MsgBox的開始位置

for(k=0;k<MAX_Sc_Len;++k){

if(memcmp(pSc_addr+k,fnbgn_str,BEGIN_STRLEN)==0){

pSc_addr+=(k+8);

break;

}

}

//找MsgBox的結尾及長度

for(k=0;k<MAX_Sc_Len;++k){

if(memcmp(pSc_addr+k,fnend_str,END_STRLEN)==0){

if(k<MAX_Sc_Len)Sc_len=k;

elsereturn;

break;

}

}

//將可執行程式碼複製到buffer

memcpy(buffer,pSc_addr,Sc_len);

//顯示

for(i=0;i<Sc_len;i++){

if(!(i%10))cout<<"/n";

printf("  %02x",buffer[i]&0xFF);

}

}

void main(){

PrintMsgBoxCode();

MsgBox();

}