diff --git a/web/some_assembly_required_3/index.html b/web/some_assembly_required_3/index.html new file mode 100644 index 0000000..6ec79d3 --- /dev/null +++ b/web/some_assembly_required_3/index.html @@ -0,0 +1,12 @@ + + + + + + +

Enter flag:

+ + +

+ + diff --git a/web/some_assembly_required_3/index.js b/web/some_assembly_required_3/index.js new file mode 100644 index 0000000..edd8a7f --- /dev/null +++ b/web/some_assembly_required_3/index.js @@ -0,0 +1,195 @@ +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") diff --git a/web/some_assembly_required_3/index.wasm b/web/some_assembly_required_3/index.wasm new file mode 100644 index 0000000..8cc55fe Binary files /dev/null and b/web/some_assembly_required_3/index.wasm differ diff --git a/web/some_assembly_required_3/index.wat b/web/some_assembly_required_3/index.wat new file mode 100644 index 0000000..96234db --- /dev/null +++ b/web/some_assembly_required_3/index.wat @@ -0,0 +1,310 @@ +(module + (table $table0 1 1 funcref) + (memory $memory0 2) + (global $global0 (mut i32) (i32.const 66864)) + (global $global1 i32 (i32.const 1072)) + (global $global2 i32 (i32.const 1067)) + (global $global3 i32 (i32.const 1024)) + (global $global4 i32 (i32.const 1328)) + (global $global5 i32 (i32.const 1024)) + (global $global6 i32 (i32.const 66864)) + (global $global7 i32 (i32.const 0)) + (global $global8 i32 (i32.const 1)) + (export "memory" (memory $memory0)) + (export "__wasm_call_ctors" (func $func0)) + (export "strcmp" (func $func1)) + (export "check_flag" (func $func2)) + (export "input" (global $global1)) + (export "copy_char" (func $func3)) + (export "key" (global $global2)) + (export "__dso_handle" (global $global3)) + (export "__data_end" (global $global4)) + (export "__global_base" (global $global5)) + (export "__heap_base" (global $global6)) + (export "__memory_base" (global $global7)) + (export "__table_base" (global $global8)) + (func $func0 + ) + (func $func1 (param $var0 i32) (param $var1 i32) (result 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) (local $var19 i32) (local $var20 i32) (local $var21 i32) (local $var22 i32) (local $var23 i32) (local $var24 i32) (local $var25 i32) (local $var26 i32) (local $var27 i32) (local $var28 i32) (local $var29 i32) (local $var30 i32) (local $var31 i32) (local $var32 i32) (local $var33 i32) (local $var34 i32) (local $var35 i32) (local $var36 i32) (local $var37 i32) (local $var38 i32) (local $var39 i32) (local $var40 i32) (local $var41 i32) (local $var42 i32) (local $var43 i32) + global.get $global0 + local.set $var2 + i32.const 32 + local.set $var3 + local.get $var2 + local.get $var3 + i32.sub + local.set $var4 + local.get $var4 + local.get $var0 + i32.store offset=24 + local.get $var4 + local.get $var1 + i32.store offset=20 + local.get $var4 + i32.load offset=24 + local.set $var5 + local.get $var4 + local.get $var5 + i32.store offset=16 + local.get $var4 + i32.load offset=20 + local.set $var6 + local.get $var4 + local.get $var6 + i32.store offset=12 + block $label1 + loop $label2 + local.get $var4 + i32.load offset=16 + local.set $var7 + i32.const 1 + local.set $var8 + local.get $var7 + local.get $var8 + i32.add + local.set $var9 + local.get $var4 + local.get $var9 + i32.store offset=16 + local.get $var7 + i32.load8_u + local.set $var10 + local.get $var4 + local.get $var10 + i32.store8 offset=11 + local.get $var4 + i32.load offset=12 + local.set $var11 + i32.const 1 + local.set $var12 + local.get $var11 + local.get $var12 + i32.add + local.set $var13 + local.get $var4 + local.get $var13 + i32.store offset=12 + local.get $var11 + i32.load8_u + local.set $var14 + local.get $var4 + local.get $var14 + i32.store8 offset=10 + local.get $var4 + i32.load8_u offset=11 + local.set $var15 + i32.const 255 + local.set $var16 + local.get $var15 + local.get $var16 + i32.and + local.set $var17 + block $label0 + local.get $var17 + br_if $label0 + local.get $var4 + i32.load8_u offset=11 + local.set $var18 + i32.const 255 + local.set $var19 + local.get $var18 + local.get $var19 + i32.and + local.set $var20 + local.get $var4 + i32.load8_u offset=10 + local.set $var21 + i32.const 255 + local.set $var22 + local.get $var21 + local.get $var22 + i32.and + local.set $var23 + local.get $var20 + local.get $var23 + i32.sub + local.set $var24 + local.get $var4 + local.get $var24 + i32.store offset=28 + br $label1 + end $label0 + local.get $var4 + i32.load8_u offset=11 + local.set $var25 + i32.const 255 + local.set $var26 + local.get $var25 + local.get $var26 + i32.and + local.set $var27 + local.get $var4 + i32.load8_u offset=10 + local.set $var28 + i32.const 255 + local.set $var29 + local.get $var28 + local.get $var29 + i32.and + local.set $var30 + local.get $var27 + local.set $var31 + local.get $var30 + local.set $var32 + local.get $var31 + local.get $var32 + i32.eq + local.set $var33 + i32.const 1 + local.set $var34 + local.get $var33 + local.get $var34 + i32.and + local.set $var35 + local.get $var35 + br_if $label2 + end $label2 + local.get $var4 + i32.load8_u offset=11 + local.set $var36 + i32.const 255 + local.set $var37 + local.get $var36 + local.get $var37 + i32.and + local.set $var38 + local.get $var4 + i32.load8_u offset=10 + local.set $var39 + i32.const 255 + local.set $var40 + local.get $var39 + local.get $var40 + i32.and + local.set $var41 + local.get $var38 + local.get $var41 + i32.sub + local.set $var42 + local.get $var4 + local.get $var42 + i32.store offset=28 + end $label1 + local.get $var4 + i32.load offset=28 + local.set $var43 + local.get $var43 + return + ) + (func $func2 (result i32) + (local $var0 i32) (local $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) + i32.const 0 + local.set $var0 + i32.const 1072 + local.set $var1 + i32.const 1024 + local.set $var2 + local.get $var2 + local.get $var1 + call $func1 + local.set $var3 + local.get $var3 + local.set $var4 + local.get $var0 + local.set $var5 + local.get $var4 + local.get $var5 + i32.ne + local.set $var6 + i32.const -1 + local.set $var7 + local.get $var6 + local.get $var7 + i32.xor + local.set $var8 + i32.const 1 + local.set $var9 + local.get $var8 + local.get $var9 + i32.and + local.set $var10 + local.get $var10 + return + ) + (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") + (data (i32.const 1067) "\f1\a7\f0\07\ed") +) diff --git a/web/some_assembly_required_3/solve.py b/web/some_assembly_required_3/solve.py new file mode 100755 index 0000000..378411f --- /dev/null +++ b/web/some_assembly_required_3/solve.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +output = b"\x9dn\x93\xc8\xb2\xb9A\x8b\x94\x90\xdd>\x94\x97\x90\xdd?\xc4\xc2\xc9\xdd4\xc2\xc5\x97\xdb1\x93\x92\xc0\xda6\x93\x93\xc1\xd9>\x91\xc1\x97\x90\x00\x00" +key = b"\xf1\xa7\xf0\x07\xed" + +def copy_char_inv(c: int, i: int) -> int: + if c != 0: + key_index = (4 - (i % 5)) + key_char = key[key_index] + c ^= key_char + return c + +def main(): + for i, c in enumerate(output): + b = copy_char_inv(c, i) + print(chr(b), end="") + print() + +if __name__ == "__main__": + main()