This post will provide information on the fundamental knowledge required to develop custom malware for Windows operating systems, including information on the Windows executable format layout, payloads, droppers, trojans, and stagers. I will also discuss modern antivirus evasion techniques to avoid heuristic and signature-based malware detection techniques.
Windows PE Layout
Windows PE (Portable Executable) format is the most common form of executable on Windows. The layout of a PE file can be simplified down to two components: headers and sections. Headers contain metadata about the executable, while section contains the actual contents of the executable.
The sections in a PE are the following:
- .text (executable code)
- .rdata (readonly data)
- .data (application data, global, static variables)
- .pdata (information about exceptions)
- .rsrc (resources, can contain different objects such as icons, pictures, manifests, other PE files, or DLL files)
- .reloc (relocation information, allows loader to load the executable into memory with randomized address space)
The main function of a dropper is to transfer your main payload to the victim machine and execute it. A dropper can be anything from a simple PowerShell script to a compiled executable binary.
Payloads can be stored in the .text, .data, or .rsrc sections in a PE file.
- .text: Include your shellcode in the executable code, for example, the main function of a program.
- .data: Store your shellcode in some global or static variable
- .rsrc: Create a file containing your payload and specify that this file should be included during compilation of the program (for example, linking it as a library dependency)
Simple AV Evasion Techniques
A very simple thing which can get caught is setting a memory block in the .text section to be PAGE_EXECUTE_READWRITE. This is very suspicious and will raise lots of red flags for any AV engines and malware analysis tools. Data Execution Prevention (DEP) will also prevent this from running at the system-level since it protects against this scenario specifically.
Instead what should be done is to allocate memory as PAGE_READWRITE (rw-), copy the payload into that block of memory, and then modify the permissions to PAGE_EXECUTE_READ (r-x).