CrySyS SecChallenge 2020: It wasm me, Stardust!
Destroying the Death Star 5/5
Here you are so close to the end. As you initiate the self-destruction, you need to enter a code to verify the action. After that your mission is complete.
Good luck rebels, may the Force be with you.
Categories
Web Security
Files
Links
Solution
From the name and links we can already guess this will be a WebAssembly reversing challenge. Looking at the environment’s source we can quickly find main_bg.wasm
. I prefer static analysis over dynamic, so I threw it into a decompiler instead of debugging:
wasm-decompile main_bg.wasm --ignore > dec.txt
In it, we can quickly find the check function and it’s used resources:
global g_a:int = 1050160;
data d_a(offset: 1024) = "haxorinvalid malloc request";
export function check(a:int, b:int):int {
var c:int = g_a - 32;
c[3]:long@1 = 1874636579285894411L;
c[11]:long@1 = 3963455813207921946L;
c[19]:short@1 = 6404;
c[21]:long@1 = 805306673345600284L;
c[29]:short@1 = 5632;
c[31]:byte = 18;
var d:int = 0;
if (b != 29) goto B_a;
b = 0;
d = 1;
loop L_b {
var e:ubyte_ptr = b / 5;
if (b > 28) goto B_a;
var f:ubyte_ptr = a + b;
e = e * -5 + 1024 + b;
var g:ubyte_ptr = c + 3 + b;
b = b + 1;
if ((e[0] ^ f[0]) == g[0]) continue L_b;
}
d = 0;
label B_a:
return d;
}
We can easily see the length is checked against 29 (if (b != 29) goto B_a;
), then the string iterated over (var f:ubyte_ptr = a + b;
) and XORed then the result checked against something ((e[0] ^ f[0]) == g[0]
). Fortunately for us, XOR is an associative operation, so we could write the previous line as (e[0] ^ g[0]) == f[0]
, so this turned into what is essentially a simple string comparison. By printing e[0] ^ g[0]
instead of comparing we can easily obtain the flag. I C++ified the code and ran it:
int main()
{
size_t b = 29;
char c[29];
*(int64_t*)(c) = 1874636579285894411L;
*(int64_t*)(c + 8) = 3963455813207921946L;
*(int16_t*)(c + 16) = 6404;
*(int64_t*)(c + 18) = 805306673345600284L;
*(int16_t*)(c + 26) = 5632;
*(int8_t*)(c + 28) = 18;
const static char d_a[] = "haxorinvalid malloc request";
int d = 0;
if (b != 29)
goto B_a;
b = 0;
d = 1;
while(true)
{
if (b > 28)
goto B_a;
//const auto f = a + b;
const auto e = (b / 5) * -5 + d_a + b;
const auto g = c + b;
b = b + 1;
/*if ((*e ^ *f) != *g)
break;*/
printf("%c", *e ^ *g);
}
d = 0;
B_a:
return d;
}
Output:
cd20{debug_this_easily_i_can}