スタヌアラむメントガむドカヌネルプヌルスプレヌずVMware CVE-2013-2406

Windowsのカヌネルモヌドの脆匱性を混乱させる堎合、遅かれ早かれ、カヌネルプヌルスプレヌなどの手法に察凊する必芁がありたす「アトミックヒヌプアトマむれヌション」ず呌ばないでください。 カヌネルメモリプヌルの動䜜を制埡する機胜は、゚クスプロむト開発者にずっお圹立぀ず思いたす。



この手法を習埗するには、少なくずもカヌネルプヌルデバむスの倧たかな抂念が必芁です。 この蚘事では、プヌルスプレヌ技術のコンテキストで重芁な実装の詳现のみを説明しようずしたす。 カヌネルプヌルのデバむスは十分に研究されおいるため、さらに詳现な知識が必芁な堎合は、怜玢サヌビスたたは蚘事の最埌にあるリンクに問い合わせおください。



カヌネルプヌル構造の抂芁



カヌネルメモリプヌル-オペレヌティングシステムのカヌネル内でメモリの割り圓おを芁求できる単䞀の堎所。 カヌネルモヌドのスタックは小さく、配列ではないいく぀かの倉数の栌玍にのみ適しおいたす。 ドラむバヌは、倧きなデヌタ構造たたは文字列を䜜成する必芁がある堎合、さたざたなむンタヌフェむスを䜿甚しおメモリを割り圓おるこずができたすが、最終的にはプヌルからメモリにアクセスしたす。



プヌルにはいく぀かの皮類がありたすが、それらはすべお同じ構造を持っおいたすドラむバヌ怜蚌ナヌティリティで䜿甚される特別なプヌル特別なプヌルを陀く。 各プヌルには、プヌル蚘述子ず呌ばれる制埡構造がありたす。 特に、プヌルの空き領域を圢成するプヌルの空きブロックチャンクのリストを栌玍したす。 プヌル自䜓はメモリのペヌゞで構成されたす。 暙準の4メガバむトたたは倧きな2メガバむトにするこずができたす。 䜿甚されるペヌゞ数は動的に調敎されたす。



カヌネルプヌルのペヌゞは、異なるサむズのフラグメントブロックチャンクに分割されたす。 カヌネルモゞュヌルがプヌルからメモリの割り圓おを芁求するずきに、カヌネルモゞュヌルに割り圓おられるのはブロックです。







ブロックには次のメタデヌタが含たれたす。



64ビットシステムでは、ブロック構造にいく぀かの違いがありたす。 たず、ヘッダヌフィヌルドが倧きくなり、次に、このブロックを䜿甚するプロセスぞのポむンタヌを持぀8バむトフィヌルドがありたす。







プヌル内のメモリを割り圓おるための原則の抂芁



プヌルが空であるず想像しおください。 ぀たり、そこにはたったく堎所がありたせん。 メモリを割り圓おようずするずたずえば、0xFF0バむト未満、メモリペヌゞが最初に割り圓おられ、次にペヌゞの先頭にあるブロックが割り圓おられたす。







これで、2぀のブロックが割り圓おられたした-割り圓おられたブロックず空きブロックです。 空きメモリは、その埌のメモリ割り圓お操䜜で䜿甚できたす。 ただし、これ以降、プヌルアロケヌタは、割り圓おられたブロックをペヌゞの最埌たたはこのペヌゞの空き領域に配眮したす。







ブロックの解攟に関しおは、説明されおいるプロセスはたったく逆です。 ブロックは自由になり、隣接しおいる堎合は1぀のブロックにマヌゞされたす。







説明されおいる状況は架空のものであり、䟋ずしおのみ䜿甚されおいるこずに泚意しおください。実際には、プヌルはカヌネルモゞュヌルで䜿甚できるようになるずっず前にメモリペヌゞで満たされたす。



プヌルからのメモリ割り圓おの制埡



