首页
社区
课程
招聘
[求助]IATHOOK DLL注入DEBUG成功并出现效果。Realse钩成功但是没出效果。
发表于: 2013-11-18 15:01 4946

[求助]IATHOOK DLL注入DEBUG成功并出现效果。Realse钩成功但是没出效果。

2013-11-18 15:01
4946
下面是我DLL注入代码

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

//定义函数原型
typedef int (WINAPI *PFNMESSAGEBOX)(HWND hWnd,  LPCTSTR lpText,  LPCTSTR lpCaption,  UINT uType);
//保存原始的MessageBox地址,注意这里
PROC g_orgProc = (PROC)MessageBox;

int WINAPI MyMessageBox(HWND hWnd,  LPCTSTR lpText,  LPCTSTR lpCaption,  UINT uType)
{
	printf("%x",(DWORD)MyMessageBox);
	printf("123");
	return ((PFNMESSAGEBOX)g_orgProc)(hWnd, "mymessagebox1111", "成功", uType);
}

//=========================================
// 函数名: EnableDebugPrivilege
// 输   入: bEnable(BOOL) - 提升:TRUE, 恢复:FALSE
// 输   出: BOOL - 成功:TRUE, 失败:FALSE
// 功   能: 提升/恢复权限
//=========================================
bool EnableDebugPriv(const char * name)
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tp;
	LUID luid;
	//打开进程令牌环
	if(!OpenProcessToken(GetCurrentProcess(),//取得句柄的令牌 OpenProcessToken()函数
		TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
		&hToken) )
	{
		printf("OpenProcessToken error./n");
		return FALSE;
	}
	//获得进程本地唯一ID
	if(!LookupPrivilegeValue(NULL,name,&luid) )//一个权限对应的LUID值
	{
		printf("LookupPrivilege error!/n");
		return FALSE;
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	tp.Privileges[0].Luid = luid;
	//调整权限
	if(!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL) )//调用AdjustTokenPrivileges对这个访问令牌进行修改
	{
		printf("AdjustTokenPrivileges error!/n");
		return FALSE;
	}

	return TRUE;
}


void SetHook()
{
	HMODULE hModule = ::GetModuleHandleA(NULL);
	IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hModule;
	IMAGE_OPTIONAL_HEADER* pOpNtHeader = (IMAGE_OPTIONAL_HEADER*)((BYTE*)hModule + pDosHeader->e_lfanew + 24); //这里加24
	IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hModule + pOpNtHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

	BOOL bFindDll = FALSE;
	while (pImportDesc->FirstThunk)
	{
		char* pszDllName = (char*)((BYTE*)hModule + pImportDesc->Name);
		printf("模块名称:%s\n", pszDllName);

		if (stricmp(pszDllName, "user32.dll") == 0)//如果是user32.dll
		{
			bFindDll = TRUE;
			break;
		}
		pImportDesc++;	
	}

	if (bFindDll)
	{
		DWORD n = 0;
		//一个IMAGE_THUNK_DATA就是一个导入函数
		IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hModule + pImportDesc->OriginalFirstThunk);
		while (pThunk->u1.Function)
		{
			//取得函数名称
			char* pszFuncName = (char*)((BYTE*)hModule+pThunk->u1.AddressOfData+2); //函数名前面有两个..
			printf("function name:%-25s,  ", pszFuncName);
			//在这里是比较的函数名称
			if (stricmp(pszFuncName, "MessageBoxA") == 0)
			{
				//取得函数地址
				PDWORD lpAddr = (DWORD*)((BYTE*)hModule + pImportDesc->FirstThunk) + n; //从第一个函数的地址,以后每次+4字节
				//在这里是比较的函数地址
				printf("addrss:%X\n", lpAddr);
				DWORD* lpNewProc = (DWORD*)MyMessageBox;
				DWORD OldProtect = 0;
				DWORD NewProtect = 0;

				VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &OldProtect);    //将指定内存设为可读写
				if (!WriteProcessMemory(GetCurrentProcess(), lpAddr, &lpNewProc, sizeof(DWORD), NULL))
				{
					printf("写入失败!\n");
					return;
				}
				VirtualProtect(lpAddr, sizeof(DWORD), OldProtect, &NewProtect );  
				printf("成功写入!\n");
				return;

			}			
			n++; //每次增加一个DWORD
		}
		printf("\n");		
	}
}

