const constants = [ 'exports', '270328ewawLo', 'instantiate', '1OsuamQ', 'Incorrect!', 'length', 'copy_char', 'value', '1512517ESezaM', 'innerHTML', 'check_flag', 'result', '1383842SQRPPf', '924408cukzgO', 'getElementById', '418508cLDohp', 'input', 'Correct!', '573XsMMHp', 'arrayBuffer', '183RUQBDE', '38934oMACea', ]; const get_const = function(addr, _seemingly_unused) { addr = addr - 0x11d; let result = constants[addr]; return result; }; // Stack aligner of some sort? (function() { while (!![]) { try { const result = -parseInt(get_const(0x122)) + -parseInt(get_const(0x12f)) + -parseInt(get_const(0x126)) * -parseInt(get_const(0x12b)) + -parseInt(get_const(0x132)) + parseInt(get_const(0x124)) + -parseInt(get_const(0x121)) * -parseInt(get_const(0x11f)) + parseInt(get_const(0x130)); if (result === 0x252604) break; else constants['push'](constants['shift']()); } catch (e) { constants['push'](constants['shift']()); } } }()); let exports; // Load the WebAssembly module and get its exports (async () => { let checkFlagWasm = await fetch('./index.wasm'), arrayBufferResult = await WebAssembly['instantiate'](await checkFlagWasm['arrayBuffer']()), arrayBufferResultInstance = arrayBufferResult['instance']; exports = arrayBufferResultInstance['exports']; })(); function onButtonPress() { let value = document['getElementById']('input')['value']; const copy_char = exports['copy_char']; for (let i = 0x0; i < value['length']; i++) { const char_code = value['charCodeAt'](i); copy_char(char_code, i); } exports['copy_char'](0x0, value['length']), exports['check_flag']() == 0x1 ? document['getElementById']('result')['innerHTML'] = 'Correct!' : document['getElementById']('result')['innerHTML'] = 'Incorrect!'; } // First attempt at reverse engineering copy_char/func3. // This is a relatively direct translation. function copy_char(var0, var1) { const key = "\xf1\xa7\xf0\x07\xed"; // (global $global0 (mut i32) (i32.const 66864)) // (global $global1 i32 (i32.const 1072)) const var2 = exports['global0']['value']; const var3 = 16; const var4 = var2 - var3; exports['memory']['buffer'][var4 + 12] = var0; exports['memory']['buffer'][var4 + 8] = var1; var5 = exports['memory']['buffer'][var4 + 12]; if (var5 !== 0) { const var6 = 4; const var7 = exports['memory']['buffer'][var4 + 8]; const var8 = 5; const var9 = var7 % var8; const var10 = var6 - var9; const var11 = key.charCodeAt(var10); const var12 = 24; const var13 = var11 << var12; const var14 = var13 >> var12; const var15 = exports['memory']['buffer'][var4 + 12]; const var16 = var15 ^ var14; exports['memory']['buffer'][var4 + 12] = var16; } const var17 = exports['memory']['buffer'][var4 + 12]; const var18 = exports['memory']['buffer'][var4 + 8]; exports['memory']['buffer'][var18 + 1072] = var17; } // Let's shorten it more and get rid of all the memory shuffling function copy_char(c, i) { const key = "\xf1\xa7\xf0\x07\xed"; if (c !== 0) { const key_index = (4 - (i % 5)); const key_char = key.charCodeAt(key_index); c ^= key_char; } exports['memory']['buffer'][i + 1072] = c; } // copy_char // (func $func3 (param $var0 i32) (param $var1 i32) // (local $var2 i32) (local $var3 i32) (local $var4 i32) (local $var5 i32) (local $var6 i32) (local $var7 i32) (local $var8 i32) (local $var9 i32) (local $var10 i32) (local $var11 i32) (local $var12 i32) (local $var13 i32) (local $var14 i32) (local $var15 i32) (local $var16 i32) (local $var17 i32) (local $var18 i32) // global.get $global0 // local.set $var2 // i32.const 16 // local.set $var3 // local.get $var2 // local.get $var3 // i32.sub // local.set $var4 // local.get $var4 // local.get $var0 // i32.store offset=12 // local.get $var4 // local.get $var1 // i32.store offset=8 // local.get $var4 // i32.load offset=12 // local.set $var5 // block $label0 // local.get $var5 // i32.eqz // br_if $label0 // i32.const 4 // local.set $var6 // local.get $var4 // i32.load offset=8 // local.set $var7 // i32.const 5 // local.set $var8 // local.get $var7 // local.get $var8 // i32.rem_s // local.set $var9 // local.get $var6 // local.get $var9 // i32.sub // local.set $var10 // local.get $var10 // i32.load8_u offset=1067 // local.set $var11 // i32.const 24 // local.set $var12 // local.get $var11 // local.get $var12 // i32.shl // local.set $var13 // local.get $var13 // local.get $var12 // i32.shr_s // local.set $var14 // local.get $var4 // i32.load offset=12 // local.set $var15 // local.get $var15 // local.get $var14 // i32.xor // local.set $var16 // local.get $var4 // local.get $var16 // i32.store offset=12 // end $label0 // local.get $var4 // i32.load offset=12 // local.set $var17 // local.get $var4 // i32.load offset=8 // local.set $var18 // local.get $var18 // local.get $var17 // i32.store8 offset=1072 // return // ) // (data (i32.const 1024) "\9dn\93\c8\b2\b9A\8b\94\90\dd>\94\97\90\dd?\c4\c2\c9\dd4\c2\c5\97\db1\93\92\c0\da6\93\93\c1\d9>\91\c1\97\90\00\00")