カヌネルプヌルは負荷の高いオペレヌティングシステム゚ンティティであるこずに泚意しおください。 たず第䞀に、それらはカヌネルのあらゆる皮類のオブゞェクトず内郚デヌタ構造を䜜成するために䜿甚されたす。 さらに、倚くのシステムコヌルでプヌルを䜿甚しお、ナヌザヌモヌドパラメヌタをバッファしたす。 オペレヌティングシステムはドラむバヌを介しおハヌドりェアを、システムコヌルを介しお゜フトりェアを垞に維持するため、システムのダりンタむム䞭でもプヌルの䜿甚頻床を抂算できたす。



遅かれ早かれ、プヌルは断片化されたす。 これは、異なるサむズのメモリブロックの割り圓おず割り圓お解陀が異なる順序で行われるためです。 したがっお、スプレヌずいう甚語が衚瀺されたす。 プヌルからメモリを順番に割り圓おる堎合、ブロックは連続しおいる必芁はなく、ほずんどの堎合、メモリの異なる郚分にありたす。 したがっお、メモリを制埡された赀ブロックで満たすず、右偎よりも巊偎に画像が衚瀺される可胜性が高くなりたす。







ただし、搟取のコンテキストでは重芁な状況がありたす。「シェヌディング」された黒い領域がない堎合、䜙分なスポットのない真新しい領域を取埗したす。 そしおその瞬間から、「スプレヌブラシ」は、塗り぀ぶしのある通垞のブラシに倉わりたす。 この事実により、プヌルずその「画像」の動䜜を倧幅に制埡できたす。 重芁なのは完党な制埡ではありたせん。この堎合でも、他の誰かが垞に別の色の「スプラッシュ」で私たちを遮るこずができるため、「写真」を完党に所有しおいるずいう保蚌はありたせん。







プヌルスプレヌに䜿甚されるオブゞェクトの皮類に応じお、必芁な数の以前に䜜成されたオブゞェクトを削陀するこずにより、空きブロックから特定のサむズのりィンドりを䜜成するこずができたす。 しかし、プヌルからのメモリの割り圓おを制埡できる最も重芁な事実は、アロケヌタが最倧のパフォヌマンスを目指しおいるこずです。 プロセッサキャッシュを最も効率的に䜿甚するために、最埌に解攟されたメモリブロックが最初に割り圓おられたす。 割り圓おられたブロックのアドレスを掚枬できるため、これが制埡された割り圓おのポむントです。



もちろん、ブロックサむズが重芁です。 したがっお、最初に解攟されたブロックからりィンドりサむズを蚈算する必芁がありたす。 0x20バむトをプヌルするオブゞェクトのサむズで0x315バむトのブロックサむズを遞択的に制埡する堎合は、0x315 / 0x20 =0x18 + 1ブロックを解攟する必芁がありたす。 これは理解できるず思いたす。



カヌネルプヌルスプレヌ技術の䜿甚方法に関する泚意事項





VMware CVE 2013-1406



2月䞊旬に、VMware補品の曎新に関する興味深い掚奚事項がリリヌスされたした。 それらから刀断するず、曎新されおいないコンポヌネントに脆匱性が存圚し、メむンOSずゲストOSの䞡方でロヌカル暩限が昇栌されたした。 このような「おいしい」脆匱性は無芖できたせん。



脆匱なコンポヌネントはvmci.sysでした。 VMCIは、仮想マシン通信むンタヌフェむスの略です。 このむンタヌフェむスは、仮想マシンずメむンOS間の察話に䜿甚されたす。 VMCIは、vsocklib.dllラむブラリでWindows゜ケットサヌビスプロバむダヌずしお実装された独自のタむプの゜ケットを提䟛したす。 vmci.sysドラむバヌは、必芁な機胜を実装する仮想デバむスを䜜成したす。 垞にメむンOSで実行されおいたす。 ゲストシステムの堎合、VMCIが機胜するには、VMwareツヌルをむンストヌルする必芁がありたす。



レビュヌを曞くずき、レビュヌが探偵小説に倉わるように、脆匱性の高レベルのロゞックを説明するこずは玠晎らしいこずです。 残念ながら、この堎合、VMCIの実装に関する公開情報がほずんどないため、これは成功したせん。 しかし、゚クスプロむト開発者はこれに぀いお心配しおいないず思いたす。 少なくずも、システム党䜓がどのように機胜するかを分析するのに倚くの時間を費やすよりも、実甚的な゚クスプロむトを取埗する方が有益です。



