#include "stdafx.h" #include <windows.h> #include <assert.h> #pragma comment(lib,"user32.lib") typedef int (*detour_MessageBoxA)(HWND hWnd,LPCSTR,LPCSTR,UINT); detour_MessageBoxA msg; char origInstr[8] = {0}; char newInstr[8] = {"\xe9\x00\x00\x00\x00"}; int _tmain(int argc, _TCHAR* argv[]) { DWORD tmp; DWORD curr; char str[] = {""}; char* funcName = NULL; HMODULE hMod = LoadLibrary("user32.dll"); char* dllBase = (char*)hMod; IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER*)dllBase; IMAGE_OPTIONAL_HEADER *pOptHeader = (IMAGE_OPTIONAL_HEADER*)((BYTE*)dllBase + pDosHeader->e_lfanew + 24); IMAGE_EXPORT_DIRECTORY *pExport = (IMAGE_EXPORT_DIRECTORY*)((BYTE*)dllBase + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); char* dllname = dllBase+pExport->Name; //函数名数组RVA,其数组元素为函数名的RVA DWORD* funcNameRvaTab = (DWORD*)(dllBase+pExport->AddressOfNames); //函数在dllBase+pExport->AddressOfFunctions数组中的索引值 WORD* funcOrdinalTab = (WORD*)(dllBase+pExport->AddressOfNameOrdinals); DWORD* exportFuncAddrTab = (DWORD*)(dllBase+pExport->AddressOfFunctions); DWORD NumberOfNames = pExport->NumberOfNames; DWORD idx; DWORD oldProct; for(idx=0;idx<NumberOfNames;idx++) { funcName = (char*)(dllBase+funcNameRvaTab[idx]); if(strcmp((const char*)funcName,"MessageBoxA")==0) { DWORD idxInFuncAddrArry = funcOrdinalTab[idx]; //获得函数在dll中的入口地址 //exportFuncAddrTab[idxInFuncAddrArry]中存放的RVA了 msg = (detour_MessageBoxA)(dllBase + exportFuncAddrTab[idxInFuncAddrArry]); #if 0 //能成功调用msgBox,但过不了checkEsp 设置调用约定_cdecl->stdcall (msg)(NULL,"","",MB_OK); #endif assert(VirtualProtect(msg,8,PAGE_EXECUTE_READWRITE,&oldProct)!=0); //save ReadProcessMemory(GetCurrentProcess(),msg,origInstr,8,&tmp); __asm { mov eax,Lab1; mov curr,eax; } //把函数入口处的指令替换为相对跳转指令,跳转的目标为Lab1 //diff的计算可以搜索网上jmp跳转计算 DWORD diff = (DWORD)curr-(DWORD)msg-5; memcpy(newInstr+1,(char*)&diff,sizeof(DWORD)); WriteProcessMemory(GetCurrentProcess(),msg,newInstr,5,&tmp); (msg)(NULL,"","",MB_OK); } } while(1) { Sleep(1); } //这段代码本应该写成函数形式 但因为要用裸函数(否则函数开始就push ebp了) //所以直接改成代码片了 Lab1: static int cnt=0; cnt++; WriteProcessMemory(GetCurrentProcess(),msg,origInstr,8,&tmp); __asm { mov eax,Lab2; mov curr,eax; } assert(VirtualProtect((DWORD*)curr,8,PAGE_EXECUTE_READWRITE,&oldProct)!=0); //计算从Lab2跳回msg入口的相对偏移 DWORD diff = (DWORD)msg-(DWORD)curr-5; __asm { mov ebx,diff; mov eax,Lab2; inc eax; mov [eax],ebx; } Lab2: __asm { _emit 0xe9; _emit 0x00; _emit 0x00; _emit 0x00; _emit 0x00; } return 0; }