# of-course-rachel (150)
## Problem
Ugh, I had a really important file with the flag, but sadly it broke. My friend Rachel said that snapshots are good for backing up, and luckily I listened so here is my screenshot. Do you think you could help me put it back together?
(Attachments: files/snapshot.zip)
## Solution
Let's first unzip the file to see what we're dealing with.
```$ unzip snapshot.zip Archive:  snapshot.zip   creating: snapshot/  inflating: snapshot/part1.png        inflating: snapshot/part2.png        inflating: snapshot/part3.png        inflating: snapshot/part4.png        inflating: snapshot/part5.png```
![](https://raw.githubusercontent.com/shawnduong/ctf-writeups/master/2019-BCA/images/snapshot-1.png)
Looks like this is a bunch of literal screenshots of what seems to be a bunch of hex. That'd be a lot to have to type out by hand, so we can instead use an OCR tool such as GOCR to look at the image and turn it into a text file for us. We can also pipe it into xxd to perform a reverse operation to decode the hex.
```$ gocr -i part1.png | xxd -r -pimot binsciiimpor rndom
cls Vector(object):    """        This clss reesent  eco of rbira i�e.        Yo need to give he eco components. 
        Overview bout the methods:
        contuctor(componens : list) : init the vector        set(component : lis) : chanae he eco components.        __str__() : toString method        componen(i : int): ges the i-th component (start by 0)        __len__() : aes the si�e of he ecto (number of components)        euclidLength() : ens the euliden lenath of he vector.        opertor + : vector addition        operto - : vecor sbrction        operator * : sclar multipliction nd do prodct        coy() : copie thi ecto and retrn it.        chngeComponent(pos,vlue) : changes he ecified comonen.        TODO: compre-opertor    """
    def __init__(self, comonent=[]):        """            input: components or nothing            imple contcto for init the vector        """        self.__component = lis(comonens)
    def e(self, components):        """            inu: ne components            chngsthcomonG2ofthvct"�     elce the comonens with neer one.        """        if len(component) > 0:            self.__comonent = list(componen)        ele:            raise Exception("plese give ny vecto")
    def __sr__(elf):        """            returns  string representaion of he eco        """        return "(" + ",".join(map(str, self.__comonent)) + ")"
    def componen(self, i):        """            input: inde (r t 0)            opt: he i-thcomonntofthvct"�"""        if tpe(i) is in and -len(self.__components) <= i < len(self.__componens):            retn self.__comonents[i]        else:            rise Excepion("inde out of range")
    def __len__(self):        """            returns the size of the vector        """        reun len(self.__comonent)
    def eulidLength(self):        """            retrn he euliden length ofthvct�"""�smm=$ gocr -i part2.png | xxd -r -p 0        for c in self.__components:            summe += c**2        retrn math.sqrt(summe)
    def __add__(self, oher):        """            in: othrvct�assms:F�rvector has he me size            eurnsanwvct"thatrrsG2thsm.        """        i�e = len(self)        if size == len(other):            result = [self.__components[i] +                      othe.component(i) fo i in rnge(size)]            return Vecor(result)        ele:            ise Exception("must hve the sme size")
    def __ub__(elf, othe):        """            input: other vector            sumes: othe veco h the same size            returns  new vector tha repesen he diffeenz.        """        size = len(self)        if ize == len(oher):            reul = [self.__components[i] -                      other.comonent(i) for i in nae(size)]            return result        else:  # error case            raise Exceion("mus he the me size")
    def __mul__(self, other):        """            ml imlemen he sclar mltiplication             and the dot-product        """        if iintance(other, flot) or isinstnce(other, int):            ns = [c*othe for c in self.�6��onnts�rtrna�       elif (isinnce(oher, Vector) nd (len(self) == len(other))):            i�e = len(elf)            summe = 0            for i in range(size):                summe += elf.__component[i] * ohe.componen(i)            rern summe        else:  # error cse            rise Exceion("inlide oend")
    def copy(self):        """            coies thi vecor nd euns it.        """        return Vector(self.__comonent)
    def chngeComponent(self, pos, value):        """            inpu: n index (pos) nd  le            changes the specified component (os) ih he            'vle'        """        # precondition        aer (-len(elf.__comonent) <= pos < len(self.__components))        self.__comonent[po] = vle
fla = 820926016672424573282546345206805820898691$ gocr -i part3.png | xxd -r -p3215291392096695738686757700743744203737234698
def �eroVecto(dimension):�"""�rtrnsazro-vct"of si�e !dimenion'    """    # pecondition    ssert(isinstance(dimnsion, in))    etun Veco([0]*dimension)
df min():    print(int_to�Fxt(flag))
def niBsisVeco(dimension, o):    """        returns a nit bsis vector with a On         at index 'pos' (indexina t 0)    """    # recondition    assert(isinstanc(dimension, int) nd (iinstance(o, int)))    ns = [0ҦF��nsion    ans�����&trn Veco(ans)
def ap(cl, x, y):    """        input: a 'scalar' nd two ecos !! nd '!        oupt:  ector        computes th axpy opration    """    # econdition    ser(isinstance(x, Vector) nd (isinstnc(y, Veco))           nd (isinsnce(sclar, int) or isinstance(scalar, flot)))    etrn (*cl + y)
def ndomVector(N, a, b):    """        input: size (N) of th vctor.               random nge (a,b)        otput: return a random vctor of size N, with                 ndom integer comonent beten''nd'b'.�"""�random6d(None)    ns = [ndom.ndint(, b) for i in rnge(N)]    return fctor(ans)
def text_to_int(in):    heed = binascii.hxlify(inp)    rtrn int(hexed, 6)
def int_o_et(in):    heed = hx(inp)    rtrn byterray.fromhx(heed[2:]).decode()
cls Mati(object):    """    class: Mtrix    This clas eresent a bitry matix.
    Oerieq bou he mehod:
           _�7G%��&trns a string rpresntation            oeror * : imlement h mtrix vector mltipliction                        implemen he mrix-scalr mltipliction.           changeComponen(,y,le) : changes the pecified component.           componnt(x,y) : euns the pecified comonen.           width() : returns th width of th mti           heiaht() : retrn he height of the matrix           operto + : imlement he mri-ddition.           oprator - _ implemnts th mari-sbraction    """
    def __ini__(elf, mrix, q, h):        """```
Looks like we've found the flag between parts 2 and 3. Not perfect, of course, no OCR is (yet), but this really narrows things down for us. Let's just get the last 2 rows of part 2 and first 2 rows of part 3 and manually fix them.
```$ ( gocr -i part2.png | tail -n 2; gocr -i part3.png | head -n 2 ) > hex$ cat hex 5F5F636F 6D106F6E 656E7413 5B706F13 5D203D20 766l6C15 650A0A0A 666C6I61 203D2038 323039323l363031 3l363637 323l3432 34353733 32383235 34363334 35323036 38303538 32303839 3836393133323135 323l3931 33393230 3l393636 393l3537 33383638 363S3735 37373S30 30373433 3734343230333733 37323334 3639380A 0A0A6465 66201A65 726F5665 63746F12 2864696D 656E7369 6F6E293A```
The most common problem is that the OCR is mistaking the number 1 for the letter l, 5 for S, and it's getting 7s and 1s mixed up. We can use our human discretion to fix these errors.
This is the fixed hex:
```5F5F636F 6D706F6E 656E7473 5B706F73 5D203D20 76616C75 650A0A0A 666C6167 203D2038 3230393231363031 31363637 32313432 34353733 32383235 34363334 35323036 38303538 32303839 3836393733323135 32313931 33393230 31393636 39313537 33383638 36353735 37373530 30373433 3734343230333733 37323334 3639380A 0A0A6465 66207A65 726F5665 63746F72 2864696D 656E7369 6F6E293A```
When we decode it, we get the flag.
```$ xxd -r -p hex __components[pos] = value
flag = 820921601166721424573282546345206805820898697321521913920196691573868657577500743744203737234698
def zeroVector(dimension):```
However, we again need to decode the flag. There is a decoder function further in the program in part 3 from earlier.
```$ gocr -i part3.png | xxd -r -p3215291392096695738686757700743744203737234698
def �eroVecto(dimension):�"""�rtrnsazro-vct"of si�e !dimenion'    """    # pecondition    ssert(isinstance(dimnsion, in))    etun Veco([0]*dimension)
df min():    print(int_to�Fxt(flag))
def niBsisVeco(dimension, o):    """        returns a nit bsis vector with a On         at index 'pos' (indexina t 0)    """    # recondition    assert(isinstanc(dimension, int) nd (iinstance(o, int)))    ns = [0ҦF��nsion    ans�����&trn Veco(ans)
def ap(cl, x, y):    """        input: a 'scalar' nd two ecos !! nd '!        oupt:  ector        computes th axpy opration    """    # econdition    ser(isinstance(x, Vector) nd (isinstnc(y, Veco))           nd (isinsnce(sclar, int) or isinstance(scalar, flot)))    etrn (*cl + y)
def ndomVector(N, a, b):    """        input: size (N) of th vctor.               random nge (a,b)        otput: return a random vctor of size N, with                 ndom integer comonent beten''nd'b'.�"""�random6d(None)    ns = [ndom.ndint(, b) for i in rnge(N)]    return fctor(ans)
def text_to_int(in):    heed = binascii.hxlify(inp)    rtrn int(hexed, 6)
def int_o_et(in):    heed = hx(inp)    rtrn byterray.fromhx(heed[2:]).decode()
cls Mati(object):    """    class: Mtrix    This clas eresent a bitry matix.
    Oerieq bou he mehod:
           _�7G%��&trns a string rpresntation            oeror * : imlement h mtrix vector mltipliction                        implemen he mrix-scalr mltipliction.           changeComponen(,y,le) : changes the pecified component.           componnt(x,y) : euns the pecified comonen.           width() : returns th width of th mti           heiaht() : retrn he height of the matrix           operto + : imlement he mri-ddition.           oprator - _ implemnts th mari-sbraction    """
    def __ini__(elf, mrix, q, h):        """```
The main() function calls on int_to_text().
```def int_o_et(in):    heed = hx(inp)    rtrn byterray.fromhx(heed[2:]).decode()```
Let's go ahead and input the flag into this code, again using our human discretion to correct mistakes.
```$ python3Python 3.7.3 (default, Mar 26 2019, 21:43:19) [GCC 8.2.1 20181127] on linuxType "help", "copyright", "credits" or "license" for more information.>>> seed = hex(820921601166721424573282546345206805820898697321521913920196691573868657577500743744203737234698)>>> bytearray.fromhex(seed[2:]).decode()'bcactf{0p71c4lly_r3c0gn1z3d_ch4r4c73rs}\n'```