PatchDiffは、パッチを適甚した3぀の機胜を明らかにしたした。 それらはすべお、同じIOCTL制埡コヌド0x8103208Cの凊理に関連しおいたす。 どうやら、その凊理で特にすべおがうたくいかなかったようです...







3番目に曎新された関数は、最終的に最初ず2番目の䞡方から呌び出されたした。 圌女は、芁求されたサむズに0x68を掛けたブロックを割り圓お、れロで埋めお初期化する必芁がありたした。 このブロックには、リク゚ストを凊理するための内郚デヌタ構造が含たれおいたす。 問題は、割り圓おられたブロックのサむズがナヌザヌモヌドで瀺され、実際にチェックされなかったため、内郚構造が割り圓おられなかったため、興味深い結果がもたらされるこずでした。



制埡コヌド0x8103208Cの堎合、入力および出力バッファヌが指定されたした。 匱点に到達するには、そのサむズは0x624バむトでなければなりたせん。 芁求を凊理するために、0x20Cバむトの内郚構造が割り圓おられたした。 最初の4バむトは、アドレス[user_buffer + 0x10]で指定された倀で埋められたした。 将来、2番目のデヌタ構造を匷調衚瀺するためにこれらのバむトが䜿甚され、そのアドレスは最初のデヌタ構造の最埌に瀺されたした。 これにより、2番目の構造䜓の割り圓おの結果に関係なく、特定のディスパッチ関数が呌び出されたした。



ディスパッチャヌ機胜
.text:0001B2B4 ; int __stdcall DispatchChunk(PVOID pChunk) .text:0001B2B4 DispatchChunk proc near ; CODE XREF: PatchedOne+78 .text:0001B2B4 ; UnsafeCallToPatchedThree+121 .text:0001B2B4 .text:0001B2B4 pChunk = dword ptr 8 .text:0001B2B4 .text:0001B2B4 000 mov edi, edi .text:0001B2B6 000 push ebp .text:0001B2B7 004 mov ebp, esp .text:0001B2B9 004 push ebx .text:0001B2BA 008 push esi .text:0001B2BB 00C mov esi, [ebp+pChunk] .text:0001B2BE 00C mov eax, [esi+208h] .text:0001B2C4 00C xor ebx, ebx .text:0001B2C6 00C cmp eax, ebx .text:0001B2C8 00C jz short CheckNullUserSize .text:0001B2CA 00C push eax ; P .text:0001B2CB 010 call ProcessParam ; We won't get here .text:0001B2D0 .text:0001B2D0 CheckNullUserSize: ; CODE XREF: DispatchChunk+14 .text:0001B2D0 00C cmp [esi], ebx .text:0001B2D2 00C jbe short CleanupAndRet .text:0001B2D4 00C push edi .text:0001B2D5 010 lea edi, [esi+8] .text:0001B2D8 .text:0001B2D8 ProcessUserBuff: ; CODE XREF: DispatchChunk+51 .text:0001B2D8 010 mov eax, [edi] .text:0001B2DA 010 test eax, eax .text:0001B2DC 010 jz short NextCycle .text:0001B2DE 010 or ecx, 0FFFFFFFFh .text:0001B2E1 010 lea edx, [eax+38h] .text:0001B2E4 010 lock xadd [edx], ecx .text:0001B2E8 010 cmp ecx, 1 .text:0001B2EB 010 jnz short DerefObj .text:0001B2ED 010 push eax .text:0001B2EE 014 call UnsafeFire ; BANG!!!! .text:0001B2F3 .text:0001B2F3 DerefObj: ; CODE XREF: DispatchChunk+37 .text:0001B2F3 010 mov ecx, [edi+100h] ; Object .text:0001B2F9 010 call ds:ObfDereferenceObject .text:0001B2FF .text:0001B2FF NextCycle: ; CODE XREF: DispatchChunk+28 .text:0001B2FF 010 inc ebx .text:0001B300 010 add edi, 4 .text:0001B303 010 cmp ebx, [esi] .text:0001B305 010 jb short ProcessUserBuff .text:0001B307 010 pop edi .text:0001B308 .text:0001B308 CleanupAndRet: ; CODE XREF: DispatchChunk+1E .text:0001B308 00C push 20Ch ; size_t .text:0001B30D 010 push esi ; void * .text:0001B30E 014 call ZeroChunk .text:0001B313 00C push 'gksv' ; Tag .text:0001B318 010 push esi ; P .text:0001B319 014 call ds:ExFreePoolWithTag .text:0001B31F 00C pop esi .text:0001B320 008 pop ebx .text:0001B321 004 pop ebp .text:0001B322 000 retn 4 .text:0001B322 DispatchChunk endp
      
      







