安全中国首页 > 文章中心 > 工具技巧
 
安全中国网友投稿专用上传FTP空间:
Ftp服务器:download.anqn.com
Ftp端口:21
用户名:anqn
密 码:anqn.com
 

第三卷 OllyDBG 改造系列 第六篇 打造处理 OutputDebugString("%s")的OD

更新时间:2008-9-29 0:59:14
责任编辑:流火
热 点:
作者:simonzh2000

最近好多壳利用 OutputDebugString 函数来对付 OD, 当然处理方法也比较简单, 更有大侠出了修改版 OD.

不过我这个人比较喜欢寻根究底, 想看看 OD 的毛病出在哪里.

1. 基础知识 from MSDN

下面是调试器和被调试进程之间的关系, 调试器用 CreateProcess 创建被调试进程.

被调试进程运行中会遇到 9 种需要向调试器汇报的事件, 调试器处理好后, 被调试进程才能继续.

平时我们最关心 Exception, 今天我们的主角是 DebugString.

EXCEPTION_DEBUG_EVENT equ 1

CREATE_THREAD_DEBUG_EVENT equ 2

CREATE_PROCESS_DEBUG_EVENT equ 3

EXIT_THREAD_DEBUG_EVENT equ 4

EXIT_PROCESS_DEBUG_EVENT equ 5

LOAD_DLL_DEBUG_EVENT equ 6

UNLOAD_DLL_DEBUG_EVENT equ 7

OUTPUT_DEBUG_STRING_EVENT equ 8

RIP_EVENT equ 9

while(WaitForDebugEvent(&DBEvent, INFINITE)) 



if (DBEvent.dwDebugEventCodeEXCEPTION_DEBUG_EVENT) 

{

// 子进程遇到一个异常



else if (DBEvent.dwDebugEventCodeOUTPUT_DEBUG_STRING_EVENT)

{

// 子进程执行了 OutputDebugString 函数

}

.... // 共有 9 种情形

ContinueDebugEvent(DBEvent.dwProcessId, DBEvent.dwThreadId, dwContinueStatus);

}

typedef struct _DEBUG_EVENT { // de 

DWORD dwDebugEventCode; 

DWORD dwProcessId; 

DWORD dwThreadId; 

union { 

EXCEPTION_DEBUG_INFO Exception; 

CREATE_THREAD_DEBUG_INFO CreateThread; 

CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; 

EXIT_THREAD_DEBUG_INFO ExitThread; 

EXIT_PROCESS_DEBUG_INFO ExitProcess; 

LOAD_DLL_DEBUG_INFO LoadDll; 

UNLOAD_DLL_DEBUG_INFO UnloadDll; 

OUTPUT_DEBUG_STRING_INFO DebugString; 

RIP_INFO RipInfo; 

} u; 

} DEBUG_EVENT; 

typedef struct _OUTPUT_DEBUG_STRING_INFO { // odsi 

LPSTR lpDebugStringData; 

WORD fUnicode; 

WORD nDebugStringLength; 

} OUTPUT_DEBUG_STRING_INFO;

int vsprintf( char *buffer, const char *format, va_list argptr ); 这个是错误的根源

2. 测试用的程序 

// TEST1.EXE 

.386

.model flat, stdcall

option casemap:none

include c:/masm32/include/kernel32.inc

include c:/masm32/include/user32.inc

includelib c:/masm32/lib/kernel32.lib

includelib c:/masm32/lib/user32.lib

include c:/masm32/include/windows.inc

.const

szOutput db "%s",0

szMessage db "The program is fine", 0

szTitle db "Test",0

szFormat db "%s",0

.data?

szBuffer db 20 dup (?)

;------------ CODE ----------

.code

main:

invoke wsprintf, offset szBuffer, offset szFormat, offset szMessage 

invoke OutputDebugString, offset szOutput

invoke MessageBox, 0, offset szBuffer, offset szTitle, MB_OK

invoke ExitProcess,0

end main

// End 

用 OD 调试 test1.exe, 执行完 OutputDebugString, OD 左下角出现了 "Debug string: "

// Test2.EXE 

其余不变, 只变一句 

szOutput db "%s%s",0

用 OD 调试 test2.exe, 执行 OutputDebugString, OD 在 4a74cf 出现访问 [00000260]异常

// Test3.EXE 

其余不变, 只变一句 

szOutput db "%s%s%s",0

用 OD 调试 test2.exe, 执行 OutputDebugString, OD 在 4a74cf 出现访问 [00000001]异常

为什么 Test1 没问题, Test2, Test3 有问题? Test2 和 Test3 有区别吗? Let\’s go

3. 我们来看看 OD 是如何处理的

将 Ollydbg.exe 拷贝到 CMD.EXe, 运行 CMD.exe, 菜单 File - Open - Ollydbg.EXE , 

这样 CMD.exe 是调试器, Ollydbg.exe 就是被调试的程序, 别搞错了. 

找 WaitForDebugEvent, 比较容易找到处理 DebugString 的地方, CMD 下断 431276.

F9 运行 Ollydbg.exe, 再用 Ollydbg.exe 打开 TEST3.EXE, F9 运行, CMD 断下, F7 跟进

00439616 > /6A 00 PUSH 0 ; /Timeout 0. ms

00439618 . 68 14574D00 PUSH OLLYDBG.004D5714 ; |pDebugEvent OLLYDBG.004D5714

0043961D . E8 E85B0700 CALL <JMP.&KERNEL32.WaitForDebugEvent> ; /WaitForDebugEvent

