小试X64 inline HOOK,hook explorer.exe--->CreateProcessInternalW监视进程创建

原始函数是这样的

kernel32!CreateProcessInternalW:
00000000`7738e750 4c8bdc          mov     r11,rsp
00000000`7738e753 53              push    rbx
00000000`7738e754 56              push    rsi
00000000`7738e755 57              push    rdi
00000000`7738e756 4154            push    r12
00000000`7738e758 4155            push    r13
00000000`7738e75a 4156            push    r14
00000000`7738e75c 4157            push    r15
00000000`7738e75e 4881ec400b0000  sub     rsp,0B40h
00000000`7738e765 488b0564cc0e00  mov     rax,qword ptr [kernel32!local_unwind+0x606b1 (00000000`7747b3d0)]


跟32位一样,在函数入口写入跳转指令,跟32不一样的是,不能再用之前的E9 xx xx xx xx这样的指令了,E9不支持64位地址跳转,最大只能支持到32位,

直接用E9大部分情况下会出错.所以我们换一种方法.

mov rax,0x1122334455667788
jmp rax


机器码是48 b8 8877665544332211 ffe0总共占了12个字节,不是我们之前用E9跳转的5字节了.

最前面的48叫REX Prefix,大家可以GOOGLE下,4是固定的,8表示使用64位寄存器.

如果没有前面的48就变成了mov eax, 0x1122334455667788了,使用32位寄存器.

我们需要把函数前面12字节改成跳转指令,正好

00000000`7738e750 4c8bdc          mov     r11,rsp
00000000`7738e753 53              push    rbx
00000000`7738e754 56              push    rsi
00000000`7738e755 57              push    rdi
00000000`7738e756 4154            push    r12
00000000`7738e758 4155            push    r13
00000000`7738e75a 4156            push    r14

这12个字节是完整的7条指令,写入12字节指令,不会破坏后面的指令.

写入跳转指令后

kernel32!CreateProcessInternalW:
00000000`7738e750 48b8001055fbfe070000 mov rax,offset x64dll!FakeCreateProcessInternal (000007fe`fb551000)
00000000`7738e75a ffe0            jmp     rax
00000000`7738e75c 4157            push    r15
00000000`7738e75e 4881ec400b0000  sub     rsp,0B40h
00000000`7738e765 488b0564cc0e00  mov     rax,qword ptr [kernel32!local_unwind+0x606b1 (00000000`7747b3d0)]
00000000`7738e76c 4833c4          xor     rax,rsp
00000000`7738e76f 48898424300b0000 mov     qword ptr [rsp+0B30h],rax
00000000`7738e777 4889a42438050000 mov     qword ptr [rsp+538h],rsp

完整代码如下.

少NTDLL.h的朋友可以去搜索下载,也可以把RtlAdjustPrivilege替换成AdjustTokenPrivileges,效果样的,只是代码多几行而已.

声明:本人很菜,水平有限,汇编功底也是相当的水,如发现有误人子弟之处,敬请指正.若您有更好的方法也请多多指教.

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <shlwapi.h>
#include <ntdll.h>

#pragma comment(lib, "shlwapi.lib")
#define CODE_LEN 12
TCHAR ModuleFile[MAX_PATH];  
DWORD dwOldProtect;
BYTE OldCode[CODE_LEN] = {0x90};

typedef HANDLE (WINAPI *__CreateProcessInternal)(HANDLE hToken,LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,PHANDLE hNewToken);
__CreateProcessInternal pfnCreateProcess = 0;

HANDLE WINAPI FakeCreateProcessInternal(HANDLE hToken,LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,PHANDLE hNewToken)
{
	MessageBox(NULL, lpCommandLine, lpApplicationName, MB_ICONASTERISK);
	return pfnCreateProcess(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL,  // handle to DLL module
		    DWORD fdwReason,     // reason for calling function
		    LPVOID lpReserved )  // reserved
{
	switch( fdwReason ) 
	{ 
	case DLL_PROCESS_ATTACH:
		::DisableThreadLibraryCalls(hinstDLL);
		GetModuleFileName(NULL, ModuleFile, _countof(ModuleFile));  

		if (StrRStrI(ModuleFile, 0, TEXT("explorer.exe")))
		{
			pfnCreateProcess = (__CreateProcessInternal)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateProcessInternalW");
			::VirtualProtect(pfnCreateProcess, CODE_LEN, PAGE_EXECUTE_READWRITE, &dwOldProtect);
			memcpy(OldCode, pfnCreateProcess, CODE_LEN);
			memset(pfnCreateProcess, 0x90, CODE_LEN);
			/*
			mov rax, FakeCreateProcessInternal
			jmp rax
			*/
			*(LPWORD)pfnCreateProcess = 0xb848;
			*(INT64*)((INT64)pfnCreateProcess+2) = (INT64)FakeCreateProcessInternal;
			*(LPWORD)((INT64)pfnCreateProcess+10) = 0xe0ff;
			::VirtualProtect(pfnCreateProcess, CODE_LEN, dwOldProtect, NULL);

			pfnCreateProcess = (__CreateProcessInternal)VirtualAlloc(NULL, CODE_LEN+12, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
			memcpy(pfnCreateProcess, OldCode, CODE_LEN);
			/*
			mov rax, CreateProcessInternalW + CODE_LEN
			jmp rax
			*/
			*(LPWORD)((INT64)pfnCreateProcess+CODE_LEN) = 0xb848;
			*(INT64*)((INT64)pfnCreateProcess+CODE_LEN+2) = (INT64)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateProcessInternalW")+CODE_LEN;
			*(LPWORD)((INT64)pfnCreateProcess+CODE_LEN+10) = 0xe0ff;
		}
		else if (StrRStrI(ModuleFile, 0, TEXT("Rundll32.exe")))  
		{  
			DWORD dwProcessId = 0;  
			HANDLE hProcess = 0;   
			HWND   hwndDeskTop;     

			hwndDeskTop = FindWindow(TEXT("ProgMan"), NULL);       

			GetModuleFileName(hinstDLL, ModuleFile, _countof(ModuleFile));  
			GetWindowThreadProcessId(hwndDeskTop, &dwProcessId);
			BOOLEAN bEnable;
			::RtlAdjustPrivilege(0x13, 1, 0, &bEnable);

			if (dwProcessId)  
			{  
				hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, NULL, dwProcessId);  
			}  

			LPVOID Param = VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_EXECUTE_READWRITE);  
			WriteProcessMemory(hProcess, Param, (LPVOID)ModuleFile, 256, NULL);  

			HANDLE hThread = CreateRemoteThread(hProcess,   
				NULL,   
				NULL,   
				(LPTHREAD_START_ROUTINE)LoadLibraryW,  
				Param,   
				NULL,   
				NULL);  

			if (hThread)  
			{  
				WaitForSingleObject(hThread, INFINITE);  
			}  

			VirtualFreeEx(hProcess, Param , 0, MEM_RELEASE);  
			CloseHandle(hThread);  
			CloseHandle(hProcess);  
		}  

		break;

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

int _stdcall Setup(void)  
{  
    return 1;  
}  


编译成DLL后,在运行里执行rundll32.exe X64Dll.dll,Setup,DLL会自动注入到explorer.exe进程.

完全工程及编译好的文件点击打开链接

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值