arrow-left

All pages
gitbookPowered by GitBook
1 of 5

Loading...

Loading...

Loading...

Loading...

Loading...

XO

Whatever we input, the binary searches for characters in our input that are the same as a character of the flag in the same position. It prints the number of characters before the first occurrence of this. For example, if the flag was FwordCTF{}, then...

Fgjehrfd -> 0

sws -> 1

gggg -> 4

Using this, we can run a simple byte by byte bruteforce in order to get the data in flag.txt - NuL1_Byt35?15_IT_the_END?Why_i_c4nT_h4ndl3_That!}

Adding the flag format, we get the flag, FwordCTF{NuL1_Byt35?15_IT_the_END?Why_i_c4nT_h4ndl3_That!}

I used backticks for padding since they were pretty much guaranteed not to be in the flag - we can send backtick_padding + char and bruteforce "char" until the number returned equals the number of backticks, the character of the flag in that position would be the char where the server returned number is equal to the number of backticks.

hashtag
Flag: FwordCTF{NuL1_Byt35?15_IT_the_END?Why_i_c4nT_h4ndl3_That!}

from pwn import *
import time
printable = "?_qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*(){},./<~\\"
host = ('xo.fword.wtf', 5554)
def getnum(string):
    while True:
        try:
            p = remote(*host)
            break
        except socket.gaierror:
            time.sleep(1)
    #p = process("./task")
    p.recvline()
    p.sendline(string)
    ans = int(p.recvline())
    p.close()
    return ans
flag = ''
i = len(flag)
while '}' not in flag:
    pad = '`'*i 
    for char in printable:
        totry = pad + char
        print(totry)
        if getnum(totry) == i:
            flag += char
            print(f"Flag: {flag}")
            break
    else:
        print(flag)
        quit()
    i += 1

Tornado

