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.exe and checking the error level.
  • D:\>mini.exe
  • D:\>echo %error level% (Output: 42)
  • The structure includes:
    • DOS Header: Indicates it's a binary file.
      • e_magic: MZ
      • e_lfanew: 0x40 (points to PE Header)
    • PE Header: Indicates it's a 'modern' binary.
      • Signature: PE\0\0
      • Machine: 0x14C (Intel 386)
      • Characteristics: 2 (Executable)
    • Optional Header: Contains executable information.
      • Magic: 0x10B (32-bit)
      • AddressOfEntryPoint: 0x140
      • ImageBase: 0x400000
      • SectionAlignment: 0x1000
      • FileAlignment: 0x200
      • MajorSubsystemVersion: 4 (NT 4 or later)
      • SizeOfImage: 0x160
      • SizeOfHeaders: 0x140
      • Subsystem: 3 (CLI)
  • X86 Assembly Code:
    • mov eax, 42
    • retn
  • Equivalent C Code:
    • return 42;

Structure of a Linux Executable File on Disk - Executable and Linkable Format (ELF)

  • Demonstration of running ./mini and checking the exit code.
  • me@nux:~$ ./mini
  • me@nux:~$ echo $? (Output: 42)
  • ELF Header:
    • e_ident: 0x7F, ELF (Identifies as an ELF type)
      • EI_MAG: Magic number
      • EI_CLASS, EI_DATA: 1 (ELFCLASS32), 1 (ELFDATA2LSB)
      • EI_VERSION: 1 (EV_CURRENT)
    • e_type: 2 (ET_EXEC) - Specifies the object file type
    • e_machine: 3 (EM_386) - Specifies the architecture
    • e_version: 1 (EV_CURRENT)
    • e_entry: 0x8000060 - Entry point address
    • e_phoff: 0x0000034 - Program header table offset
    • e_ehsize: 0x0034 - ELF header size
    • e_phentsize: 0x0020 - Program header entry size
    • e_phnum: 1 - Number of program header entries
  • Program Header Table:
    • p_type: LOAD
    • p_offset: 0
    • p_vaddr: 0x8000000
    • p_paddr: 0x8000000
    • p_filesz: 0x0000070
    • p_memsz: 0x0000070
    • p_flags: 5 (PFR|PFX)
  • X86 Assembly Code:
    • mov ebx, 42
    • mov eax, 1
    • int 80h
  • Equivalent C Code:
    • _ISC_EXIT
    • return 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 ./mini and checking the exit code.
  • mac:~ me$ ./mini
  • mac:~ 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: 3
    • sizeofcmds: 0x88
  • Segment Command: Mapping information
    • cmd: 1 (LC_SEGMENT)
    • cmdsize: 0x38
    • vmaddr: 0
    • vmsize: 0xc0
    • fileoff: 0
    • filesize: 5
    • initprot: 5 (R/X)
  • Thread Command:
    • cmd: 0x1A (LC_UNIXTHREAD)
    • cmdsize: 0x50
  • Thread State:
    • Flavor: 1 (x86THREADSTATE32)
    • Count: 0x10
  • X86 Assembly Code:
    • push 42
    • mov eax, 1
    • sub 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 meterpreter shellcode embedded in the .text section (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 meterpreter shellcode also embedded in the .data section (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 meterpreter array and its size.

Malware in .rsrc

  • Example of how malware can be hidden within resources (.rsrc section).
  • 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, and WaitForSingleObject.
  • 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 NumberOfSections elements.
        • It is checked for validity with FileAlignments and SectionAlignments.
      • For each section:
        • A SizeOfRawData sized block is read from the file at PointerToRawData offset.
        • Loaded in memory at the address ImageBase + VirtualAddress in a VirtualSize sized block.
        • The section is loaded with specific characteristics (e.g., CODE EXECUTE READ, INITIALIZED READ, DATA READ WRITE).
  • Sections Table:

NameVirtual SizeVirtual AddressSizeOfRawDataPointerToRawDataCharacteristics
.text0x10000x10000x2000x200CODE EXECUTE READ
.rdata0x10000x20000x2000x400INITIALIZED READ
.data0x10000x30000x2000x600DATA 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 .idata section.