マイクロソフトは、アプリケーションを保護するための新しいテクノロジを何度も実装することで、エクスプロイト記述子を使った終わりのない戦争に勝つ試みを放棄しません。 今回、Windowsオペレーティングシステムの開発者は、この問題に根本的に取り組み、問題の根本に視点を移しました。 何らかの形でのほぼすべてのエクスプロイトの作業は、アプリケーション実行のフローを傍受することを目的としているため、この瞬間を監視するためにアプリケーションを「教える」ことは害になりません。
制御フローの整合性の概念は、2005年に説明されました。 そして今、10年後、Microsoftの開発者は、このコンセプトの不完全な実装であるControl Flow Guardを発表しました。
制御フローガードとは何ですか?
制御フローガード(Guard CF、CFG)は、ユーザーおよびカーネルモードアプリケーションのバイナリ脆弱性を悪用するプロセスを複雑にすることを目的とした比較的新しいWindowsエクスプロイト緩和メカニズムです。 このメカニズムの機能は、間接呼び出しを検証することです。これにより、攻撃者が実行スレッドを傍受するのを防ぎます(たとえば、仮想関数のテーブルを上書きすることにより)。 以前の防御メカニズム( SafeSEH 、 ASLR 、 DEPなど)と組み合わせることで 、エクスプロイトの作成者にとっては頭痛の種です。
このセキュリティ機能は、Microsoft Windows 8.1(Update 3、KB3000850)およびWindows 10のユーザーが利用できます。
CFGをサポートするプログラムのコンパイルは、Microsoft Visual Studio 2015で利用できます( 有効にする方法は? )。
LinuxファミリのOSの制御フロー整合性の概念に基づく保護メカニズムの同様の実装は、 PaX拡張で利用できます。
制御フローガードの仕組み
ユーザーモードでのCFGの原理を考慮してください。 このメカニズムには、2つの主要なコンポーネントがあります。アドレスのビットマップ(カーネルによって制御される)と、呼び出された関数のポインターをチェックする手順(ユーザーアプリケーションによって使用される)です。
すべてのCFG IMAGE_LOAD_CONFIG_DIRECTORY
は、コンパイル時にIMAGE_LOAD_CONFIG_DIRECTORY
実行可能ファイルに記録されます。
-
GuardCFCheckFunctionPointer
検証手順へのポインター -
GuardCFFunctionTable
関数の有効なアドレスのテーブル(カーネルがビットマップを初期化するために使用) -
GuardCFFunctionCount
テーブル内の関数の数 -
GuardFlags
フラグ
IMAGE_DLLCHARACTERISTICS_GUARD_CF
フラグがIMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics
ヘッダーに入力され、この実行可能ファイルがCFGメカニズムをサポートしていることを示します。
すべてのサービス情報は、 /loadconfig
実行することにより、Microsoft Visual Studio 2015のdumpbin.exe
ツール( Microsoft Visual Studio 14.0 \ VC \ bin \ dumpbin.exe )を使用して/loadconfig
ます。
ガードフラグ
Windows 10(1511)のwinnt.h
ヘッダーファイルには、次のCFGフラグが含まれています(後者はフラグであり、マスクではありません)。
-
IMAGE_GUARD_CF_INSTRUMENTED
(0x00000100)-モジュールは、システムのサポートで実行フローをチェックします -
IMAGE_GUARD_CFW_INSTRUMENTED
(0x00000200)-モジュールは、実行の完全性をチェックし、スレッドを書き込みます -
IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT
(0x00000400)-モジュールには有効な関数のテーブルが含まれています -
IMAGE_GUARD_SECURITY_COOKIE_UNUSED
(0x00000800)-モジュールはセキュリティCookieを使用しません(/ GS) -
IMAGE_GUARD_PROTECT_DELAYLOAD_IAT
(0x00001000)-モジュールは読み取り専用の遅延ロードインポートテーブル、読み取り専用をサポートします -
IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION
(0x00002000)-遅延読み込みインポートテーブルは独自の.didat
セクションにあります -
IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK
(0xF0000000)-有効な関数Guard CFのテーブルの1つの要素のステップは、これらのビットでエンコードされます(各要素の追加バイト数)
これは、既存のフラグの不完全なリストであることに注意してください。 最も完全なリストは、 link.exe
ファイル(リンカー)の内部から取得できます。
また、いくつかの興味深いフラグの存在に注意を払う価値がありますが、その公式情報は入手できません。 マイクロソフトの開発者は、書き込みアドレス( IMAGE_GUARD_CFW_INSTRUMENTED
)を確認するために、追加のCFGメカニズムをテストしているようです。
ビットマップ
カーネルがOS( nt!MiInitializeCfg
)をnt!MiInitializeCfg
と、 nt!MiInitializeCfg
ビットマップが作成されます。これは、すべてのプロセスの共有セクションです。 CFGをサポートするプロセスを開始すると、プロセスのアドレス空間へのビットマップのマッピング(マッピング)が発生します。 その後、アドレスとビットマップサイズがntdll!LdrSystemDllInitBlock
入力されます。
関数アドレスとビットマップのビットとの比較は、実行可能ファイルローダー( nt!MiParseImageCfgBits
)によって実行されます。 ビットマップの各ビットは、8バイトのユーザープロセスアドレス空間を担当します。 すべての有効な関数の先頭のアドレスは、ビットマップ内の対応するオフセットの単一ビットに関連付けられており、それ以外はすべて0です。
呼び出された関数のポインターを確認する手順
コンパイル段階でのプログラム内の暗黙的な呼び出しは、呼び出された関数のアドレスをチェックすることによりフレーム化されます。 検証手順のアドレスは、空の手順のアドレスが最初に設定されたため、実行可能ファイルのローダーによって設定され、それにより下位互換性が維持されます。
わかりやすくするために、CFGなしでコンパイルされた同じコードを見てみましょう。
元のC ++コード:
class CSomeClass { public: virtual void doSomething() { std::cout << "hello"; } }; int main() { CSomeClass *someClass = new CSomeClass(); someClass->doSomething(); return 0; }
ASMリスト(クリッピング):
mov eax, [ecx] ; EAX = CSomeClass::vftable call dword ptr [eax] ; [EAX] = CSomeClass::doSomething()
コンパイルキー/ガードを使用:cf:
mov eax, [edi] ; EAX = CSomeClass::vftable mov esi, [eax] ; ESI = CSomeClass::doSomething() mov ecx, esi call ds:___guard_check_icall_fptr ; checks that ECX is valid function pointer mov ecx, edi call esi
最初のケースでは、コードは仮想関数テーブルスプーフィング手法を使用した攻撃を受けやすくなります。 攻撃者がこの脆弱性の悪用中にオブジェクトのデータを上書きできる場合、関数someClass->doSomething()
を呼び出すと、攻撃者が制御するコードを実行するように仮想関数テーブルを置き換え、アプリケーション実行フローをインターセプトできます。
制御フローガードを使用する場合は、呼び出された関数のアドレスが最初にビットマップで検証されます。 対応するビットがゼロの場合、ソフトウェア例外が発生します。
Guard CFメカニズムをサポートするOSでこのアプリケーションを起動すると、実行可能ファイルローダーがビットマップを作成し、チェックプロシージャのアドレスをntdll!LdrpValidateUserCallTarget
。
Windows 10(ビルド1511)のこの機能は、次のように実装されています。
入力アドレス0x0B3385B0の例を使用して、この関数のアルゴリズムを研究します。
B3385B0 16 = 10110011001110000101 10110 000 2
この関数は、 ecx
介して検証済みアドレスを受け取りecx
。 ビットマップアドレスは、 edx
入力edx
ます。 私の場合、ビットマップは0x01430000にあります。
3バイト(24ビット)の上位(下線付き)アドレスは、ビットマップのオフセットに対応します。 この場合、オフセットは0xB3385
ます。 ビットマップの単位は4バイト(32ビット)であるため、目的のセルを取得するに + * 4
を計算する必要があります。 この例では、 0x01430000 + 0xB3385 * 4 = 0x16FCE14
ます。 ビットマップセル値はedx
書き込まedx
ます。
ターゲットセルを取得しました。次に、興味のあるビットの数を決定する必要があります。 数値は、アドレスの次の5ビットの値です(太字で強調表示)。 ただし、チェック対象のアドレスが16バイトの境界で整列されていない場合( address & 0xf != 0
)、奇数ビットが使用されることに注意してください( offset | 0x1
)。 この場合、アドレスは整列され、ビット番号は10110 2 = 22 10になります。
現在は、ビットテストを実行してビット値をチェックするだけです。 bt
命令は、最初のレジスタのビット値をチェックします。そのシーケンス番号は、2番目のレジスタの最下位5ビット(モジュロ32)から取得されます。 ビットが1の場合、 Carry Flag (CF)
が設定され、プログラムは通常モードで実行され続けます。
それ以外の場合、 ntdll!RtlpHandleInvalidUserCallTarget
関数が呼び出され、プログラムはスタック上の0xAパラメーターを持つ29番目の割り込みで終了しますnt!_KiRaiseSecurityCheckFailure(FAST_FAIL_GUARD_ICALL_CHECK_FAILURE)
つまり、 nt!_KiRaiseSecurityCheckFailure(FAST_FAIL_GUARD_ICALL_CHECK_FAILURE)
。
22ビット目をチェックすることにより、呼び出された関数のアドレスが有効であることを確認できます。
Pythonでのこのアルゴリズムの実装は次のとおりです。
def calculate_bitmap_offset(addr): offset = (addr >> 8) * 4 bit = (addr >> 3) % 32 aligned = (addr & 0xF == 0) if not aligned: bit = bit | 1 print "addr = 0x%08x, offset = 0x%x, bit index = %u, aligned? %s" % (addr, offset, bit, "yes" if aligned else "no") calculate_bitmap_offset(0x0B3385B0)
スクリプトの結果:
addr = 0x0b3385b0, offset = 0x2cce14, bit index = 22, aligned? yes
例外
すべての場合において、無効な関数の呼び出しが29番目の割り込みで終了するわけではありません。 ntdll!RtlpHandleInvalidUserCallTarget
関数では、次のチェックが行われます。
- 現在のプロセスでDEPが有効になっていますか?
- 宛先アドレスに必要な権限がありますか(
PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE
) - 「抑制された」呼び出しが
ntdll!RtlGuardAllowSuppressedCalls
ますntdll!RtlGuardAllowSuppressedCalls
- 宛先アドレスは「抑制」されています
ntdll!RtlpGuardIsSuppressedAddress
この関数の擬似コードは次のとおりです。
「抑制された」コールに関する公式情報はありません。 これらの呼び出しにはコンパイラーのサポートが必要であるとしか言えませんGuardFlags
フラグでIMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK
マスクを設定し、コンパイラーが拡張テーブルを生成する必要があります。 このマスクに対応するバイトには、 GuardCFFunctionTable
テーブルの要素の追加サイズの値が格納されます。 関数のアドレスが「抑制」されている場合、アドレスに続くバイトは1に等しくなければなりません。
たとえば、必要なアプリケーションのCFGOptions
パラメーターを1に設定することにより、レジストリブランチHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\
を使用して、「抑制された」呼び出しを解決できます。
制御フローガードの弱点
他の防御メカニズムと同様に、CFGにはいくつかの弱点があります。
この場合、
ntdll!RtlpHandleInvalidUserCallTarget
は常に無効なアドレスの実行を許可するため、プロセスDEPをオフにするとCFGチェックの意味が失われます。
ビットマップアドレスは固定アドレスに保存され、ユーザーモードから簡単に計算できます。 ユーザーはビットマップ内のデータを変更することを禁じられていますが、悪用者は何らかの形でこの制限を回避する方法を見つけます。
実行可能ファイルがCFGサポートを使用してコンパイルされていない場合、実行可能ファイルによってロードされたモジュールのCFGサポートはその意味を失います。 検証手順のビットマップとアドレスは、実行可能ファイルがCFGメカニズムをサポートしている場合にのみ入力されるため、モジュールコード内のチェックは単純なスタブになります。
CFGはコンパイルプロセスに依存しているため、サードパーティのモジュールや古いMicrosoftモジュールでさえ、CFGで保護された実行可能ファイルの脆弱性です。 ビットマップは、コンパイラーによって生成される有効な関数アドレスのテーブルに従ってコンパイルされるため、CFGサポートのないすべてのモジュールコードは、ビットマップで有効な宛先としてマークされます。
アドレス空間の8バイトごとに1ビットが責任を負いますが、実際には、1つの整列アドレスが1つの偶数ビットに対応し、次の奇数ビットがアドレス空間の15バイトに直ちに対応します。 これを確認するには、上記のPythonスクリプトをループで実行し、結果を分析します。
addr = 0x08f38480, offset = 0x23ce10, bit index = 16, aligned? yes addr = 0x08f38481, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38482, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38483, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38484, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38485, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38486, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38487, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38488, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38489, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f3848a, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f3848b, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f3848c, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f3848d, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f3848e, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f3848f, offset = 0x23ce10, bit index = 17, aligned? no addr = 0x08f38490, offset = 0x23ce10, bit index = 18, aligned? yes addr = 0x08f38491, offset = 0x23ce10, bit index = 19, aligned? no addr = 0x08f38492, offset = 0x23ce10, bit index = 19, aligned? no addr = 0x08f38493, offset = 0x23ce10, bit index = 19, aligned? no addr = 0x08f38494, offset = 0x23ce10, bit index = 19, aligned? no ...
攻撃者は、信頼されていない機能が調整されていない限り、信頼された機能のすぐ近くで信頼できない機能を呼び出す機会を持つことになります。
動的に生成される関数(たとえば、 JIT関数)は、関数の生成段階で暗黙的な呼び出しのチェックを提供する必要があるため、開発者からの特別な注意が必要です。 これに加えて、
ntdll!NtAllocVirtualMemory
およびntdll!NtProtectVirtualMemory
の標準的な動作では、メモリが実行可能になった場合(PAGE_EXECUTE_*
)、Control Flow Guardビットマップのメモリ領域全体に1ビットを配置することを考慮する必要があります。
CFGは、攻撃者が関数のリターンアドレスを変更したときに、実行スレッドがインターセプトされるのを防ぐことはできません。
- CFGの観点からのライブラリ関数(WinAPIなど)の呼び出しは有効ですが、攻撃者は必要なパラメーターでスタック/レジスターを埋める問題を解決する必要があります。
Adobe Flash Playerの例を使用した制御フローガードバイパスの実装
Windows 8以降、Adobe Flash PlayerプラグインはInternet Explorerに統合され、Windows 8.1(Update 3)ではCFGサポートが付属しています。 Adobe Flash Playerのエクスプロイトには、コントロールフローガードバイパスの実装がいくつかありますが、そのいくつかは現在でも関連しています。
ダイナミックコードバイパス
Adobe Flash PlayerはJITコンパイルを広範囲に使用するため、ActionScriptコードの解釈などのリソースを大量に消費する操作を回避できます。 ただし、前述のように、動的に生成された関数には、開発者による追加の注意が必要です。 以下に説明する2つの回避策は、メモリ割り当てに関する開発者の省略の結果です。
動的コードでの暗黙的な呼び出しチェックの欠如
この方法は、Core Securityの研究者であるFranciscoFalcónによるCVE-2015-0311のエクスプロイト分析で提案および実装されました。 元の記事では、回避策のプロセスについてかなり詳細に説明しています。 このメソッドの本質は、特定のActionScriptクラスの仮想関数の内部テーブルを変更することです。 その後、このクラスのメソッドの1つを、動的に生成された関数の本体から呼び出す必要があります。 ByteArray
クラスは、この目的に適しています。
ByteArray
オブジェクトの構造:
オフセット$ + 8には、クラスVTable
オブジェクトへのポインターがあります。
VTable
クラスは、ActionScriptクラスの仮想関数テーブルの内部表現です(つまり、C ++が生成するものではありません)。
このクラスのオブジェクトには、 MethodEnv
クラスのオブジェクトへのポインターが含まれています。
このクラスはActionScriptメソッドの説明であり、メモリ内のオフセット$ + 4にある関数本体へのポインターが含まれています。
オフセット$ + D4のVTable
オブジェクトには、 ByteArray::toString()
メソッドの説明が含まれています。 メモリへの任意の読み取りおよび書き込みが可能なため、攻撃者はByteArray::toString()
実行することで、関数ポインターを関数本体( MethodEnv + 4
)に変更し、アプリケーション実行フローを安全にインターセプトできます。
これは、このクラスのメソッドがJITコードから呼び出されるという事実により可能になります。
上記のスクリーンショットでわかるように、この関数は動的に生成されたため、最初に呼び出されたアドレスをチェックせずに暗黙的な呼び出しが発生します。
このCFGの回避策は、Adobe Flash Playerバージョン18.0.0.160(KB3065820、2015年6月)のリリースで修正されました。 修正の構成は次のとおりです。JIT関数に暗黙的な呼び出しが含まれている場合、JITコンパイラは暗黙的な呼び出しの直前にテストプロシージャ呼び出しを挿入します。
動的関数の本文内のアドレスはすべて有効です。
以前の回避策は、暗黙的な呼び出しを行う関数の欠陥のために可能でした。 そして、このメソッドは、暗黙的に呼び出される関数の欠陥のために可能です。
Center of Vulnerability ResearchのYuri DrozdovとLyudmila Drozdovaの研究者は、 Defcon Russia Conference(St. Petersburg、2015)でこのCFGバイパス手法を発表しました ( プレゼンテーション 、 記事 )。 彼らの方法は、実行可能メモリを割り当てるときに、カーネルがすべての割り当てられたメモリのCFGビットマップに単一ビットを設定するという事実に基づいています。 この動作が何につながるかを見てみましょう。
アドレス0x69BC9080に特定のJIT関数があり、その本文に次のコードが含まれているとします。
この関数が正確に何をするのかは興味がありません;アドレス0x69BC90F0のFF D0
命令の2バイトに注意するだけです。 機能の開始がこの命令の途中に突然移動するとどうなりますか? ここに何があります:
FF D0
はcall eax
ことに他なりません! これは、一見無害な機能が攻撃者にとって優れた標的になった方法です。つまり、制御フローガードをチェックしない暗黙的な呼び出しです。 必要なバイトシーケンスを達成する方法と、必要なアドレスをレジスタに書き込む方法の2つだけの質問に対処する必要があります。
必要なシーケンスは、ActionScriptコードを試すだけで生成できます。 Nanojit( AVM JITコンパイラー)が生成されたコードを難読化するという事実を考慮するだけでよいため、簡単な方法はありません。 Nanojitがこの機能をどのように変えるかを見てみましょう。
public static function useless_func():uint { return 0xD5EC; }
結果:
まったく期待していなかった。 経験的に、たとえば、このバージョンのコードにアクセスできます。
public static function useless_func():void { useless_func2(0x11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); } public static function useless_func2(arg1:uint, arg2:uint, arg3:uint, a, b, c, d, e, f, g, h, i, j, k, l, m, n, p, q, r, s, t, u, v, w, x, y, z):void { }
最初の関数の本体には、次の指示が含まれます。
興味のあるFF 11
バイトはcall [ecx]
命令です:
暗黙の呼び出しがありました。今、 ecx
制御されたアドレスを入力する必要があります。 useless_func()
関数がuseless_func()
れたときに、このレジスタに何が格納されているかを確認します。
関数が呼び出された時点で、 MethodEnv
クラスのオブジェクトはecx
レジスタにあります。 このクラスの最初のDWORDは 、仮想関数テーブル(C ++コンパイラーによって生成されたもの)へのポインターです。 このテーブルはuseless_func()
メソッドの呼び出し時には使用されないため、メソッドが呼び出される前に攻撃者がポインターを自分の権利に置き換えることを妨げるものは何もありません。
このアルゴリズムの実装は次のとおりです。
var class_addr:uint = read_addr(UselessClass); var vtable:uint = read_dword(class_addr + 8); var methodenv:uint = read_dword(vtable + 0x54); // $+54 = useless_func var func_ptr:uint = read_dword(methodenv + 4); write_dword(methodenv + 4, func_ptr + offset_to_call_ecx); write_dword(methodenv, rop_gadget); // ecx <- pointer to rop gadgets UselessClass.useless_func(); // call [ecx]
したがって、アプリケーションの実行フローをインターセプトし、この場合はROPガジェットの実行に移動することができました。
このCFGの回避策は、バージョン18.0.0.194(KB3074219、2015年6月)で修正されています。 修正は、新しいフラグを使用することです
PAGE_TARGETS_INVALID/PAGE_TARGETS_NO_UPDATE
(0x40000000)は、新しいWinAPI関数SetProcessValidCallTargets
と組み合わせたVirtualAlloc
およびVirtualProtect
関数用です。
実行可能メモリを割り当てるときのPAGE_TARGETS_INVALID
フラグは、メモリロケーション全体にPAGE_TARGETS_NO_UPDATE
し、メモリタイプを実行可能に変更するときはPAGE_TARGETS_NO_UPDATE
フラグにより、ターゲットメモリロケーションのビットマップが変更されません。
この修正は、AVMカーネルソースコード ( AVMPI / MMgcPortWin.cpp )のAVMPI_makeCodeMemoryExecutable
関数で確認できます。
SetProcessValidCallTargets
関数の呼び出しSetProcessValidCallTargets
、 AVMPI_makeTargetValid
( AVMPI / MMgcPortWin.cpp )で実装されていAVMPI_makeTargetValid
。
このことから、CFG条件下で動的に生成されたコードをメモリに配置するときのアクションの正しいシーケンスは次のようになると結論付けることができます。
-
VirtualAlloc(PAGE_READWRITE)
- 選択した領域にコードを書く
-
VirtualProtect(PAGE_EXECUTE_READ |
PAGE_TARGETS_NO_UPDATE)
-
SetProcessValidCallTargets()
そして、もちろん、動的コード内の暗黙的な呼び出しを忘れないでください。
WinAPIの回避策
制御フローガードの確認では、着信アドレスの検証が行われますが、ユーザー機能の開始だけが有効なアドレスではありません。 すべてのWinAPI関数は、インポートテーブルの他の関数と同様に、暗黙的な呼び出しの有効な宛先です。 攻撃者が実行スレッドを直接ライブラリ関数に変換し、シェルコードまたはROPガジェットをバイパスすることを妨げるものは何もありません。 これに適した候補は、WinAPI関数kernel32!WinExec
です。
Yuki Chen Qihoo 360 Vulcan Team SyScan (, 2015) , Internet Explorer 11 . BlackHat (, 2015) Francisco Falcón Adobe Flash Player.
Francisco Falcón toString()
Vector
, , .
, WinExec
. , , 2 : LPCSTR lpCmdLine
UINT uCmdShow
.
-
lpCmdLine
— , ( ). -
uCmdShow
— .
:
3 . . , 0 = SW_HIDE
( ). MethodEnv
.
, 4 , ActionScript- . 4 , WinExec
.
, 4 . , , cmd\0
( Windows). , , , .
:
var class_addr:uint = read_addr(UselessClass); var vtable:uint = read_dword(class_addr + 8); var methodenv:uint = read_dword(vtable + 0x50); // $+50 = useless_func var winexec:uint = get_proc_addr("kernel32.dll", "WinExec"); write_dword(methodenv + 4, winexec); // useless_func() --> WinExec() write_dword(methodenv, 0x00646d63); // '\0', 'd', 'm', 'c' UselessClass.useless_func();
WinAPI Flash- . , , Flash Exploiter Metasploit.
, :
, , , .
Flash- (payload) HackingTeam. . WinAPI kernel32!VirtualProtect
, , , Control Flow Guard.
apply()
Function
( core/FunctionClass.cpp )
core->exec->apply(get_callEnv(), thisArg, (ArrayObject*)AvmCore::atomToScriptObject(argArray));
, , ActionScript.
, GitHub . 64- Flash Metasploit .
Control Flow Guard
CFG Adobe Flash Player. Flash, , Control Flow Guard Internet Explorer 11.
- Zhang Yunhai @ Black Hat 2015
read-only___guard_check_icall_fptr
CustomHeap::Heap
Jscript9
. - Yuki Chen @ SyScan 2015
WinAPIkernel32!LoadLibraryA
- Rafal Wojtczuk & Jared DeMott @ DerbyCon 2015 (video) , Bromium Labs
, — " " (stack desync). , Control Flow Guard . (calling convention).
おわりに
, Control Flow Guard Windows. Microsoft , , Control Flow Integrity, , . , Microsoft .
, CFG.
. Intel, , , ROP- — CET (Control-flow Enforcement Technology) ( ). , CET Control Flow Guard.
Jack Tang, Trend Micro Threat Solution Team. Exploring Control Flow Guard in Windows 10.
mj0011, Qihoo 360 Vulcan Team. Windows 10 Control Flow Guard Internals.
Source code for the Actionscript virtual machine, GitHub.
Francisco Falcon, Core Security. Exploiting Adobe Flash Player in the era of Control Flow Guard.