00439622 . 85C0 TEST EAX,EAX

00439624 . 75 44 JNZ SHORT OLLYDBG.0043966A

...

0043977D . 51 PUSH ECX ; /Arg1

0043977E . E8 4D54FFFF CALL OLLYDBG.0042EBD0 ; /OLLYDBG.0042EBD0, F7 跟进

0042EBD0 /$Content$nbsp;55 PUSH EBP

0042EBD1 |. 8BEC MOV EBP,ESP

0042EBD3 |. 81C4 04F0FFFF ADD ESP,-0FFC

0042EBD9 |. 50 PUSH EAX

0042EBDA |. 81C4 00F5FFFF ADD ESP,-0B00

0042EBE0 |. 53 PUSH EBX

0042EBE1 |. 56 PUSH ESI

0042EBE2 |. 57 PUSH EDI

0042EBE3 |. 8B35 1C574D00 MOV ESI,DWORD PTR DS:[4D571C] ; dwThreadID

0042EBE9 |. 56 PUSH ESI

0042EBEA |. E8 5DF8FFFF CALL OLLYDBG.0042E44C

0042EBEF |. 8BF8 MOV EDI,EAX

0042EBF1 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]

0042EBF4 |. 59 POP ECX

0042EBF5 |. 8938 MOV DWORD PTR DS:[EAX],EDI

0042EBF7 |. 8B15 14574D00 MOV EDX,DWORD PTR DS:[4D5714] ; pDebugEvent

0042EBFD |. 83FA 09 CMP EDX,9 ; Switch (cases 1..9) 被调试进程遇到的9种情况

0042EC00 |. 0F87 EE270000 JA OLLYDBG.004313F4

0042EC06 |. FF2495 0DEC42>JMP DWORD PTR DS:[EDX*4+42EC0D]

0042EC0D |. F4134300 DD OLLYDBG.004313F4 ; Switch table used at 0042EC06

0042EC11 |. 35EC4200 DD OLLYDBG.0042EC35

0042EC15 |. FF0C4300 DD OLLYDBG.00430CFF

0042EC19 |. D70D4300 DD OLLYDBG.00430DD7

0042EC1D |. 3F0F4300 DD OLLYDBG.00430F3F

0042EC21 |. 37104300 DD OLLYDBG.00431037

0042EC25 |. 2D114300 DD OLLYDBG.0043112D

0042EC29 |. B7114300 DD OLLYDBG.004311B7

0042EC2D |. 76124300 DD OLLYDBG.00431276 ; OUTPUT_DEBUG_STRING_EVENT 在 431276 处理

0042EC31 |. C7134300 DD OLLYDBG.004313C7

00431276 |> /830D 74574D00>OR DWORD PTR DS:[4D5774],4 ; Case 8 of switch 0042EBFD

0043127D |. 68 0A674B00 PUSH OLLYDBG.004B670A ; /Arg2 004B670A ASCII "Debug string: "

00431282 |. 8D95 98FDFFFF LEA EDX,DWORD PTR SS:[EBP-268] ; |

00431288 |. 52 PUSH EDX ; |Arg1 12F340

00431289 |. E8 9E590700 CALL OLLYDBG.004A6C2C ; /int sprintf(char *buffer,const char *format,...)

0043128E |. 83C4 08 ADD ESP,8

00431291 |. 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX ; "Debug string: " 的长度

00431294 |. 0FB71D 26574D>MOVZX EBX,WORD PTR DS:[4D5726] ; debug_string 的长度

0043129B |. 85DB TEST EBX,EBX

0043129D |. 7D 0A JGE SHORT OLLYDBG.004312A9

0043129F |. B8 01000000 MOV EAX,1

004312A4 |. E9 7C010000 JMP OLLYDBG.00431425

004312A9 |> 66:833D 24574>CMP WORD PTR DS:[4D5724],0 ; 是否 unicode ? 

004312B1 |. 74 6B JE SHORT OLLYDBG.0043131E ; 由于我们使用了 OutputDebugStringA, 不是 unicode 

0043131E |> BA 00010000 MOV EDX,100 ; 包括 "Debug string: " 最长 100h 长度

00431323 |. 2B55 F4 SUB EDX,DWORD PTR SS:[EBP-C]

00431326 |. 4A DEC EDX

00431327 |. 3BDA CMP EBX,EDX

00431329 |. 7E 09 JLE SHORT OLLYDBG.00431334

0043132B |. BB 00010000 MOV EBX,100

00431330 |. 2B5D F4 SUB EBX,DWORD PTR SS:[EBP-C]

00431333 |. 4B DEC EBX

00431334 |> 6A 03 PUSH 3 ; /Arg4 00000003

00431336 |. 53 PUSH EBX ; |Arg3 长度

00431337 |. A1 20574D00 MOV EAX,DWORD PTR DS:[4D5720] ; |

0043133C |. 50 PUSH EAX ; |Arg2 > 00402018 debug_string 在被调试进程中的地址

0043133D |. 8D95 98FDFFFF LEA EDX,DWORD PTR SS:[EBP-268] ; |

00431343 |. 0355 F4 ADD EDX,DWORD PTR SS:[EBP-C] ; |

00431346 |. 52 PUSH EDX ; |Arg1 0012F34E, Buffer, 紧接"Debug string: "

00431347 |. E8 C0FF0200 CALL OLLYDBG._Readmemory ; /_Readmemory( 调用 ReadProcessMemory )

1 2 下一页

 
相关文章
一日一文章
 
一日一软件
一日一动画