夏天薄荷的微凉 發表於 2019-11-30 08:34:00

DLL Injection with Delphi(转载)

<p></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">原始链接</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">I had recently spent some time playing around with the simple to use <strong>DelphiDetours</strong> package from <strong>Mahdi Safsafi</strong></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://github.com/MahdiSafsafi/DDetours</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">One missing feature is the ability to inject a DLL into an external process. This is something that I wanted to do for a project that I am currently working on, so I started doing some reading. To me, the topic always seemed to be a <strong><em>Black Art</em></strong>, and something left for the assembly language developers to use, but it turns out to be much more widely accessible and fairly easy to do.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">I added a few routines to my <strong>dxLib</strong> open source project on GitHub to assist with the DLL injection task:</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://github.com/darianmiller/dxLib</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">I also put a new repository online yesterday, initially containing Delphi projects to create an example custom DLL, a basic victim process, and an example DLL Injector. This repo can be found at:</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://github.com/darianmiller/dxInjectionDetours</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">The screen shot below demonstrates a successful detour of a simple <strong>MessageBox</strong> call utilizing the projects from the dxInjectionDetours repo:</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0 _1hD8w">
<div class="_1Lhwj image-container" data-hook="imageViewer">
<div class="xdJBZ"><img class="_1Fjtc _2E02D" src="https://static.wixstatic.com/media/ec6db6_98b68f414ddd4b61ba4c3066415df735~mv2.png/v1/fit/w_300,h_300,al_c,q_5/file.png" alt="Sample Windows API method intercepted"><img class="_1Fjtc _2lDdg" src="https://static.wixstatic.com/media/ec6db6_98b68f414ddd4b61ba4c3066415df735~mv2.png/v1/fill/w_1061,h_937,al_c,q_90/ec6db6_98b68f414ddd4b61ba4c3066415df735~mv2.webp" alt="Sample Windows API method intercepted" data-pin-url="https://www.ideasawakened.com/post/dll-injection-with-delphi" data-pin-media="https://static.wixstatic.com/media/ec6db6_98b68f414ddd4b61ba4c3066415df735~mv2.png/v1/fit/w_1061,h_937,al_c,q_80/file.png"></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div class="_3ULLf image-caption" data-hook="imageViewerCaption">Sample Windows API method intercepted</div>
</div>
</div>
</div>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">Define which ProcessID to target</h2>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</h2>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">First, I wanted to offer a list of running processes, so the user can simply select a DLL injection target from a list. There's a new <strong>dxLib_ProcessList</strong> unit with a simple TdxProcessEntryList class which can be populated with a call to its SnapShotActiveProcesses method:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">https://docs.microsoft.com/en-us/windows/win32/toolhelp/taking-a-snapshot-and-viewing-processes</span>
<span style="color: rgba(0, 0, 255, 1)">function</span> TdxProcessEntryList.SnapshotActiveProcesses(<span style="color: rgba(0, 0, 255, 1)">const</span> pLookupFullPathName:Boolean=False):Boolean;</pre>
</div>
<p>&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">The list is generated using the Kernel32.dll API method: <span class="sDZYg" style="text-decoration: underline"><strong>CreateToolhelp32Snapshot</strong></span> and related helper routines. It's a quick snapshot of active processes (along with heaps, modules and threads used...which I may extend later.) You can use the related <span class="sDZYg" style="text-decoration: underline"><strong>Process32First</strong></span> and <span class="sDZYg" style="text-decoration: underline"><strong>Process32Next</strong></span> API methods to build a list of <span class="sDZYg" style="text-decoration: underline"><strong>PROCESSENTRY32</strong></span> items that contain interesting entries like <strong>ProcessID</strong>, <strong>ParentProcessID</strong>, and <strong>ExeFile </strong>name. One potential problem is the ExeFile provided is just the file name without the full path.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">You actually do not need the full path name to inject a DLL, but I thought it was a nice feature to add to the demo so I added an optional parameter to utilize another Kernel32 API method <strong>QueryFullProcessImageName</strong> which returns the full path name of a given process. There are two versions of this method available, one <strong><span class="sDZYg" style="text-decoration: underline">ANSI</span></strong> and one <strong><span class="sDZYg" style="text-decoration: underline">Unicode</span></strong>.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Since I'm using this in a loop, to cache the calls to GetModuleHandle/GetProcAddress, there was a utility class created (<strong>TdxProcessNameToId</strong>) and a simple method to return the full path name for a given ProcessID:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">requires Vista or later</span>
<span style="color: rgba(0, 0, 255, 1)">function</span> TdxProcessNameToId.GetFileNameByProcessID(<span style="color: rgba(0, 0, 255, 1)">const</span> pTargetProcessID:DWORD):<span style="color: rgba(0, 0, 255, 1)">string</span>;</pre>
</div>
<p>&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0">
<div class="hnvPV _34EUx" data-hook="HtmlComponent">&nbsp;</div>
</div>
</div>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Note that this method calls OpenProcess with the PROCESS_QUERY_LIMITED_INFORMATION access right, which provides a subset of information. This reduced access grants further calls to QueryFullProcessImageName (along with GetExitCodeProcess, GetPriorityClass, and IsProcessInJob.)</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><strong>Note</strong>: OpenProcess will fail on some system processes.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Since some system processes will generate errors, the SnapshotActiveProcesses method simply skips over them. There typically no good reasons to be sniffing into these system processes anyway. (If you need that, then you should get out of User Land and get yourself into Kernel mode.)</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">We now have a simple routine to easily get a full list of active processes for a user to select from, which will provide a specific <strong>ProcessID</strong> to target.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">Create a custom DLL to inject</h2>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</h2>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">The interesting part of this task involves creating the DLL which contains our API hook, intercept, detour, or the terminology of your choice. Using the DelphiDetours package, it's really simple to do.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><strong>Remember </strong>to 'match your bitness' - create a 32-bit DLL to inject into a 32-bit process, and a 64-bit DLL for a 64-bit process.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">There is a long history of DLL support in Delphi. Unfortunately, there's not a lot of documentation provided for some areas. For example, if you look up the DLLProc global variable, you likely won't find much. Fortunately, there is a succinct <span class="sDZYg" style="text-decoration: underline"><strong>StackOverflow</strong></span> response by <strong>Sertac Akyuz</strong> which explains basic usage:</p>
<div class="cnblogs_code">
<pre>Unfortunately when <span style="color: rgba(0, 0, 255, 1)">begin</span> <span style="color: rgba(0, 0, 255, 1)">is</span> executed <span style="color: rgba(0, 0, 255, 1)">in</span> your dll code, the OS has already called DllMain <span style="color: rgba(0, 0, 255, 1)">in</span> your <span style="color: rgba(0, 0, 255, 1)">library</span>. So<br> when your DllProc := DllMain; statement executes it <span style="color: rgba(0, 0, 255, 1)">is</span> already too late. <br>The Delphi compiler does <span style="color: rgba(0, 0, 255, 1)">not</span> allow user code <span style="color: rgba(0, 0, 255, 1)">to</span> execute when the dll <span style="color: rgba(0, 0, 255, 1)">is</span> attached <span style="color: rgba(0, 0, 255, 1)">to</span> a process. <br>The suggested workaround (<span style="color: rgba(0, 0, 255, 1)">if</span> you can call that a workaround) <span style="color: rgba(0, 0, 255, 1)">is</span> <span style="color: rgba(0, 0, 255, 1)">to</span> call your own DllMain <br><span style="color: rgba(0, 0, 255, 1)">function</span> yourself <span style="color: rgba(0, 0, 255, 1)">in</span> a <span style="color: rgba(0, 0, 255, 1)">unit</span> initalization section <span style="color: rgba(0, 0, 255, 1)">or</span> <span style="color: rgba(0, 0, 255, 1)">in</span> the <span style="color: rgba(0, 0, 255, 1)">library</span> code:<br><br></pre>
</div>
<p>&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0">
<div class="hnvPV _34EUx" data-hook="HtmlComponent">&nbsp;</div>
</div>
</div>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">We set this DLLProc system variable and call it ourselves with DLL_PROCESS_ATTACH. This is the .DPR source for an example DLL:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">library</span><span style="color: rgba(0, 0, 0, 1)"> dxDetours_InterceptAPI_MessageBox;