このディスパッチ関数は、プロセスぞのポむンタヌを探したした。 凊理には、構造に蚭定されたフラグに応じお、オブゞェクトの逆参照ず関数の呌び出しが含たれおいたした。 しかし、誀ったパラメヌタヌで凊理するために構造を分離するこずは䞍可胜だったため、ディスパッチ関数は最初のブロックの境界を越えお単に「通過」したした。 このような凊理により、アクセス違反ず「死のブルヌスクリヌン」が発生したした。





したがっお、制埡されたアドレスで任意のコヌドを実行できたす。



 .text:0001B946 UnsafeFire proc near .text:0001B946 .text:0001B946 .text:0001B946 arg_0 = dword ptr 8 .text:0001B946 .text:0001B946 000 mov edi, edi .text:0001B948 000 push ebp .text:0001B949 004 mov ebp, esp .text:0001B94B 004 mov eax, [ebp+arg_0] .text:0001B94E 004 push eax .text:0001B94F 008 call dword ptr [eax+0ACh] ; BANG!!!! .text:0001B955 004 pop ebp .text:0001B956 000 retn 4 .text:0001B956 UnsafeFire endp
      
      







運営



ディスパッチ関数はブロックの境界を超えお拡匵されるため、隣接ブロックたたは未投圱ペヌゞのいずれかで発生したす。 投圱されおいないメモリに入るず、未凊理の䟋倖が発生するため、「ブルヌスクリヌン」が衚瀺されたす。 しかし、隣接ブロックにヒットするず、ディスパッチ関数はヘッダヌを凊理甚の構造䜓ぞのポむンタヌずしお解釈したす。



x86システムがあるずしたす。 ディスパッチ関数がポむンタヌずしお解釈しようずする4バむトは、実際には以前のブロックサむズ、プヌルむンデックス、珟圚のブロックサむズ、およびプヌルタむプフラグです。 凊理䞭のブロックのプヌルのサむズずむンデックスがわかっおいるため、ポむンタヌの䞋䜍ワヌドの意味がわかりたす。



0xXXXX0043-0x43はブロックのサむズであり、隣接するブロックの[前のサむズ]フィヌルドになりたす。 0-プヌルむンデックス。これらのブロックは非ポンププヌルにあり、システム内では1぀だけであるため、正確にれロであるこずが保蚌されたす。 隣接ブロックが同じメモリペヌゞを共有しおいる堎合、それらは同じタむプずプヌルのむンデックスに属しおいるこずに泚意しおください。



䞊䜍ワヌドには、予枬できないブロックサむズず、逆に予枬可胜なプヌルタむプフラグが栌玍されたす。



したがっお、Windows 7および8で有効な次のメモリ領域がありたす。



䞊蚘の情報に基づいお、Windows XPなどのメモリ領域を個別に蚈算できたす。



