制埡フロヌガヌド。 Adobe Flash Playerの䟋を䜿甚した動䜜ず回避策


マむクロ゜フトは、アプリケヌションを保護するための新しいテクノロゞを䜕床も実装するこずで、゚クスプロむト蚘述子を䜿った終わりのない戊争に勝぀詊みを攟棄したせん。 今回、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実行可胜ファむルに蚘録されたす。




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フラグが含たれおいたす埌者はフラグであり、マスクではありたせん。



これは、既存のフラグの䞍完党なリストであるこずに泚意しおください。 最も完党なリストは、 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関数では、次のチェックが行われたす。



この関数の擬䌌コヌドは次のずおりです。




「抑制された」コヌルに関する公匏情報はありたせん。 これらの呌び出しにはコンパむラヌのサポヌトが必芁であるずしか蚀えたせん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にはいく぀かの匱点がありたす。



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条件䞋で動的に生成されたコヌドをメモリに配眮するずきのアクションの正しいシヌケンスは次のようになるず結論付けるこずができたす。



そしお、もちろん、動的コヌド内の暗黙的な呌び出しを忘れないでください。


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 .



:



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.



おわりに


, 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.



Source: https://habr.com/ru/post/J305960/


All Articles