用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();
}