/*
int main(int argc, char* argv[])
{
	::MessageBoxA(NULL, "before hook", "", MB_OK);
	EnableDebugPriv(SE_DEBUG_NAME);
	SetHook();
	::MessageBoxA(NULL, "AFTERE hook", "", MB_OK);
	return 0;
}*/
		

BOOL WINAPI DllMain( HMODULE hInstance,
					DWORD fdwReason,
					LPVOID lp)
{


	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		MessageBox(NULL, "DLL加载成功!", NULL, MB_OK);
		if (!EnableDebugPriv(SE_DEBUG_NAME))
		{
			MessageBox(NULL, "提权失败!", NULL, MB_OK);
		}
		MessageBox(NULL, "提权成功!", NULL, MB_OK);
		MessageBox(NULL, "提权成功!11111", NULL, MB_OK);
		SetHook();
		break; 
	case DLL_THREAD_ATTACH:
	case DLL_PROCESS_DETACH:
	case DLL_THREAD_DETACH:
		break;
	}
	return TRUE;
}


下面是我的测试DEMO。当这个DEMO 是DEBUG模式下编译的情况下成功出现效果。当时Realse情况下是不成功的!不解!
如果需要权限的话。我已经加了提权代码了。
两外Realse情况下,用XT观察了下,也是正确勾住了函数的。但是确没出现效果。

#include "stdio.h"
#include "windows.h"

int main()
{
	printf("test---\n");
	while(1)
	{
		getchar();
		MessageBoxA(NULL, "原来的", "原来的", 0);
	}
	return 0;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
自己解决了,造福后人。分析如下:

00401000 > $  56            push esi
00401001   .  57            push edi
00401002   .  68 F4204000   push TestDemo.004020F4                   ; /format = "test---
"
00401007   .  FF15 A4204000 call dword ptr ds:[<&MSVCR90.printf>]    ; \printf
0040100D   .  8B35 A0204000 mov esi,dword ptr ds:[<&MSVCR90.getchar>>;  MSVCR90.getchar
00401013   .  8B3D AC204000 mov edi,dword ptr ds:[<&USER32.MessageBo>;  USER32.MessageBoxA
00401019   .  83C4 04       add esp,4
0040101C   .  8D6424 00     lea esp,dword ptr ss:[esp]
00401020   >  FFD6          call esi                                 ;  程序刚开始是断在这里,但是MessageBoxA地址已经保存在EDI
00401022   .  6A 00         push 0
00401024   .  68 00214000   push TestDemo.00402100
00401029   .  68 00214000   push TestDemo.00402100
0040102E   .  6A 00         push 0
00401030   .  FFD7          call edi                                 ;  这里CALL  MessageBoxA并不通过IAT了,直接CALL地址
00401032 > .^ EB EC         jmp short TestDemo.00401020
00401034 > .  3B0D 00304000 cmp ecx,dword ptr ds:[__security_cookie]
0040103A   .  75 02         jnz short TestDemo.0040103E
0040103C   .  F3:           prefix rep:
0040103D   .  C3            retn

事实就是RELEASE版本,编译的时候对程序进行了,优化。将MessageBoxA函数地址放与一个固定寄存器中,因此下面每次CALL的时候都是 CALL 寄存器而不是通过IAT表查找函数。当然这只是因为这个程序太简单了~
2013-11-18 15:51
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
3
就算是Release版为了优化事先把API的地址放在了寄存器里,这个API的地址也是从IAT从取到的啊,所以IAT HOOK应该还是能钩住的才对

00401013   .  8B3D AC204000 mov edi,dword ptr ds:[<&USER32.MessageBo>;  USER32.MessageBoxA
2013-11-18 20:58
0
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
IAT Hook不靠谱,如果只是想简单快速的实现API Hook可以用Hot Patching
2013-11-19 11:01
0
游客
登录 | 注册 方可回帖
返回
//