能力值:
( 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
|
能力值:
( 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
|
能力值:
( 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
|
能力值:
( 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都有影响,好像返回不了宿主程序?
|