Thanks drome for sharing his knowledge and skills! He completed all 10 challenges and this series of writeups is done by him :)
08_beelogin
You’re nearly done champ, just a few more to go. we put all the hard ones at the beginning of the challenge this year so its smooth sailing from this point. Call your friends, tell ’em you won. They probably don’t care. Flare-On is your only friend now.
We are given a HTML file with a lot of JS code inside, and the page looks like this in the browser:
The form has the following fields:
1
2
3
4
5
< input type = "Password" name = "LLfYTmPiahzA3WFXKcL5BczcG1s1" id = "LLfYTmPiahzA3WFXKcL5BczcG1s1" placeholder = "LLfYTmPiahzA3WFXKcL5BczcG1s1" >< br >< br >
< input type = "Password" name = "qpZZCMxP2sDKX1PZU6sSMfBJA" id = "qpZZCMxP2sDKX1PZU6sSMfBJA" placeholder = "qpZZCMxP2sDKX1PZU6sSMfBJA" >< br >< br >
< input type = "Password" name = "ZuAHehme2RWulqFbEWBW" id = "ZuAHehme2RWulqFbEWBW" placeholder = "ZuAHehme2RWulqFbEWBW" >< br >< br >
< input type = "Password" name = "ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2" id = "ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2" placeholder = "ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2" >< br >< br >
< input type = "Password" name = "Xxb6fjAi1J1HqcZJIpFv16eS" id = "Xxb6fjAi1J1HqcZJIpFv16eS" placeholder = "Xxb6fjAi1J1HqcZJIpFv16eS" >< br >< br >
Removing redundant functions
There is a lot of junk code in the JS code/functions that never gets called, for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function VPDuWp7OyscVQRf ( lfkbVmO1 ) {
assert . expect ( 1 );
var elem = jQuery ( "#firstp" )
, log = []
, check = [];
jQuery . each ( new Array ( 100 ), function ( i ) {
elem . on ( "click" , function () {
log . push ( i );
});
check . push ( i );
});
elem . trigger ( "click" );
assert . equal ( log . join ( "," ), check . join ( "," ), "Make sure order was maintained." );
elem . off ( "click" );
}
;
We write a script to remove all the unused functions,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import re
def get_matching_brace_offset ( brace_offset , jsfile ):
i = brace_offset
height = 1
while height :
i += 1
if jsfile [ i ] == '{' :
height += 1
if jsfile [ i ] == '}' :
height -= 1
return i
def remove_useless_functions ( jsfile ):
function_names = list ( set ( re . findall ( r "function (\w+)\(\w+\) {" , jsfile )))
print ( f " { len ( function_names ) } functions found." )
print ( "Removing useless functions" )
for function_name in function_names :
if function_name == 'Add' :
continue
pattern1 = r "function " + function_name + r "\(\w+\) ({)"
pattern2 = function_name
if len ( re . findall ( pattern1 , jsfile )) != len ( re . findall ( pattern2 , jsfile )):
continue
brace_offsets = []
for m in re . finditer ( pattern1 , jsfile ):
offset = m . start ( 1 )
brace_offsets . append (( offset , get_matching_brace_offset ( offset , jsfile )))
prev_offset = 0
new_parts = []
for s , e in brace_offsets :
new_parts . append ( jsfile [ prev_offset : s ])
prev_offset = e + 1
new_parts . append ( jsfile [ prev_offset :])
new_jsfile = "" . join ( new_parts )
new_jsfile = re . sub ( r "function " + function_name + r "\(\w+\) " , "" , new_jsfile )
jsfile = new_jsfile
return jsfile
def remove_semicolons ( jsfile ):
print ( "Removing semicolons" )
jsfile = re . sub ( r ";\n" , "" , jsfile )
return jsfile
def main ():
with open ( 'script_beautified.js' , 'r' ) as fp :
jsfile = fp . read ()
jsfile = remove_useless_functions ( jsfile )
jsfile = remove_semicolons ( jsfile )
with open ( 'script_no_functions.js' , 'w' ) as fp :
fp . write ( jsfile )
if __name__ == '__main__' :
main ()
Removing junk variables
Afterwards we use an online JS beautifier to remove the newlines and fix the indentation, and get a file that is 183 lines long.
There is another obfuscation method being used here, which is where they take a form object and then call .split('')
, then eval
it if it is less than rFzmLyTiZ6AHlL1Q4xV7G8pW32
, but throwing away the result, which means it’s just junk code.
We initially tried to remove those lines using Sublime Text with the following patterns:
\w+ = formObject\.\w+\.value\.split\(''\)
if \('rFzmLyTiZ6AHlL1Q4xV7G8pW32' >= \w+\) eval\(\w+\)
which gives us a 21-line file that is much easier to analyze:
However, this would cause us to delete lines like the one below that are of use:
1
qguBomGfcTZ6L4lRxS0TWx1IwG = xDyuf5ziRN1SvRgcaYDiFlXE3AwG . ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2 . value . split ( ';' )
Hence, we instead went with a script to filter out and delete only the useless variables that have 3 occurrences — 1 from the .split('')
line and 2 from the eval
lines.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import re
def remove_useless_evals ( jsfile ):
eval_vars = list ( set ( re . findall ( r "(\w+) = xDyuf5ziRN1SvRgcaYDiFlXE3AwG\.\w+\.value\.split\(';'\)" , jsfile )))
print ( f " { len ( eval_vars ) } eval variables found." )
print ( "Removing useless eval variables" )
for eval_var in eval_vars :
pattern1 = eval_var + r " = xDyuf5ziRN1SvRgcaYDiFlXE3AwG\.\w+\.value\.split\(';'\)"
pattern2 = r "if \('rFzmLyTiZ6AHlL1Q4xV7G8pW32' >= " + eval_var + r "\) eval\(" + eval_var + r "\)"
if re . search ( pattern2 , jsfile ) is None :
continue
if len ( re . findall ( eval_var , jsfile )) != 3 :
continue
jsfile = re . sub ( pattern1 , "" , jsfile )
jsfile = re . sub ( pattern2 , "" , jsfile )
return jsfile
def main ():
with open ( 'script_no_functions_beautified.js' , 'r' ) as fp :
jsfile = fp . read ()
jsfile = remove_useless_evals ( jsfile )
with open ( 'script_no_functions_no_evals.js' , 'w' ) as fp :
fp . write ( jsfile )
if __name__ == '__main__' :
main ()
After beautifying and renaming variables, we get this final function, with the first Base64 string truncated because it’s gigantic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Add ( form_object ) {
b64_str1 = "4fny3zLzDRYIOe37Axvh5Toquw4GGWWdN..."
b64_str2 = "b2JDN2luc2tiYXhLOFZaUWRRWTlSeXdJbk9lVWxLcHlrMXJsRnk5NjJaWkQ4SHdGVjhyOENQeFE5dGxUaEd1dGJ5ZDNOYTEzRmZRN1V1emxkZUJQNTN0Umt6WkxjbDdEaU1KVWF1M29LWURzOGxUWFR2YjJqQW1HUmNEU2RRcXdFSERzM0d3emhOaGVIYlE3dm9aeVJTMHdLY2Vhb3YyVGQ4UnQ2SXUwdm1ZbGlVYjA4YVRES2xESnlXU3NtZENMN0J4MnBYdlZET3RUSmlhY2V6Y3B6eUM2Mm4yOWs="
form_str = form_object . ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2 . value . split ( ';' )
decoded_str1 = atob ( b64_str1 ). split ( '' )
decoded_str1_len = decoded_str1 . length
decoded_str2 = atob ( b64_str2 ). split ( '' )
password = 'gflsdgfdjgflkdsfjg4980utjkfdskfglsldfgjJLmSDA49sdfgjlfdsjjqdgjfj' . split ( '' )
if ( form_str [ 0 ]. length == 64 ) password = form_str [ 0 ]. split ( '' )
for ( i = 0 ; i < decoded_str2 . length ; i ++ ) {
decoded_str2 [ i ] = ( decoded_str2 [ i ]. charCodeAt ( 0 ) + password [ i % 64 ]. charCodeAt ( 0 )) & 0xFF
}
decrypted_str = decoded_str1
for ( i = 0 ; i < decoded_str1_len ; i ++ ) {
decrypted_str [ i ] = ( decrypted_str [ i ]. charCodeAt ( 0 ) - decoded_str2 [ i % decoded_str2 . length ]) & 0xFF
}
final_eval_str = ""
for ( i = 0 ; i < decoded_str1 . length ; i ++ ) {
final_eval_str += String . fromCharCode ( decrypted_str [ i ])
}
if ( 'rFzmLyTiZ6AHlL1Q4xV7G8pW32' >= final_eval_str ) eval ( final_eval_str )
}
Decryption
The decryption algorithm is decrypted[i] = str1[i] - str2[i] - password[i]
, not considering mod effects after 64 bytes.
We initially tried guessing some 64 byte password that would give a valid value that can be evaluated. Considering the lengths of the default values in the form inputs,
LLfYTmPiahzA3WFXKcL5BczcG1s1
- 28
qpZZCMxP2sDKX1PZU6sSMfBJA
- 25
ZuAHehme2RWulqFbEWBW
- 20
ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2
- 34
Xxb6fjAi1J1HqcZJIpFv16eS
- 24
we tried to concat them as passwords but none of them made sense.
We decided to checked the website’s background image which was suspicious because it was labelled as a GIF but its file format was actually JPEG, but we couldn’t find anything particular about the file format, or any information hidden with steganography.
New strategy: the decoded string must contain only valid JS characters. We know the pattern the decrypted files will be in so we can use that to narrow the possible ranges of password.
Hence we can write a script to find a possible password:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
with open ( 'script_original.js' , 'rb' ) as fp :
jsfile = fp . read ()
allowed_chars = list ( set ( jsfile ))
print ( allowed_chars )
with open ( 'decoded_b64_1' , 'rb' ) as fp :
str1 = fp . read ()
str2 = b "obC7inskbaxK8VZQdQY9RywInOeUlKpyk1rlFy962ZZD8HwFV8r8CPxQ9tlThGutbyd3Na13FfQ7UuzldeBP53tRkzZLcl7DiMJUau3oKYDs8lTXTvb2jAmGRcDSdQqwEHDs3GwzhNheHbQ7voZyRS0wKceaov2Td8Rt6Iu0vmYliUb08aTDKlDJyWSsmdCL7Bx2pXvVDOtTJiacezcpzyC62n29k"
password = [ - 1 for _ in range ( 64 )]
for i in range ( 64 ):
for b in allowed_chars :
valid = True
for j in range ( i , len ( str2 ), 64 ):
if not valid :
break
for k in range ( j , len ( str1 ), len ( str2 )):
new_char = ( str1 [ k ] - b - str2 [ j ]) & 0xff
if new_char not in allowed_chars :
valid = False
break
if valid :
password [ i ] = b
print ( bytes ( password ))
Which gives us ChVCVYzI1dU9cVg1ukBqO2u4UGr9aVCNWHpMUuYDLmDO22cdhXq3oqp8jmKBHUWI
, and trying to decipher the message with that key gives us the following
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//Yes, but who can deny the heart that is yearning?
//Affirmative!
//Uh-oh!
//This.
//At least you're out in the world. You must meet girls.
//Why is yogurt night so difficult?!
//I feel so fast and free!
//Good idea! You can really see why he's considered one of the best lawyers...
//One's bald, one's in a boat, they're both unconscious!
//You know what a Cinnabon is?
//Just one. I try not to use the competition.
//Heads up! Here we go.
//Whose side are you on?
//Did you ever think, "I'm a kid from The Hive. I can't do this"?
//Can I get help with the Sky Mall magazine? I'd like to order the talking inflatable nose and ear hair trimmer.
//It's a close community.
//Which one?
//That's why I want to get bees back to working together. That's the bee way! We're not made of Jell-O.
//Yeah. It doesn't last too long.
//Not that flower! The other one!
//Surf's up, dude!
//My parents wanted me to be a lawyer or a doctor, but I wanted to be a florist.
//Bees don't smoke!
//Good idea! You can really see why he's considered one of the best lawyers...
//Nah.
//Like what? Give me one example.
//Why not? Isn't John Travolta a pilot?
//What were they like?
//You know what your problem is, Barry?
//This is a bit of a surprise to me. I mean, you're a bee!
//Hey, you want rum cake?
//You have no job. You're barely a bee!
//My mosquito associate will help you.
//Yes, I know.
//I know.
//Up on a float, surrounded by flowers, crowds cheering.
//This is a total disaster, all my fault.
//Black and yellow.
//Oh, my.
//I assume wherever this truck goes is where they're getting it. I mean, that honey's ours.
//Yeah.
//What's the difference?
//My only interest is flowers.
//Coming!
//You did? Was she Bee-ish?
//Oh, no. More humans. I don't need this.
//What are you?
//Yeah.
//Maybe I'll pierce my thorax. Shave my antennae. Shack up with a grasshopper. Get a gold tooth and call everybody "dawg"!
//But I have another idea, and it's greater than my previous ideas combined.
//To the final Tournament of Roses parade in Pasadena.
//Giant, scary humans!
//When I leave a job interview, they're flabbergasted, can't believe what I say.
//Oh, this is so hard!
//You'll regret this.
//You want a smoking gun? Here is your smoking gun.
//You're in Sheep Meadow!
//Mamma mia, that's a lot of pages.
//My sweater is Ralph Lauren, and I have no pants.
//Here's your change. Have a great afternoon! Can I help who's next?
[][( ! [] + [])[ + []] + ( ! [] + [])[ !+ [] +!+ []] + ( ! [] + [])[ +!+ []] + ( !! [] + [])[ + []]]...
The last line is a huge JSFuck string. We put it into this online deobfuscator , rename the variables, and get something very similar to our original password finding function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
( function ( qguBomGfcTZ6L4lRxS0TWx1IwG ) {
b64_str1 = "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" ;
b64_str2 = "N0l2N2l2RTVDYlNUdk5UNGkxR0lCbTExZmI4YnZ4Z0FpeEpia2NGN0xGYUh2N0dubWl2ZFpOWm15c0JMVDFWeHV3ZFpsd2JvdTVSTW1vZndYRGpYdnhrcGJFS0taRnZOMnNJU1haRXlMM2lIWEZtN0RSQThoMG8yYUhjNFZLTGtmOXBDOFR3OUpyT2RwUmFOOUdFck12bXd2dnBzOUVMWVpxRmpnc0ZHTFFtMGV4WW11Wmc1bWRpZWZ6U3FoZUNaOEJiMURCRDJTS1o3SFpNRzcwRndMZ0RCNFFEZWZsSWE4Vg==" ;
str1 = atob ( b64_str1 ). split ( '' );
str1_len = str1 . length ;
str2 = atob ( b64_str2 ). split ( '' );
password = '87gfds8f4h4dsahfdjhkDHKHF83hNNFDHHKFBDSAKFSfsd47lmkbfjghgdfgda34' . split ( '' );
if ( qguBomGfcTZ6L4lRxS0TWx1IwG [ 1 ]. length == 64 ) password = qguBomGfcTZ6L4lRxS0TWx1IwG [ 1 ]. split ( '' );
for ( i = 0 ; i < str2 . length ; i ++ ) {
str2 [ i ] = ( str2 [ i ]. charCodeAt ( 0 ) + password [ i % 64 ]. charCodeAt ( 0 )) & 0xFF ;
};
for ( i = 0 ; i < str1_len ; i ++ ) {
str1 [ i ] = ( str1 [ i ]. charCodeAt ( 0 ) - str2 [ i % str2 . length ]) & 0xFF ;
};
str1 = String . fromCharCode . apply ( null , str1 );
if ( 'rFzmLyTiZ6AHlL1Q4xV7G8pW32' >= Oz9nOiwWfRL6yjIwvM4OgaZMIt0B ) eval ( str1 );
})( qguBomGfcTZ6L4lRxS0TWx1IwG );
We search for qguBomGfcTZ6L4lRxS0TWx1IwG
in the original script, and find that it is also from the password field after splitting it by ;
.
After making slight modifications to our password finding script, we get UQ8yjqwAkoVGm7VDdhLoDk0Q75eKKhTfXXke36UFdtKAi0etRZ3DoHPz7NxJPgHl
as the second password. Decrypting it gives us more JSFuck code, so we decode it and get this final JS code containing our flag:
1
alert ( "I_h4d_v1rtU411y_n0_r3h34rs4l_f0r_th4t@flare-on.com" )
Using the password to get the flag
This is not necessary since we already have the flag, but if you type this as the password under the ZJqLM97qEThEw2Tgkd8VM5OWlcFN6hx4y2
field:
ChVCVYzI1dU9cVg1ukBqO2u4UGr9aVCNWHpMUuYDLmDO22cdhXq3oqp8jmKBHUWI;UQ8yjqwAkoVGm7VDdhLoDk0Q75eKKhTfXXke36UFdtKAi0etRZ3DoHPz7NxJPgHl
the flag will appear as an alert:
Flag
I_h4d_v1rtU411y_n0_r3h34rs4l_f0r_th4t@flare-on.com