Chapter 20 Notes
to accompany Sikorski and Honig, Practical Malware Analysis, no starch press
Shellcode Analysis
Shellcode is a payload of raw executable code. Usually position-independent, and embedded in a running process.
But shellcode can't rely on services provided by the Windows loader, such as relocation
and external symbol resolution.
shellcode_launcher.exe is supposed to be available at practicalmalwareanalysis.com, but I can't find it :-(
but it is available on github shellcode_launcher
No fixed address?
- since shellcode cannot know in advance where it will be loaded, it has to be tolerant
- position-independent code (PIC) has no fixed addresses for code or data
- software cannot access the Instruction Pointer, so how can code figure out where it's been loaded?
- call followed by a pop lets you store EIP into register of your choice, see Example 20-1
- call/pop can also be an anti-disassembly technique!
- fnstenv instruction lets EIP be extracted from a certain place in the FpuSaveState block - yipes
Manual Symbol Resolution
- Addresses of system calls need to be filled in by the shellcode, since the Windows loader isn't used
- "Shellcode must dynamically locate the functions in order to work reliably in different environments, and for that task, it typically uses LoadLibraryA and GetProcAddress."
- But these functions must be extracted from kernel32.dll!
- To find kernel32.dll in memory, crawl through some OS data:
- use FS register to get to the TEB, then to the PEB, and then crawl the LDR_DATA_TABLE structures
- look in the name field for kernel32, and then the base address
- more system data structures...
- simple hash functions can be used to help shellcode find the addresses of various system functions
- text has examples
Shellcode Encodings
- Depending on exploit used to launch malware, shellcode may be constrained, e.g. to have no null characters that would terminate an unsafe strcpy
- An encoding such as XOR or base64 can help
- Encoded shellcode is less likely to be spotted by A/V or IDS
NOP Sleds
- preface the shellcode with a bunch of NOPs (or similar harmless instructions) so that if execution gets close, shellcode will run
- NOP is 0x90, but other instructions can be used
Finding Shellcode
- Small size means shellcode could be in media files, web pages, network traffic, whatever
- Javascript, for example, has features that convert encoded shellcode into executable binary
- So look for the initial decoder that unpacks the rest of the shellcode