</span><span style="color: rgba(0, 0, 255, 1)">uses</span><span style="color: rgba(0, 0, 0, 1)">
WinApi.Windows,
dxDetours_InterceptAPI_MessageBox_CustomImplementation </span><span style="color: rgba(0, 0, 255, 1)">in</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">..\..\Source\dxDetours_InterceptAPI_MessageBox_CustomImplementation.pas</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$R *.RES</span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> DllEntry(pReason:DWORD);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
   <span style="color: rgba(0, 0, 255, 1)">case</span> pReason <span style="color: rgba(0, 0, 255, 1)">of</span><span style="color: rgba(0, 0, 0, 1)">
   DLL_PROCESS_ATTACH: CreateIntercepts();
   DLL_PROCESS_DETACH: RemoveIntercepts();
   DLL_THREAD_ATTACH:;
   DLL_THREAD_DETACH:;
   </span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
DllProc:</span>=<span style="color: rgba(0, 0, 0, 1)"> @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);

</span><span style="color: rgba(0, 0, 255, 1)">end</span>.</pre>
</div>
<p>&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0">
<div class="hnvPV _34EUx" data-hook="HtmlComponent">&nbsp;</div>
</div>
</div>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">We then need to define CreateIntercepts() and RemoveIntercepts() in our custom implementation unit as in the example below. DelphiDetours does most of the heavy lifting. We just need to define which API calls to intercept and what to replace them with.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">In this example, we're going to replace the two variations of MessageBox with our own custom implementation. For this very simple example, we will call the intercepted (original version) MessageBox with our custom message and caption whenever the target process calls MessageBox:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">unit</span><span style="color: rgba(0, 0, 0, 1)"> dxDetours_InterceptAPI_MessageBox_CustomImplementation;

