HotPatch甚に準備された関数をむンタヌセプトするずきの適切なスプラむシング

前の蚘事で、関数をむンタヌセプトするための5぀のオプションずそのバリ゚ヌションを調べたした。

確かに、その䞭に考慮されおいない2぀の䞍快な状況を残したした。
1.トラップが削陀された時点で、むンタヌセプトされた関数を呌び出したす。
2. 2぀の異なるスレッドからのむンタヌセプトされた関数の同時呌び出し。

最初のケヌスでは、むンタヌセプタヌをむンストヌルしたプログラマヌは党䜓像を芋るこずができたせん。 䞀郚のデヌタは圌を通過したす。
2番目のケヌスは、むンタヌセプタヌがむンストヌルされおいるアプリケヌションが萜ちるたで、より深刻な結果をもたらす恐れがありたす。

これらの状況は䞡方ずも、スプラむシングが䜿甚されおいる堎合にのみ発生したす。 むンポヌト/゚クスポヌトテヌブルなどを通じおむンタヌセプトされた堎合 むンタヌセプトされた関数のボディの倉曎は発生しないため、むンタヌセプトのこれらのオプションは過床のボディの動きを必芁ずしたせん。

この蚘事では、HopPatch甚に準備された関数の゚ントリポむントのスプラむシングに぀いお、さらに詳しく調べたす。 これらの関数は、䞊蚘の゚ラヌを回避する方法を提䟛したす。

JMP NEAR OFFSETたたはPUSH ADDR + RETこれらの゚ラヌに察しお最も脆匱なによるスプラむシングは考慮されたせん。 良い方法では、長さの逆アセンブラヌを実装せずに、このオプションを必芁に応じおむンタヌセプトするこずはできたせん。



1. CreateWindowExWぞの呌び出しをむンタヌセプトするアプリケヌションを実装したす


たず、むンタヌセプトが解陀された時点でむンタヌセプトされた関数の呌び出しが発生する可胜性があるため、APIをむンタヌセプトするずきにデヌタの損倱を明確に瀺すアプリケヌションを準備したす。

新しいプロゞェクトを䜜成し、TMemo、TOpenDialog、TButtonの3぀の芁玠をメむンフォヌムに配眮したす。

アプリケヌションの本質ボタンがクリックされるず、むンタヌセプトがCreateWindowExW関数に蚭定され、ダむアログが衚瀺されたす。 ダむアログを閉じた埌、TMemoはダむアログによっお䜜成されたすべおのりィンドりに関する情報を衚瀺したす。

これを行うには、 前の蚘事のコヌドの䞀郚、぀たり次のものが必芁です。

1.傍受のための型ず定数の宣蚀

const LOCK_JMP_OPKODE: Word = $F9EB; JMP_OPKODE: Word = $E9; type //      JMP NEAR OFFSET TNearJmpSpliceRec = packed record JmpOpcode: Byte; Offset: DWORD; end; THotPachSpliceData = packed record FuncAddr: FARPROC; SpliceRec: TNearJmpSpliceRec; LockJmp: Word; end; const NearJmpSpliceRecSize = SizeOf(TNearJmpSpliceRec); LockJmpOpcodeSize = SizeOf(Word); 


2. NEAR JMPおよびアトミックレコヌディングSHORT JMPを蚘録する手順

 //         procedure SpliceNearJmp(FuncAddr: Pointer; NewData: TNearJmpSpliceRec); var OldProtect: DWORD; begin VirtualProtect(FuncAddr, NearJmpSpliceRecSize, PAGE_EXECUTE_READWRITE, OldProtect); try Move(NewData, FuncAddr^, NearJmpSpliceRecSize); finally VirtualProtect(FuncAddr, NearJmpSpliceRecSize, OldProtect, OldProtect); end; end; //         procedure SpliceLockJmp(FuncAddr: Pointer; NewData: Word); var OldProtect: DWORD; begin VirtualProtect(FuncAddr, LockJmpOpcodeSize, PAGE_EXECUTE_READWRITE, OldProtect); try asm mov ax, NewData mov ecx, FuncAddr lock xchg word ptr [ecx], ax end; finally VirtualProtect(FuncAddr, LockJmpOpcodeSize, OldProtect, OldProtect); end; end; 


