Article Index

Edit Last Memo

Option 2. Let's give it a run.



A few things to notice. First, it doesn't prompt you what item to edit. Second, notice those strange unprintable characters at the end. These are often times indicators that the program is over-reading memory. This is because the way strings are stored in C code is a null terminated character array. Note the null terminated portion. If the array is not null-terminated, then when you print a string (such as printf("%s",mystring)), your program will happily keep printing along until it find a null. The problems are notoriously difficult to find with fuzzing since the program often times will not crash. Let's see what's going on under the hood.



The first block it performs a similar action to leave message. It loads up an offset to the memo array using the index global that we just set in leave message. It then loads up what is at that index and makes sure that it isn't zero. If it is zero, it assumes that we haven't left a memo there yet and gives an error. Let's break down the left block:


  1. print message
  2. using the global index value, load up the offset into the memo lengths array (figure out how much space was allocated... ish...)
  3. grab the pointer to your global array based on the last memo index
  4. Read up to the previously designated size of bytes into previously malloc'd space
  5. print message
  6. print it back as a string (??)


Take a close look at that print statement. Turns out it's missing a step. It's not dereferencing the pointer before printing. What it's actually doing is printing the array of pointers as a string. Pointers don't generally print well as strings, thus it looks weird. We can verify this by breaking at that print statement and seeing what's there.


[0x00400e39]> drr
   rax 0x0000000000000000  rax
   rbx 0x0000000000000000  rax
   rcx 0x00007f8d8f1fc6e0  (/lib/x86_64-linux-gnu/ rcx library R X 'cmp rax, -0xfff' ''
   rdx 0x00007f8d8f4cb780  (unk0) rdx R W 0x0 --> rax
    r8 0x00007f8d8f6c3700  (unk1) r8 R W 0x7f8d8f6c3700
    r9 0x000000000000000e  (.comment) r9
   r10 0x0000000000000000  rax
   r11 0x0000000000000246  r11
   r12 0x00000000004008a0  (.text) (/home/user/bkp/pwn/memo/memo) r12 entry0 program R X 'xor ebp, ebp' 'memo'
   r13 0x00007ffe5ff19e40  r13 stack R W 0x1 --> (.comment)
   r14 0x0000000000000000  rax
   r15 0x0000000000000000  rax
   rsi 0x0000000000602a70  (.bss) (/home/user/bkp/pwn/memo/memo) rsi program ascii R W 0x209b010 --> heap R W 0xa74736574 (test
   rdi 0x00000000004013d8  (.rodata) (/home/user/bkp/pwn/memo/memo) rdi fcn.0040127d program R X 'and eax, 0xa0a73' 'memo' (%s

   rsp 0x00007ffe5ff19d10  rsp stack R W 0x400a32 (2
@) --> (.text) (/home/user/bkp/pwn/memo/memo) fcn.004009ea program R X 'add al, ch' 'memo'
   rbp 0x00007ffe5ff19d20  rbp stack R W 0x7ffe5ff19d60 --> stack R W 0x401200 --> (.text) (/home/user/bkp/pwn/memo/memo) fcn.00401200 fcn.00401200 program R X 'push r15' 'memo'
   rip 0x0000000000400e39  (.text) (/home/user/bkp/pwn/memo/memo) rip fcn.00400da8 program R X 'call 0x400830' 'memo'
    cs 0x0000000000000033  (.comment) ascii
rflags                 1I  rflags
  orax 0xffffffffffffffff  orax
    ss 0x000000000000002b  (.comment) ascii
fs_base 0x00007f8d8f6c3700  (unk1) r8 R W 0x7f8d8f6c3700
gs_base 0x0000000000000000  rax
    ds 0x0000000000000000  rax
    es 0x0000000000000000  rax
    fs 0x0000000000000000  rax
    gs 0x0000000000000000  rax


Note the rsi variable. It's pointing to a pointer that points to text. Thus, what we're actually seeing is the printf function frantically trying to make sense of printing a "string" that definitely isn't a string. What this means from an attacker perspective is, we have a trivial memory leak of heap space. Since the heap itself isn't randomized, we now have completely derandomized the heap.


On to view memo.