Looking at the script, it scrambles the flag (by using one of the flag's characters as the seed), splits it into blocks of 2 bytes, and then pads them, and then AES encrypts them with a known key.

We start by decrypting each block with the key to get a long string: aaFho_i_aC2b_abfc8edFw!kolae_ngbom_r__f_9T525eg__ihedd}{pmertt

Then, we bruteforce the seed by trying each of the characters of the flag as the seed. We do this by scrambling our own string (I chose ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789) with the seed, and then comparing it to the above string and see if it's in flag format.

Seeing as "w" only appears once, and it is in the flag format, I based my check on this. We check if our output string[21] is equal to "B", since this is its place in the flag format.

We get our seed as "h", and we encrypt our string with it. Last thing to do is to match each character up to its original position. Script below:

hashtag
Flag: FwordCTF{peekabooi_am_the_flag!_i_am_the_danger_52592bbfcd8}

a = "aaFho_i_aC2b_abfc8edFw!kolae_ngbom_r__f_9T525eg__ihedd}{pmertt"
b = "sUHoQmijkF23xd4568LEABgMCcNpqtuOPVWDhabT1Gyz0KefRSYZr79IJlvwXn"

a = list(a)
b = list(b)
c = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
o = ""
for i in range(len(a)):
  d = b.index(c[i])
  o += a[d]
print(o)

Rev

Beginner Rev

As usual angr went brrr after I stopped being stupid and made it search for the success address, not output, which resulted in file errors.

import angr
import claripy #the solver engine

proj = angr.Project("./welcome", auto_load_libs=False)
sym_arg_size = 0x10 #Length in Bytes because we will multiply with 8 later
inp = [claripy.BVS('flag_%d' % i, 8 ) for i in range(sym_arg_size)]
flag = claripy.Concat(*inp + [claripy.BVV(b'\n')])
state = proj.factory.full_init_state(args=["./welcome"], stdin=flag)
for byte in inp:
    state.solver.add(byte >= ord('0'))
    state.solver.add(byte <= ord('9'))

simgr = proj.factory.simulation_manager(state)
good = 0x400000 + 0x12b2
bad = [0x400000 + 0x1669, 0x400000 + 0x167b]

simgr.use_technique(angr.exploration_techniques.DFS())
simgr.explore(find=good)
found = simgr.found[0]
print(found.solver.eval(flag, cast_to=bytes))
The solved input is 1755121917194838

hashtag
FLAG: FwordCTF{luhn!_wh4t_a_w31rd_n4m3}

Fibo

Here's what the program does

First of all, use a mess function to encode the flag. This mess function is easily byte by byte bruteforceable if we use the printable range of characters.

Let's call this mflag.

def mess(msg):
    enc=""
    for i in msg:
        enc+=chr((ord(i)+ord(i))%256)
    return enc
printable = string.printable
def demess(msg):
    # Byte by byte bruteforce
    dec = ""
    for i in range(len(msg)):
        for char in printable:
            if mess(char) == msg[i]:
                dec += char
                break
        else:
            dec += "-"
    return dec

Next, it pads the mflag so that it's length is a multiple of 9 using .

Then, it encrypts the mflag using matrix multiplication. Splitting the mflag into bunches of 9, it fills up a 3x3 matrix using the ascii values, multiplies it by a key that we know, transposes the resulting matrix, and turns it into a string result of of form

This is all done using the messig_up function. Then, it takes the output, parses it, and uses an encode function to encode each of the numbers, writing them all to the output file. I didn't reverse the encode function, and instead just did a classic bruteforce to get the numbers which were all less than 2500.

Here's how the solve script operates.

  1. Create a mapping of all possible encodings. Now, decode all the number encodings using this mapping.

  2. Split the numbers into groups of 9, fill up 3x3 matrices, and transpose these matrices to get the pure matrix multiplication outputs.

  3. Calculate the matrix inverse of the matrix key, then multiply the matrices by this inverse to get the original matrices

Script below:

hashtag
Flag: FwordCTF{whatever_you_do_i_can_do_it_better!!!!}

matrix[0,0] matrix[0,1] matrix[0,2] matrix[1,0] .... ----- matrix2[0,0] .....

String together all these matrices back into a string by taking the ascii values(we call round, as the results will be floats) to get mess(flag)

  • Use our byte by byte bruteforce mess function to decode the messed flag.

  • import string
    def mess(msg):
        enc=""
        for i in msg:
            enc+=chr((ord(i)+ord(i))%256)
        return enc
    printable = string.printable
    def demess(msg):
        # Byte by byte bruteforce
        dec = ""
        for i in range(len(msg)):
            for char in printable:
                if mess(char) == msg[i]:
                    dec += char
                    break
            else:
                dec += "-"
        return dec
    import random
    import numpy as np
    key=np.matrix("1 2 3;0 1 4;5 6 0")
    def recur_fibo(n):
        if n<=1:
            return 1
        else:
            return recur_fibo(n-1)+recur_fibo(n-2)
    def messig_up(message,key):
        parts=""
        while len(message)!=0:
            to_work_with=message[:9]
            first_one=np.zeros((3,3))
            k=0
            for i in range(3):
                for j in range(3):
                    first_one[i][j]=ord(to_work_with[k])
                    k+=1
            finish=np.transpose(np.matmul(first_one,key))
            for i in range(3):
                for j in range(3):
                    parts=parts + str(finish[i,j])+ " "
            parts+="-----"
            message=message[9:]
        return parts
    def encode(n):
        i=1
        fib=recur_fibo(i)
        t_f=[]
        while fib<n:
            t_f.append(fib)
            i+=1
            fib=recur_fibo(i)
        _sum=0
        a_f=[]
        for i in range(len(t_f)-1,-1,-1):
            if _sum==n:
                break
            if _sum+t_f[i]<=n:
                a_f.append(t_f[i])
                _sum+=t_f[i]
        exis=[]
        for i in t_f:
            if i in a_f:
                exis.append(1)
            else:
                exis.append(0)
        return t_f,exis
    encmap = []
    for i in range(2500):
        encmap.append(encode(i))
    stuff = open("output.txt").readlines()
    data = []
    for line in stuff:
        data.append(eval(line))
    nums = []
    for piece in data:
        nums.append(encmap.index(piece))
    print(nums)
    invkey = np.linalg.inv(key)
    dec = ""
    for i in range(0,len(nums),9):
        split = nums[i:i+9]
        goodmat = np.array([split[j:j+3] for j in range(0,9,3)])
        goodmat = np.transpose(goodmat)
        matr = np.matmul(goodmat,invkey)
        print(matr)
        for x in range(3):
            for y in range(3):
                dec += chr(round(matr[x,y]))
    print(len(dec))
    print(demess(dec).encode())