首页
社区
课程
招聘
[求助]写DLL脱壳机中获取某一模块上下文内容的问题
发表于: 2008-6-1 18:53 7061

[求助]写DLL脱壳机中获取某一模块上下文内容的问题

2008-6-1 18:53
7061
模拟OD调试DLL的方法,程序加载LoadDll.exe,利用命令行"LoadDll.exe *.DLL"加载dll进行调试脱壳。
基本步骤:
1、CreateProcess时采用"LoadDll.exe *.dll"命令行方式创建调试进程
2、CREATE_PROCESS_DEBUG_EVENT时获取被调试进程的进程句柄:DBEvent.u.CreateProcessInfo.hProcess和线程句柄DBEvent.u.CreateProcessInfo.hThread
3、LOAD_DLL_DEBUG_EVENT时遍历模块列表,当加载*.dll模块后设置相应断点后ResumeThread DBEvent.u.CreateProcessInfo.hThread,Sleep 100后SuspendThread DBEvent.u.CreateProcessInfo.hThread,用GetThreadContext获取Context.regEip,这时出现了死循环,调试后发现Context.regEip返回的都是同一个值:ntdll.KiFastSystemCallRet,取不了*.dll模块的上下文内容,不知道是什么原因!!

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
2
也拿了PECompact加壳的DLL来做测试,主要源码:
ProcessDll proc
LOCAL Buffer [64]:byte
LOCAL BP1_data,BP2_data,BP3_data,BP4_data:DWORD
LOCAL BP1,BP2,BP3,BP4:DWORD
LOCAL hProcess:dword
LOCAL tempaddr:dword
LOCAL dlls_imported,PatchAddr:dword
LOCAL szContext[1024]:byte
LOCAL TEB,LDR:dword

        mov flag,0
        invoke GetTempPath, sizeof TempPath, addr TempPath
        invoke wsprintf,addr OutBuff,addr Format,addr loaddllPath,addr FilePath  ;loaddll.exe 2.dll
        invoke GetStartupInfo,addr startinfo
        invoke CreateProcess,NULL,addr OutBuff,NULL,NULL,FALSE,DEBUG_PROCESS+DEBUG_ONLY_THIS_PROCESS ,NULL,addr TempPath,addr startinfo,addr ProcessInfo
        .while TRUE               
                       invoke WaitForDebugEvent,addr DBEvent,INFINITE              
                       mov dwDebugOperation,DBG_CONTINUE                     
                       .if DBEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT                                       
                                     invoke OutputInfo,CTEXT("Exit Debug"),0                                  
                                     .break 
                      .elseif DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT 
                        mov edx,DBEvent.u.CreateProcessInfo.hProcess
                        mov myProcess,edx
                        mov ecx,DBEvent.u.CreateProcessInfo.hThread
                        mov myThread,ecx  
                       .elseif DBEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT
                               mov eax,DBEvent.u.LoadDll.lpBaseOfDll
                               mov dwModBase,eax 
                               .if  dwModBase < 60000000h
                                             invoke ReadProcessMemory,myProcess,DBEvent.u.LoadDll.lpImageName,addr OutBuff,4,NULL
                                             mov eax,dword ptr OutBuff
                                             invoke ReadProcessMemory,myProcess,eax,addr pDllName,256,NULL
                                             invoke Unicode2Ansi,addr pDllName,addr outinf
                                             invoke lstrcmp,addr outinf,addr FilePath
                                             .if eax==0
                                                     inc flag
                                                     invoke wsprintf,addr OutBuff,CTEXT("加载Dll成功: 句柄:%08Xh,基址:%08Xh,名称:%s",13,10,0),DBEvent.u.LoadDll.hFile,DBEvent.u.LoadDll.lpBaseOfDll,addr outinf
                                                     invoke OutputInfo,addr OutBuff,0
                                                     mov esi,DBEvent.u.LoadDll.lpBaseOfDll
                                                     mov DllBase,esi 
                                                     mov eax,DBEvent.u.LoadDll.hFile
                                                     mov hDll,eax
                                             .elseif flag==1                                                       
                                                     mov edi,DllBase
                                                     add edi,EntryPiont
                                                     add edi,1
                                                     lea esi,Buffer
                                                     invoke ReadProcessMemory,myProcess,edi,esi,4,0
                                                     mov edi,dword ptr [esi] 
                                                     invoke wsprintf,addr OutBuff,CTEXT("%s: %.08X",13,10,0),CTEXT("得到 mov eax,xxxxxxxx 的地址"),edi 
                                                     invoke OutputInfo,addr OutBuff,0
                                                     invoke Searchcode,myProcess,edi,0ffd7h
                                                     .if eax==0
                                                             invoke MessageBox,0,CTEXT("搜索内存错误"),0,MB_OK
                                                             jmp @@exit
                                                     .endif
                                                     mov BP1,eax
                                                     invoke ReadProcessMemory,myProcess,BP1,addr BP1_data,2,0    
                                                     invoke WriteProcessMemory,myProcess,BP1,CTEXT(0EBh,0FEh),2,0
                                                     invoke wsprintf,addr OutBuff,CTEXT("%s: %.08X",13,10,0),CTEXT("在 'CALL EDI' 处下断"),BP1 
                                                     invoke OutputInfo,addr OutBuff,0                                                     
                                                     invoke Searchcode,myProcess,BP1,0FFe0h 
                                                     mov BP2,eax
                                                     invoke wsprintf,addr OutBuff,CTEXT("%s: %.08X",13,10,0),CTEXT("在 'JMP EAX' 处下断"),BP2
                                                     invoke OutputInfo,addr OutBuff,0  
                                                     invoke ReadProcessMemory,myProcess,BP2,addr BP2_data,2,0 
                                                     invoke WriteProcessMemory,myProcess,BP2,CTEXT(0EBh,0FEh),2,0   
                                                     _10MB equ 1024*1024*10
                                                     invoke VirtualAlloc,0,_10MB,MEM_COMMIT,PAGE_READWRITE
                                                     mov pNewImports,eax
                                                     invoke OutputInfo,CTEXT("开始脱壳",13,10,0),0  
                                        invoke ResumeThread,myThread  
                                        invoke Sleep,100                                        
                                        mov esi,pNewImports
                                        assume esi:ptr IMAGE_IMPORT_DESCRIPTOR
                                        mov dlls_imported,0
                                        mov borland_flag,FALSE
                                        mov redirection_flag,FALSE
                                @loop:
                                        invoke SuspendThread,myThread 
                                        mov Context.ContextFlags,CONTEXT_FULL
                                        invoke GetThreadContext,myThread,addr Context 
                                        mov eax,Context.regEip 
                                        .if eax==BP1
                                                invoke wsprintf,addr OutBuff,CTEXT("在地址 %.08X 处断下 ",13,10,0),BP1 
                                                invoke OutputInfo,addr OutBuff,0  
                                                invoke WriteProcessMemory,myProcess,BP1,addr BP1_data,2,0
                                                mov eax,Context.regEdi 
                                                mov tempaddr,eax 
                                                invoke Searchcode,myProcess,eax,5751h
                                                add eax,3
                                                mov ebx,eax
                                                mov BP3,ebx
                                                invoke ReadProcessMemory,myProcess,BP3,addr BP3_data,2,0 
                                                invoke WriteProcessMemory,myProcess,ebx,CTEXT(0EBh,0FEh),2,0 
                                                add ebx,6
                                                mov BP4,ebx
                                                invoke ReadProcessMemory,myProcess,BP4,addr BP4_data,2,0
                                                invoke Searchcode,myProcess,tempaddr,4040h
                                                invoke Searchcode,myProcess,tempaddr,8902h
                                                add eax,1
                                                mov PatchAddr,eax
                                                invoke WriteProcessMemory,myProcess,eax,CTEXT(16h),1,0 
                                        .elseif eax==BP3
                                                invoke WriteProcessMemory,myProcess,BP3,addr BP3_data,2,0 
                                                invoke WriteProcessMemory,myProcess,BP4,CTEXT(0EBh,0FEh),2,0  
                                                mov eax,Context.regEcx
                                                sub eax,DllBase
                                                mov [esi].Name1,eax
                                                mov eax, Context.regEdi
                                                .if borland_flag!=TRUE                             
                                                        pushad
                                                        invoke  ReadProcessMemory,myProcess,Context.regEdi,addr Buffer,4,0             
                                                        .if Buffer!=0 
                                                                mov ebx,PatchAddr                                                                  
                                                                sub ebx,3                                                                          
                                                                    invoke WriteProcessMemory,myProcess,ebx,CTEXT(90h,90h,90h,90h),4,0       
                                                                 mov borland_flag,TRUE
                                                                       invoke OutputInfo,CTEXT("检测到Borland信息 - 注入代码2",13,10,0),0
                                                        .endif
                                                no_borland:
                                                        popad
                                                .endif
                                                sub eax,ImageBase
                                                mov [esi].FirstThunk,eax
                                                add esi,sizeof IMAGE_IMPORT_DESCRIPTOR
                                                inc dlls_imported
                                        .elseif eax==BP4
                                                invoke WriteProcessMemory,myProcess,BP4,addr BP4_data,2,0
                                                invoke WriteProcessMemory,myProcess,BP3,CTEXT(0EBh,0FEh),2,0 
                                        .elseif eax==BP2 
                                                invoke WriteProcessMemory,myProcess,BP2,addr BP2_data,2,0
                                                invoke wsprintf,addr OutBuff,CTEXT("在地址 %.08X 处断下 ",13,10,0),BP2 
                                                invoke OutputInfo,addr OutBuff,0  
                                                mov eax,Context.regEax
                                                invoke wsprintf,addr OutBuff,CTEXT("%s: %.08X",13,10,0),CTEXT(13,10,"发现OEP"),eax
                                                invoke OutputInfo,addr OutBuff,0
                                                invoke MessageBox,0,addr OutBuff,CTEXT("得到OEP"),MB_OK
                                                jmp @f
                                        .endif
                                        invoke ResumeThread,myThread 
                                                     invoke Sleep,8
                                                     jmp @loop
                                              @@:        
                                                     call FixIAT 
                                                     call NewPEinfo 
                                             .endif 
                                    .endif  
                      .endif
                      invoke ContinueDebugEvent,DBEvent.dwProcessId,DBEvent.dwThreadId,dwDebugOperation 
       .endw  
