透明加解密的基础操作HOOK API:演示了通过jump和push-ret两种不同方式进行hook的操作,以及简单的shellcode
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <windows.h>
using namespace std;
typedef int (WINAPI* FUNC_MESSAGEBOXW)(HWND hwnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
typedef BOOL (WINAPI* FUNC_DELETEFILEW)(LPCWSTR filepath);
typedef void (WINAPI *FUNC)();
FUNC_MESSAGEBOXW RealMessageBoxW = ::MessageBoxW;
FUNC_DELETEFILEW RealDeleteFileW = ::DeleteFileW;
BOOL WINAPI MyDeleteFileW(LPCWSTR filepath)
{
return ::MessageBoxW(0,L"DeleteFile被hook了",L"hook",0);
}
int WINAPI MyMessageBoxW(HWND hwnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
{
return RealMessageBoxW(0,L"MessageBox被hook了",L"hook",0);
}
void HookApi_JMP(BYTE** ppRealApi,BYTE* pMyApi) //JMP方式只破坏5字节,目测可HOOK大多数函数
{
//构造真实的messagebox
DWORD old;
BYTE* tmp = new BYTE[20];
::VirtualProtect(tmp, 20, PAGE_EXECUTE_READWRITE, &old);
::memcpy(tmp,*ppRealApi,5);
tmp[5] = 0xe9;
*(int*)(&tmp[6]) = (int)*ppRealApi-(int)&tmp[5];
//hook原始的messagebox
::VirtualProtect(*ppRealApi, 5, PAGE_EXECUTE_READWRITE, &old);
*(*ppRealApi) = 0xe9;
*(int*)(&(*ppRealApi)[1]) = (int)pMyApi-((int)*ppRealApi+5);
//保存真实的messagebox
*ppRealApi = tmp;
}
void HookApi_PUSH(BYTE** ppRealApi,BYTE* pMyApi) //PUSH-RET方式破坏了6个字节,连MessageBoxW都无法HOOK
{
//构造真实的messagebox
DWORD old;
BYTE* tmp = new BYTE[20];
::VirtualProtect(tmp, 20, PAGE_EXECUTE_READWRITE, &old);
::memcpy(tmp,*ppRealApi,6);
tmp[6] = 0x68;
*(int*)(&tmp[7]) = (int)*ppRealApi+6;
tmp[11] = 0xC3;
//hook原始的messagebox
::VirtualProtect(*ppRealApi, 6, PAGE_EXECUTE_READWRITE, &old);
*(*ppRealApi) = 0x68;
*(int*)(&(*ppRealApi)[1]) = (int)pMyApi;
*(*ppRealApi+5) = 0xC3;
//保存真实的messagebox
*ppRealApi = tmp;
}
void HookApi_IAT(int RealApi,int MyApi) //IAT方式虽然简单通用,但是对拿到真实API地址的调用显然无法拦截
{
int base = (int)GetModuleHandle(NULL);
IMAGE_NT_HEADERS* ntheader = (IMAGE_NT_HEADERS *)(base+((IMAGE_DOS_HEADER*)base)->e_lfanew);
IMAGE_IMPORT_DESCRIPTOR* imp = (IMAGE_IMPORT_DESCRIPTOR*)(base+ntheader->OptionalHeader.DataDirectory[1].VirtualAddress);
while(imp->FirstThunk)
{
IMAGE_THUNK_DATA* td = (IMAGE_THUNK_DATA*)(base+imp->FirstThunk);
while(td->u1.AddressOfData)
{
if(*(int*)td==(int)RealApi)
*(int*)td = (int)MyApi;
td ++;
}
imp++;
}
}
void HookApiPushTest()
{
HookApi_PUSH((BYTE**)&RealDeleteFileW,(BYTE*)MyDeleteFileW);
::DeleteFileW(NULL);
}
void HookApiJmpTest()
{
HookApi_JMP((BYTE**)&RealMessageBoxW,(BYTE*)MyMessageBoxW);
::MessageBoxW(0,0,0,0);
}
void HookApiIATTest()
{
HookApi_IAT((int)RealMessageBoxW,(int)MyMessageBoxW);
::MessageBoxW(0,0,0,0);
}
void ShellCodeTest()
{
BYTE shellcode[] = {0x55,0x8b,0xec,0x6a,0x00,0x6a,0x00,0x6a,0x00,0x6a,0x00,0xB8,0xCF,0xFE,0xEE,0x75,0xFF,0xD0,0x8b,0xe5,0x5d,0xc3};
//BYTE shellcode[] = {0x55,0x89,0xe5,0x6a,0x00,0x6a,0x00,0x6a,0x00,0x6a,0x00,0xB8,0xCF,0xFE,0xEE,0x75,0xFF,0xD0,0x89,0xec,0x5d,0xc3};
/*_asm
{
push ebp; 0x55
mov ebp,esp; 0x8B,0xEC / 0x89,0xE5
push 0; 0x6A,0x00
push 0; 0x6A,0x00
push 0; 0x6A,0x00
push 0; 0x6A,0x00
mov eax,MessageBoxW; 0xB8,0xCF,0xFE,0xEE,0x75
call eax; 0xFF,0xD0
mov esp,ebp 0x8B,0xE5 / 0x89,0xEC
pop ebp 0x5D
ret 0xC3
}*/
*(int*)(&shellcode[12]) = (int)::MessageBoxW;
DWORD old = 0;
VirtualProtect(shellcode,sizeof(shellcode),PAGE_EXECUTE_READWRITE,&old);
FUNC fun = (FUNC)&shellcode[0];
fun();
}
int main()
{
//HookApiPushTest();
HookApiJmpTest();
//HookApiIATTest();
//ShellCodeTest();
system("pause");
return 0;
}