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