Lesson 20-Advanced Assembly Features

Linking and Relocation Mechanisms

Object File Format Comparison

ELF/PE/COFF Core Structure Comparison:

FeatureELF (Linux)PE (Windows)COFF (Legacy Windows)
File HeaderElf_EhdrIMAGE_NT_HEADERSIMAGE_FILE_HEADER
Section TableElf_ShdrIMAGE_SECTION_HDRIMAGE_SECTION_HDR
Symbol TableElf_SymIMAGE_SYMBOLIMAGE_SYMBOL
Relocation TableElf_Rel/Elf_RelaIMAGE_RELOCIMAGE_RELOC
Dynamic Linking.dynamic sectionImport/Export tablesLimited support

ELF File Example:

# View ELF header information
readelf -h /bin/ls
# Output key fields:
# Type: EXEC (Executable file)
# Machine: x86-64
# Entry point address: 0x400520

Symbol Table and Relocation

Symbol Representation Example (ELF):

// Symbol type definitions
#define STT_NOTYPE  0  // Unspecified type
#define STT_OBJECT  1  // Data object
#define STT_FUNC    2  // Function
#define STT_SECTION 3  // Section

// Symbol binding attributes
#define STB_LOCAL   0  // Local symbol
#define STB_GLOBAL  1  // Global symbol
#define STB_WEAK    2  // Weak symbol

Relocation Table Processing Flow:

  1. Calculate symbol virtual address (VA)
  2. Determine relocation type (e.g., R_X86_64_PC32)
  3. Apply offset correction:
// R_X86_64_PC32 relocation formula
*reloc_addr = (symbol_addr - reloc_addr - 4) & 0xFFFFFFFF;

Linker Working Principles

Static Linking Process:

  1. Symbol resolution: Build global symbol table
  2. Relocation merging: Merge identical sections
  3. Address allocation: Determine final VA
  4. Relocation correction: Fix all references

Dynamic Linking Key Mechanisms:

// Dynamic linker (ld.so) workflow
1. Load dependent libraries (recursively resolve DT_NEEDED)
2. Symbol address binding (PLT/GOT mechanism)
3. Initialize .init_array section
4. Lazy binding

PLT/GOT Dynamic Call Example:

; Dynamic function call process
call printf@PLT
; Actually expands to:
jmp *[GOT_offset]  ; First call jumps to resolution code
; After resolution, GOT stores real address

Shared Libraries and Dynamic Loading

dlopen Dynamic Loading Process:

void* handle = dlopen("libfoo.so", RTLD_LAZY);
void (*func)() = dlsym(handle, "foo_func");
func();
dlclose(handle);

LD_PRELOAD Hijacking Principle:

# Override functions via preloaded library
LD_PRELOAD=./hack.so ./program
# Same-name function in hack.so is resolved preferentially

Position-Independent Code (PIC)

PIC Implementation Key Technologies:

  1. GOT (Global Offset Table):
    • Stores global variable/function addresses
    • Dynamically resolved at runtime
  2. PLT (Procedure Linkage Table):
    • Lazy binding mechanism
    • Resolve function addresses on demand

PIC Function Call Example:

; PIC function call
call puts@PLT
; Corresponding assembly:
jmp *[GOT + puts_offset]  ; First call triggers resolution

Debugging and Disassembly Techniques

Debugging Information Formats

DWARF Debugging Information Structure:

.debug_info       # Core debugging information
.debug_abbrev     # Abbreviation table
.debug_line       # Line number information
.debug_str        # String pool
.debug_loc        # Variable locations

PDB (Windows) Key Structures:

  • TPI Stream (Type information)
  • DBI Stream (Debugging information)
  • Symbol Records (Symbol table)

Disassembly Tool Comparison

IDA Pro Advanced Features:

  • FLIRT signature recognition for library functions
  • Cross-reference analysis (Xrefs)
  • Pseudocode generation (Hex-Rays Decompiler)

Ghidra Unique Features:

  • Open-source scripting engine (Python/Java)
  • Collaborative analysis server
  • Custom decompiler

Debugging Techniques in Practice

GDB Advanced Usage:

# Conditional breakpoint
break file.c:123 if variable == 42

# Memory watchpoint
watch *(int*)0x7fffffffdcfc

# Disassemble current function
disassemble /m function_name

# Modify register value
set $rax = 0x1234

WinDbg Debugging Commands:

# Kernel debugging example
bp ntoskrnl.exe!IofCallDriver
dt _DEVICE_OBJECT 0xffffe00012345678

Reverse Engineering Fundamentals

Function Recognition Techniques:

  1. Entry characteristics (prologue/epilogue)
  2. Calling convention analysis (cdecl/stdcall)
  3. String cross-references
  4. Imported function calls

Control Flow Analysis Methods:

; Basic block division example
block1:
    cmp eax, ebx
    jne block2
    jmp block3

block2:
    mov ecx, edx

block3:
    ret

Assembly Optimization Refactoring

Code Optimization Case:

; Before optimization
mov eax, [mem1]
add eax, [mem2]
mov [mem3], eax

; After optimization (reduce memory accesses)
mov eax, [mem1]
add eax, [mem2]  ; Keep result in register
mov [mem3], eax

Structure Refactoring Example:

// Reverse-engineer structure from assembly
struct Example {
    int a;      // offset 0
    char b;     // offset 4
    double c;   // offset 8
};

Compiler and Assembly Interaction

Compiler Assembly Output

GCC Assembly Generation Example:

gcc -S -O2 test.c -o test.s
# Key compilation options:
# -fomit-frame-pointer (omit frame pointer)
# -masm=intel (Intel syntax)
# -fverbose-asm (add comments)

MSVC Assembly Output:

cl /FAtest.asm /Fa test.c
# View calling convention differences:
# __cdecl (caller cleans stack)
# __stdcall (callee cleans stack)

High-Level Language Mapping

Function Calling Convention Comparison:

Featurex86 cdeclx64 System VARM AAPCS
Parameter PassingStackRegisters + StackRegisters + Stack
Return ValueEAXXMM0/RAXR0
Stack CleanupCallerCalleeCallee
Register PreservationEBX/ESI/EDI/EBPRBX/RBP/R12-R15R4-R11

Loop Optimization Case:

// Original code
for(int i=0; i<n; i++) {
    a[i] = b[i] + c[i];
}

// Compiler-optimized assembly
mov rsi, b
mov rdi, c
mov rdx, a
mov ecx, n
rep movsq  ; SIMD-optimized version

Compiler Optimization Options

GCC Optimization Level Comparison:

LevelOptimization FocusTypical Techniques
-O0Debug supportNo optimization
-O1Basic optimizationRemove redundant code
-O2Balanced optimizationFunction inlining, loop unrolling
-O3Aggressive optimizationAuto-vectorization, function inlining
-OsCode size optimizationInstruction selection optimization

Specific Optimization Flags:

-fprofile-generate  # Profile-guided optimization
-flto               # Link-time optimization
-fvectorize         # Auto-vectorization

Inline Assembly Interaction

GCC Inline Assembly Syntax:

asm volatile (
    "movl %1, %%eax
\t"
    "addl $1, %%eax
\t"
    "movl %%eax, %0"
    : "=r"(result)      // Output operand
    : "r"(input)        // Input operand
    : "%eax"            // Clobbered registers
);

Constraint Descriptions:

ConstraintMeaningExample
rAny general register“r”(var)
mMemory reference“m”(ptr)
=rOutput operand (write)“=r”(res)
+rInput/output operand“+r”(val)

Compiler Security Mechanisms

Buffer Overflow Protection Techniques:

  1. Stack protection (Canary):
; GCC stack protection example
mov rax, fs:0x28   ; Load Canary value
mov [rbp-8], rax   ; Store to stack frame
; Before function return, check
cmp [rbp-8], fs:0x28
je .no_overflow
call __stack_chk_fail
  1. Address Space Layout Randomization (ASLR):
  • Randomize stack/heap/library load addresses
  • Controlled via /proc/sys/kernel/randomize_va_space
  1. Control Flow Integrity (CFI):
  • Validate indirect jump targets
  • Shadow Stack technology

ROP Attack Protection:

# Enable RELRO protection
gcc -Wl,-z,relro,-z,now program.c
# Generate non-executable stack
gcc -fstack-protector-strong -z noexecstack

By deeply understanding these low-level technologies, developers can achieve:

  1. High-performance binary optimization
  2. Security vulnerability analysis and protection
  3. Cross-platform binary compatibility
  4. Complex system debugging capabilities
  5. Compiler-level performance tuning
  6. Advanced reverse engineering capabilities
Share your love