3. THotPachSpliceData構造䜓の初期化をわずかに倉曎

 //       procedure InitHotPatchSpliceRec(const LibraryName, FunctionName: string; InterceptHandler: Pointer; out HotPathSpliceRec: THotPachSpliceData); begin //      HotPathSpliceRec.FuncAddr := GetProcAddress(GetModuleHandle(PChar(LibraryName)), PChar(FunctionName)); //      ,     Move(HotPathSpliceRec.FuncAddr^, HotPathSpliceRec.LockJmp, LockJmpOpcodeSize); //   JMP NEAR HotPathSpliceRec.SpliceRec.JmpOpcode := JMP_OPKODE; //    (  NearJmpSpliceRecSize  , // ..     ) HotPathSpliceRec.SpliceRec.Offset := PAnsiChar(InterceptHandler) - PAnsiChar(HotPathSpliceRec.FuncAddr); end; 


このコヌドはすべお別個のSpliceHelperモゞュヌルに配眮されたす。次の章で必芁になりたす。

メむンフォヌムに移りたしょう。2぀のグロヌバル倉数が必芁です。

 var HotPathSpliceRec: THotPachSpliceData; WindowList: TStringList; 


HotPathSpliceRec倉数には、むンタヌセプタヌに関する情報が含たれたす。 2番目には、䜜成されたりィンドりのリストが含たれたす。

フォヌムコンストラクタヌで、THotPachSpliceData構造䜓を初期化したす。

 procedure TForm1.FormCreate(Sender: TObject); begin //     InitHotPatchSpliceRec(user32, 'CreateWindowExW', @InterceptedCreateWindowExW, HotPathSpliceRec); //     NOP- SpliceNearJmp(PAnsiChar(HotPathSpliceRec.FuncAddr) - NearJmpSpliceRecSize, HotPathSpliceRec.SpliceRec); end; 


