丁同亚的博客
夺朱非正色
  1. 创建DLL
  2. 在Dll  DLL_PROCESS_ATTACH 时  OutputDebugString(L"[+] DLL已经注入-----");
  3. 创建一个程序用来将Dll注入进去
  4. 获取目标进程的进程ID,打开进程,(注意权限参数)获取进程句柄,
  5. 通过VirtualAllocEx申请目标进程的一块空间,将注入DLL的路径写进去
  6. 创建远程线程,注意第四第五个参数,线程函数的地址,和线程参数,这个线程参数回同时就是线程函数的参数,这样的话线程函数是Loadlibrary,参数是DLL地址,开启线程就会执行DLL加载,我们的DLL就会被加载进入.
    1.   
      // IATHook.cpp : 定义控制台应用程序的入口点。
      //
      
      #include "stdafx.h"
      #include <windows.h>
      #include <tlhelp32.h>
      #include <stdio.h>
      #include <cwchar>
      #include <iostream>
      #include <cstring>
      int contains_string_optimized(const TCHAR* target, const TCHAR* substr) {
      	return (target && substr) ? (_tcsstr(target, substr) != NULL) : 0;
      }
      PROCESSENTRY32* EnumProcesses() {
      	// 1. 创建进程快照
      	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      	if (hSnapshot == INVALID_HANDLE_VALUE) {
      		printf("快照创建失败\n");
      		return NULL;
      	}
      
      	// 2. 初始化结构体
      	PROCESSENTRY32 pe;
      	pe.dwSize = sizeof(PROCESSENTRY32);  // 必须初始化大小[2,4](@ref)
      
      	// 3. 遍历首个进程
      	if (!Process32First(hSnapshot, &pe)) {
      		printf("遍历失败\n");
      		CloseHandle(hSnapshot);
      		return NULL;
      	}
      
      	int size = 0;
      	// 4. 循环输出进程信息
      	do {
      		size++;
      	} while (Process32Next(hSnapshot, &pe));  // 继续遍历[1,2](@ref)
      
      	PROCESSENTRY32* ProcessList = (PROCESSENTRY32*)malloc((size + 1)*sizeof(PROCESSENTRY32));
      	memset(ProcessList, 0, (size + 1)*(sizeof(PROCESSENTRY32)));
      	// 3. 遍历首个进程
      	if (!Process32First(hSnapshot, &pe)) {
      		printf("遍历失败\n");
      		CloseHandle(hSnapshot);
      		return NULL;
      	}
      
      	int i = 0;
      	// 4. 循环输出进程信息
      	do {
      		memcpy((void*)(ProcessList + i), &pe, sizeof(PROCESSENTRY32));
      		i++;
      	} while (Process32Next(hSnapshot, &pe));  // 继续遍历[1,2](@ref)
      	memset((void*)(ProcessList + i), 0, sizeof(PROCESSENTRY32));
      	// 5. 释放资源
      	CloseHandle(hSnapshot);
      	return ProcessList;
      }
      
      int gethProcessByName(TCHAR* procName){
      	PROCESSENTRY32* procList = EnumProcesses();
      	while (*(int*)procList->szExeFile)
      	{
      		if (contains_string_optimized((const TCHAR*)procList->szExeFile, (const TCHAR*)procName)){
      		
      			return  procList->th32ProcessID;
      		}
      		procList++;
      	}
      	return NULL;
      }
      
      int _tmain(int argc, _TCHAR* argv[])
      {
      
      	TCHAR* szDllPath = L"C:\\Users\\dty\\Desktop\\IATHOOKbyDLL.dll";
      	printf("Hello...\n");
      	OutputDebugString(L"[+] -----");
      
      	HANDLE processId = (HANDLE)gethProcessByName(L"IATHookTarget");
      	if (processId == NULL){
      	
      		printf("没有找到进程...\n");
      		return NULL;
      	}
      
      	HANDLE hProcess = OpenProcess(
      		PROCESS_VM_OPERATION |   // 内存操作权限
      		PROCESS_VM_WRITE |       // 写入内存权限
      		PROCESS_CREATE_THREAD |  // 创建远程线程权限(关键)
      		PROCESS_QUERY_INFORMATION,  // 查询进程信息权限
      		FALSE,                                   // 不继承句柄
      		(DWORD)processId                                // 目标进程ID
      		);
      	if (hProcess == NULL) {
      		DWORD err = GetLastError();
      		// 处理错误...
      	}
      
      
      	LPVOID pRemoteMem = VirtualAllocEx((HANDLE)hProcess, NULL, (wcslen(szDllPath) + 1) * sizeof(WCHAR), MEM_COMMIT
      		, PAGE_READWRITE);
      
      	WriteProcessMemory(hProcess, pRemoteMem, szDllPath, (wcslen(szDllPath) + 1) * sizeof(WCHAR), NULL);
      
      	HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
      		(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"LoadLibraryW")
      		,
      		pRemoteMem,0,NULL
      		);
      
      	if (hThread == NULL) {
      		DWORD err = GetLastError();
      		// 处理错误...
      	}
      	printf("%0X\n",hThread);
      	WaitForSingleObject(hThread,INFINITE);
      	system("pause");
      	return 0;
      }

       

  7. 我们的DLL里 对IAT表处理,将要hook的函数换成我们的函数地址,然后我们的函数里调用原来的函数
    1.  首先 根据DLL名称和函数名词遍历导入表 获取存放函数地址的地址(IAT表项的地址)
    2.    定义我们的函数
      1.   参数和调用方式要和原来的函数一致,然后对参数拦截然后调用原来的函数
    3. 修改IAT表
      1.   首先把IAT表变成可写的
      2. 将我们得函数地址写到IAT表项里,这里注意 第一步获取的是IAT表项的地址 (函数地址的地址)
    4. 编译后用注入程序注入进去

 

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
typedef int(WINAPI* MessageBoxW_Type)(HWND,LPCWSTR,LPCWSTR,UINT);
MessageBoxW_Type OriginalMessageBoxW = nullptr;
FARPROC* targetAddr;//指向IAT表项 存放函数地址的那个地址

