Lecture13

Introduction
  • Topic of discussion: Code reuse with nonexecutable memory and partial Address Space Layout Randomization (ASLR).

  • Nonexecutable memory (e.g., Data Execution Prevention - DEP): A security feature that marks certain memory regions as non-executable, preventing attackers from running arbitrary injected code. Code reuse techniques like ROP are designed to bypass such protections by executing existing legitimate code.

Address Space Layout Randomization (ASLR)
  • Definition: A security technique that randomizes the memory allocations of a process, making it difficult for attackers to predict the location of specific functions or data in memory.

    • ASLR shuffles the locations of key memory regions, including the stack, heap, and shared libraries (like LibC), at runtime.

    • This makes it harder for exploit writers to hardcode memory addresses, thereby increasing the difficulty of reliable exploitation.

  • Discussed modes of ASLR:

    • Full ASLR: Every section of a process's memory space, including the main executable, stack, heap, and all loaded libraries, is randomized.

    • Partial ASLR: Only certain sections are randomized (typically the stack, heap, and shared libraries), leaving some sections (often the main executable's text and data segments) at fixed, predictable addresses. This predictability can be exploited.

  • Importance of knowing fixed addresses in the binary to bypass ASLR protections:

    • The main binary's code (text section) and static data addresses are often fixed because the compiler hard codes them, especially if Position Independent Executables (PIE) are not enabled for the main binary. Without PIE, the executable is loaded at a consistent base address.

    • In contrast, addresses of libraries such as LibC are typically subject to randomization. This means payloads that rely on direct calls to library functions (e.g., system, execve) or returning into any part of a randomized library (like in Return-to-LibC or specific Return-to-EUclipse scenarios) are directly affected by ASLR.

Fixed ASLR Regions
  • Key regions in memory management that often remain fixed under partial ASLR:

    • Binary text section: Contains the executable code of the main application.

    • Data section: Stores initialized global and static variables.

    • BSS section: Stores uninitialized global and static variables (often zero-initialized at program start).

  • Explanation:

    • In partial ASLR environments, even though memory regions like the stack, heap, and dynamically linked libraries are randomized, the main application binary's base addresses and the relative offsets within its text, data, and BSS sections often remain unchanged.

    • Attackers can exploit this fixed portion by locating predictable gadgets or data within the main executable itself, thereby establishing a stable foundation for their exploit chain even when other parts of memory are unpredictable.

Attack Strategy
Finding Non-Randomized References
  • Objective: Identify memory references (e.g., function entry points, data pointers, or instruction sequences) that are not randomized and can be leveraged during an attack.

  • Key focus areas:

    • Accessing functions and libraries from fixed addresses: This often involves finding fixed pointers within the main binary's data section that point to external library functions, or identifying useful ROP gadgets directly within the main binary's fixed text section.

    • Understanding how applications call external library functions (e.g., printf): Such calls often go through the Procedure Linkage Table (PLT) and Global Offset Table (GOT), which, while involved in dynamic linking, can also present fixed points for exploitation when the main binary is not randomized.

Return Oriented Programming (ROP)
  • Definition: A sophisticated security exploit technique that allows an attacker to execute arbitrary code (or achieve arbitrary computation) in the presence of modern security defenses like ASLR and DEP (Data Execution Prevention), without injecting any new code.

    • ROP leverages existing legitimate instruction sequences within the program or its loaded libraries.

  • Conceptual Overview:

    • Attackers craft an exploit by chaining together small instruction sequences, known as "gadgets." Each gadget typically ends with a RET (return) instruction.

    • The RET instruction pops an address from the stack and jumps to it. By controlling the stack, an attacker can specify a sequence of addresses, each pointing to a gadget.

    • Gadgets perform specific, limited operations (e.g., POP, MOV, arithmetic operations, system calls).

    • Examples of gadgets can include pop eax; ret, mov ebx, edx; ret, add esp, 0x10; ret.

  • ROP as generalized stack lifting:

    • Standard stack lifting (or stack pivoting) is generally limited to adjusting the stack pointer to a controlled region of memory, such as an overflowed buffer.

    • ROP is a generalization because it allows for arbitrary computational logic. By carefully selecting and chaining gadgets, an attacker can achieve complex tasks, effectively building a Turing-complete program using existing code fragments. This is done by controlling the instruction pointer indirectly via the stack, dictating the flow of execution through a series of returns.

Dynamic Linking and Symbol Resolution
Procedure Linkage Table (PLT) and Global Offset Table (GOT)
  • PLT: The Procedure Linkage Table contains small stub functions (PLT entries) that facilitate dynamic linking. When an external function (e.g., printf, system) is called for the first time, its call is redirected through a PLT entry.

  • GOT: The Global Offset Table stores the actual memory addresses of external functions after they have been resolved by the dynamic linker. Each PLT entry corresponds to a GOT entry.

  • Relationship between PLT and GOT:

    • When an external function is called, the program first jumps to its corresponding PLT entry.

    • The PLT entry then jumps to the address stored in the relevant GOT entry.

    • If the function has not yet been resolved (first call), the PLT stub will invoke the dynamic linker to find the function's actual address in memory. The dynamic linker then updates the GOT entry with this real address.

    • Subsequent calls to the same function will directly use the resolved address stored in the GOT, bypassing the dynamic linker step.

  • Importance in exploiting vulnerabilities:

    • The PLT and GOT are crucial when attackers seek to leverage functionality from external libraries in code reuse scenarios.

    • In scenarios where ASLR is partial (main binary fixed), attackers can find the address of a PLT entry (which is fixed relative to the binary's base) and use it to call an external library function.

    • If the GOT can be written to, an attacker might overwrite a GOT entry to redirect a legitimate function call to an arbitrary address, potentially pointing to attacker-controlled code or ROP gadgets.

Attacks on ASLR
  • Detecting Partial ASLR:

    • Methods for determining ASLR use include running an application multiple times and observing if the memory addresses of its stack, heap, and loaded libraries change. Tools like cat /proc/PID/maps or a debugger (e.g., GDB) can be used to monitor these addresses.

    • Analyzing the binary itself: Using tools like readelf -l or objdump -p can help identify if the executable is a Position Independent Executable (PIE). If PIE is not enabled, the main binary's text, data, and BSS sections will typically load at static, predictable base addresses.

    • Reverse engineering: Directly examining the binary's loading behavior and import tables can reveal fixed address locations.

Leveraging Gadgets in Exploits
Collecting Gadgets
  • Methods to identify gadgets:

    • Static analysis: Tools like ROPgadget, pwntools, or even objdump with specific scripting can be used to scan the binary's text section (and any loaded libraries if their base addresses are known or can be leaked) for instruction sequences that end with RET.

    • Searching for patterns that denote useful operations followed by RET. For example, a pop reg; ret sequence is highly valuable for loading arbitrary values into registers.

    • Example of common gadgets found:

      • pop eax; ret: Loads a value from the stack into the eax register.

      • pop ebx; ret: Loads a value from the stack into the ebx register.

      • add esp, N; ret (or add rsp, N; ret on x64x64): Adjusts the stack pointer, useful for clearing arguments or skipping over unwanted data.

      • mov [reg1], reg2; ret: Stores the value in reg2 at the memory address pointed to by reg1.

      • syscall; ret or int 0x80; ret: Useful for making system calls (if syscall or int 0x80 instruction is available as a gadget).

  • Importance of different gadgets combined to achieve attack objectives: By combining a sequence of diverse gadgets, an attacker can perform complex operations, such as setting up arguments for a system call (execve("/bin/sh", 0, 0)), calling external functions, or even writing data to arbitrary memory locations.

Example Computation Using ROP
  • Given a situation where you need to add two values, say 55 and 1010, and store the result ( 1515 ) in a specific memory location (0x804A0000x804A000):

    1. Load value 55: Use a pop eax; ret gadget, followed by the value 55 on the stack.

    2. Load value 1010: Use a pop ebx; ret gadget, followed by the value 1010 on the stack.

    3. Perform addition: Use an add eax, ebx; ret gadget. Now eax holds 1515.

    4. Load target address: Use a pop ecx; ret gadget, followed by the address 0x804A0000x804A000 on the stack.

    5. Store result: Use a mov [ecx], eax; ret gadget to write the value 1515 from eax into memory at address ecx (0x804A0000x804A000).

  • This example demonstrates how multiple gadgets are chained together to achieve desired computational goals, manipulating registers and memory.

Final Exploit Assembly
Final Steps in Payload Construction
  • Constructing payloads using established fixed addresses from the main binary: Given partial ASLR, the base address of the main executable doesn't change. Attackers determine this base address (often by simple observation or by inspecting the process's memory map) and then calculate the exact offsets to their chosen ROP gadgets or GOT entries within that fixed binary.

  • Managing string references dynamically instead of statically to ensure success against ASLR:

    • If a payload requires strings (e.g., "/bin/sh" for execve), these cannot be hardcoded at fixed addresses if the string's location is in a randomized section (like the stack or heap).

    • Attackers typically place required strings directly onto the stack as part of their ROP chain arguments or identify existing strings within the fixed data sections of the main binary.

    • Offsets on the stack need to be calculated dynamically during the execution of the exploit, relative to the controlled stack pointer, rather than relying on absolute addresses.

Conclusion
  • This discussion has delved into the necessary aspects of Return-Oriented Programming (ROP) for bypassing Address Space Layout Randomization (ASLR), particularly in partial ASLR environments, and highlighted the operational importance of correctly constructing ROP payloads.

  • Future discussions will further explore more advanced techniques against complete ASLR, emphasizing concepts like information leaks to determine randomized base addresses and more complex gadget chaining strategies.

Summary of Key Definitions
  • ASLR: A security technique to randomize memory addresses of key program regions (stack, heap, libraries), improving security by making it difficult for attackers to predict where code and data are located.

  • ROP: A security exploit technique that constructs a malicious payload by chaining together small, legitimate instruction sequences (gadgets) already present in the program's memory. This bypasses data execution prevention (DEP) by not injecting new code.

  • PLT/GOT: Mechanisms (Procedure Linkage Table and Global Offset Table) that facilitate dynamic linking to external library functions. They are key to understanding how to harness external functions in code reuse scenarios and can be targets for exploitation.

  • Gadget: A short sequence of legitimate machine instructions within a program's executable memory that typically ends with a RET instruction. Gadgets are the building blocks of ROP chains, enabling attackers to achieve arbitrary computations or control flow.