使用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'
_emit
0
Func1:
call Func2
_emit
'H'
_emit
'e'
_emit
'l'
_emit
'l'
_emit
'o'
_emit
0
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;
else
return;
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();
}