64位Shellcode方式注入DLL

利用LdrLoadDll作为跳板,可以用其他api

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <winternl.h>

#define DEF_INJECT_MODULE	"\\WorkCore.dll"

/*
	
*/
typedef NTSTATUS(NTAPI *pRtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);
typedef NTSTATUS(NTAPI *pLdrLoadDll)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE);
typedef HANDLE(NTAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVOID);

#pragma pack(push,1)
typedef struct _PARAM_DATA{
	pRtlInitUnicodeString fnRtlInitUnicodeString;
	pLdrLoadDll fnLdrLoadDll;
	UNICODE_STRING UnicodeString;
	WCHAR DllName[260];
	PWCHAR DllPath;
	ULONG Flags;
	HANDLE ModuleHandle;
	BYTE szBackupCode[50];
}PARAM_DATA, *PPARAM_DATA;

typedef struct _JMP_PATCH {
	WORD	REax;	//B848 mov rax
	UINT64	uAddress;
	WORD	JMP;    //E0FF
}JMP_PATCH,*PJMP_PATCH;
#pragma pack(pop)

NTSTATUS NTAPI MyLdrLoadDll(PWCHAR pDllPath, ULONG uFlag, PUNICODE_STRING pString, PHANDLE pHandle) {
	PPARAM_DATA data = (PPARAM_DATA)0x1234567890;
	//修复
	UINT64 uFixAddr = (UINT64)data->fnLdrLoadDll;
	for (int n = 0; n < sizeof(JMP_PATCH); n++) {
		*(byte*)(uFixAddr + n) = data->szBackupCode[n];
	}
	//加载DLL
	data->fnRtlInitUnicodeString(&data->UnicodeString, data->DllName);
	data->fnLdrLoadDll(data->DllPath, data->Flags, &data->UnicodeString, &data->ModuleHandle);

	return data->fnLdrLoadDll(pDllPath,uFlag,pString,pHandle);
}
DWORD WINAPI MyLdrLoadDllEnd()
{
	return 0;
}

UINT64 GetRemoteNtdllImagebase(HANDLE hGameHandle, UINT64 uCheckTargetFuncAddr,UINT64 uOffset) {
	UINT64 uAddr = 0x10000;
	MEMORY_BASIC_INFORMATION Mbi;
	while (uAddr < 0x8000000000000) {
		if (VirtualQueryEx(hGameHandle, (PVOID)uAddr, &Mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION)) {
			if ((Mbi.RegionSize == 0x1000) && (Mbi.Protect == PAGE_READONLY)) {
				IMAGE_DOS_HEADER ImageDosHeader = { 0 };
				SIZE_T Lp = 0;
				if (ReadProcessMemory(hGameHandle, (PVOID)Mbi.BaseAddress, &ImageDosHeader, sizeof(IMAGE_DOS_HEADER), &Lp)) {
					if (ImageDosHeader.e_magic == IMAGE_DOS_SIGNATURE) {
						IMAGE_NT_HEADERS ImageNtHeader = { 0 };
						if (ReadProcessMemory(hGameHandle, (PVOID)((UINT64)Mbi.BaseAddress + ImageDosHeader.e_lfanew), &ImageNtHeader, sizeof(IMAGE_NT_HEADERS), &Lp)) {
							if (ImageNtHeader.Signature == IMAGE_NT_SIGNATURE) {
								WORD wCmpByte = 0;
								if (ReadProcessMemory(hGameHandle, (PVOID)((UINT64)Mbi.BaseAddress + uOffset), &wCmpByte, sizeof(WORD), &Lp)) {
									if (wCmpByte == *(WORD*)uCheckTargetFuncAddr) {
										return (UINT64)Mbi.BaseAddress;
									}
								}
							}
						}
					}
				}
			}
			uAddr += Mbi.RegionSize;
		}
		else {
			break;
		}
	}
	return 0;
}