@@exit:      
        invoke CloseHandle,myProcess 
        invoke CloseHandle,ProcessInfo.hThread         
        ret

ProcessDll endp
2008-6-4 10:15
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
3
看情况,windows 把LOAD_DLL_DEBUG_EVENT事件传给调试器时,貌似此时被调试进程还没把dll加进自己的虚存空间。
2008-6-4 11:17
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
4
不调用ContinueDebugEvent,被调试的进程是不会运行的,即使你 ResumeThread 也是没用的

另外,我看你用 EB FE 作为断点。。。
这样调试器是收不到异常的
2008-6-4 11:28
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
5
所以我用了标志位,当DLL刚刚被LOAD_DLL_DEBUG_EVENT加载时,此时DLL还没有被加载到线程空间,再一次循环后才开始调试调试Dll的,这个可以用模块列表中看处:
上传的附件:
  • 1.gif (10.40kb,160次下载)
2008-6-4 11:55
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
6
我现在调试的不是主进程,挂起的也不是主线程,而是被调试进程的线程句柄,读取内存写内存用的都是被调试进程的线程句柄和进程句柄,这个进程中无论怎么设置断点(我也试了CC)永远不会产生EXCEPTION_DEBUG_EVENT,可以试试在这个线程上设置CC断点,直接ContinueDebugEvent,也是没有EXCEPTION_DEBUG_EVENT。
下面就是这个例子:
上传的附件:
2008-6-4 12:11
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
7
跟踪了OD原版,也基本上试这样做的,但是用了TEB枚举线程的方法获取DLL句柄, 但是GetThreadContext后一大堆的处理内容看不懂。
跟踪几个关键的函数:

