13 minutes
rgbCTF2020 | RE Writeups
Too Slow 50pts
I've made this flag decryptor! It's super secure, but it runs a little slow.
~ungato#3536
a.out Size: 16.46KB MD5: 0552728acb42e5f59c2ff3e8dcafc04d
In this challenge we are given an a.out binary file.
❯ file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=462dfe207acdfe1da2133cac6b69b45de5169ee2, for GNU/Linux 3.2.0, not stripped
❯ ./a.out
Flag Decryptor v1.0
Generating key...
^C
If we execute the file, the program only runs without stopping. Let’s dive deeper into understanding the workings of the program.
[0x000010a0]> pdg@main
undefined8 main(undefined8 argc, char **argv)
{
uint32_t uVar1;
char **var_10h;
int64_t var_4h;
sym.imp.puts("Flag Decryptor v1.0");
sym.imp.puts();
uVar1 = sym.getKey();
sym.win((uint64_t)uVar1);
return 0;
}
[0x000010a0]> pdg@sym.getKey
uint32_t sym.getKey(void)
{
uint32_t var_8h;
uint32_t var_4h;
var_8h = 0;
while (var_8h < 0x265d1d23) {
var_4h = var_8h;
while (var_4h != 1) {
if ((var_4h & 1) == 0) {
var_4h = (int32_t)var_4h / 2;
} else {
var_4h = var_4h * 3 + 1;
}
}
var_8h = var_8h + 1;
}
return var_8h;
}
After looking at the pseudocode of the program, there are two interesting functions getKey
& win
. In the getKey
function there is a looping of 0x265d1d23
. If we note the getKey
function will only return the result of the variable var_8h after increment, so the key would be 0x265d1d23
.
[0x000010a0]> pdg@sym.win
void sym.win(int64_t arg1)
{
...
...
iVar1 = *(int64_t *)(in_FS_OFFSET + 0x28);
var_30h = (char *)0x12297e12426e6f53; // 0x42642a41473e425717696a7c49334216426e2e4d79242e48796e714112297e12426e6f53
var_34h = 0;
while (var_34h < 9) {
*(uint32_t *)((int64_t)&var_30h + (uint64_t)var_34h * 4) =
*(uint32_t *)((int64_t)&var_30h + (uint64_t)var_34h * 4) ^ (uint32_t)arg1;
var_34h = var_34h + 1;
}
sym.imp.printf("Your flag: rgbCTF{%36s}\n", &var_30h);
if (iVar1 != *(int64_t *)(in_FS_OFFSET + 0x28)) {
sym.imp.__stack_chk_fail();
}
return;
}
In the win
function every four bytes of the var_30h
variable in xor with the key we got from the getKey
function. Without the need to wait for a very long loop, let’s make a simple script to solve this challenge.
>>> from Crypto.Util.number import bytes_to_long as btl
>>> from Crypto.Util.number import long_to_bytes as ltb
>>>
>>> xor = lambda x,y : b''.join(ltb(btl(enc[i*4:i*4+4]) ^ y)[::-1] for i in range(len(x)//4))
>>>
>>> enc = ltb(0x42642a41473e425717696a7c49334216426e2e4d79242e48796e714112297e12426e6f53)
>>> key = 0x265d1d23
>>>
>>> xor(enc, key)
b'pr3d1ct4bl3_k3y_n33d5_no_w41t_cab79d'
FLAG : rgbCTF{pr3d1ct4bl3_k3y_n33d5_no_w41t_cab79d}
Advanced Reversing Mechanics 1 216pts
Very very advanced trust me
71, 66, 61, 42, 53, 45, 7A, 40, 51, 4C, 5E, 30, 79, 5E, 31, 5E, 64, 59, 5E, 38, 61, 36, 65, 37, 63, 7C
~ungato#3536
arm_easy.o Size: 1.40KB MD5: ee06c35e5e65c89fe91729dc5150bd19
In the following challenge we ARM binary file arm_easy.o
❯ file easy.o
easy.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped
In this challenge I have a little problem because I don’t know how to execute the program, so we have to do a static analysis. Let’s look at the pseudocode of this program.
[0x08000034]> afl
0x08000034 3 36 sym.encryptFlag
0x08000058 7 124 sym.main
[0x08000034]> pdg@sym.encryptFlag
void sym.encryptFlag(int32_t arg1)
{
char cVar1;
// [01] -r-x section size 36 named .text
cVar1 = *(char *)arg1;
if (cVar1 == '\0') {
return;
}
do {
*(char *)arg1 = cVar1 + -1;
arg1 = arg1 + 1;
cVar1 = *(char *)arg1;
} while (cVar1 != '\0');
return;
}
As you can see there is an encryptFlag function where the function receives an arg1 parameter and each character on arg1 is summed with -1. Btw on this challenge we are given an output, chances are it is a flag that has been encrypted using this program. Here is a simple script to solve this challenge.
>>> s = [0x71, 0x66, 0x61, 0x42, 0x53, 0x45, 0x7A, 0x40, 0x51, 0x4C, 0x5E, 0x30, 0x79, 0x5E, 0x31, 0x5E, 0x64, 0x59, 0x5E, 0x38, 0x61, 0x36, 0x65, 0x37, 0x63, 0x7C]
>>> msg = ''.join(chr(i+1) for i in s)
>>> msg
'rgbCTF{ARM_1z_2_eZ_9b7f8d}'
FLAG : rgbCTF{ARM_1z_2_eZ_9b7f8d}
Object Oriented Programming 413pts
There's this small up and coming language called java I want to tell you about
~Quintec#0689
src.zip Size: 6.85KB MD5: ea5c341ca73f54b8dd8f52e34403760a
In this challenge we are given the src.zip file which contains java programs. Let’s extract and compile the challenge.
❯ cd src
❯ ls
bv.java cd.java fg.java gl.java gq.java gx.java iy.java Main.java
mo.java pr.java qa.java qg.java vh.java wz.java xp.java xq.java
❯ javac *.java
❯ java Main
IO is online.
After a few hours of analyzing the source code of the program, I finally understood how to work from this challenge.
...
public static final int SIXTEEN = BigInteger.valueOf(16).intValue();
...
String userInput = getUserInputMethodFromScannerAndInvokeAndReturnOutput(scanner);
if (userInput.length() != SIXTEEN)
System.exit(0);
if (executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut(userInput).equals(scanner.getClass().getPackageName().replace(".", ""))) {
invokePrintLineMethodForOutputPrintStream(outputPrintStream, printLineMethod, "Nice. Flag: rgbCTF{" + userInput + "}");
} else {
invokePrintLineMethodForOutputPrintStream(outputPrintStream, printLineMethod, "Try again.");
}
As you can see the length of our input must be 16, the next step of our input will be compared with the package name of the scanner
that is javautil
. Before our input is compared with javautil
, we must find out what the executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut
method does with our input.
public static String executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut(String stringToExecuteAforementionedCodeOn) throws Exception {
String encryptedString = reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepReadingTheseRidiculouslyLongMethodNames(stringToExecuteAforementionedCodeOn);
...
protected static char secureEncryptionKey; //it's protected, how you gonna crack it now?
public static String reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepReadingTheseRidiculouslyLongMethodNames(String stringToQuoteUnquoteEncrypt) throws Exception {
secureEncryptionKey = new EncryptionKeyInstantiator().getEncryptionKeyFactory().getEncryptionKey();
Integer[] encryptedArrayToBeCalledByStringConstructor = new Integer[stringToQuoteUnquoteEncrypt.length()];
for (int loopIndexIterator = ZERO; loopIndexIterator < stringToQuoteUnquoteEncrypt.length(); loopIndexIterator++) {
encryptedArrayToBeCalledByStringConstructor[loopIndexIterator] = stringToQuoteUnquoteEncrypt.charAt(loopIndexIterator)^secureEncryptionKey;
}
After being in the executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut
method our input is sent to the reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepRead...
, method, The possibility of first seeing the source code of this challenge will be a little confusing because of the strange method names and variables, but in fact this is just a simple program. As you can see there are the secureEncryptionKey
and for loop variables, where each of our input characters will be xor with secureEncryptionKey
. To find out the value of secureEncryptionKey
I made a few changes to the source code to display the value of secureEncryptionKey
.
public static String reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepReadingTheseRidiculouslyLongMethodNames(String stringToQuoteUnquoteEncrypt) throws Exception {
secureEncryptionKey = new EncryptionKeyInstantiator().getEncryptionKeyFactory().getEncryptionKey();
System.out.println("Key : "+(int)secureEncryptionKey); // <----- A little change
Integer[] encryptedArrayToBeCalledByStringConstructor = new Integer[stringToQuoteUnquoteEncrypt.length()];
for (int loopIndexIterator = ZERO; loopIndexIterator < stringToQuoteUnquoteEncrypt.length(); loopIndexIterator++) {
encryptedArrayToBeCalledByStringConstructor[loopIndexIterator] = stringToQuoteUnquoteEncrypt.charAt(loopIndexIterator)^secureEncryptionKey;
}
// Recompile the program and execute again
❯ javac *.java
❯ java Main
IO is online.
AAAAAAAAAAAAAAAA
Key : 2
Exception in thread "main" java.lang.ClassNotFoundException: CC
...
Now that we know that our input will be xored with a value of 2, okay let’s continue the analysis of the previous method.
...
public static final int TWO = BigInteger.valueOf(2).intValue();
public static final int FOUR = BigInteger.valueOf(4).intValue();
...
public static String executeCodeThatDoesSomethingThatYouProbablyNeedToFigureOut(String stringToExecuteAforementionedCodeOn) throws Exception {
String encryptedString = reallyBasicQuoteUnquoteEncryptionFunctionThatWillOnlyTakeTimeToFigureOutIfYouKeepReadingTheseRidiculouslyLongMethodNames(stringToExecuteAforementionedCodeOn);
String returnValueOfThisFunction = new String();
String[] chunksOfEncryptedStringOfLengthFour = splitStringIntoChunksOfLength(encryptedString, FOUR);
...
The next step after our input is encrypted, our input will be split into four parts with the splitStringIntoChunksOfLength
method,
...
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;
}
After dividing it into four parts, our input will be further divided into two parts. In this section I will explain it briefly, where the first part defines a Class and the second part defines a Method and there is a loop for three times, the looping result will produce a string stored in the returnValueOfThisFunction
variable and will be compared with the javautil
string . So from here we have to choose the right Class and Method to produce a string as we want.
Following are my observations and simple scripts to solve this challenge.
1. gl.vg().we().rb() = "ja"
2. pr.pk().te().wj() = "va"
3. qg.am().xs().mb() = "ut"
4. fg.gg().mg().oa() = "il"
input = "glvgprpkqgamfggg" ^ 2
>>> xor = lambda x : ''.join(chr(ord(i) ^ 2) for i in x)
>>>
>>> xor('glvgprpkqgamfggg')
'enterprisecodeee'
❯ java Main
IO is online.
enterprisecodeee
Key : 2
Nice. Flag: rgbCTF{enterprisecodeee}
FLAG : rgbCTF{enterprisecodeee}
sadistic reversing 1 490pts
[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]
sadrev
In this challenge we are given a binary file itJX.so and an output in the description.
❯ file itJX.so
itJX.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=14acf351a09cb300f6bb1d4f4cc474cd3009f525, for GNU/Linux 3.2.0, stripped
After a few hours analyzing the pseudocode of the program, I still did not know how the program works. For a moment I thought that the output possible in the description was a flag, so I tried using different inputs.
❯ cat output.txt
[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]
❯ ./itJX.so aaaaa
[97, 3, 101, 7, 105]
❯ ./itJX.so rgbCTF
[114, 20, 119, 59, 104, 47]
❯ ./itJX.so rgbCTF{
[114, 20, 119, 59, 104, 47, 75]
❯ ./itJX.so rgbCTF{a
[114, 20, 119, 59, 104, 47, 75, 45]
❯ ./itJX.so rgbCTF{b
[114, 20, 119, 59, 104, 47, 75, 46]
❯ ./itJX.so rgbCTF{c
[114, 20, 119, 59, 104, 47, 75, 47]
As you can see when I try to enter “rgbCTF{” the result is the same as the output in the description, and when I add one character ‘a, b, c’ the output is the same and does not affect the previous character. So we can do brute force to guess the next character.
The following is the output from my solver.
❯ python3 solver.py
Found : rgbCTF{th1s_pr0bably_w@s_d1ff1cult6362}
FLAG : rgbCTF{th1s_pr0bably_w@s_d1ff1cult6362}
sadistic reversing 2 496pts
hopefully harder now
[117, 148, 123, 5, 54, 9, 61, 234, 45, 4, 2, 40, 88, 111, 65, 65, 46, 23, 114, 110, 102, 148, 136, 123, 30, 5, 214, 231, 225, 255, 239, 138, 211, 208, 250, 232, 178, 187, 171, 242, 255, 30, 39, 19, 64, 17, 40, 29, 13, 27]
sadrev
The following challenge we are given a binary file itwk.so and output it in the description.
❯ file itwk.so
itwk.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c701432ac4d8bbaffbcb1bca17fd413a4027f4a1, for GNU/Linux 3.2.0, stripped
Similar to the previous challenge of sadistic reversing 1
, in this challenge we have to guess the right character.
❯ ./itwk.so a
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -31
at java.lang.String.substring(String.java:1841)
at sadrev.leftrotate(sadrev.java:15)
at sadrev.main(sadrev.java:21)
❯ ./itwk.so aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 245, 239, 228, 52, 61, 233, 246, 228, 57, 57, 59, 34, 70, 46]
❯ ./itwk.so aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 245, 239, 228, 52, 61, 233, 246, 228, 57, 57, 59, 34, 70, 46, 122, 65, 117, 146, 193, 192, 34, 37, 30, 255, 244, 222, 132, 213, 223, 239, 251, 222]
❯ ./itwk.so rgbCTF{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 134, 154, 146, 96, 124, 143, 234, 248, 37, 37, 39, 62, 90, 50, 102, 93, 105, 142, 221, 220, 62, 57, 2, 227, 232, 194, 152, 201, 195, 243, 231, 194]
As you can see when I try to enter the character ‘a’, we get the message Exception: index out of range: -31. After adding 31 characters the program displays output without errors. But the output in the description is 50, so I add 18 more characters and combine it with the flag format. Even though I have combined it with the flag format, the program still produces the same output. If we look more closely, only 18 indexes produce the same output, even though the initial 7 characters have changed to “rgbCTF{”. So I decided to shoot the exact index location in the hope that the value of ‘71’ changed.
❯ ./itwk.so rgbCTF{baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 134, 154, 146, 96, 124, 143, 234, 251, 38, 38, 36, 61, 89, 49, 101, 94, 106, 141, 222, 223, 61, 58, 1, 224, 235, 193, 155, 202, 192, 240, 228, 193]
❯ ./itwk.so rgbCTF{abaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 134, 154, 146, 96, 124, 143, 234, 248, 38, 38, 36, 61, 89, 49, 101, 94, 106, 141, 222, 223, 61, 58, 1, 224, 235, 193, 155, 202, 192, 240, 228, 193]
❯ ./itwk.so rgbCTF{aabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 134, 154, 146, 96, 124, 143, 234, 248, 37, 38, 36, 61, 89, 49, 101, 94, 106, 141, 222, 223, 61, 58, 1, 224, 235, 193, 155, 202, 192, 240, 228, 193]
❯ ./itwk.so rgbCTF{aaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[71, 85, 79, 137, 143, 130, 133, 171, 107, 71, 51, 25, 98, 167, 142, 132, 230, 227, 134, 154, 146, 96, 124, 143, 234, 248, 37, 37, 36, 61, 89, 49, 101, 94, 106, 141, 222, 223, 61, 58, 1, 224, 235, 193, 155, 202, 192, 240, 228, 193]
...
...
❯ ./itwk.so rgbCTF{aaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaa
[68, 86, 76, 138, 140, 129, 134, 168, 104, 68, 48, 26, 97, 164, 141, 135, 229, 224, 133, 153, 145, 99, 127, 140, 233, 251, 38, 38, 36, 61, 89, 49, 101, 94, 106, 141, 222, 223, 61, 58, 1, 224, 235, 193, 155, 202, 192, 240, 228, 193]
...
...
❯ ./itwk.so rgbCTF{aaaaaaaaaaaaaaaaaaaaaaaaa3aaaaaaaaaaaaaaaaa
[117, 103, 125, 187, 189, 176, 183, 153, 89, 117, 1, 43, 80, 149, 188, 182, 212, 209, 180, 168, 160, 82, 78, 189, 216, 202, 23, 23, 21, 12, 104, 0, 84, 111, 91, 188, 239, 238, 12, 11, 48, 209, 218, 240, 170, 251, 241, 193, 213, 240]
...
...
❯ ./itwk.so rgbCTF{aaaaaaaaaaaaaaaaaaaaaaaaa32aaaaaaaaaaaaaaaa
[117, 148, 142, 72, 78, 67, 68, 106, 170, 134, 242, 216, 163, 102, 79, 69, 39, 34, 71, 91, 83, 161, 189, 78, 43, 57, 228, 228, 230, 255, 155, 243, 167, 156, 168, 79, 28, 29, 255, 248, 195, 34, 41, 3, 89, 8, 2, 50, 38, 3]
After taking a long time, as you can see when the character ‘b’ is in the index 33 the program displays the value ‘68’. After knowing the exact index the next step I tried to guess the right character and I got the character ‘3’ having the same output as the description. Moving to the next index, the character ‘2’ has the same output as the description.
After knowing the correct index we can do brute force for each index, the following is the output of my solver.
❯ python3 solver.py
Found : ********************************3*****************
Found : ********************************32****************
Found : ********************************324***************
Found : ********************************3249**************
Found : ********************************32494*************
Found : ********************************324943************
Found : ********************************3249432***********
Found : ********************************32494328**********
Found : ********************************32494328f*********
Found : ********************************32494328fd********
Found : ********************************32494328fds*******
Found : ********************************32494328fdsa******
Found : ********************************32494328fdsaj*****
Found : ********************************32494328fdsajs****
Found : ********************************32494328fdsajsf***
Found : ********************************32494328fdsajsfk**
Found : ********************************32494328fdsajsfkl*
Found : ********************************32494328fdsajsfkl}
Found : r*******************************32494328fdsajsfkl}
Found : rg******************************32494328fdsajsfkl}
Found : rgb*****************************32494328fdsajsfkl}
Found : rgbC****************************32494328fdsajsfkl}
Found : rgbCT***************************32494328fdsajsfkl}
Found : rgbCTF**************************32494328fdsajsfkl}
Found : rgbCTF{*************************32494328fdsajsfkl}
Found : rgbCTF{h************************32494328fdsajsfkl}
Found : rgbCTF{ho***********************32494328fdsajsfkl}
Found : rgbCTF{hop**********************32494328fdsajsfkl}
Found : rgbCTF{hope*********************32494328fdsajsfkl}
Found : rgbCTF{hopef********************32494328fdsajsfkl}
Found : rgbCTF{hopefu*******************32494328fdsajsfkl}
Found : rgbCTF{hopeful******************32494328fdsajsfkl}
Found : rgbCTF{hopefull*****************32494328fdsajsfkl}
Found : rgbCTF{hopefully****************32494328fdsajsfkl}
Found : rgbCTF{hopefully_***************32494328fdsajsfkl}
Found : rgbCTF{hopefully_t**************32494328fdsajsfkl}
Found : rgbCTF{hopefully_th*************32494328fdsajsfkl}
Found : rgbCTF{hopefully_thi************32494328fdsajsfkl}
Found : rgbCTF{hopefully_this***********32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_**********32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_w*********32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_wa********32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was*******32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_******32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_h*****32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_ha****32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_har***32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_hard**32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_harde*32494328fdsajsfkl}
Found : rgbCTF{hopefully_this_was_harder32494328fdsajsfkl}
FLAG : rgbCTF{hopefully_this_was_harder32494328fdsajsfkl}