CSEC 202 - W2 Review + File Formats - Spring 2025
Review of Compilation Process
- When a C program is compiled, the compiler generates object code.
- Object files contain machine language instructions.
- Object files are not executable.
- After generating the object code, the compiler also invokes the linker.
- Linking refers to the creation of a single executable file from multiple object files.
- The linker takes all the object files generated by the compiler and combines them into a single executable program.
- In addition to linking object files, the linker can also link library files.
Static Linking vs. Dynamic Linking
- Static Linking:
- Source code is compiled into machine language code.
- The machine language code and library are linked together by the linker to produce an executable file.
- Dynamic Linking:
- Source code is compiled into machine language code.
- The machine language code and library are linked by the linker to produce an executable file. The library is linked at runtime rather than compile time.
Compiling vs. Assembling
- Source Code (.c file) is processed by the Compiler to generate Assembly code.
- The Assembler converts Assembly code into Object code (.obj files).
- The Linker combines Object code with libraries (.lib files) to produce Executable machine code (.exe).
Structure of an Executable File on Disk (Windows) - Portable Executable (PE)
- Demonstration of running
mini.exeand checking the error level. D:\>mini.exeD:\>echo %error level%(Output: 42)- The structure includes:
- DOS Header: Indicates it's a binary file.
e_magic:MZe_lfanew:0x40(points to PE Header)
- PE Header: Indicates it's a 'modern' binary.
Signature:PE\0\0Machine:0x14C(Intel 386)Characteristics:2(Executable)
- Optional Header: Contains executable information.
Magic:0x10B(32-bit)AddressOfEntryPoint:0x140ImageBase:0x400000SectionAlignment:0x1000FileAlignment:0x200MajorSubsystemVersion:4(NT 4 or later)SizeOfImage:0x160SizeOfHeaders:0x140Subsystem:3(CLI)
- DOS Header: Indicates it's a binary file.
- X86 Assembly Code:
mov eax, 42retn
- Equivalent C Code:
return 42;
Structure of a Linux Executable File on Disk - Executable and Linkable Format (ELF)
- Demonstration of running
./miniand checking the exit code. me@nux:~$ ./minime@nux:~$ echo $?(Output: 42)- ELF Header:
e_ident:0x7F, ELF(Identifies as an ELF type)EI_MAG: Magic numberEI_CLASS, EI_DATA:1(ELFCLASS32),1(ELFDATA2LSB)EI_VERSION:1(EV_CURRENT)
e_type:2(ET_EXEC) - Specifies the object file typee_machine:3(EM_386) - Specifies the architecturee_version:1(EV_CURRENT)e_entry:0x8000060- Entry point addresse_phoff:0x0000034- Program header table offsete_ehsize:0x0034- ELF header sizee_phentsize:0x0020- Program header entry sizee_phnum:1- Number of program header entries
- Program Header Table:
p_type:LOADp_offset:0p_vaddr:0x8000000p_paddr:0x8000000p_filesz:0x0000070p_memsz:0x0000070p_flags:5(PFR|PFX)
- X86 Assembly Code:
mov ebx, 42mov eax, 1int 80h
- Equivalent C Code:
_ISC_EXITreturn 42;
- Used in various operating systems and platforms, including Linux, Android, BSD, Solaris, BeOS, PSP, PlayStation, Dreamcast, GameCube, Wii, and microcontrollers from Atmel, Texas Instruments, Samsung, Ericsson, and Nokia.
Structure of a Mach-O Executable File on Disk
- Demonstration of running
./miniand checking the exit code. mac:~ me$ ./minimac:~ me$ echo $?(Output: 42)- Mach Header:
magic:0xFEEDFACE(Identifies as a Mach-O type)cputype:7(CPUTYPEI386)cpusubtype:3(CPUSUBTYPEI386_ALL)filetype:2(MH_EXECUTE)ncmds:3sizeofcmds:0x88
- Segment Command: Mapping information
cmd:1(LC_SEGMENT)cmdsize:0x38vmaddr:0vmsize:0xc0fileoff:0filesize:5initprot:5(R/X)
- Thread Command:
cmd:0x1A(LC_UNIXTHREAD)cmdsize:0x50
- Thread State:
- Flavor:
1(x86THREADSTATE32) - Count:
0x10
- Flavor:
- X86 Assembly Code:
push 42mov eax, 1sub esp, 4(Stack Adjustment)int 0x80(System call)
- Equivalent C Code:
return 42;
- Used by macOS, iOS, NeXTSTEP, and on iPhones, iPods, and Macs. The Mach-O format comes from the Mach kernel, created at Carnegie Mellon University in 1985.
More on the PE File Format
- Executable files (
.exe) are composed of:- Header: Contains technical details about the executable.
- Sections: Contain the actual contents of the executable (code and data).
More on the PE File Format - Continued
- Shows hex representations of various parts:
- DOS Header
- PE Header
- Optional Header (Executable Information)
- Data Directories (Pointers to extra structures like exports, imports,…)
- Sections Table (Defines how the file is loaded in memory)
- Sections (.text, .rdata, .data) - Contains contents of the executable, such as code, read-only data and initialized data.
- Imports (Link between the executable and Windows libraries)
- Information used by the code
Sections in Section Table
- Describes sections of a PE file for a Windows executable:
.text: Contains the executable code..rdata: Holds read-only data that is globally accessible within the program..data: Stores global data accessed throughout the program..idata: Stores the import function information (if not present, stored in.rdata)..edata: Stores the export function information (if not present, stored in.rdata)..pdata: Present only in 64-bit executables and stores exception-handling information..rsrc: Stores resources needed by the executable..reloc: Contains information for relocation of library files.
Malware in .text
- Example of
meterpretershellcode embedded in the.textsection (executable code section). - Shellcode is a sequence of machine code instructions that can be injected into a program's memory and executed.
unsigned char meterpreter[] = {
/* Shellcode bytes... */
};
Malware in .data
- Example of
meterpretershellcode also embedded in the.datasection (data section). - Demonstrates that malicious code is not confined to the .text section and can reside in data sections as well.
- C code snippet showing the
meterpreterarray and its size.
Malware in .rsrc
- Example of how malware can be hidden within resources (
.rsrcsection). - Resource section stores resources like images, icons, and other non-executable data, but can also hide malicious payloads.
- Code demonstrates how a resource (
IDR_PAYLOAD1) is accessed, loaded, and executed. - Key functions used include
FindResource,LoadResource,LockResource,SizeofResource,VirtualAlloc,RtlMoveMemory,CreateThread, andWaitForSingleObject. - Project structure: Includes header files (
resource.h), resource files (dropper-rev.rc), and source files (Source.cpp).
What Happens When a PE File Runs
Loading Process:
- Headers Parsing:
- The DOS Header is parsed.
- The PE Header is parsed (its offset is found in DOS Header's
e_lfanew). - The Optional Header is parsed (it follows the PE Header).
- Mapping:
- The file is mapped into memory based on:
ImageBase: Base address where the executable is loaded.SizeOfHeaders: Size of all headers.Sections table
- Sections Table:
- The Sections table is parsed (located at offset(OptionalHeader) + SizeOfOptionalHeader).
- It contains
NumberOfSectionselements. - It is checked for validity with
FileAlignmentsandSectionAlignments.
- For each section:
- A
SizeOfRawDatasized block is read from the file atPointerToRawDataoffset. - Loaded in memory at the address
ImageBase + VirtualAddressin aVirtualSizesized block. - The section is loaded with specific characteristics (e.g., CODE EXECUTE READ, INITIALIZED READ, DATA READ WRITE).
- A
- The file is mapped into memory based on:
- Headers Parsing:
Sections Table:
| Name | Virtual Size | Virtual Address | SizeOfRawData | PointerToRawData | Characteristics |
|---|---|---|---|---|---|
| .text | 0x1000 | 0x1000 | 0x200 | 0x200 | CODE EXECUTE READ |
| .rdata | 0x1000 | 0x2000 | 0x200 | 0x400 | INITIALIZED READ |
| .data | 0x1000 | 0x3000 | 0x200 | 0x600 | DATA READ WRITE |
- Diagram: Overview of how sections are loaded in memory relative to
ImageBase,SizeOfHeaders, and the virtual addresses.
What Happens When a PE File Runs - Import Tables
- INT (Import Name Table):
- Contains information about the functions imported from external DLLs.
- This is static and is used to locate the addresses of the needed functions.
- IAT (Import Address Table):
- Contains the addresses of the functions that are imported from external DLLs.
- Used to call the imported functions.
- May be modifiable, allowing for debugging or malicious function hooking.
- Both are found in the
.idatasection.