HOOK与ShellCode的简单演示

透明加解密的基础操作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;
}