</span><span style="color: rgba(0, 0, 255, 1)">interface</span>
<span style="color: rgba(0, 0, 255, 1)">uses</span><span style="color: rgba(0, 0, 0, 1)">
Windows,
DDetours;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> CreateIntercepts();
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> RemoveIntercepts();

</span><span style="color: rgba(0, 0, 255, 1)">var</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">definitions of methods to be replaced - ensure exact match to target methods</span>
InterceptMessageBoxA: <span style="color: rgba(0, 0, 255, 1)">function</span>(hWnd: hWnd; lpText, lpCaption: LPCSTR; uType: UINT): Integer; <span style="color: rgba(0, 0, 255, 1)">stdcall</span> = <span style="color: rgba(0, 0, 255, 1)">nil</span><span style="color: rgba(0, 0, 0, 1)">;
InterceptMessageBoxW: </span><span style="color: rgba(0, 0, 255, 1)">function</span>(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; <span style="color: rgba(0, 0, 255, 1)">stdcall</span> = <span style="color: rgba(0, 0, 255, 1)">nil</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>


<span style="color: rgba(0, 0, 255, 1)">function</span> MyCustomMessageBoxA(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; <span style="color: rgba(0, 0, 255, 1)">stdcall</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Result :</span>= InterceptMessageBoxA(hWnd, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">My custom message</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ANSI Version Hooked</span><span style="color: rgba(128, 0, 0, 1)">'</span>, MB_OK <span style="color: rgba(0, 0, 255, 1)">or</span><span style="color: rgba(0, 0, 0, 1)"> MB_ICONEXCLAMATION);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;


</span><span style="color: rgba(0, 0, 255, 1)">function</span> MyCustomMessageBoxW(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; <span style="color: rgba(0, 0, 255, 1)">stdcall</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Result :</span>= InterceptMessageBoxW(hWnd, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">My custom message</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">UNICODE Version Hooked</span><span style="color: rgba(128, 0, 0, 1)">'</span>, MB_OK <span style="color: rgba(0, 0, 255, 1)">or</span><span style="color: rgba(0, 0, 0, 1)"> MB_ICONEXCLAMATION);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;


</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> CreateIntercepts();
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
BeginHooks;
    @InterceptMessageBoxA :</span>=<span style="color: rgba(0, 0, 0, 1)"> InterceptCreate(@MessageBoxA, @MyCustomMessageBoxA);
    @InterceptMessageBoxW :</span>=<span style="color: rgba(0, 0, 0, 1)"> InterceptCreate(@MessageBoxW, @MyCustomMessageBoxW);
EndHooks;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;


</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> RemoveIntercepts();
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> Assigned(InterceptMessageBoxA) <span style="color: rgba(0, 0, 255, 1)">then</span>
<span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
    BeginUnHooks;
    InterceptRemove(@InterceptMessageBoxA);
    InterceptRemove(@InterceptMessageBoxW);
    InterceptMessageBoxA :</span>= <span style="color: rgba(0, 0, 255, 1)">nil</span><span style="color: rgba(0, 0, 0, 1)">;
    InterceptMessageBoxW :</span>= <span style="color: rgba(0, 0, 255, 1)">nil</span><span style="color: rgba(0, 0, 0, 1)">;
    EndUnHooks;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">end</span>.</pre>
</div>
<p>&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0">
<div class="hnvPV _34EUx" data-hook="HtmlComponent">&nbsp;</div>
</div>
</div>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Thanks to DelphiDetours, this isn't a <strong><em>Black Art</em></strong> at all (at least in our code...DelphiDetours is certainly full of magic.) The major caveat is to ensure that the API method definition exactly matches the original. It's best to utilize the Delphi-provided definitions whenever possible (like those found in the Windows.pas file.)</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">We now have a DLL ready to inject into a target process!</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">Inject your DLL into an active process</h2>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</h2>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Now the fun part - actually injecting this custom DLL into a target process. (Note that there are ways to prep a process to load one or more DLLs automatically on startup which could be detailed in a future blog post.)</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Unfortunately, the DelphiDetours package doesn't provide the injection capability. I've added a new unit to dxLib so handle this task: <strong>dxLib_WinInjection</strong>. This has a single utility method, <strong>InjectDLL</strong> as defined below:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span> InjectDLL(<span style="color: rgba(0, 0, 255, 1)">const</span> pTargetProcessID:DWORD; <span style="color: rgba(0, 0, 255, 1)">const</span> pSourceDLLFullPathName:<span style="color: rgba(0, 0, 255, 1)">string</span>; <span style="color: rgba(0, 0, 255, 1)">const</span> pSuppressOSError:Boolean=True):Boolean;</pre>
</div>
<p>&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0">
<div class="hnvPV _34EUx" data-hook="HtmlComponent">&nbsp;</div>
</div>
</div>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">You just need the ProcessID and the filename (including full path) of the DLL to inject and it returns success or failure.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">This method calls <span class="sDZYg" style="text-decoration: underline"><strong>OpenProcess</strong></span> with extended access rights (PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ) It then allocates enough memory (via <span class="sDZYg" style="text-decoration: underline"><strong>VirtualAllocEx</strong></span> which returns the memory location) to write the DLL full pathname (via <span class="sDZYg" style="text-decoration: underline"><strong>WriteProcessMemory</strong></span>) to the process memory space. It then calls <span class="sDZYg" style="text-decoration: underline"><strong>CreateRemoteThread</strong></span> with a function pointer to <strong>LoadLibrary</strong> (<span class="sDZYg" style="text-decoration: underline"><strong>ANSI</strong></span> or <span class="sDZYg" style="text-decoration: underline"><strong>Unicode</strong></span> variant, depending on your Delphi version) and the memory location of the DLL to be loaded. When this occurs, the interception(s) defined in the custom DLL get put into place.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Now, there is a bit of <em><strong>Black Art</strong></em> in this code, as the remote thread starts with a LoadLibrary call in Kernel32.dll. This will only work because LoadLibrary exists in every process at the <em>same virtual memory address</em> (otherwise we would have to look-up the location of LoadLibrary in the target process' memory space.) We start a new thread executing LoadLibrary with the DLL full filename. This nice <strong><span class="sDZYg" style="text-decoration: underline">blog post</span></strong> from <strong>Brandon Arvanaghi</strong> goes into more detail. As his post suggests, there is an alternative way of injecting a DLL and that is to write enough space to the external process to hold the entire contents of the DLL instead of just the filename. (Perhaps we'll attempt that task for fun in a future blog post.)</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">I confess to reading different pieces of sample code a few times before understanding what was going on. Most samples that I found were cryptic without any comments and it seemed odd to be writing the DLL filename to some random memory location - until it finally clicked. Perhaps one way to look at it is to compare it to a simple post-it note. We write the full pathname of the DLL to a post-it note and stick it inside the memory space of the target process. This note is only used by when calling the LoadLibrary routine in a new thread, and then it's discarded/ignored.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">What's next?</h2>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</h2>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Next up is to inject a custom DLL into <strong>every active process</strong>. In the ancient versions of Windows, it was much easier (and a very important reason why viruses were much more rampant back then!) These days, this is going to take a system driver and it's beyond the scope of our simple InjectDLL call. DelphiDetours is a nice package, but it's also missing this functionality. However, there is hope as we can fall back to a famous Delphi classic tool: <strong><span class="sDZYg" style="text-decoration: underline">madCodeHook</span></strong> from <strong>Mathias Rauen</strong>.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Mathias is no longer offering a freeware version of this package. It's also not available for sale without some sort of background check. Apparently, this powerful tool has been used in the past by malware authors. I've contacted the author directly and was provided a purchase link. (We also connected on LinkedIn. If you are interested in this sort of topic, feel free to reach out to me as well: <strong><span class="sDZYg" style="text-decoration: underline">https://www.linkedin.com/in/darianm/</span></strong>) I plan on purchasing madCodeHook soon and implementing a system wide hook using the driver-based approach. That fun will hopefully be documented in a future blog post. I wanted to get the current task working before tackling the much larger driver-based approach.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">Further Information</h2>
<h2 class="_3f-vr _208Ie blog-post-title-font _3tzpp _5aNAR css-x4x4qs _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</h2>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">When looking at intercepting Windows APIs, the industry reference is the <strong>Detours</strong> package directly from <strong>Microsoft</strong>. This was available historically as a fairly expensive commercial package but is now available on GitHub under a fee MIT open source license.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://github.com/microsoft/Detours</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">There is also apparently some Injection code in the venerable JEDI Code Library for Delphi, which also may be looked at in a future blog post.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://github.com/project-jedi/jcl</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">Finally, I used a few tools for composing this blog post. The first is a free source code beautifier available online called <strong>Hilite.me</strong> by <strong>Alexander Kojevnikov</strong>. Simply paste code into the <em>Source Code</em> box, pick the <em>Language</em>, optionally pick the <em>Style</em> (I selected <strong>vs</strong>) and click on the <em>Highlight!</em> button. It will generate the HTML in another edit box, as well as display a preview. It's super-easy and works great.</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>http://hilite.me/</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">For the short-animated demo below, I used a free tool called <strong>ScreenToGif</strong> by <strong>Nicke Manarin.</strong></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://www.screentogif.com/</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_"><span class="sDZYg" style="text-decoration: underline"><strong>https://github.com/NickeManarin/ScreenToGif</strong></span></p>
<p class="XzvDs _208Ie _2Dym_ blog-post-text-font blog-post-text-color _2QAo- _25MYV _2R0Lu _2Dym_">&nbsp;</p>
<div class="q2uC4 _2vlB-">
<div class="_2CvYQ c-Mgr _1K2V0 _1K2V0 _1hD8w">
<div class="_1Lhwj image-container" data-hook="imageViewer">
<div class="xdJBZ"><img class="_1Fjtc _2E02D" src="https://static.wixstatic.com/media/ec6db6_e7a1a0c0b2d54beb9a53a3d3ec8d1ab6~mv2.gif/v1/fit/w_300,h_300,al_c,q_5/file.gif" alt="DLL injection demo"><img class="_1Fjtc _2lDdg" src="https://static.wixstatic.com/media/ec6db6_e7a1a0c0b2d54beb9a53a3d3ec8d1ab6~mv2.gif" alt="DLL injection demo" data-pin-url="https://www.ideasawakened.com/post/dll-injection-with-delphi" data-pin-media="https://static.wixstatic.com/media/ec6db6_e7a1a0c0b2d54beb9a53a3d3ec8d1ab6~mv2.gif/v1/fit/w_1050,h_901,al_c,q_80/file.png"></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div class="_3ULLf image-caption" data-hook="imageViewerCaption">DLL injection demo</div>
</div>
</div>
</div>
<p></p><br><br>
来源:https://www.cnblogs.com/xalion/p/11961255.html
頁: [1]
查看完整版本: DLL Injection with Delphi(转载)