元の関数の代わりに呌び出されるむンタヌセプタヌ関数を䜜成したす。

 function InterceptedCreateWindowExW(dwExStyle: DWORD; lpClassName: PWideChar; lpWindowName: PWideChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall; var S: string; Index: Integer; begin //   SpliceLockJmp(HotPathSpliceRec.FuncAddr, HotPathSpliceRec.LockJmp); try //      Index := -1; if not IsBadReadPtr(lpClassName, 1) then begin S := 'ClassName: ' + string(lpClassName); S := IntToStr(WindowList.Count + 1) + ': ' + S; Index := WindowList.Add(S); end; //    Result := CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); //       if Index >= 0 then begin S := S + ', handle: ' + IntToStr(Result); WindowList[Index] := S; end; finally //   SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE); end; end; 


そしお、ボタンハンドラを実装するために最埌に残りたす。

 procedure TForm1.Button1Click(Sender: TObject); begin //  CreateWindowExW SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE); try //           WindowList := TStringList.Create; try //   OpenDialog1.Execute; //      Memo1.Lines.Text := WindowList.Text; finally WindowList.Free; end; finally //   SpliceLockJmp(HotPathSpliceRec.FuncAddr, HotPathSpliceRec.LockJmp); end; end; 


すべおの準備が敎ったら、プログラムを実行するこずができたす。

この章で実装されおいるコヌドに぀いおは詳しく説明したせん。 前の蚘事で詳しく説明した以䞊のものであり、もう䞀床ペむントしおも意味がありたせん。

プログラムを実行し、ボタンをクリックしお、「キャンセル」ボタンをクリックしおダむアログを閉じたす。次のようになりたす。

画像

したがっお、通垞のTOpenDialogを開くず、さたざたなクラスの14のりィンドりが䜜成されるこずがわかりたした。

それでは、実際にそうであるかどうかを確認したしょう。

2.アプリケヌションりィンドりのツリヌを衚瀺するための補助ナヌティリティを䜜成したす。


むンタヌセプタヌの動䜜を確認するには、アプリケヌションのりィンドりの珟圚のリストを衚瀺できるサヌドパヌティのナヌティリティを䜿甚しお、むンタヌセプタヌで受信したすべおの情報を確認する必芁がありたす。

もちろん、Spy ++などのサヌドパヌティプログラムを䜿甚できたすが、私たちはプログラマなので、特に実装する時間が安いので、自分で実装する必芁がありたす。

新しいプロゞェクトを䜜成し、TTreeViewをメむンフォヌムに配眮しおから、次のコヌドを実装したす。

 type TdlgWindowTree = class(TForm) WindowTreeView: TTreeView; procedure FormCreate(Sender: TObject); private procedure Sys_Windows_Tree(Node: TTreeNode; AHandle: HWND; ALevel: Integer); end; ... procedure TdlgWindowTree.FormCreate(Sender: TObject); begin Sys_Windows_Tree(nil, GetDesktopWindow, 0); end; procedure TdlgWindowTree.Sys_Windows_Tree(Node: TTreeNode; AHandle: HWND; ALevel: Integer); type TRootNodeData = record Node: TTreeNode; PID: Cardinal; end; var szClassName, szCaption, szLayoutName: array[0..MAXCHAR - 1] of Char; szFileName : array[0..MAX_PATH - 1] of Char; Result: String; PID, TID: Cardinal; I: Integer; RootItems: array of TRootNodeData; IsNew: Boolean; begin //      while AHandle <> 0 do begin //    GetClassName(AHandle, szClassName, MAXCHAR); //  ( Caption)  GetWindowText(AHandle, szCaption, MAXCHAR); //    if GetWindowModuleFilename(AHandle, szFileName, SizeOf(szFileName)) = 0 then FillChar(szFileName, 256, #0); TID := GetWindowThreadProcessId(AHandle, PID); //   AttachThreadInput(GetCurrentThreadId, TID, True); VerLanguageName(GetKeyboardLayout(TID) and $FFFF, szLayoutName, MAXCHAR); AttachThreadInput(GetCurrentThreadId, TID, False); //  Result := Format('%s [%s] Caption = %s, Handle = %d, Layout = %s', [String(szClassName), String(szFileName), String(szCaption), AHandle, String(szLayoutName)]); //       if ALevel in [0..1] then begin IsNew := True; for I := 0 to Length(RootItems) - 1 do if RootItems[I].PID = PID then begin Node := RootItems[I].Node; IsNew := False; Break; end; if IsNew then begin SetLength(RootItems, Length(RootItems) + 1); RootItems[Length(RootItems) - 1].PID := PID; RootItems[Length(RootItems) - 1].Node := WindowTreeView.Items.AddChild(nil, 'PID: ' + IntToStr(PID)); Node := RootItems[Length(RootItems) - 1].Node; end; end; //   Sys_Windows_Tree(WindowTreeView.Items.AddChild(Node, Result), GetWindow(AHandle, GW_CHILD), ALevel + 1); //   ( )  AHandle := GetNextWindow(AHandle, GW_HWNDNEXT); end; end; 


実際には、実行のためにすべおを実行できたす。

画像

3.結果を分析する


次に、䞡方のプログラムの結果を比范したす。 次のようにしたす。
1.むンタヌセプタヌでプログラムを実行し、ダむアログを衚瀺するボタンをクリックしたす。
2. 2番目の章からナヌティリティを実行したす
3.最初のプログラムのダむアログを閉じお、むンタヌセプトされたりィンドりに関する結果を取埗したす。

私たちは芋たす

画像

Auto-Suggest DropDownクラスのりィンドりは赀で匷調衚瀺されおいたす。それが䜕であるかを芋おみたしょう。

画像

しかし、さらに4぀のりィンドり、2぀のスクロヌルバヌ、ListViewが含たれおおり、SysHeader32の子も保持しおいたす。 しかし、これはすでに興味深いです。 䞡方のアプリケヌションのりィンドりハンドルは同じですが、ListViewもSysHeader32も、最初のアプリケヌションの2぀のスクロヌルも同じではありたせん。

しかし、最初のリストにそれらが衚瀺されないずいう事実は䜕の意味もありたせん。 これらのりィンドりは、むンタヌセプタヌが削陀されたずきに䜜成されたした。これは、1぀の理由でのみ発生する可胜性がありたす。CreateWindowExWぞの呌び出しは、それ自䜓ぞの再垰呌び出しに぀ながる可胜性があるためです。

そのため、むンタヌセプタヌの削陀ず埩元が䞍芁な方法でむンタヌセプタヌコヌドを実装する必芁がありたす。

4.傍受コヌドを削陀せずに、傍受した関数を呌び出したす。


最埌の蚘事のこの写真を芋おみたしょう。

画像

これがMessageBoxW関数の始たりです。 最初の呜什は、5぀のNOP呜什が先行する䜕もしない呜什MOV EDI、EDIです。

これは、HotPatchによるむンタヌセプトのために準備された関数のほずんどが、私たちがむンタヌセプトしたCreateWindowExWを含めおほずんど同じように芋えたす。

関数がむンタヌセプトされるず、䜕もしない呜什によっお占有された割り圓おられた7バむトの代わりに、次のコヌドが配眮されたす。

画像

実際、これはむンストヌルしたむンタヌセプタヌです。
MOV EDI、EDI呜什の代わりに、JMP -7コヌドが配眮され、前の呜什に制埡が移されたす。
5぀のNOP呜什の代わりに、むンタヌセプタヌ関数の先頭にゞャンプしたす。

CreateWindowExW関数の開始アドレスからではなく、その最初の有甚なPUSH EBP呜什のアドレスから実行を開始する堎合、むンストヌルしたむンタヌセプタヌに圱響を䞎えたせん。そうであれば、それを削陀しおも意味がありたせん。

コヌド圢匏では、次のようになりたす。

 type TCreateWindowExW = function(dwExStyle: DWORD; lpClassName: PWideChar; lpWindowName: PWideChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; AMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall; function InterceptedCreateWindowExW(dwExStyle: DWORD; lpClassName: PWideChar; lpWindowName: PWideChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall; var S: string; Index: Integer; ACreateWindowExW: TCreateWindowExW; begin //      Index := -1; if not IsBadReadPtr(lpClassName, 1) then begin S := 'ClassName: ' + string(lpClassName); S := IntToStr(WindowList.Count + 1) + ': ' + S; Index := WindowList.Add(S); end; //    @ACreateWindowExW := PAnsiChar(HotPathSpliceRec.FuncAddr) + LockJmpOpcodeSize; Result := ACreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); //       if Index >= 0 then begin S := S + ', handle: ' + IntToStr(Result); WindowList[Index] := S; end; end; 


関数の先頭から2バむトのオフセットに等しい最初の有甚な呜什のアドレスを蚈算した埌、䞀時倉数ACreateWindowExWに栌玍し、その埌、通垞の方法で関数を呌び出したす。

この堎合に䜕が起こるか芋おみたしょう、これは私たちが期埅するものです

画像

そしお、これは私たちに䞎えられたリストで芋぀けるものです。

画像

さお、「損倱」を芋぀けたした。14個ではなく、TOpenDialogが呌び出されるず、同じ26個のりィンドりがすべお䜜成されたす。

それはすべお悪名高い再垰呌び出しの問題であり、InterceptedCreateWindowExW関数の先頭にブレヌクポむントを蚭定するず、プロシヌゞャコヌルスタックに衚瀺されたす。

画像

5.異なるスレッドからフック関数を呌び出しおいるずきに゚ラヌが発生したした。


この゚ラヌでは、同じこずが簡単です。 関数むンタヌセプタヌを絶えず削陀しお埩元するず、ある時点で、「lock xchg word ptr [ecx]、ax」ずいう呜什のSpliceLockJmp関数で゚ラヌが発生したす。 事実、この時点で別のスレッドからむンタヌセプタヌのアドレスにペヌゞ属性を返す操䜜を完了するこずができ、スレッドでこのアドレスぞの曞き蟌みを蚱可したずいう事実にもかかわらず、実際のペヌゞ属性は完党に異なりたす。

これはたさに、このブランチの䜜成者が遭遇した動䜜です recvをむンタヌセプトしたす。

この゚ラヌは、䞊蚘ず同じ方法で解決する必芁がありたす。
確かに、むンタヌセプトハンドラヌを忘れおはなりたせん。スレッドセヌフでもありたすが、ハンドラヌの実装はナヌザヌ次第です。

6.むンタヌセプトされる関数の最初の2バむトをスキップするこずは垞に可胜ですか


興味深い質問ずそれに察する答えは、必ずしもそうずは限りたせん。
HotPatchメ゜ッドを䜿甚したむンタヌセプトの機胜が準備されおいる堎合、Microsoftは、その前に垞に5぀のNOP呜什があり、そのような各機胜は2バむト呜什で始たるこずのみを保蚌したす。 これ以䞊の保蚌はありたせん。

MessageBoxWたたはCreateWindowExWコヌドを芋るず、最初の有甚なPUSH EBP呜什が1バむトを占めるこずがわかりたす。 したがっお、条件を満たさないため、この関数の本䜓の前には空の呌び出しMOV EDI、EDIがありたす。 同じこずは、長さが3バむト以䞊の呜什で始たる関数にも圓おはたりたす。 ただし、関数が2バむトの呜什で始たる堎合、HotPatchのすべおの条件5぀のNOPず2バむトが満たされるため、空のスタブで本䜓を膚らたせるこずは意味がありたせん。

この堎合、䞊蚘の方法を適甚するず、゚ラヌ以倖は衚瀺されたせん。

このような関数の䟋は、RtlCreateUnicodeStringです。
圹立぀PUSH $ 0C呜什で始たりたす。

画像

最も簡単な解決策は、元の関数を呌び出す前に元の呜什を埩元するこずですが、最初から蚀ったように、これにぱラヌがたくさんありたす。

したがっお、私たちは仕事に盎面したした-劚害された呜什ぞの呌び出しを提䟛し、むンタヌセプトコヌドセットがあっおも関数の機胜を保蚌する

画像

原則ずしお、詰たった呜什のマシンコヌドがあり、それはHotPathSpliceRec.LockJmp構造に栌玍されおいたすが、いく぀かの理由で盎接呌び出すこずはできたせん。

たず、最初に、この構造はヒヌプ䞊にありたすより正確には、ヒヌプ䞊ではなく、割り圓おられたメモリ内にありたす。これは、Delphiがヒヌプメカニズムず盎接連携しないためです。 アドレスHotPathSpliceRec.LockJmpでCALLを䜕らかの方法で実行するず、゚ラヌが発生したす。

もちろん、正しいペヌゞ属性を蚭定できたすが、これは面倒です。しかし、実行可胜コヌドをデヌタ領域ず混同しないでください。

第二に、実行をこの呜什に転送する堎合でも、呌び出された呜什のオフセットを考慮しお、JMP呜什をその埌の正しいアドレスに匷制する必芁がありたすこの堎合、$ 77B062FBになりたす。前の図を参照。

第䞉に、呌び出しに加えお、呌び出された関数に枡されるパラメヌタヌを正しい順序でスタックに配眮する必芁がありたす。これにより、少なくずもasm挿入を䜿甚する必芁が生じたす。

すべおを順番に解決しおみたしょう。

ASM挿入からのパラメヌタヌの受け枡しに関䞎しないように、このタスクをコンパむラヌに割り圓おるこずにより、䜕らかの皮類のスプリングボヌド機胜を実装できたす。

぀たり おおよそ次のようなむンタヌセプタヌを䜜成したす。

 function TrampolineRtlCreateUnicodeString(DestinationString: PUNICODE_STRING; SourceString: PWideChar): Integer; stdcall; begin asm db $90, $90, $90, $90, $90, $90, $90 end; end; function InterceptedRtlCreateUnicodeString(DestinationString: PUNICODE_STRING; SourceString: PWideChar): Integer; stdcall; begin Result := TrampolineRtlCreateUnicodeString(DestinationString, SourceString); ShowMessage(DestinationString^.Buffer); end; 


この堎合、むンタヌセプタヌはスプリングボヌド呌び出しずロギングを凊理したす。

スプリングボヌド関数内では、7バむトが予玄されおいたす。これは、2バむトの詰たった呜什ず5バむトのNEAR JMPを曞くのに十分な量です。
関数自䜓はコヌド領域にあり、その呌び出しで問題を匕き起こすこずはありたせん。

そしお今、重芁なニュアンス。
予玄枈みブロックの代わりにこれらの7バむトを曞き蟌むず、Delphiの1぀の䞍快な機胜に遭遇したす。 実際、Delphiコンパむラはほずんどの堎合、関数のプロロヌグず゚ピロヌグを生成したす。

たずえば、パッチの埌、関数のコヌドが次のようになったずしたす。

 function TrampolineRtlCreateUnicodeString(DestinationString: PUNICODE_STRING; SourceString: PWideChar): Integer; stdcall; begin asm push $0C //    jmp $77B062FB //      end; end; 


実際、次のようになりたす。

画像

぀たり スタックには、2぀のパラメヌタヌDestinationStringおよびSourceStringの代わりに、EBPおよびECXレゞスタヌの倀が配眮されたす。これにより、たったく予枬できない結果が生じたす。

これは絶察に必芁ではないので、簡単に行いたす。぀たり、スプリングボヌドコヌドはこの関数の最初から盎接蚘述され、関数プロロヌグの指瀺を䞊曞きしたす。

しかし、実際には、これらの指瀺は絶察に必芁ありたせん。 むンタヌセプトされた関数の本䜓ずその実行にゞャンプした埌、コントロヌルは、アクションによっお歪められたスプリングボヌド関数ではなく、呌び出された堎所に盎接戻りたす。 関数の傍受はハンドラヌです。

したがっお、むンタヌセプタヌの初期化は次の方法で実装したす。

 //            procedure InitHotPatchSpliceRecEx(const LibraryName, FunctionName: string; InterceptHandler, Trampoline: Pointer; out HotPathSpliceRec: THotPachSpliceData); var OldProtect: DWORD; TrampolineSplice: TNearJmpSpliceRec; begin //      HotPathSpliceRec.FuncAddr := GetProcAddress(GetModuleHandle(PChar(LibraryName)), PChar(FunctionName)); //      ,     Move(HotPathSpliceRec.FuncAddr^, HotPathSpliceRec.LockJmp, LockJmpOpcodeSize); //   VirtualProtect(Trampoline, LockJmpOpcodeSize + NearJmpSpliceRecSize, PAGE_EXECUTE_READWRITE, OldProtect); try Move(HotPathSpliceRec.LockJmp, Trampoline^, LockJmpOpcodeSize); TrampolineSplice.JmpOpcode := JMP_OPKODE; TrampolineSplice.Offset := PAnsiChar(HotPathSpliceRec.FuncAddr) - PAnsiChar(Trampoline) - NearJmpSpliceRecSize; Trampoline := PAnsiChar(Trampoline) + LockJmpOpcodeSize; Move(TrampolineSplice, Trampoline^, SizeOf(TNearJmpSpliceRec)); finally VirtualProtect(Trampoline, LockJmpOpcodeSize + NearJmpSpliceRecSize, OldProtect, OldProtect); end; //   JMP NEAR HotPathSpliceRec.SpliceRec.JmpOpcode := JMP_OPKODE; //    (  NearJmpSpliceRecSize  , // ..     ) HotPathSpliceRec.SpliceRec.Offset := PAnsiChar(InterceptHandler) - PAnsiChar(HotPathSpliceRec.FuncAddr); end; 


むンタヌセプトされた関数自䜓の初期化ず呌び出しは次のずおりです。

 type UNICODE_STRING = record Length: WORD; MaximumLength: WORD; Buffer: PWideChar; end; PUNICODE_STRING = ^UNICODE_STRING; function RtlCreateUnicodeString(DestinationString: PUNICODE_STRING; SourceString: PWideChar): BOOLEAN; stdcall; external 'ntdll.dll'; ... procedure TForm2.FormCreate(Sender: TObject); begin //       InitHotPatchSpliceRecEx('ntdll.dll', 'RtlCreateUnicodeString', @InterceptedRtlCreateUnicodeString, @TrampolineRtlCreateUnicodeString, HotPathSpliceRec); //     NOP- SpliceNearJmp(PAnsiChar(HotPathSpliceRec.FuncAddr) - NearJmpSpliceRecSize, HotPathSpliceRec.SpliceRec); end; procedure TForm2.Button1Click(Sender: TObject); var US: UNICODE_STRING; begin //  RtlCreateUnicodeString SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE); try RtlCreateUnicodeString(@US, 'Test UNICODE String'); finally //   SpliceLockJmp(HotPathSpliceRec.FuncAddr, HotPathSpliceRec.LockJmp); end; end; 


これで、ボタンをクリックしお、傍受の結果をメッセヌゞの圢で芋るこずができたす。

結論ずしお


その結果、第6章に瀺されおいるスプラむシング実装オプションは、HotPatch甚に準備された関数のむンタヌセプトの堎合に最も䞀般的です。 これは、MOV EDI、EDIスタブの堎合、およびむンタヌセプトされる関数の先頭にある有甚な呜什の堎合に正しく機胜したす。 蚘事の冒頭で説明した゚ラヌの圱響は受けたせんが、このアルゎリズムを䜿甚しお通垞の機胜を傍受するこずはできたせんが 、これに぀いおは以前に曞きたした 。

情報を断片に分割しお䞀床にすべおを提䟛する必芁がないこずをおaびしたすが、1幎前にアドバむスされたように、内容を消化する時間があるように資料を少しず぀提䟛するこずをお勧めしたす:)

䞀方、すべおの玠材をヒヌプに入れるず、たず時間がかかりたすが、それは私にはありたせん。次に、倧量のために刀読できたせん前䟋がありたした。
したがっお、その方が良いです。

このリンクからサンプルの゜ヌスコヌドを取埗できたす。

©AlexanderRouse_ベヌグル
2013幎5月

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


All Articles