00477958  |.  E8 73760300   call    <jmp.&KERNEL32.CreateProcessA>   ; \CreateProcessA
...
0047797F  |> \8B95 14E4FFFF mov     edx, dword ptr [ebp-1BEC]        ;  hProcess=000000D8
00477985  |.  8915 605A4D00 mov     dword ptr [4D5A60], edx
0047798B  |.  8B8D 18E4FFFF mov     ecx, dword ptr [ebp-1BE8]        ;  hThread=000000BC
00477991  |.  890D 645A4D00 mov     dword ptr [4D5A64], ecx
00477997  |.  C705 685A4D00>mov     dword ptr [4D5A68], 6            ;   mov     szhProcess, 6
004779A1  |.  C705 6C5A4D00>mov     dword ptr [4D5A6C], 6            ;   mov     subProcess, 6
004779AB  |.  8B85 1CE4FFFF mov     eax, dword ptr [ebp-1BE4]        ;  dwProcessId=00000838
004779B1  |.  A3 705A4D00   mov     dword ptr [4D5A70], eax
004779B6  |.  8B95 20E4FFFF mov     edx, dword ptr [ebp-1BE0]        ;  dwThreadId=000005E0

.text:00439616                 push    0               ; dwMilliseconds
.text:00439618                 push    offset DebugEvent ; lpDebugEvent ;  DebugEvent结构中得到 hThread==000000D4,hProcess==000000D0
.text:0043961D                 call    WaitForDebugEvent

