REV
babyasm
더보기
값을 입력할 수 있는 웹페이지를 받는다.
값이 플래그와 동일하면 correct를 출력해준다.
code = [ 0,97,115,109,1,0,0,0,1,56,9,80,0,95,1,127,1,80,0,94,99,0,1,96,0,0,96,1,127,1,100,1,96,3,99,1,127,127,0,96,2,99,1,127,1,127,96,4,99,1,127,127,127,0,96,1,99,1,1,127,96,1,99,1,1,127,3,8,7,2,3,4,5,6,7,8,6,118,20,127,1,65,224,0,11,127,1,65,229,0,11,127,1,65,20,11,127,1,65,177,1,11,127,1,65,155,1,11,127,1,65,244,0,11,127,1,65,236,0,11,127,1,65,197,0,11,127,1,65,212,0,11,127,1,65,237,0,11,127,1,65,231,0,11,127,1,65,238,0,11,127,1,65,239,0,11,127,1,65,223,0,11,127,1,65,244,0,11,127,1,65,231,0,11,127,1,65,225,0,11,127,1,65,200,0,11,127,1,65,20,11,127,1,65,59,11,7,45,7,1,49,0,0,4,105,110,105,116,0,1,10,97,114,114,97,121,95,102,105,108,108,0,2,1,51,0,3,1,52,0,4,1,53,0,5,5,99,104,101,99,107,0,6,10,184,8,7,142,1,0,35,0,65,19,115,36,0,35,1,65,55,115,36,1,35,2,65,32,115,36,2,35,3,65,36,115,36,3,35,4,65,19,115,36,4,35,5,65,55,115,36,5,35,6,65,32,115,36,6,35,7,65,36,115,36,7,35,8,65,19,115,36,8,35,9,65,55,115,36,9,35,10,65,32,115,36,10,35,11,65,36,115,36,11,35,12,65,19,115,36,12,35,13,65,55,115,36,13,35,14,65,32,115,36,14,35,15,65,36,115,36,15,35,16,65,19,115,36,16,35,17,65,55,115,36,17,35,18,65,32,115,36,18,35,19,65,36,115,36,19,11,9,0,32,0,251,7,1,16,0,11,22,0,32,0,32,1,32,2,65,19,106,65,64,107,251,0,0,65,1,251,16,1,11,13,0,32,0,32,1,251,11,1,251,2,0,0,11,109,0,32,1,65,0,70,4,64,32,0,32,2,32,0,32,2,16,3,32,3,106,65,32,115,16,2,5,32,1,65,1,70,4,64,32,0,32,2,32,0,32,2,16,3,32,3,106,65,36,115,16,2,5,32,1,65,2,70,4,64,32,0,32,2,32,0,32,2,16,3,32,3,106,65,19,115,16,2,5,32,1,65,3,70,4,64,32,0,32,2,32,0,32,2,16,3,32,3,106,65,55,115,16,2,11,11,11,11,11,172,3,1,1,127,32,0,65,0,16,3,65,137,175,2,70,4,64,32,1,65,1,106,33,1,5,11,32,0,65,1,16,3,65,200,4,70,4,64,32,1,65,1,106,33,1,11,32,0,65,2,16,3,65,226,5,70,4,64,32,1,65,1,106,33,1,11,32,0,65,3,16,3,65,194,173,2,70,4,64,32,1,65,1,106,33,1,11,32,0,65,4,16,3,65,193,242,3,70,4,64,32,1,65,1,106,33,1,11,32,0,65,5,16,3,65,135,5,70,4,64,32,1,65,1,106,33,1,11,32,0,65,6,16,3,65,193,6,70,4,64,32,1,65,1,106,33,1,11,32,0,65,7,16,3,65,242,240,3,70,4,64,32,1,65,1,106,33,1,11,32,0,65,8,16,3,65,166,243,2,70,4,64,32,1,65,1,106,33,1,11,32,0,65,9,16,3,65,238,3,70,4,64,32,1,65,1,106,33,1,11,32,0,65,10,16,3,65,151,5,70,4,64,32,1,65,1,106,33,1,11,32,0,65,11,16,3,65,229,241,2,70,4,64,32,1,65,1,106,33,1,11,32,0,65,12,16,3,65,225,139,4,70,4,64,32,1,65,1,106,33,1,11,32,0,65,13,16,3,65,129,5,70,4,64,32,1,65,1,106,33,1,11,32,0,65,14,16,3,65,151,6,70,4,64,32,1,65,1,106,33,1,11,32,0,65,15,16,3,65,174,137,4,70,4,64,32,1,65,1,106,33,1,11,32,0,65,16,16,3,65,225,149,2,70,4,64,32,1,65,1,106,33,1,11,32,0,65,17,16,3,65,177,4,70,4,64,32,1,65,1,106,33,1,11,32,0,65,18,16,3,65,161,5,70,4,64,32,1,65,1,106,33,1,11,32,0,65,19,16,3,65,234,147,2,70,4,64,32,1,65,1,106,33,1,11,32,1,65,20,70,4,127,65,1,5,65,0,11,11,218,2,0,32,0,65,0,65,1,32,0,65,0,16,3,35,0,106,16,4,32,0,65,1,65,2,32,0,65,1,16,3,35,1,107,16,4,32,0,65,2,65,3,32,0,65,2,16,3,35,2,108,16,4,32,0,65,3,65,0,32,0,65,3,16,3,35,3,115,16,4,32,0,65,0,65,5,32,0,65,4,16,3,35,4,106,16,4,32,0,65,1,65,6,32,0,65,5,16,3,35,5,107,16,4,32,0,65,2,65,7,32,0,65,6,16,3,35,6,108,16,4,32,0,65,3,65,4,32,0,65,7,16,3,35,7,115,16,4,32,0,65,0,65,9,32,0,65,8,16,3,35,8,106,16,4,32,0,65,1,65,10,32,0,65,9,16,3,35,9,107,16,4,32,0,65,2,65,11,32,0,65,10,16,3,35,10,108,16,4,32,0,65,3,65,8,32,0,65,11,16,3,35,11,115,16,4,32,0,65,0,65,13,32,0,65,12,16,3,35,12,106,16,4,32,0,65,1,65,14,32,0,65,13,16,3,35,13,107,16,4,32,0,65,2,65,15,32,0,65,14,16,3,35,14,108,16,4,32,0,65,3,65,12,32,0,65,15,16,3,35,15,115,16,4,32,0,65,0,65,17,32,0,65,16,16,3,35,16,106,16,4,32,0,65,1,65,18,32,0,65,17,16,3,35,17,107,16,4,32,0,65,2,65,19,32,0,65,18,16,3,35,18,108,16,4,32,0,65,3,65,16,32,0,65,19,16,3,35,19,115,16,4,32,0,16,5,11,0,45,4,110,97,109,101,1,38,7,0,1,49,1,4,105,110,105,116,2,10,97,114,114,97,121,95,102,105,108,108,3,1,51,4,1,52,5,1,53,6,5,99,104,101,99,107 ];
const byte_code = new Uint8Array(code);
const wasmModule = new WebAssembly.Module(byte_code);
const wasmInstance = new WebAssembly.Instance(wasmModule, {});
const wasm = wasmInstance.exports;
const consoleDiv = document.getElementById('console');
const inputField = document.getElementById('input');
inputField.addEventListener('keydown', function (event) {
if (event.key === 'Enter') {
const inputText = inputField.value;
processInput(inputText);
inputField.value = '';
}
});
function processInput(text) {
const p = document.createElement('p');
if (text.startsWith('TetCTF{') && text.endsWith('}') && text.length === 27) {
let array_size= 20;
let array_obj = wasm.init(array_size);
for (var i = 0; i < array_size; i++) {
wasm.array_fill(array_obj, i, text.charCodeAt(i+7));
}
if (wasm.check(array_obj )){
p.textContent = '> Correct!';
} else {
p.textContent = '> Incorrect!';
}
} else {
p.textContent = '> Incorrect!';
}
consoleDiv.appendChild(p);
consoleDiv.scrollTop = consoleDiv.scrollHeight;
}
검증 기능은 web assembly로 구현되어 있다.
어셈 코드를 확인하면 다음과 같다.
(module
(type $type0 (struct (field $field0 (mut i32))))
(type $type1 (array (field (mut (ref null $type0)))))
(global $global0 (mut i32) (i32.const 96))
(global $global1 (mut i32) (i32.const 101))
(global $global2 (mut i32) (i32.const 20))
(global $global3 (mut i32) (i32.const 177))
(global $global4 (mut i32) (i32.const 155))
(global $global5 (mut i32) (i32.const 116))
(global $global6 (mut i32) (i32.const 108))
(global $global7 (mut i32) (i32.const 69))
(global $global8 (mut i32) (i32.const 84))
(global $global9 (mut i32) (i32.const 109))
(global $global10 (mut i32) (i32.const 103))
(global $global11 (mut i32) (i32.const 110))
(global $global12 (mut i32) (i32.const 111))
(global $global13 (mut i32) (i32.const 95))
(global $global14 (mut i32) (i32.const 116))
(global $global15 (mut i32) (i32.const 103))
(global $global16 (mut i32) (i32.const 97))
(global $global17 (mut i32) (i32.const 72))
(global $global18 (mut i32) (i32.const 20))
(global $global19 (mut i32) (i32.const 59))
(func $1 (;0;) (export "1")
global.get $global0
i32.const 19
i32.xor
global.set $global0
global.get $global1
i32.const 55
i32.xor
global.set $global1
global.get $global2
i32.const 32
i32.xor
global.set $global2
global.get $global3
i32.const 36
i32.xor
global.set $global3
global.get $global4
i32.const 19
i32.xor
global.set $global4
global.get $global5
i32.const 55
i32.xor
global.set $global5
global.get $global6
i32.const 32
i32.xor
global.set $global6
global.get $global7
i32.const 36
i32.xor
global.set $global7
global.get $global8
i32.const 19
i32.xor
global.set $global8
global.get $global9
i32.const 55
i32.xor
global.set $global9
global.get $global10
i32.const 32
i32.xor
global.set $global10
global.get $global11
i32.const 36
i32.xor
global.set $global11
global.get $global12
i32.const 19
i32.xor
global.set $global12
global.get $global13
i32.const 55
i32.xor
global.set $global13
global.get $global14
i32.const 32
i32.xor
global.set $global14
global.get $global15
i32.const 36
i32.xor
global.set $global15
global.get $global16
i32.const 19
i32.xor
global.set $global16
global.get $global17
i32.const 55
i32.xor
global.set $global17
global.get $global18
i32.const 32
i32.xor
global.set $global18
global.get $global19
i32.const 36
i32.xor
global.set $global19
)
(func $init (;1;) (export "init") (param $var0 i32) (result (ref $type1))
local.get $var0
array.new_default $type1
call $1
)
(func $array_fill (;2;) (export "array_fill") (param $var0 (ref null $type1)) (param $var1 i32) (param $var2 i32)
local.get $var0
local.get $var1
local.get $var2
i32.const 19
i32.add
i32.const -64
i32.sub
struct.new $type0
i32.const 1
array.fill $type1
)
(func $3 (;3;) (export "3") (param $var0 (ref null $type1)) (param $var1 i32) (result i32)
local.get $var0
local.get $var1
array.get $type1
struct.get $type0 $field0
)
(func $4 (;4;) (export "4") (param $var0 (ref null $type1)) (param $var1 i32) (param $var2 i32) (param $var3 i32)
local.get $var1
i32.const 0
i32.eq
if
local.get $var0
local.get $var2
local.get $var0
local.get $var2
call $3
local.get $var3
i32.add
i32.const 32
i32.xor
call $array_fill
else
local.get $var1
i32.const 1
i32.eq
if
local.get $var0
local.get $var2
local.get $var0
local.get $var2
call $3
local.get $var3
i32.add
i32.const 36
i32.xor
call $array_fill
else
local.get $var1
i32.const 2
i32.eq
if
local.get $var0
local.get $var2
local.get $var0
local.get $var2
call $3
local.get $var3
i32.add
i32.const 19
i32.xor
call $array_fill
else
local.get $var1
i32.const 3
i32.eq
if
local.get $var0
local.get $var2
local.get $var0
local.get $var2
call $3
local.get $var3
i32.add
i32.const 55
i32.xor
call $array_fill
end
end
end
end
)
(func $5 (;5;) (export "5") (param $var0 (ref null $type1)) (result i32)
(local $var1 i32)
local.get $var0
i32.const 0
call $3
i32.const 38793
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
else
end
local.get $var0
i32.const 1
call $3
i32.const 584
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 2
call $3
i32.const 738
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 3
call $3
i32.const 38594
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 4
call $3
i32.const 63809
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 5
call $3
i32.const 647
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 6
call $3
i32.const 833
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 7
call $3
i32.const 63602
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 8
call $3
i32.const 47526
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 9
call $3
i32.const 494
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 10
call $3
i32.const 663
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 11
call $3
i32.const 47333
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 12
call $3
i32.const 67041
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 13
call $3
i32.const 641
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 14
call $3
i32.const 791
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 15
call $3
i32.const 66734
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 16
call $3
i32.const 35553
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 17
call $3
i32.const 561
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 18
call $3
i32.const 673
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var0
i32.const 19
call $3
i32.const 35306
i32.eq
if
local.get $var1
i32.const 1
i32.add
local.set $var1
end
local.get $var1
i32.const 20
i32.eq
if (result i32)
i32.const 1
else
i32.const 0
end
)
(func $check (;6;) (export "check") (param $var0 (ref null $type1)) (result i32)
local.get $var0
i32.const 0
i32.const 1
local.get $var0
i32.const 0
call $3
global.get $global0
i32.add
call $4
local.get $var0
i32.const 1
i32.const 2
local.get $var0
i32.const 1
call $3
global.get $global1
i32.sub
call $4
local.get $var0
i32.const 2
i32.const 3
local.get $var0
i32.const 2
call $3
global.get $global2
i32.mul
call $4
local.get $var0
i32.const 3
i32.const 0
local.get $var0
i32.const 3
call $3
global.get $global3
i32.xor
call $4
local.get $var0
i32.const 0
i32.const 5
local.get $var0
i32.const 4
call $3
global.get $global4
i32.add
call $4
local.get $var0
i32.const 1
i32.const 6
local.get $var0
i32.const 5
call $3
global.get $global5
i32.sub
call $4
local.get $var0
i32.const 2
i32.const 7
local.get $var0
i32.const 6
call $3
global.get $global6
i32.mul
call $4
local.get $var0
i32.const 3
i32.const 4
local.get $var0
i32.const 7
call $3
global.get $global7
i32.xor
call $4
local.get $var0
i32.const 0
i32.const 9
local.get $var0
i32.const 8
call $3
global.get $global8
i32.add
call $4
local.get $var0
i32.const 1
i32.const 10
local.get $var0
i32.const 9
call $3
global.get $global9
i32.sub
call $4
local.get $var0
i32.const 2
i32.const 11
local.get $var0
i32.const 10
call $3
global.get $global10
i32.mul
call $4
local.get $var0
i32.const 3
i32.const 8
local.get $var0
i32.const 11
call $3
global.get $global11
i32.xor
call $4
local.get $var0
i32.const 0
i32.const 13
local.get $var0
i32.const 12
call $3
global.get $global12
i32.add
call $4
local.get $var0
i32.const 1
i32.const 14
local.get $var0
i32.const 13
call $3
global.get $global13
i32.sub
call $4
local.get $var0
i32.const 2
i32.const 15
local.get $var0
i32.const 14
call $3
global.get $global14
i32.mul
call $4
local.get $var0
i32.const 3
i32.const 12
local.get $var0
i32.const 15
call $3
global.get $global15
i32.xor
call $4
local.get $var0
i32.const 0
i32.const 17
local.get $var0
i32.const 16
call $3
global.get $global16
i32.add
call $4
local.get $var0
i32.const 1
i32.const 18
local.get $var0
i32.const 17
call $3
global.get $global17
i32.sub
call $4
local.get $var0
i32.const 2
i32.const 19
local.get $var0
i32.const 18
call $3
global.get $global18
i32.mul
call $4
local.get $var0
i32.const 3
i32.const 16
local.get $var0
i32.const 19
call $3
global.get $global19
i32.xor
call $4
local.get $var0
call $5
)
)
스크립트에 나온 init, fill_array, check 함수에 대한 분석을 수행한다.
init 함수를 호출하면 배열을 만들고 global 변수들에 대해 xor 연산을 수행한다.
fill_array 함수를 호출하면 배열의 해당 인덱스에 값을 넣는데 +83한 값을 넣는다.
check 함수에서 플래그 값과 동일한지 확인하여 결과를 알려준다.
check 함수 내부에선 $4 함수로 연산하고, $5 함수로 검증을 수행했다.
분석해서 다음과 같이 브루트포스를 수행하는 파이썬 코드를 짰다.
data_li = [64 for _ in range(20)]
result_li = [38793, 584, 738, 38594, 63809, 647, 833, 63602, 47526, 494, 663, 47333, 67041, 641, 791, 66734, 35553, 561, 673, 35306]
global_li = [115, 82, 52, 149, 136, 67, 76, 97, 71, 90, 71, 74, 124, 104, 84, 67, 114, 127, 52, 31]
def fun4(var1,var2,var3):
if var1 == 0:
data_li[var2] = (data_li[var2] + var3) ^ 32
data_li[var2] += 83
elif var1 == 1:
data_li[var2] = (data_li[var2] + var3) ^ 36
data_li[var2] += 83
elif var1 == 2:
data_li[var2] = (data_li[var2] + var3) ^ 19
data_li[var2] += 83
elif var1 == 3:
data_li[var2] = (data_li[var2] + var3) ^ 55
data_li[var2] += 83
for n in range(0,20,4):
for a in range(0x20,0x80):
for b in range(0x20,0x80):
data_li[n+0] = a + 83
data_li[n+1] = b + 83
fun4((n+0)%4, n+1, data_li[n+0]+global_li[n+0])
if data_li[n+1] == result_li[n+1]:
for c in range(0x20,0x80):
data_li[n+0] = a + 83
data_li[n+1] = b + 83
data_li[n+2] = c + 83
fun4((n+0)%4, n+1, data_li[n+0]+global_li[n+0])
fun4((n+1)%4, n+2, data_li[n+1]-global_li[n+1])
if data_li[n+2] == result_li[n+2]:
for d in range(0x20,0x80):
data_li[n+0] = a + 83
data_li[n+1] = b + 83
data_li[n+2] = c + 83
data_li[n+3] = d + 83
fun4((n+0)%4, n+1, data_li[n+0]+global_li[n+0])
fun4((n+1)%4, n+2, data_li[n+1]-global_li[n+1])
fun4((n+2)%4, n+3, data_li[n+2]*global_li[n+2])
fun4((n+3)%4, n+0, data_li[n+3]^global_li[n+3])
if data_li[n] == result_li[n] and data_li[n+1] == result_li[n+1] and data_li[n+2] == result_li[n+2] and data_li[n+3] == result_li[n+3]:
print(chr(a)+chr(b)+chr(c)+chr(d),end='')
결과는 다음과 같다.
WebAss3mblyMystique}
TetCTF{WebAss3mblyMystique}
'CTF' 카테고리의 다른 글
Shakti CTF 2024 (0) | 2024.03.10 |
---|---|
osu!gaming CTF 2024 (0) | 2024.03.04 |
vsCTF 2023 (0) | 2023.09.25 |
CSAW CTF Qualification Round 2023 (0) | 2023.09.18 |
SECCON CTF 2023 Quals (0) | 2023.09.17 |