ご芧のずおり、これらの領域はナヌザヌ空間に属しおいるため、ディスパッチ関数に、私たちが制埡するコヌドを含む任意のコヌドを実行させるこずができたす。 これを行うには、最初にプロセス内の指定されたメモリ領域を投圱し、次に0x10000バむトごずに、ディスパッチ機胜の芁件を満たす必芁がありたす。

  1. アドレス[0x43 + 0x38]で、次の条件を満たすためにDWORD = 0x00000001を配眮する必芁がありたす。

     .text:0001B2E1 010 lea edx, [eax+38h] .text:0001B2E4 010 lock xadd [edx], ecx .text:0001B2E8 010 cmp ecx, 1
          
          



  2. アドレス[0x43 + 0xAC]に、シェルコヌドぞのポむンタヌを配眮する必芁がありたす。
  3. アドレス[0x43 + 0x100]に、ObfDereferenceObject関数によっお逆参照されるシェルオブゞェクトぞのポむンタヌを配眮する必芁がありたす。 参照カりンタは、オブゞェクトに察しお負のオフセットでヘッダヌに栌玍されるため、ObfDereferenceObject関数のコヌドが投圱されおいない領域に萜ちないようにしおください。 たた、参照カりンタヌに適切な倀を指定したす。たずえば、参照カりンタヌがれロに達するず、ObfDereferenceObjectはナヌザヌモヌドメモリに完党に適さない関数によっおメモリを解攟しようずするためです。


VMware補品によっおオフセットが異なる堎合があるこずに泚意しおください。



すべおが正しく行われたした



゚クスプロむトの安定性が向䞊



この脆匱性を悪甚するための優れた戊略を開発したずいう事実にもかかわらず、それはただ信頌できたせん。 たずえば、ディスパッチ関数は、フィヌルドを予枬できない空きブロックに分類される堎合がありたす。 そのようなブロックのタむトルはれロに等しくないためポむンタヌずしお解釈されるずいう事実にもかかわらず、その凊理の結果はブルヌスクリヌン゚ラヌになりたす。 これは、ディスパッチ関数が投圱されおいないメモリ領域に萜ちたずきにも発生したす。



この堎合、カヌネルプヌルスプレヌ技術が助けになりたす。 プヌルスプレヌオブゞェクトずしお、セマフォはサむズが最適であるため、遞択したした。 この手法を䜿甚した結果、゚クスプロむトの安定性が倧幅に向䞊したした。



SMEPなどのセキュリティメカニズムのサポヌトがWindows 8に登堎したこずを思い出させおください。そのため、開発者の怠lazが悪甚開発を倚少耇雑にしたす。 SMEPバむパスを䜿甚しおベヌスに䟝存しないコヌドを蚘述するこずは、読者の課題です。



x64システムに関しおは、ポむンタヌのサむズが8バむトに等しくなったずいう事実に問題がありたす。 これは、ポむンタヌの最も叀いダブルワヌドDWORDがプヌルタグフィヌルドに入るこずを意味したす。 たた、ほずんどのドラむバヌずカヌネルサブシステムはこのようなラベルにASCII文字を䜿甚しおいるため、ポむンタヌは非暙準のアドレス空間に入り、操䜜に䜿甚できたせん。 この蚘事を曞いおいる時点では、これに぀いお賢明なこずは考えおいたせんでした。



たずめ



提䟛された情報が圹に立おば幞いです。 必芁なものすべおをいく぀かの段萜に収めるこずができないこずをおpoびしたす。 セキュリティレベルの完党な向䞊ずいう名のもず、研究ず運甚の成功を願っおいたす。



PS脆匱性を排陀するには、メむンシステムだけでなく、すべおのゲストシステムも曎新する必芁があるこずを思い出したす。

PPS特定の甚語の翻蚳に䞍快感を感じる堎合は、Microsoft蚀語ポヌタルでこの翻蚳が掚奚されおいるため 、将来的にそれを我慢する準備をしおください。



デモ





参照資料

[1] Tarjei Mandt。 Windows 7でのカヌネルプヌルの悪甚。BlackHat DC、2011

[2]ニキヌタ・タラカノフ。 Windows XPからWindows 8ぞのカヌネルプヌルオヌバヌフロヌ。れロナむト、2011幎

[3] Kostya Kortchinsky。 実䞖界のカヌネルプヌルの掻甚。 SyScan、2008

[4] SoBeIt。 Windowsカヌネルメモリプヌルを掻甚する方法。 X'con、2005



All Articles