Search This Blog

Showing posts with label CTF. Show all posts
Showing posts with label CTF. Show all posts

Saturday, February 17, 2024

[pwnable_tw - pwn] start (100 pts)

This pwn challenge is quite easy. got nervous at first but eventually got it. challenge provides a netcat IP and port to connect to, to run the exploit script against as well as the 32 bit binary that's running on that port for local debugging. so, let's look at the binary.



Challenge has every protection disabled which just indicates any shellcode injection into the challenge process will work as the stack is executable. Running the binary just asks for user input and simply exits after input is given. Let's look at what's happening under the hood.

The binary is stripped so the symbols are not present for us to see. However a entry function is present in the disassembly.


entry0() function does a few things:

- pushes esp and _exit onto the stack

- performs xor operations on eax, ebx, ecx and edx (which basically zeroes out these registers)

- pushes a total of 20 bytes onto the stack (which turns out to be the "Let's start the CTF:" string the binary outputs when it executes)

- calls write() syscall (represented by mov bl, 1 instruction)

- calls read() syscall (represented by mov al, 4 instruction) and recieves input of 60 bytes in length

- Adds 20 bytes of address in esp

- finally a 'ret' instruction is called, with eip pointing to _exit() function (0x804809d = _exit() address)


To exploit the challenge, a couple of things need to be done. Firstly, we need to utilise the buffer overflow vuln to have eip control to eventually leak the stack address. since NX bit is disabled, shellcode injection into challenge process is viable, with a twist. usually a 'jmp esp, instruction would be used to have program execution jump to the injected shellcode as its located on the stack when its injected. However, the 'jmp esp' gadget is not in the binary so another gadget has to be used to perform the same thing, to leak the stack address.


The gadget above is actually similar to the instructions within the entry binary, specifically from the ret instruction, backwards to the mov ecx, esp. If analyzed carefully, this sets up eip to point to the state in the program before sys_read syscall is invoked (state of program before sys_read = 0x08048086 approx., sys_read call invokation = 0x08048087)


the payload = padding (input buffer to eip_control offset) + stack address + length of the padding + shellcode. As seen above, padding, which is user input starts at esp + 0 which is the offset pointing to the top of the stack. shellcode was extracted from shellstorm website.

Normally the padding would be a bunch of 0x41(A) until eip control but utilising a NOP sled (bunch of 0x90 instructions that do nothing) yielded a more successful result.

Final exploit script





pwned.

 


Tuesday, February 6, 2024

[imaginaryCTF - pwn] roppy (75 pts)

Hi. back with another writeup for the imaginaryCTF 'roppy' pwn challenge. This challenge is old but still a good one to brush up on basic pwning.

Challenge description:


Challenge description shows that it's just another rop challenge. means that the stack protection NX is probably enabled. we can run checksec on the binary to confirm the suspicion:


As suspected, NX is disabled. So ret2shellcode attack won't work. User input to saved return address (RIP) control is 72 bytes. This can be calculated by creating cyclic paattern of 100 bytes, insert binary into pwndbg (gdb extension), and calculate offset with 'cyclic -l'


next, we jump to the middle of the main function to execute system(/bin/sh) to finally get shell. Can find the address of the middle of the main function in gdb.

Exploit script.




exploit script works. we get shell! 


Wednesday, January 24, 2024

"write4" x64 exploitation - ROP EMPORIUM [PWNED!!!!]


In this challenge, we will go over quite a more advanced strategy to exploit the binary and leak the flag. 

In the previous ROP Emporium challenges, the flag.txt string was always included within the challenge. We simply had to find where the flag.txt pointer is located in memory and use that for the exploit. In this challenge, the string is not located in the binary, which makes exploitation more harder. The challenge has similar protections as the previous challenges. NX is enabled which equals no shellcoding injections. So we will abuse an arbitrary-write primitive to ultimately leak the flag.

The buffer overflow vulnerability is confirmed by a segmentation fault. additionally, we also confirm the offset from junk byte input to RIP is 40 bytes.

P.S: There are 2 ways of confirming the vulnerability. You can either dynamically analyze the program's behaviour to input like I've done for this write-up or you can go down the route of plugging the binary into a disassembler like IDA or ghidra, analyze the code and establish the presence of the vulnerability that way.

 
 
program crashes at RIP from trying to access an invalid memory address. 

Now that we know the offset, onto the next step. We want to ultimately call print_file@plt with the function parameter as flag.txt so we can leak the flag. But remember the flag.txt string does not exist in the binary, so we need to find a gadget within the binary that we can utilise to write flag.txt to a read-write memory section.

we have to look for a gadget that looks similar to this.

mov [reg], reg
 
A basic understanding of x84_64 intel syntax is necessary to understand this. I'll use ROPGadget tool to scan through the binary and find where a gadget of that syntax is located as it will be useful for crafting the overall ROP chain for the payload.
 


Good. We've now located a gadget with the applied syntax above. The mov qword ptr just shows that is a quadword pointer, which is the address of the readable-writeable memory section, and r15 is the value we want to write to that said section, which is 'flag.txt'. cool.

We do this because at a later stage, the print_file function will have to use the flag.txt as a parameter in order to leak the flag. So for that to happen, the flag,txt has to be written into memory first since we know from the challenge authors that the string is not present in the binary at all. 

Now, we need to actually find a memory section within the binary that has read-write permissions. 
 

 
The .bss section of the binary along with .data section have read-write permissions along with any others. I'll go with the .bss section, .data section or any other with read-write permissions would work. 

Now, we need to find another gadget that is going to pop values from the stack into the r14 and r15 registers respectively. Understanding push and pop stack operations in memory will also be useful to understanding this.

 

Gadget found! Now lastly, we need to fin. the last gadget we will use to have the print_file() function in the binary use the flag.txt written in the .bss section as a parameter. We will have to specifically look for a pop rdi, ret gadget as this gadget will ensure 'flag.txt' is stored in the rdi register, as x86_64 calling convention requires that function parameters are to be stored in the RDI, RSI, RDX and so on. But for this specific exploit, we just store the 'flag.txt' in RDI.


Let's go over the exploit strategy to see how we can exploit the challenge and get the flag.

1. we start by overwriting the buffer and establish the offset from input to RIP is 40 bytes.

2. After we change execution by changing RDI to POP R14; R15; RET

3. We then write the value of R14 in the stack for POP R14 (.bss section memory address)

4. We then write the value of R15, which is flag.txt string in the stack for POP R15.

5. After, execution is then redirected again to MOV QWORD PTR [R14], R15, RET to write the 'flag.txt' string into the .bss section which is readable-writable.

6. Next, POP RDI, to prepare the argument for the print_file() function.
 
7. After the location of flag.txt in bss is written (for RDI)
 
8. Finally, print_file() function with 'flag.txt' in RDI is called to ultimately leak the flag.
 
Final Exploit Script
 
 
 
the script just predefines all the gadgets found and stores them in the relevant variables and appends all the gadgets together to form the final payload. When we run the exploit script, the flag is leaked and challenge is complete.