FARPROC* FindIATEntryAddress(LPCSTR szDllName, LPCSTR szFuncName)
{
	// 获取当前模块基地址
	HMODULE hModule = GetModuleHandle(NULL);
	if (!hModule)
		return NULL;

	// 解析PE头结构
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
	if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
		return NULL;

	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDosHeader->e_lfanew);
	if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
		return NULL;

	// 获取导入表信息
	IMAGE_DATA_DIRECTORY importDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
	if (importDir.VirtualAddress == 0 || importDir.Size == 0)
		return NULL;

	// 遍历导入描述符
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*)hModule + importDir.VirtualAddress);
	while (pImportDesc->Name)
	{

		// 获取DLL名称并比较
		LPCSTR currentDllName = (LPCSTR)((BYTE*)hModule + pImportDesc->Name);
		OutputDebugString(L"[+] DLL名称:");
		OutputDebugStringA(currentDllName);

		if (_stricmp(currentDllName, szDllName) == 0)
		{
			// 获取导入名称表(INT)和导入地址表(IAT)
			PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((BYTE*)hModule +
				(pImportDesc->OriginalFirstThunk ?
				pImportDesc->OriginalFirstThunk :
				pImportDesc->FirstThunk));

			// 计算IAT项地址
			ULONG_PTR* pIatEntry = (ULONG_PTR*)((BYTE*)hModule + pImportDesc->FirstThunk);

			// 遍历函数列表
			while (pThunk->u1.AddressOfData)
			{
				// 检查是否为名称导入
				if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))
				{
					PIMAGE_IMPORT_BY_NAME pImport = (PIMAGE_IMPORT_BY_NAME)(
						(BYTE*)hModule + pThunk->u1.AddressOfData);
					OutputDebugString(L"[+] 函数名称:");
					OutputDebugStringA(pImport->Name);
					// 比较函数名称
					if (strcmp(pImport->Name, szFuncName) == 0)
					{
						OutputDebugString(L"[+] 函数名称比对成功-----------");
						// 返回IAT项的地址
						return (FARPROC*)pIatEntry;
					}
				}
				pThunk++;
				pIatEntry++;
			}
		}
		pImportDesc++;
	}

	return NULL;
}

//我们的函数
//
int WINAPI HookedMessageBoxW(HWND hwnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType){
	OutputDebugString(L"[+] MessageBoxA被拦截");

	DWORD rtn= OriginalMessageBoxW(hwnd, L"内容已被修改", lpCaption, uType);
    //卸载hook
	//OriginalMessageBoxW = (MessageBoxW_Type)*targetAddr;
	*targetAddr = (FARPROC)OriginalMessageBoxW;
	return rtn;

}


void* Hook(HMODULE hModule, LPCSTR Dllname, LPCSTR FunName, PROC HookedFun, PROC* OriginFun){

	OutputDebugString(L"[+] DLL已经注入-----");

	targetAddr = FindIATEntryAddress(Dllname, FunName);

	if (!targetAddr){
		OutputDebugString(L"[+] 获取函数地址失败-----");
	}

	// 在修改内存前添加权限修改
	DWORD oldProtect = 0;
	if (!VirtualProtect(targetAddr, sizeof(FARPROC), PAGE_READWRITE, &oldProtect)) {
		OutputDebugString(L"[-] 修改内存权限失败");
		return NULL;
	}

	WCHAR debugMsg[128];
	swprintf_s(debugMsg, L"[+] 修改前函数地址: 0x%p", (void*)*targetAddr);
	OutputDebugString(debugMsg);
    // 保存原来的函数的地址
    //将IAT表项的值修改成我们的函数地址
	OriginalMessageBoxW = (MessageBoxW_Type)*targetAddr;
	*targetAddr = (FARPROC)&HookedMessageBoxW;
 

	WCHAR debugMsg1[128];
	swprintf_s(debugMsg1, L"[+] 修改后函数地址: 0x%p", (void*)*targetAddr);
	OutputDebugString(debugMsg1);

	// 恢复原始保护属性(可选)
	//VirtualProtect(targetAddr, sizeof(FARPROC), oldProtect, &oldProtect);

	return NULL;
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:

		Hook(GetModuleHandle(NULL), "user32.dll", "MessageBoxW", (PROC)HookedMessageBoxW, (PROC*)&OriginalMessageBoxW);



		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

效果

 

hook后

 

posted on 2025-03-21 21:58  丁同亚的博客  阅读(28)  评论(0)    收藏  举报