• 逆向工程核心原理——第三十二章


    计算器显示中文数字

    此实验中使用的代码只适用于x86系统。

    本章讲解API钩取技术时将以Windows计算器( calc.exe)为示例,向计算器进程插人用户的
    DLL文件,钩取IAT的user32.SetWindowTextW() API地址。

    SetWindowTextW() API的作用是显示计算器中的数字,而我们会将这个数字改为中文数字。

    我们知道,当程序需要调用源程序之外的函数时,需要访问导入表(IAT),IAT中存放着需要调用的函数的地址,而这次的实验,我们就需要钩出这个地址,替换成别的地址,从而使阿拉伯数字变为汉字数字。

    我们在图中可以看到:

    这里计算器(cala.exe)运行到01002628时调用user32.dll,调用完成后回到cala.exe

    而我们修改后的运行顺序为:

    EXE:

    //InjectDll.exe
    
    #include "stdio.h"  
    #include "windows.h"  
    #include "tlhelp32.h"  
    #include "winbase.h"  
    #include "tchar.h"  
    #include<iostream>
    using namespace std;
    
    void usage()
    {
    	printf("
    InjectDll.exe by ReverseCore
    "
    		"- USAGE : InjectDll.exe <i|e> <PID> <dll_path>
    
    ");
    }
    
    
    BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)
    {
    	HANDLE hProcess, hThread;
    	LPVOID pRemoteBufferData;  //远程进程中的内存
    	DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);
    	LPTHREAD_START_ROUTINE pThreadProc;
    
    	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
    	{
    		DWORD dwErr = GetLastError();
    		return FALSE;
    	}
    
    	//申请内存 可读可写
    	pRemoteBufferData = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
    
    	//像内存写入dll路径
    	WriteProcessMemory(hProcess, pRemoteBufferData, (LPVOID)szDllName, dwBufSize, NULL);
    
    	//获得loadlibraryw地址
    	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
    
    	//创建远程线程
    	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBufferData, 0, NULL);
    	WaitForSingleObject(hThread, INFINITE);
    
    	CloseHandle(hThread);
    	CloseHandle(hProcess);
    
    	return TRUE;
    }
    
    
    BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
    {
    	BOOL bMore = FALSE, bFound = FALSE;
    	HANDLE hSnapshot, hProcess, hThread;
    	MODULEENTRY32 me = { sizeof(me) };
    	LPTHREAD_START_ROUTINE pThreadProc;
    
    	if (INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)))
    	{
    		return FALSE;
    	}
    
    
    	bMore = Module32First(hSnapshot, &me);
    	for (; bMore; bMore = Module32Next(hSnapshot, &me))
    	{
    		if (!_tcsicmp(me.szModule, szDllName) || !_tcsicmp(me.szExePath, szDllName))
    		{
    			bFound = TRUE;
    			break;
    		}
    	}
    
    	if (!bFound)
    	{
    		CloseHandle(hSnapshot);
    		return FALSE;
    	}
    
    	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
    	{
    		CloseHandle(hSnapshot);
    		return FALSE;
    	}
    
    	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "FreeLibrary");
    	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL);
    	WaitForSingleObject(hThread, INFINITE);
    
    	CloseHandle(hThread);
    	CloseHandle(hProcess);
    	CloseHandle(hSnapshot);
    
    	return TRUE;
    }
    
    
    DWORD _EnableNTPrivilege(LPCTSTR szPrivilege, DWORD dwState)
    {
    	DWORD dwRtn = 0;
    	HANDLE hToken;
    	if (OpenProcessToken(GetCurrentProcess(),
    		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    	{
    		LUID luid;
    		if (LookupPrivilegeValue(NULL, szPrivilege, &luid))
    		{
    			BYTE t1[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
    			BYTE t2[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
    			DWORD cbTP = sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES);
    
    			PTOKEN_PRIVILEGES pTP = (PTOKEN_PRIVILEGES)t1;
    			PTOKEN_PRIVILEGES pPrevTP = (PTOKEN_PRIVILEGES)t2;
    
    			pTP->PrivilegeCount = 1;
    			pTP->Privileges[0].Luid = luid;
    			pTP->Privileges[0].Attributes = dwState;
    
    			if (AdjustTokenPrivileges(hToken, FALSE, pTP, cbTP, pPrevTP, &cbTP))
    				dwRtn = pPrevTP->Privileges[0].Attributes;
    		}
    
    		CloseHandle(hToken);
    	}
    
    	return dwRtn;
    }
    
    
    int _tmain(int argc, TCHAR* argv[])
    {
    	if (argc != 4)
    	{
    		usage();
    		return 1;
    	}
    
    	// adjust privilege  
    	_EnableNTPrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED);
    
    	// InjectDll.exe <i|e> <PID> <dll_path>  
    	if (!_tcsicmp(argv[1], L"i"))
    	{
    		InjectDll((DWORD)_tstoi(argv[2]), argv[3]);
    	}
    	else if (!_tcsicmp(argv[1], L"e"))
    	{
    		EjectDll((DWORD)_tstoi(argv[2]), argv[3]);
    	}
    
    
    	return 0;
    }
    

    DLL:

    //hookiat.dll
    
    #include "stdio.h"  
    #include "wchar.h"  
    #include "windows.h"  
    
    
    // typedef  
    typedef BOOL(WINAPI* PFSETWINDOWTEXTW)(HWND hWnd, LPWSTR lpString); //SetWindowsTextW()的地址
    
    
    // 原函数地址
    FARPROC g_pOrginalFunction = NULL;
    
    
    BOOL WINAPI MySetWindowTextW(HWND hWnd, LPWSTR lpString)
    {
    	wchar_t* pNum = L"零一二三四五六七八九";
    	wchar_t temp[2] = { 0, };
    	int i = 0, nLen = 0, nIndex = 0;
    
    	nLen = wcslen(lpString);
    	for (i = 0; i < nLen; i++)
    	{
    		//   将阿拉伯数字转换为中文数字  
    		//   lpString是宽字符版本(2个字节)字符串  
    		if (L'0' <= lpString[i] && lpString[i] <= L'9')
    		{
    			temp[0] = lpString[i];
    			nIndex = _wtoi(temp);
    			lpString[i] = pNum[nIndex];
    		}
    	}
    
    	//   调用原函数;user32.SetWindowTextW  
    	//   (修改lpString缓冲区中的内容)  
    	return ((PFSETWINDOWTEXTW)g_pOrginalFunction)(hWnd, lpString);
    }
    
    /**********************************/
    //    函数名:hook_iat
    //	  功能  :负责实施IAT钩取的核心函数
    /**********************************/
    BOOL hook_iat(LPCSTR szDllName, PROC pfnOrg, PROC pfnNew)
    {
    	HMODULE hMod;
    	LPCSTR szLibName;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
    	PIMAGE_THUNK_DATA pThunk;
    	DWORD dwOldProtect, dwRVA;
    	PBYTE pAddr;
    
    	// hMod, pAddr = ImageBase of calc.exe  
    	//             = VA to MZ signature (IMAGE_DOS_HEADER)  
    	hMod = GetModuleHandle(NULL);
    	pAddr = (PBYTE)hMod;
    
    	// pAddr = VA to PE signature (IMAGE_NT_HEADERS)  
    	pAddr += *((DWORD*)&pAddr[0x3C]);
    
    	// dwRVA = RVA to IMAGE_IMPORT_DESCRIPTOR Table  
    	dwRVA = *((DWORD*)&pAddr[0x80]);
    
    	// pImportDesc = VA to IMAGE_IMPORT_DESCRIPTOR Table  
    	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hMod + dwRVA);
    
    	for (; pImportDesc->Name; pImportDesc++)
    	{
    		// szLibName = VA to IMAGE_IMPORT_DESCRIPTOR.Name  
    		szLibName = (LPCSTR)((DWORD)hMod + pImportDesc->Name);
    		if (!_stricmp(szLibName, szDllName))
    		{
    			// pThunk = IMAGE_IMPORT_DESCRIPTOR.FirstThunk  
    			//        = VA to IAT(Import Address Table)  
    			pThunk = (PIMAGE_THUNK_DATA)((DWORD)hMod +
    				pImportDesc->FirstThunk);
    
    			// pThunk->u1.Function = VA to API  匹配成功
    			for (; pThunk->u1.Function; pThunk++)
    			{
    				if (pThunk->u1.Function == (DWORD)pfnOrg)
    				{
    					// 更改为可读写模式  
    					VirtualProtect((LPVOID)&pThunk->u1.Function,
    						4,
    						PAGE_EXECUTE_READWRITE,
    						&dwOldProtect);
    
    					// 修改IAT的值  
    					pThunk->u1.Function = (DWORD)pfnNew;
    
    					//修改完成后,恢复原保护属性
    					VirtualProtect((LPVOID)&pThunk->u1.Function,
    						4,
    						dwOldProtect,
    						&dwOldProtect);
    
    					return TRUE;
    				}
    			}
    		}
    	}
    
    	return FALSE;
    }
    
    
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	switch (fdwReason)
    	{
    	case DLL_PROCESS_ATTACH:
    		// 保存原始API的地址  
    		g_pOrginalFunction = GetProcAddress(GetModuleHandle(L"user32.dll"),
    			"SetWindowTextW");
    
    		// # hook  
    		//   用hookiat.MySetWindowText钩取user32.SetWindowTextW  
    		hook_iat("user32.dll", g_pOrginalFunction, (PROC)MySetWindowTextW);
    		break;
    
    	case DLL_PROCESS_DETACH:
    		// # unhook  
    		//   将calc.exe的IAT恢复原值  
    		hook_iat("user32.dll", (PROC)MySetWindowTextW, g_pOrginalFunction);
    		break;
    	}
    
    	return TRUE;
    }
    
  • 相关阅读:
    12.18-java复习-UserBean
    12.17-javaweb复习
    12.16-javaweb复习
    Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
    java建议
    个人表现
    今日总结
    今日总结
    今日总结
    今日总结
  • 原文地址:https://www.cnblogs.com/lex-shoukaku/p/13786385.html
Copyright © 2020-2023  润新知