TL;DR

ret2dlresolve with unexpected no gadget ahh.

Challenge

1794195196102303309.png

Recon

Firstly, we checksec this challenge to know that is the protection and how to approach.

~/ctf/playit/pwn/kukyo
❯ checksec kukyo                                                                󰥔 13:28:10
[*] '/home/claritys/ctf/playit/pwn/kukyo/kukyo'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    Stripped:   No

Yang nyala hanya Partial RELRO (tetep bisa GOT overwrite) dan NX Enabled (nggak bisa shellcode).

Sekarang kita decompile chall ini untuk mengetahui flownya.


//----- (000000000040115F) ----------------------------------------------------
ssize_t __fastcall exact(char *a1, size_t a2)
{
  ssize_t result; // rax
  ssize_t v4; // [rsp+10h] [rbp-10h]
  char *buf; // [rsp+18h] [rbp-8h]

  result = (ssize_t)a1;
  buf = a1;
  while ( a2 != 0 )
  {
    v4 = read(0, buf, a2);
    if ( v4 <= 0 )
      _exit(0);
    buf += v4;
    result = v4;
    a2 -= v4;
  }
  return result;
}

//----- (00000000004011BE) ----------------------------------------------------
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char v4[64]; // [rsp+0h] [rbp-40h] BYREF

  exact(ledger, 0x40u);
  exact(v4, 0xA0u);
  close(0);
  return 0;
}

Vulnerability

Kita mulai dari function main, ada function close(0) yang di mana menjadikan kita nanti nggak bisa dapetin shell tetapi harus langsung direct ke tempat flagnya. Because close(0) dia menutup standard input, so we can’t input some character to run a command like cat /flag.txt when you got the /bin/bash.

For the function exact, dia cara kalau dipanggil nanti parameter pertama menjadi ukuran untuk menaruh inputan kita (tapi nggak ditaruh di situ), untuk parameter kedua itu untuk menentukan berapa byte input kita yang bisa kita masukkan ke function read.

But the catch is, jumlah input kita harus sama dengan paramer kedua (a2), karena a2 != 0. a2 harus = 0. Biar nanti programnya bisa return.

Anyhow, there’s a mysterious function that does nothing at decompiler.

//----- (0000000000401156) ----------------------------------------------------
void handle()
{
  ;
}