004314E6 >|> \57            push    edi                              ; /ContinueStatus
004314E7  |.  A1 1C574D00   mov     eax, dword ptr [4D571C]          ; |
004314EC  |.  50            push    eax                              ; |ThreadId = 5E0
004314ED  |.  8B15 18574D00 mov     edx, dword ptr [4D5718]          ; |
004314F3  |.  52            push    edx                              ; |ProcessId => 838
004314F4  |.  E8 C5DA0700   call    <ContinueDebugEvent>             ; \ContinueDebugEvent

0042E4A6  |.  56            |push    esi                             ; /pContext
0042E4A7  |.  8B45 E8       |mov     eax, dword ptr [ebp-18]         ; |
0042E4AA  |.  8B50 0C       |mov     edx, dword ptr [eax+C]          ; |
0042E4AD  |.  52            |push    edx                             ; |hThread==000000D4
0042E4AE  |.  E8 0D0C0800   |call    <GetThreadContext>              ; \GetThreadContext

0046141D >|> \6A 00         push    0                                ; /pBytesRead = NULL
0046141F  |.  57            push    edi                              ; |BytesToRead
00461420  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]           ; |
00461423  |.  A1 685A4D00   mov     eax, dword ptr [4D5A68]          ; |
00461428  |.  51            push    ecx                              ; |Buffer
00461429  |.  56            push    esi                              ; |pBaseAddress
0046142A  |.  50            push    eax                              ; |hProcess => 000000D0 (window)
0046142B  |.  E8 3EDD0400   call    <ReadProcessMemory>              ; \ReadProcessMemory

00461814 >|> \6A 00         push    0                                ; /pBytesWritten = NULL
00461816  |.  A1 685A4D00   mov     eax, dword ptr [4D5A68]          ; |
0046181B  |.  8B55 10       mov     edx, dword ptr [ebp+10]          ; |
0046181E  |.  52            push    edx                              ; |BytesToWrite=1
0046181F  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]           ; |
00461822  |.  51            push    ecx                              ; |Buffer
00461823  |.  56            push    esi                              ; |Address
00461824  |.  50            push    eax                              ; |hProcess => 000000D0 (window)
00461825  |.  E8 F8D90400   call    <WriteProcessMemory>             ; \WriteProcessMemory

0046141D >|> \6A 00         push    0                                ; /pBytesRead = NULL
0046141F  |.  57            push    edi                              ; |BytesToRead
00461420  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]           ; |
00461423  |.  A1 685A4D00   mov     eax, dword ptr [4D5A68]          ; |
00461428  |.  51            push    ecx                              ; |Buffer
00461429  |.  56            push    esi                              ; |pBaseAddress
0046142A  |.  50            push    eax                              ; |hProcess => 000000D0
0046142B  |.  E8 3EDD0400   call    <ReadProcessMemory>              ; \ReadProcessMemory
2008-6-4 12:21
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
8
如果有DEBUG_PROCESS标志

ntdll在初始化的时候会调用一次ntdll.DbgBreakPoint
因此,调试器收到的第一个CC异常,其实是系统断点
2008-6-4 13:48
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
9
dll其实可以当作exe来调试,只需要做到可以在dll入口停下来就和exe一样了
2008-6-4 13:54
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
10
如果把DLL当中EXE直接拿来调试,CreateProcess创建不了调试环境。如果试静态脱壳机,也许没问题,但是想用调试器是不可能了,以前大多是用记录SEH的方法Hook KiUserExceptionDispatcher让其断下,然后用NtContinue继续,这样比较麻烦,没有调试API来的干脆。
2008-6-4 14:07
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
11
没说清楚,我的意思是:
dll和exe调试其实是一样的,用LoadDll.exe,需要做好的是,在LoadDll.exe 加载dll的时候,停在Dll的入口处,然后就可以像调试exe一样去调试dll了
2008-6-4 14:11
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
12
重新弄了下,把部分处理过程搬到EXCEPTION_DEBUG_EVENT中,但还是有问题:
创建线程的时候在loaddll中预留的位置下int 3断点产生异常:
loaddll中:
        mov hwnd,eax
        invoke ShowWindow,eax,SW_RESTORE