void InstallShellCode(HANDLE hGameHandle, LPCWSTR lpcwDllPath) {
	HMODULE hNtDLL = GetModuleHandle("ntdll.dll");
	if (hNtDLL) {
		//计算偏移
		UINT64 uFuncAddr = (UINT64)GetProcAddress(hNtDLL, "LdrLoadDll");
		UINT64 uOffset = uFuncAddr - (UINT64)hNtDLL;
		/*
			进程直接挂起无法获取到快照表,只能使用内存枚举,然后直接特征码比对
		*/
		UINT64 uTargetNtdllBase = GetRemoteNtdllImagebase(hGameHandle, uFuncAddr, uOffset);
		
		//找到目标NTDLL的基址了
		if (uTargetNtdllBase != 0) {
			//初始化shellcode使用的参数数据结构
			PARAM_DATA data = { 0 };
			data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)(uTargetNtdllBase + ((UINT64)GetProcAddress(hNtDLL, "RtlInitUnicodeString") - (UINT64)hNtDLL));
			data.fnLdrLoadDll = (pLdrLoadDll)(uTargetNtdllBase + uOffset);
			memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
			data.DllPath = NULL;
			data.Flags = 0;
			data.ModuleHandle = INVALID_HANDLE_VALUE;
			//备份恢复代码
			if (ReadProcessMemory(hGameHandle, (PVOID)(uTargetNtdllBase + uOffset), &data.szBackupCode, sizeof(JMP_PATCH) + 3, NULL)) {
				printf("Save BackupCode Success!\r\n");
			}

			//存放数据
			PVOID pDataAdr = VirtualAllocEx(hGameHandle, NULL, sizeof(PARAM_DATA), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
			if (pDataAdr) {
				//存放代码
				UINT64 SizeOfCode = (UINT64)MyLdrLoadDllEnd - (UINT64)MyLdrLoadDll; //计算长度
				PVOID pCode = VirtualAllocEx(hGameHandle, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
				if (pCode) {
					BYTE *pCache = new byte[SizeOfCode];
					if (pCache) {
						//代码拷出来
						memcpy(pCache, &MyLdrLoadDll, SizeOfCode);
						//修正shellcode参数地址
						for (DWORD i = 0; i < SizeOfCode; i++) {
							if (*(UINT64*)((UINT64)pCache + i) == 0x1234567890) {
								*(UINT64*)((UINT64)pCache + i) = (UINT64)pDataAdr;
								break;
							}
						}
						//写入参数
						if (WriteProcessMemory(hGameHandle, pDataAdr, &data, sizeof(PARAM_DATA), NULL)) {
							printf("Write ParamData Success! [%p]\r\n", pDataAdr);
						}
						//写入shellcode
						if (WriteProcessMemory(hGameHandle, pCode, pCache, SizeOfCode, NULL)) {
							printf("Write ShellCode Success! [%p]\r\n", pCode);
						}
						//HOOK 目标API
						DWORD oldProtect = 0;
						if (VirtualProtectEx(hGameHandle, (PVOID)(uTargetNtdllBase + uOffset), sizeof(JMP_PATCH), PAGE_EXECUTE_READWRITE, &oldProtect) == TRUE) {
							JMP_PATCH JmpPatch = { 0 };
							JmpPatch.REax = 0xB848;
							JmpPatch.JMP = 0xE0FF;
							JmpPatch.uAddress = (UINT64)pCode;
							if (WriteProcessMemory(hGameHandle, (PVOID)(uTargetNtdllBase + uOffset) , &JmpPatch, sizeof(JMP_PATCH), NULL)) {
								printf("Write Patch Success! [0x%llX]\r\n", uTargetNtdllBase + uOffset );
							}
						}

					}
				}				
			}			
		}
	}
}

int main(int argc, char *argv[]){
	printf("Shellcode Inject Tools Build 20230718\r\n");
	if (argc > 1) {
		char szBin[MAX_PATH] = { 0 };
		sprintf_s(szBin,"%s -launch", argv[1]);
		printf("Launch Command: %s\r\n" , szBin);

		char szInjectModulePath[MAX_PATH] = { 0 };
		GetCurrentDirectory(MAX_PATH, szInjectModulePath);
		strcat_s(szInjectModulePath, DEF_INJECT_MODULE);
		printf("Inject Module Path:%s\r\n", szInjectModulePath);

		STARTUPINFO si = { sizeof(si) };
		PROCESS_INFORMATION pi;
		if (CreateProcess(NULL, szBin, NULL, NULL,FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
			printf("Game Launch Pid:%d ...\r\n", pi.dwProcessId);
			WCHAR wLoadFile[MAX_PATH * 2] = { 0 };
			if (MultiByteToWideChar(CP_ACP, 0, szInjectModulePath, strlen(szInjectModulePath), wLoadFile, MAX_PATH * 2) > 0) {
				//安装shellcode
				InstallShellCode(pi.hProcess, wLoadFile);
			}		
			ResumeThread(pi.hThread);
			
			printf("Game Start...");
			Sleep(3 * 1000);

		}
	}else {
		printf("Params Wrong!Need game bin path\r\n");
		system("pause");
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值