-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlevel35.ts
More file actions
70 lines (61 loc) · 10 KB
/
level35.ts
File metadata and controls
70 lines (61 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { Level } from './types';
export const level35: Level = {
id: 35,
title: "Info Leak: The Glimpse",
description: "ASLR (Address Space Layout Randomization) enabled - libc.so base address randomized per-process execution (0xB7E00000 → 0xB7D5F000 → 0xB7C23000, unpredictable). Hardcoded addresses from previous exploits fail. However, relative offsets within a library remain constant across executions. printf() always at BASE+0x49020, system() always at BASE+0x40190. Strategy: information leakage via format string vulnerability. Vulnerable code: printf(user_input) without format specifier. Format string tokens: %x (hex dword from stack), %p (pointer), %s (string), %n (write). Exploit: payload='AAAA%p.%p.%p.%p' leaks stack contents. One leaked value: 0xB7E49020 (printf address in libc). Calculation: LIBC_BASE = LEAKED_PRINTF - PRINTF_OFFSET (0xB7E49020 - 0x49020 = 0xB7E00000). Now calculate any function: system() = BASE + 0x40190, /bin/sh = BASE + 0x160A24. Chain with ret2libc (Level 34) for full exploit. This level: simulate format string leak - LEAKED_ADDR pre-populated with printf address. Calculate BASE, then derive SYSTEM/BINSH addresses. Foundation for defeating ASLR in modern exploits.",
requiredSkill: "Memory Disclosure",
objective: (s) => {
const baseAddrUpper = (s.baseAddress || '').toUpperCase().replace('0X', '');
const libcBaseUpper = (s.libcBase || '').toUpperCase().replace('0X', '');
const eipUpper = (s.eip || '').toUpperCase().replace('0X', '');
const leakedValid = baseAddrUpper === 'B7E49020';
const printfOffsetValid = s.sortValue1 === 0x49020;
const libcBaseValid = libcBaseUpper === 'B7E00000';
const systemAddrValid = s.sortValue2 === 0xB7E40190;
const binshAddrValid = eipUpper === 'B7F60A24';
const aslrEnabled = s.debugDetected === true;
const leakSuccess = s.isAdmin === true;
return leakedValid && printfOffsetValid && libcBaseValid && systemAddrValid && binshAddrValid && aslrEnabled && leakSuccess;
},
hint: "Seven-stage ASLR bypass via format string info leak. Stage 1: Read LEAKED_ADDR (baseAddress, simulated format string leak, printf actual address: 0xB7E49020). Stage 2: Set PRINTF_OFFSET (sortValue1 decimal, known offset of printf in libc.so, value: 299040 / 0x49020). Stage 3: Calculate LIBC_BASE = LEAKED_ADDR - PRINTF_OFFSET (libcBase pointer, 0xB7E49020 - 0x49020 = 0xB7E00000). Stage 4: Calculate SYSTEM_ADDR = LIBC_BASE + 0x40190 (sortValue2 decimal, system() function, result: 3085173136). Stage 5: Calculate BINSH_ADDR = LIBC_BASE + 0x160A24 (eip pointer hex, '/bin/sh' string, result: 0xB7F60A24). Stage 6: Verify ASLR_ENABLED=true (debugDetected, auto-set). Stage 7: Verify LEAK_SUCCESS=true (isAdmin, auto-triggers when all calculations correct). Real exploit: printf(user_input) with %p tokens → Leak libc pointer from stack → Calculate base → Combine with ret2libc. Use Memory Scanner to read LEAKED_ADDR, then calculate offsets using ExploitWorkshop/MemoryScanner. Formula: BASE = LEAKED - OFFSET, TARGET = BASE + TARGET_OFFSET.",
tutorPersona: "PaX Team/Nergal: The map changes every time you look at it. Learn to read the stars instead. History: 2000 - PaX Team introduces ASLR (Address Space Layout Randomization) in PaX patch for Linux kernel. Motivation: Exploits rely on hardcoded addresses (shellcode at 0xBFFFFFFF, libc at 0x40000000). Randomize memory layout → Attacker cannot predict jump targets → Exploitation requires brute force (impractical with 16-bit entropy: 65536 attempts, process crash detection). Mechanism: Kernel randomizes mmap base (libraries), stack base, heap base, executable base (PIE) on each execve(). Example: libc.so maps at 0xB7E00000 in Process A, 0xB7C5A000 in Process B, 0xB7D12000 in Process C. Attacker's hardcoded 0xB7E40190 (system) only works in 1/65536 cases. 2001 - OpenBSD implements W^X and ASLR-like randomization (stack gap randomization). 2003 - PaX ASLR matures: full randomization of all segments. Challenge to exploitation community: ret2libc (Level 34) broken by ASLR. Need new technique. Enter: Information Leakage. 2001-2005 - Format String Vulnerabilities (discovered 2000, popularized by tf8's Phrack 59 article 'Exploiting Format String Vulnerabilities', September 2001). Concept: printf(user_input) without format specifier. Attacker controls format string: printf('%x.%x.%x') reads stack memory, printf('%s') dereferences pointers (arbitrary read), printf('%n') writes to memory (arbitrary write). Memory Disclosure via Format Strings: Vulnerable code: void log_error(char *msg) { printf(msg); }. Attacker input: '%p.%p.%p.%p.%p.%p.%p.%p' → printf walks stack, prints 8 pointers. Stack contains: saved EBP, return addresses (code pointers), libc function pointers (__libc_start_main, printf PLT entry). Example leak: 0xbffff7a8.0x08048520.0xb7e49020.0xbffff7c4 → Third value 0xb7e49020 is in libc range (0xb7______). Identify function: Compare to known offsets. If printf offset in libc.so is 0x49020 (find via nm -D /lib/i386-linux-gnu/libc.so.6 | grep ' printf$'), then: LIBC_BASE = 0xb7e49020 - 0x49020 = 0xb7e00000. Calculate any function: system = BASE + 0x40190 = 0xb7e40190, /bin/sh = BASE + 0x160A24 = 0xb7f60a24. Chain with ret2libc: overflow buffer → Use leaked addresses → Exploit succeeds despite ASLR. 2003-2004 - Information leaks become standard ASLR bypass. Nergal's 'The advanced return-into-lib(c) exploits' (Phrack 58, 2001) predicts this: ASLR + info leak = pwn. Memory Disclosure Techniques: 1. Format String (%x/%p read stack/registers), 2. Buffer Over-read (Heartbleed pattern: read past buffer boundary, leak heap/memory), 3. Use-After-Free (read freed object, leak heap pointers), 4. Side-Channel (timing attacks, cache analysis to infer addresses). Real-world examples: 2003 - CVE-2003-0165: Apache mod_php format string → leak libc → ret2libc. 2009 - CVE-2009-1897: Linux kernel NULL dereference → mmap 0x0 → leak kernel addresses → privilege escalation. 2014 - Heartbleed (CVE-2014-0160): OpenSSL buffer over-read → leak process memory → ASLR bypass + private keys. 2014 - Rowhammer: bit flips in DRAM → corrupt page tables → leak physical addresses → defeat KASLR. Modern ASLR (2010-present): 2005 - Linux kernel 2.6.12 includes ASLR (exec-shield, PaX merged features). 2007 - Windows Vista introduces ASLR + DEP by default. 2012 - Android 4.0 (Ice Cream Sandwich) enables ASLR. 2016 - iOS 4.3 (2011) and Android 5.0 (2014) introduce strong ASLR. Entropy improvements: 32-bit: ~16 bits (mmap), ~8 bits (stack) → 65536 attempts, feasible brute force. 64-bit: ~28 bits (mmap), ~30 bits (stack) → 268 million attempts, impractical brute force. Limitations of ASLR: Relative offsets constant (leak one address → calculate all). Information leaks common (format string, over-read, dangling pointers). Partial overwrites (overwrite low byte of pointer, bypass randomization). 32-bit entropy low (brute force feasible with crash-resistant targets like forking servers). Defenses stacking: ASLR + NX + Stack Canary + RELRO + PIE + CFI (Control Flow Integrity) = modern baseline. ASLR alone insufficient, but forces attacker to add info leak stage (increases exploit complexity). This level: ASLR enabled (libc base randomized), format string vulnerability simulated (LEAKED_ADDR pre-populated with printf address 0xB7E49020). Calculate LIBC_BASE via subtraction (BASE = LEAKED - OFFSET). Demonstrates core ASLR bypass pattern: leak → calculate → exploit. Educational foundation for modern ROP+leak chains (2012-present standard). Technique used in 90% of modern exploits (ASLR universal on Linux/Windows/iOS/Android). Info leak is first stage of every post-2007 exploit. Historical context: 2000 ASLR introduced → 2001 format string info leaks discovered → 2003 community realizes leak+ASLR_bypass pattern → 2005-2007 becomes standard exploitation flow → 2010-present mandatory in CTF/pentest/real-world. PaX Team quote (2003): 'Randomization raises the bar. Information leakage lowers it. Defense in depth requires eliminating leak primitives, not just randomizing.' Modern reality: Leak primitives persist (Spectre, Meltdown, race conditions, side-channels). ASLR+leak arms race continues (CFI, shadow stacks, memory tagging). This level teaches the equilibrium: ASLR forces info leak, info leak enables ret2libc/ROP.",
memoryLayout: [
{ key: 'baseAddress', label: 'LEAKED_ADDR', type: 'pointer', offset: 0x0, isStatic: true },
{ key: 'sortValue1', label: 'PRINTF_OFFSET', type: 'int', offset: 0x4 },
{ key: 'libcBase', label: 'LIBC_BASE', type: 'pointer', offset: 0x10 },
{ key: 'sortValue2', label: 'SYSTEM_ADDR', type: 'int', offset: 0x14 },
{ key: 'eip', label: 'BINSH_ADDR', type: 'pointer', offset: 0x18 },
{ key: 'debugDetected', label: 'ASLR_ENABLED', type: 'bool', offset: 0x800 },
{ key: 'isAdmin', label: 'LEAK_SUCCESS', type: 'bool', offset: 0x30 }
],
initialState: {
baseAddress: 'B7E49020',
sortValue1: 0,
libcBase: '00000000',
sortValue2: 0,
eip: '00000000',
debugDetected: true,
isAdmin: false
},
update: (s) => {
const leakedAddr = parseInt((s.baseAddress || 'B7E49020').replace('0x', ''), 16);
const printfOffset = s.sortValue1 || 0;
const libcBaseCalc = leakedAddr - printfOffset;
const libcBaseCurrent = parseInt((s.libcBase || '00000000').replace('0x', ''), 16);
const expectedLibcBase = 0xB7E00000;
const expectedPrintfOffset = 0x49020;
const expectedSystemAddr = expectedLibcBase + 0x40190;
const expectedBinshAddr = expectedLibcBase + 0x160A24;
const libcBaseValid = libcBaseCurrent === expectedLibcBase;
const printfOffsetValid = printfOffset === expectedPrintfOffset;
const systemAddrValid = s.sortValue2 === expectedSystemAddr;
const binshAddr = parseInt((s.eip || '00000000').replace('0x', ''), 16);
const binshAddrValid = binshAddr === expectedBinshAddr;
const updates: any = {};
if (libcBaseValid && printfOffsetValid && systemAddrValid && binshAddrValid) {
updates.isAdmin = true;
}
return updates;
},
platforms: [{ id: 'p1', x: 0, y: 280, width: 800, height: 40, type: 'static' }]
};