zoukankan      html  css  js  c++  java
  • 逆向 | IATHook 全屏加速挂

    和上一篇随笔原理是一样的IAThook
    这次hook的是timeGetTime这个函数,位于winmm.dll中,直接上代码了。

    1.dll:

    // 1.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    #include <stdio.h>
    
    
    DWORD g_dwOldAddr;         // 原始函数地址
    DWORD g_dwNewAddr;         // Hook函数地址
    DWORD g_dwIATHookFlag;     // 标志有没有被hook
    
    BOOL SetIATHook(DWORD dwOldAddr, DWORD dwNewAddr){
    	BOOL bFlag = FALSE;
    	DWORD dwImageBase = 0;
    	PDWORD pFuncAddr = NULL;
    	PIMAGE_NT_HEADERS pNtHeader = NULL;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL;
    	DWORD dwOldProtect = 0;
    
    	// 得到exe模块基址
    	dwImageBase = (DWORD)GetModuleHandle(NULL);
    	pNtHeader = (PIMAGE_NT_HEADERS)(dwImageBase + ((PIMAGE_DOS_HEADER)dwImageBase)->e_lfanew);
    	pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase + 
    		pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    	
    	
    	// 遍历IAT表 找到这个函数的地址
    	while (pImportDescriptor->FirstThunk != 0 && bFlag == FALSE)
    	{
    		printf("pImportDescriptor: %x 
    ", pImportDescriptor);
    		pFuncAddr = (PDWORD)(dwImageBase + pImportDescriptor->FirstThunk);
    		while (*pFuncAddr) // 遍历该模块中的函数
    		{
    			if(dwOldAddr == *pFuncAddr){
    				// 找到要Hook的函数,先修改内存页的属性
    				VirtualProtect(pFuncAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
    				printf("found IAT Addr: %x
    ", pFuncAddr);
    				*pFuncAddr = dwNewAddr;   // !!!更改过IAT中函数的地址
    				VirtualProtect(pFuncAddr, sizeof(DWORD), dwOldProtect, 0);
    				bFlag = TRUE;
    				break;
    			}
    			pFuncAddr ++;
    		}
    		pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDescriptor+sizeof(IMAGE_IMPORT_DESCRIPTOR));
    	}
    	if(bFlag == FALSE){
    		// 没找到
    		printf("iat not found...
    ");
    	}
    	// 修改状态
    	g_dwOldAddr = dwOldAddr;
    	g_dwNewAddr = dwNewAddr;
    	g_dwIATHookFlag = 1;
    	return bFlag;
    }        
    
    BOOL UnIATHook(){
    	BOOL bFlag = FALSE;
    	DWORD dwImageBase = 0;
    	PDWORD pFuncAddr = NULL;
    	PIMAGE_NT_HEADERS pNtHeader = NULL;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL;
    	DWORD dwOldProtect = 0;
    
    	// 判断是否hook
    	if (!g_dwIATHookFlag)
    	{
    		OutputDebugString("UnIATHook失败:尚未进行IAT Hook!");
    		return bFlag;
    	}
    	
    	// 得到exe模块基址
    	dwImageBase = (DWORD)GetModuleHandle(NULL);
    	pNtHeader = (PIMAGE_NT_HEADERS)(dwImageBase + ((PIMAGE_DOS_HEADER)dwImageBase)->e_lfanew);
    	pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase + 
    		pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    	
    	// 遍历IAT表 找到这个函数的地址
    	while (pImportDescriptor->FirstThunk != 0 && bFlag == FALSE)
    	{
    		pFuncAddr = (PDWORD)(dwImageBase + pImportDescriptor->FirstThunk);
    		while (*pFuncAddr) // 遍历该模块中的函数
    		{
    			if(g_dwNewAddr == *pFuncAddr){
    				// 找到要Hook的函数,先修改内存页的属性
    				VirtualProtect(pFuncAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
    				*pFuncAddr = g_dwOldAddr;   // !!!更改过IAT中函数的地址
    				VirtualProtect(pFuncAddr, sizeof(DWORD), dwOldProtect, 0);
    				bFlag = TRUE;
    				break;
    			}
    			pFuncAddr ++;
    		}
    		pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDescriptor+sizeof(PIMAGE_IMPORT_DESCRIPTOR));
    	}
    	// 修改状态
    	g_dwOldAddr = 0;
    	g_dwNewAddr = 0;
    	g_dwIATHookFlag = 1;
    	return bFlag;
    }       
    
    
    int WINAPI MyHookFunc(){
    	static int last_time = 100;
    	static int i = 0;
    	// 定义函数指针
    	typedef DWORD (WINAPI *PFNTIMEGETTIME)(VOID);
    
    	// 执行真正的函数
    	int ret = ((PFNTIMEGETTIME)g_dwOldAddr)();
    	ret = ret + last_time*i;
    	i++;
    	return ret;
    }
    
    
    
    
    // 线程函数
    DWORD WINAPI ThreadProc(LPVOID lpParameter){
    	// 保存原始函数地址
    	DWORD pOldFuncAddr = (DWORD)GetProcAddress(LoadLibrary("winmm.dll"), "timeGetTime");
    	printf("Get Original func addr: %x
    ", pOldFuncAddr);
    	// 安装或者卸载HOOK
    	if (!g_dwIATHookFlag){
    		SetIATHook(pOldFuncAddr, (DWORD)MyHookFunc);
    	}else{
    		UnIATHook();
    	}
    	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;
    }
    

    然后注入用的是之前的:
    injection.cpp:

    #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 
    ", (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 
    ", hProcess);
        if (hProcess == NULL)
        {
            OutputDebugString("fail to open process 
    ");
            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 
    ");
            CloseHandle(hProcess);
            return FALSE;
        }
        //拷贝dll路径名字到目标进程的内存
        bRet = WriteProcessMemory(hProcess, lpAllocAddr,szDllPathName,dwLength,NULL);
        if (bRet == NULL){
            OutputDebugString("bRet error 
    ");
            CloseHandle(hProcess);
            return FALSE;
        }
        //获取kernel32.dll的地址
        hModule = GetModuleHandle("Kernel32.dll");
        if (!hModule)
        {
            OutputDebugString("GetModuleHandle error 
    ");
            CloseHandle(hProcess);
            return FALSE;
        }
        //获取LoadLibraryA函数地址
        dwLoadAddr = (DWORD)GetProcAddress(hModule, "LoadLibraryA");
        if (!dwLoadAddr )
        {
            OutputDebugString("GetProcAddress error 
    ");
            CloseHandle(hProcess);
            CloseHandle(hModule);
            return FALSE;
        }
    	
        //创建远程线程,加载dll
        hThread = CreateRemoteThread(hProcess, NULL, 0, (unsigned long (__stdcall *)(void *))dwLoadAddr, lpAllocAddr, 0, NULL);
        printf("%x 
    ", hThread);
        if (hThread == NULL)
        {
            OutputDebugString("fail to open RomoteThread 
    ");
            CloseHandle(hProcess);
            return FALSE;
        }
        CloseHandle(hProcess);
    	
        return TRUE;
    }
    
    //之后在main函数中调用即可
    //例:load_dll(1304, "C:\Documents and Settings\Administrator\桌面\线程注入\6.dll");
    //popcapgame1.exe
    void main(){
    	load_dll(GetPid("popcapgame1.exe"), "C:\Users\thinkpad\Desktop\IATHook\dll2全屏加速\1\Debug\1.dll");
    }
    

    本文来自博客园,作者:Mz1,转载请注明原文链接:https://www.cnblogs.com/Mz1-rc/p/15309822.html

    如果有问题可以在下方评论或者email:mzi_mzi@163.com

  • 相关阅读:
    项目经理手记
    自动填写版权信息
    在批处理中实现等待/延迟/暂停
    使用 PowerDesigner 设计数据库
    如何让PowerDesigner支持自动生成含SQL Server 2000的表和列注释的角本
    管理人员的招聘始末谈
    PowerDesign 6简易介绍
    PowerDesigner11.0使用总结
    用表单字段加亮的方式为用户提供友好的界面
    择才有道——企业招聘方式比较
  • 原文地址:https://www.cnblogs.com/Mz1-rc/p/15309822.html
Copyright © 2011-2022 走看看