fisetbp:   
        nop                         ; 供调试器设置断点用,用OD查找该地址,设置CC断点产生异常
WINLOOP:    
        .if PROCADR==0
                jmp NoCall
        .endif
        mov ORIGESP,esp
        mov ORIGEBP,ebp

正好是窗口窗口创建以后,此时已经经过了LoadLibrary,loaddll以及引进目标dll的进程。od中查出这个地址是:004011B5,下面还有个int 3,执行后自动停止。OD最后在dll入口下了CC断点。

改调试器代码:
       	        .elseif DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT 
	                mov edx,DBEvent.u.CreateProcessInfo.hProcess
	                mov myProcess,edx
	                mov ecx,DBEvent.u.CreateProcessInfo.hThread
	                mov myThread,ecx  
	                mov BreakPoint1,004011B5h  ;loaddll中加载窗口后的地址
	                mov BreakPoint2,004012B6h  
	                invoke ReadProcessMemory,ProcessInfo.hProcess,BreakPoint1,addr oldbyte1,1,NULL
	                invoke WriteProcessMemory,ProcessInfo.hProcess,BreakPoint1,CTEXT(0CCh),1,NULL	
	                invoke ReadProcessMemory,ProcessInfo.hProcess,BreakPoint2,addr oldbyte2,1,NULL
	                invoke WriteProcessMemory,ProcessInfo.hProcess,BreakPoint2,CTEXT(0CCh),1,NULL	
;...
;...
       	        .elseif DBEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT 
       	       	       .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
       	       	               mov Context.ContextFlags, CONTEXT_FULL
       	       	               invoke GetThreadContext, ProcessInfo.hThread, addr Context
       	       	               mov eax,Context.regEip
       	       	               inc BreakPoint1
       	       	               .if eax == BreakPoint1
       	       	                       dec Context.regEip
       	       	                       invoke wsprintf,addr OutBuff,CTEXT("断在LoadDll的 %.08X 处",13,10,0),Context.regEip
                                       invoke OutputInfo,addr OutBuff,0
                                       invoke WriteProcessMemory,ProcessInfo.hThread,BreakPoint1,addr oldbyte1,1,NULL
       	       	                       invoke SetThreadContext,ProcessInfo.hThread, addr Context
       	       	                       //...  
       	       	                       inc BreakPoint1
       	       	               .elseif eax == BreakPoint2
       	       	                       dec Context.regEip
       	       	                       invoke wsprintf,addr OutBuff,CTEXT("断在LoadDll的 %.08X 处",13,10,0),Context.regEip
                                       invoke OutputInfo,addr OutBuff,0
                                       invoke WriteProcessMemory,ProcessInfo.hThread,BreakPoint2,addr oldbyte2,1,NULL 
       	       	                       invoke SetThreadContext,ProcessInfo.hThread, addr Context  
       	       	                       inc BreakPoint2
       	       	               .elseif eax==7C921231h
       	       	                       dec BreakPoint1
       	       	               .endif
       	       	       invoke ContinueDebugEvent,DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE 
       	       	       .continue
       	       	       .endif
       	        .endif   


loaddll中后面有个寄存器赋值操作,不知道怎么利用:
WINLOOP:    
        .if PROCADR==0
                jmp NoCall
        .endif
        mov ORIGESP,esp
        mov ORIGEBP,ebp
        push 0              
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        push 0
        mov ecx,NARG
        jecxz @@44
        .if ecx>0Ah
        	 invoke MessageBox,0,CTEXT("参数太多"),0,MB_OK
                 invoke ExitProcess,0
        .endif
        mov eax,offset ARGLIST
@@42:   
        push [eax]   
        add eax,4
        loop  @@42  
@@44:   
        mov [EXPESP],esp
        mov eax,[REGEAX]
        mov ecx,[REGECX]
        mov edx,[REGEDX]
        mov ebx,[REGEBX]
        mov esi,[REGESI]
        mov edi,[REGEDI]
