web/some_assembly_required_3
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h4>Enter flag:</h4>
|
||||
<input type="text" id="input"/>
|
||||
<button onclick="onButtonPress()">Submit</button>
|
||||
<p id="result"></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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")
|
||||
Binary file not shown.
@@ -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")
|
||||
)
|
||||
Executable
+20
@@ -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()
|
||||
Reference in New Issue
Block a user