Listen to this Post

Introduction
Embedding and executing shellcode in a Portable Executable (PE) file is a common technique in offensive security, but traditional methods relying on WinAPI functions like `FindResource` and `LoadResource` can trigger detection mechanisms. This article explores a stealthier approach: manually parsing PE headers and resource directories to extract and execute shellcode without WinAPI calls.
Learning Objectives
- Understand how to navigate PE file structures to locate embedded resources.
- Learn how to extract shellcode stored in the `.rsrc` section without WinAPI.
- Implement a 4-step shellcode execution flow (allocate, copy, protect, execute) while evading EDR.
1. PE Header Parsing Basics
Command/C++ Snippet
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleBase; PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE)moduleBase + dosHeader->e_lfanew);
Step-by-Step Guide
- Locate DOS Header: The PE file starts with a
DOS_HEADER. The `e_lfanew` field points to theNT_HEADERS. - Access NT Headers: Contains critical metadata like the
OPTIONAL_HEADER, which includes the `DataDirectory` array. - Resource Directory: The 3rd entry in `DataDirectory` (
IMAGE_DIRECTORY_ENTRY_RESOURCE) holds the RVA (Relative Virtual Address) of the resource section.
2. Traversing the Resource Directory
Command/C++ Snippet
PIMAGE_RESOURCE_DIRECTORY rootDir = (PIMAGE_RESOURCE_DIRECTORY)(moduleBase + resourceDir->VirtualAddress);
Step-by-Step Guide
- Locate Root Directory: Use the RVA from `DataDirectory` to find the root resource directory.
- Iterate Entries: Resource entries are organized in a tree. Check `NumberOfNamedEntries` and `NumberOfIdEntries` to loop through resources.
- Find RCDATA: Identify your shellcode blob by its ID (e.g.,
101).
3. Extracting Shellcode from RCDATA
Command/C++ Snippet
PIMAGE_RESOURCE_DATA_ENTRY dataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)(dirEntry + 1); BYTE shellcode = (BYTE)moduleBase + dataEntry->OffsetToData;
Step-by-Step Guide
- Access Data Entry: After locating the correct directory entry, the `OffsetToData` field points to the raw shellcode.
- Calculate Address: Add the module base address to `OffsetToData` to get a pointer to the shellcode.
4. Executing Shellcode (EDR-Evasive)
Command/C++ Snippet
LPVOID execMem = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT, PAGE_READWRITE); memcpy(execMem, shellcode, shellcodeSize); VirtualProtect(execMem, shellcodeSize, PAGE_EXECUTE_READ, &oldProtect); CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)execMem, NULL, 0, NULL);
Step-by-Step Guide
- Allocate Memory: Use `VirtualAlloc` with `PAGE_READWRITE` to avoid suspicious `PAGE_EXECUTE` flags.
- Copy Shellcode: Write the shellcode to the allocated memory.
3. Adjust Permissions: Switch to `PAGE_EXECUTE_READ` using `VirtualProtect`.
- Execute: Trigger execution via
CreateThread,QueueUserAPC, or other techniques.
5. Debugging and Validation
Command/C++ Snippet
printf("Shellcode base: 0x%p\n", shellcode);
Step-by-Step Guide
- Verify Addresses: Print pointers to confirm correct shellcode extraction.
- Check Permissions: Use tools like Process Hacker to inspect memory regions.
What Undercode Say
- Key Takeaway 1: Manual PE parsing bypasses API hooks, reducing detection risk.
- Key Takeaway 2: Combining this with indirect execution (e.g., process injection) further evades EDR.
This technique exemplifies the cat-and-mouse game in cybersecurity: as defenders monitor APIs, attackers shift to lower-level methods. Future advancements in EDR may focus on heuristic analysis of PE structure manipulation, making obfuscation and dynamic loading even more critical.
Note: Always use these techniques ethically and in authorized environments.
IT/Security Reporter URL:
Reported By: Mikegropp Storing – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