Prepatch:    
        nop                  
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
CallDLL: 
        call [PROCADR] 
        nop                    
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        mov [REGEAX],eax
        mov [REGECX],ecx
        mov [REGEDX],edx
        mov [REGEBX],ebx
        mov [REGESI],esi
        mov [REGEDI],edi
        mov eax,esp
        sub eax,[EXPESP]
        mov [ESPDIFF],eax
        mov ebp,[ORIGEBP]
        mov esp,[ORIGESP]
        mov [PROCADR],0
        nop
Finished: 
        int 3                  
        nop
        
NoCall:   
        invoke Sleep,0 
        invoke PeekMessage,offset msg,0,0,0,PM_REMOVE
        .if eax==0
        	jmp WINLOOP
        .endif
2008-6-5 19:54
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
13
loaddll源码,作用:在DLL入口设置int 3, 再调用入口函数让调试器产生异常。同时把dll的一些基本信息传给调试器,这里记录了三个主要的参数,基址、入口、映像,当然也可以在调试器中获取这三个参数。
.686 
.model flat,stdcall 
option casemap:none 

include windows.inc
include kernel32.inc
include user32.inc
include gdi32.inc
include Comctl32.inc
include comdlg32.inc
include shell32.inc
include masm32.inc
include dbghelp.inc
include msvcrt.inc
include Libc.inc

includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib
includelib Comctl32.lib
includelib comdlg32.lib
includelib shell32.lib
includelib masm32.lib
includelib dbghelp.lib
includelib msvcrt.lib
includelib LIBC.LIB

LoadDll proto :dword	
ico 	        equ 2001

.data? 
hInstance	dd ?
oldbyte         dd ?
EP              dd ?
OutBuff         db 256 dup(?)
OldProtect    dd ?
DllBase         dd ?
SizeOfImage     dd ?
CTEXT macro Text:VARARG
	local szText
	.data
	 szText byte Text, 0
	.code
	exitm <offset szText>
endm
.code 

start: 
        invoke GetModuleHandle,0
        mov hInstance,eax
        invoke GetCommandLine
        mov esi,eax
        inc esi
        cmp al, 22h
        je @next
@@:
        .if al==0
                invoke MessageBox,0,CTEXT("Missing DLL name"),0,MB_OK
                invoke ExitProcess,0
        .endif
        mov al, byte ptr [esi+1]
        inc esi
        cmp al, 22h
        jnz @b
@next:
        mov al, byte ptr [esi+1]
        inc esi
        cmp al, 20h
        jnz @load
@@:
        mov al, byte ptr [esi+1]
        inc esi
        cmp al, 20h
        je @b
@load:
        invoke LoadLibraryEx,esi,NULL,DONT_RESOLVE_DLL_REFERENCES         
        .if eax==0
                invoke MessageBox,0,CTEXT("Unable to load DLL"),0,MB_OK
                invoke ExitProcess,0
        .endif
        mov DllBase,eax
        invoke ImageNtHeader,DllBase
        mov edi,eax
        assume edi:ptr IMAGE_NT_HEADERS
        mov eax,[edi].OptionalHeader.AddressOfEntryPoint
        add eax,DllBase
        mov EP,eax
        mov ecx,[edi].OptionalHeader.SizeOfImage
        mov SizeOfImage,ecx
        mov edi,DllBase   
        mov esi,EP
        movzx edx, byte ptr [esi]
        mov byte ptr [esi],0CCh
        call EP
        invoke	ExitProcess,NULL
        
end start 


