Hack The Box Write Up: Invitation Code

Spoilers Alert: Reading this will kill all your fun figuring out how to register at Hack The Box . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Now Let’s Begin!

From this page we start.

1 . Looking into the source of the pages, we shall find a script called /js/inviteapi.min.js. Open it just to realize it is a piece of code decoding itself into actual codes.

[Global search invitation gives the clue]

We can beautify it and read it:

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
eval(
function(p,a,c,k,e,d){
e=function(c){return c.toString(36)};
if(!''.replace(/^/,String)){
while(c--){
d[c.toString(a)]=k[c]||c.toString(a)
}
k=[function(e){return d[e]}];
e=function(){return'\\w+'};
c=1
};
while(c--){
if(k[c]){
p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])
}
}
return p
}
('1 i(4){h 8={"4":4};$.9({a:"7",5:"6",g:8,b:\'/d/e/n\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}1 j(){$.9({a:"7",5:"6",b:\'/d/e/k/l/m\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}',
24,
24,
'response|function|log|console|code|dataType|json|POST|formData|ajax|type|url|success|api|invite|error|data|var|verifyInviteCode|makeInviteCode|how|to|generate|verify'.split('|'),
0,
{}
)
)

2 . But there isn’t much point to really figure out how everything is decoded, because we can just run it inside the console with some slight modifications:

1
2
// Running this in the console
function testt(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p};testt('1 i(4){h 8={"4":4};$.9({a:"7",5:"6",g:8,b:\'/d/e/n\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}1 j(){$.9({a:"7",5:"6",b:\'/d/e/k/l/m\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}',24,24,'response|function|log|console|code|dataType|json|POST|formData|ajax|type|url|success|api|invite|error|data|var|verifyInviteCode|makeInviteCode|how|to|generate|verify'.split('|'),0,{})

returns what we want(beautified)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function verifyInviteCode(code){
var formData={"code":code};
$.ajax({type:"POST",
dataType:"json",
data:formData,
url:'/api/invite/verify',
success:function(response){console.log(response)},
error:function(response){console.log(response)}})
}
function makeInviteCode(){
$.ajax({type:"POST",
dataType:"json",
url:'/api/invite/how/to/generate',
success:function(response){
console.log(response)
},
error:function(response){
console.log(response)
}})
}

3 . What we are interested will be the makeInviteCode(). Run it and we got a reply of Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/vaivgr/trarengr:

[Return result of our POST]

4 . Find some ROT13 decoder and decode it, we get In order to generate the invite code, make a POST request to /api/invite/generate.

5 . That seems clear enough, that all we need is to replace /api/invite/how/to/generate to /api/invite/generate and run everything again in the console like this:

1
2
3
4
5
6
7
8
9
10
11
12
function makeInviteCode(){
$.ajax({type:"POST",
dataType:"json",
url:'/api/invite/generate', // Change here
success:function(response){
console.log(response)
},
error:function(response){
console.log(response)
}})
}
makeInviteCode();

6 . This time we received a base64 encoded string S0NMWVctWEJFV0QtVE1QSkwtVkxFVVAtV0xXTkE= (might differ for different trials).

[Return result of our modified POST]

7 . Decode it and we have our invitation code!

1
2
~$ echo "S0NMWVctWEJFV0QtVE1QSkwtVkxFVVAtV0xXTkE="|base64 -d
KCLYW-XBEWD-TMPJL-VLEUP-WLWNA

8 . Enter the code and start the adventure!