首页 > 其他分享 >逆向 | inlinehook 简单实践

逆向 | inlinehook 简单实践

时间:2022-08-14 21:45:27浏览次数:62  
标签:逆向 return 实践 dll LENGTH DWORD PATCH inlinehook hProcess

逆向 | inlinehook 简单实践

好久之前就学过了,结果代码找不到了,今儿留个档。

总结一下就是:

  1. 整个被注入的dll,在里头进行hook的操作
  2. 整个exe来注入上面那个dll

代码如下:

测试的被注入程序(test.exe):

#include <stdio.h>
#include <windows.h>
int main(){
	while (1){
		getchar();
		MessageBoxA(0,"啊哈",0,0);
	}

	return 0;
}

被注入的dll(关键部分,inject_dll.dll):
我在调试的时候不知道咋地一开始memcpy过不了,然后过了会儿它自己就好了。。。

// inject_dll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <stdio.h>
#include <gl/glut.h>


DWORD g_dwOldAddr;         // 原始函数地址
DWORD g_dwNewAddr;         // Hook函数地址
DWORD g_dwHookFlag;     // 标志有没有被hook


#define PATCH_LENGTH 5

DWORD dwRetAddress;
BOOL setInlineHook(DWORD dwOldAddr, DWORD dwNewAddr){
	BOOL bRet = FALSE;
	dwRetAddress = dwOldAddr + PATCH_LENGTH;       // hook结束以后的返回地址
	BYTE byJmpCode[PATCH_LENGTH] = {0xe9};
	DWORD dwOldProtect;
	
	// 之前的字节码
	static BYTE byOriginalCode[PATCH_LENGTH] = {0};
	static BOOL bHookFlag = FALSE;

	// 测试用
	char buf[1024] = {0};

	
	// 1. 初始化byJmpCode
	memset(&byJmpCode[1], 0x90, PATCH_LENGTH-1);
	
	// 2. 存储跳转地址
	*(DWORD*)&byJmpCode[1] = (DWORD)dwNewAddr - (DWORD)dwOldAddr - 5;
	
	// 3. 备份被覆盖的code
	memcpy(byOriginalCode, (LPVOID)dwOldAddr, PATCH_LENGTH);
	

	// 4. 开始patch
	if (!bHookFlag)
	{
		// hook
		VirtualProtect((LPVOID)dwOldAddr,
			PATCH_LENGTH, PAGE_EXECUTE_READWRITE, &dwOldProtect);     // 这个是成功执行的

		// 好了它又没问题了,不知道咋回事之前会崩溃
		memcpy((LPVOID)dwOldAddr, byJmpCode, PATCH_LENGTH);     // 这里拷贝的时候有问题,会出现不可写的问题

		
		VirtualProtect((LPVOID)dwOldAddr, PATCH_LENGTH, dwOldProtect, 0);
		bHookFlag = TRUE;
		bRet = TRUE;
	}else{
		// 取消hook
		VirtualProtect((LPVOID)dwOldAddr,
			PATCH_LENGTH, PAGE_EXECUTE_READWRITE, &dwOldProtect);
		memcpy((LPVOID)dwOldAddr, byOriginalCode, PATCH_LENGTH);
		VirtualProtect((LPVOID)dwOldAddr, PATCH_LENGTH, dwOldProtect, 0);
		bHookFlag = FALSE;
		bRet = TRUE;
	}

	return bRet;
}

char szNewText[] = "Hook!";
void __declspec(naked) MyglBegin(GLenum mode){
	__asm{
		// 1. 保存寄存器
		pushad;
		pushfd;
		// 2. 修改数据
		lea eax, dword ptr ds:[szNewText];
		mov dword ptr ss:[esp+0x24+8], eax;

		// 3. 恢复寄存器
		popfd;
		popad;
		// 4. 执行覆盖的代码
		mov edi, edi;
		push ebp;
		mov ebp, esp;
		// 5. 返回执行
		jmp dwRetAddress;
	}
}


/*
void WINAPI MyglBegin(GLenum mode)
{
	MessageBox(0,"获取到调用",0,0);
	if(mode==GL_TRIANGLE_STRIP||mode==GL_TRIANGLE_FAN)
	{
		glDisable(GL_DEPTH_TEST);
		MessageBox(0,"获取到调用",0,0);
	} 
	
	glBegin(mode);
}
*/


// 线程函数
DWORD WINAPI ThreadProc(LPVOID lpParameter){
	// 保存原始函数地址
	//DWORD pOldFuncAddr = (DWORD)GetProcAddress(LoadLibrary("opengl32.dll"), "glBegin");
	DWORD pOldFuncAddr = (DWORD)GetProcAddress(LoadLibrary("user32.dll"), "MessageBoxA");
	char buf[1024] = {0};
	sprintf(buf, "获取到函数地址:%p ", pOldFuncAddr);
	MessageBox(0, buf, 0, 0);
	
	// 安装或者卸载HOOK
	BOOL ret;
	if (!g_dwHookFlag){
		ret = setInlineHook(pOldFuncAddr, (DWORD)MyglBegin);
		if (ret){
			MessageBox(0, "安装hook成功!", 0, 0);
		}else{
			MessageBox(0, "安装hook失败!", 0, 0);
		}
		
	}

	return 0;
}




BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	switch ( ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL,0,
            (LPTHREAD_START_ROUTINE)ThreadProc,
            NULL, 0,NULL);//创建新线程执行代码
        break;
    case DLL_PROCESS_DETACH:
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
	}
    return TRUE;
}

注入用的程序,常规操作远程线程注入:

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

DWORD GetPid(char* szName){
    HANDLE hprocessSnap = NULL;
    PROCESSENTRY32 pe32 = {0};
    hprocessSnap = CreateToolhelp32Snapshot(
        TH32CS_SNAPPROCESS,
        0);//捕捉所有进程的快照
    if (hprocessSnap == INVALID_HANDLE_VALUE){
        //快照失败
        return 0;
    }
    //初始化pe32结构体
    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(hprocessSnap, &pe32)){
        do{
            if (!strcmp(szName, pe32.szExeFile)){
                printf("Process Found, PID: %d \n", (int)pe32.th32ProcessID);
                return (int)pe32.th32ProcessID;
            }
            //遍历查找进程名
        }while (Process32Next(hprocessSnap, &pe32));
    }else{
        CloseHandle(hprocessSnap);
    }
    return 0;
}



//远程线程注入
BOOL load_dll(DWORD dwProcessID, char* szDllPathName)
//进程PID和dll完整的路径
{
    BOOL bRet;
    HANDLE hProcess;
    HANDLE hThread;
    DWORD dwLength;
    DWORD dwLoadAddr;
    LPVOID lpAllocAddr;
    DWORD dwThreadID;
    HMODULE hModule;
    //获取进程句柄
    hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessID);
    printf("%x \n", hProcess);
    if (hProcess == NULL)
    {
        OutputDebugString("fail to open process \n");
        return FALSE;
    }
    //把DLL文件路径字符串存入被注入进程的内存空间
    //计算dll路径名字长度,并且加上结尾0的空间
    dwLength = strlen(szDllPathName)+1;
    //远程申请内存空间
    lpAllocAddr = (LPVOID)VirtualAllocEx(hProcess,NULL,dwLength,MEM_COMMIT,PAGE_READWRITE);
    if (lpAllocAddr == NULL){
        OutputDebugString("VirtualAllocEx error \n");
        CloseHandle(hProcess);
        return FALSE;
    }
    //拷贝dll路径名字到目标进程的内存
    bRet = WriteProcessMemory(hProcess, lpAllocAddr,szDllPathName,dwLength,NULL);
    if (bRet == NULL){
        OutputDebugString("bRet error \n");
        CloseHandle(hProcess);
        return FALSE;
    }
    //获取kernel32.dll的地址
    hModule = GetModuleHandle("Kernel32.dll");
    if (!hModule)
    {
        OutputDebugString("GetModuleHandle error \n");
        CloseHandle(hProcess);
        return FALSE;
    }
    //获取LoadLibraryA函数地址
    dwLoadAddr = (DWORD)GetProcAddress(hModule, "LoadLibraryA");
    if (!dwLoadAddr )
    {
        OutputDebugString("GetProcAddress error \n");
        CloseHandle(hProcess);
        CloseHandle(hModule);
        return FALSE;
    }
	
    //创建远程线程,加载dll
    hThread = CreateRemoteThread(hProcess, NULL, 0, (unsigned long (__stdcall *)(void *))dwLoadAddr, lpAllocAddr, 0, NULL);
    printf("%x \n", hThread);
    if (hThread == NULL)
    {
        OutputDebugString("fail to open RomoteThread \n");
        CloseHandle(hProcess);
        return FALSE;
    }
    CloseHandle(hProcess);
	
    return TRUE;
}
void main(){
	load_dll(GetPid("test.exe"),
		"C:\\Users\\thinkpad\\Desktop\\hookopengl\\inject_dll\\inject_dll\\Debug\\inject_dll.dll");
}

标签:逆向,return,实践,dll,LENGTH,DWORD,PATCH,inlinehook,hProcess
From: https://www.cnblogs.com/Mz1-rc/p/16586411.html

相关文章

  • 脚本入门实践
    Linuxshell脚本入门到实战详解入门小站 入门小站 2022-07-2522:02 发表于湖北收录于合集#Linux478个一、shell入门简介1.1什么是shellshell脚本简介#......
  • ExtJS - ExtJS最佳实践
    更新记录转载请注明出处:https://www.cnblogs.com/cqpanda/p/16583543.html2022年8月14日发布。2022年8月13日从笔记迁移到博客。ExtJS教程汇总:https://www.cnblogs......