主程序源码,当loaddll调用入口函数时产生EXCEPTION_BREAKPOINT异常,对比是否停在入口,由于考虑到dll的重定位,所以在loaddll使用LoadLibrary,这样会产生LOAD_DLL_DEBUG_EVENT事件,这时可以从DBEvent.u.LoadDll.lpBaseOfDll获取当前运行的基址,再从PEinfo中获取EP的RVA,这样可以确定所运行的DLL的EP:
ProcessDll proc
LOCAL Buffer [64]:byte
LOCAL EP,EP_data:dword
LOCAL hProcess:dword
LOCAL tempaddr:dword
LOCAL dlls_imported,PatchAddr:dword
LOCAL szContext[1024]:byte
LOCAL TEB,LDR:dword

        invoke GetTempPath, sizeof TempPath, addr TempPath
        invoke wsprintf,addr OutBuff,addr Format,addr loaddllPath,addr FilePath  
        invoke GetStartupInfo,addr startinfo
        invoke CreateProcess,NULL,addr OutBuff,NULL,NULL,FALSE,DEBUG_PROCESS+DEBUG_ONLY_THIS_PROCESS ,NULL,addr TempPath,addr startinfo,addr ProcessInfo
        .while TRUE       	
       	        invoke WaitForDebugEvent,addr DBEvent,INFINITE	      
       	        .if DBEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT            	      	     
       	      	        invoke OutputInfo,CTEXT("Exit Debug"),0       	      	     
       	      	        .break 
       	        .elseif DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT 
	                mov edx,DBEvent.u.CreateProcessInfo.hProcess
	                mov myProcess,edx
	                mov ecx,DBEvent.u.CreateProcessInfo.hThread
	                mov myThread,ecx  
                .elseif DBEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT
       	                mov eax,DBEvent.u.LoadDll.lpBaseOfDll
       	                mov dwModBase,eax 
       	                .if  dwModBase < 80000000h
       	      	                invoke ReadProcessMemory,myProcess,DBEvent.u.LoadDll.lpImageName,addr OutBuff,4,NULL
       	      	                mov eax,dword ptr OutBuff
       	      	                invoke ReadProcessMemory,myProcess,eax,addr pDllName,256,NULL
       	      	                invoke Unicode2Ansi,addr pDllName,addr outinf
       	      	                invoke lstrcmp,addr outinf,addr FilePath
       	      	                .if eax==0
       	      	                        invoke wsprintf,addr OutBuff,CTEXT("加载Dll成功: 句柄:%08Xh,基址:%08Xh,名称:%s",13,10,0),DBEvent.u.LoadDll.hFile,DBEvent.u.LoadDll.lpBaseOfDll,addr outinf
       	      	                        invoke OutputInfo,addr OutBuff,0
       	      	                        mov esi,DBEvent.u.LoadDll.lpBaseOfDll
       	      	                        mov DllBase,esi 
       	      	                        add esi,EntryPiont
       	      	                        mov firstbp,esi
       	      	                        mov eax,DBEvent.u.LoadDll.hFile
       	      	                        mov hDll,eax
       	      	                .endif	 
       	      	       .endif              
       	        .elseif DBEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT 
       	       	       .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
       	       	               mov Context.ContextFlags, CONTEXT_FULL
       	       	               invoke GetThreadContext, ProcessInfo.hThread, addr Context
       	       	               mov eax,Context.regEip
       	       	               mov ecx,firstbp
       	       	               inc ecx
       	       	               .if eax == ecx  
       	       	                       dec Context.regEip
       	       	                       invoke wsprintf,addr OutBuff,CTEXT("断在内存地址 %.08X 处 ",13,10,0),Context.regEip
                                       invoke OutputInfo,addr OutBuff,0                                        
                                       mov edi,Context.regEdi
                                       mov DllBase,edi                        
                                       mov eax,Context.regEax
                                       mov firstbp,eax
                                       mov ecx,Context.regEcx
                                       mov SizeOfImage,ecx
                                       mov edx,Context.regEdx
                                       mov oldbyte,edx
                                       invoke WriteProcessMemory,ProcessInfo.hProcess,Context.regEip,oldbyte,1,0 
                                       invoke wsprintf,addr OutBuff,CTEXT("EP: %.08X,基址: %.08X,映像大小: %.08X ",13,10,0),firstbp,DllBase,SizeOfImage
                                       invoke OutputInfo,addr OutBuff,0  
                                       invoke MessageBox,0,addr OutBuff,CTEXT("dll信息"),MB_OK
                                       invoke TerminateProcess,myProcess,0
       	       	               .endif
       	       	               invoke ContinueDebugEvent,DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE 
       	       	               .continue          	       	          	       
       	       	       .endif
       	        .endif
       	        invoke ContinueDebugEvent,DBEvent.dwProcessId,DBEvent.dwThreadId,DBG_CONTINUE 
        .endw  
@@exit:      
        invoke CloseHandle,myProcess 
        invoke CloseHandle,ProcessInfo.hThread         
	ret

ProcessDll endp


另外,是不是装了卡巴和瑞星对LoadLibrary都有影响,好像返回不了宿主程序?
上传的附件:
2008-6-8 12:56
0
游客
登录 | 注册 方可回帖
返回
//