:D [转贴]挫败反跟踪(一) :D
不久就要进入总复习阶段,如果我不幸没能保送入高中,可能有一段时间不能来论坛了。这里利用我倒数第二个休息日介绍一些常见反跟踪技术,望能避免一些新出道的 Cracker 作重复劳动,高手就不要在此费神了。我的文笔不是很好,还望诸位看官海涵。
一、TEB/TIB
TEB(Thread Environment Block) 在 Windows 9x 系列中被称为 TIB(Thread Information Block),它记录了线程的重要信息,且每一个线程皆对应一个 TEB 结构。 Matt Pietrek 已列出了它的结构(摘自 Matt Pietrek 的 Under The Hood - MSJ 1996):
//===========================================================
// file: TIB.H
// Author: Matt Pietrek
// From: Microsoft Systems Journal "Under the Hood", May 1996
//===========================================================
#pragma pack(1)
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct _EXCEPTION_REGISTRATION_RECORD * pNext;
FARPROC pfnHandler;
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
typedef struct _TIB
{
PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list
PVOID pvStackUserTop; // 04h Top of user stack
PVOID pvStackUserBase; // 08h Base of user stack
union // 0Ch (NT/Win95 differences)
{
struct // Win95 fields
{
WORD pvTDB; // 0Ch TDB
WORD pvThunkSS; // 0Eh SS selector used for thunking to 16 bits
DWORD unknown1; // 10h
} WIN95;
struct // WinNT fields
{
PVOID SubSystemTib; // 0Ch
ULONG FiberData; // 10h
} WINNT;
} TIB_UNION1;
PVOID pvArbitrary; // 14h Available for application use
struct _tib *ptibSelf; // 18h Linear address of TIB structure
union // 1Ch (NT/Win95 differences)
{
struct // Win95 fields
{
WORD TIBFlags; // 1Ch
WORD Win16MutexCount; // 1Eh
DWORD DebugContext; // 20h
DWORD pCurrentPriority; // 24h
DWORD pvQueue; // 28h Message Queue selector
} WIN95;
struct // WinNT fields
{
DWORD unknown1; // 1Ch
DWORD processID; // 20h
DWORD threadID; // 24h
DWORD unknown2; // 28h
} WINNT;
} TIB_UNION2;
PVOID* pvTLSArray; // 2Ch Thread Local Storage array
union // 30h (NT/Win95 differences)
{
struct // Win95 fields
{
PVOID* pProcess; // 30h Pointer to owning process database
} WIN95;
} TIB_UNION3;
} TIB, *PTIB;
#pragma pack()
结构很复杂,但多数与我们无关,我们只关心这些:
DWORD DebugContext; // 20h
PVOID* pProcess; // 30h Pointer to owning process database
曾经看过 ProcDump 代码的人一定记得 DebugContext ,ProDump 就是通过将其置零隐藏自身的。
而 pProcess “拥有者”,当用用户模式调试器如 OllyDbg 调试程序时,调试器会将程序作为一个子线程进行跟踪,在这种情况下,被调试程序的“拥有者”就是调试器,也就是说,其 TEB 的 30h 偏移所指内容定不为 0 ,程序利用这一点,判断 30h 偏移指向的内容,来判断是否有调试器跟踪。若看过 IsDebuggerPresent 函数的代码,会发现它也是利用 pProcess 工作的:
mov eax, fs:[18]; 取 TEB 结构线性偏移地址
mov eax, dword ptr [eax+30h]; 取 pProcess 中的值
movzx eax, byte ptr [eax+2h]
ret
调试时遇到任何访问 FS 段 20h / 30h 偏移地址的代码就要小心了,他们十有八九是要检测调试器的,不想被发现的话将其所用寄存器的值置零或者在其判断语句之后反转 ZF 标志位吧。
二、SEH
Asprotect / tElock 等流行保护程序无一例外使用了 SEH ,关于 SEH ,我不想对它扫盲,如果不了解,请参阅 Hume 的 SEH 教程。
SEH 不但可以改变流程干扰跟踪,还可以通过修改 Context 来做一些“不良勾当”。这里是 Context 结构定义:
CONTEXT STRUC
cx_ContextFlags DD ?
;CONTEXT_DEBUG_REGISTERS
cx_Dr0 DD ? ;04
cx_Dr1 DD ? ;08
cx_Dr2 DD ? ;0C
cx_Dr3 DD ? ;10
cx_Dr6 DD ? ;14
cx_Dr7 DD ? ;18
;CONTEXT_FLOATING_POINT
cx_ControlWord DD ?
cx_StatusWord DD ?
cx_TagWord DD ?
cx_ErrorOffset DD ?
cx_ErrorSelector DD ?
cx_DataOffset DD ?
cx_DataSelector DD ?
SIZE_OF_80387_REGISTERS EQU 80
cx_RegisterArea DB SIZE_OF_80387_REGISTERS DUP (?)
cx_Cr0NpxState DD ?
;CONTEXT_SEGMENTS
cx_SegGs DD ? ;8C
cx_SegFs DD ? ;90
cx_SegEs DD ? ;94
cx_SegDs DD ? ;98
;CONTEXT_INTEGER
cx_Edi DD ? ;9C
cx_Esi DD ? ;A0
cx_Ebx DD ? ;A4
cx_Edx DD ? ;A8
cx_Ecx DD ? ;AC
cx_Eax DD ? ;B0
;CONTEXT_CONTROL
cx_Ebp DD ? ;B4
cx_Eip DD ? ;B8
cx_SegCs DD ? ;BC
cx_EFlags DD ? ;C0
cx_Esp DD ? ;C4
cx_SegSs DD ? ;C8
_CONTEXT ENDS
;size of CONTEXT is 0CCH bytes
对我们有帮助的是:
cx_Dr0 DD ? ;04
cx_Dr1 DD ? ;08
cx_Dr2 DD ? ;0C
cx_Dr3 DD ? ;10
cx_Dr6 DD ? ;14
cx_Dr7 DD ? ;18
cx_Eip DD ? ;B8
Dr0、Dr1、Dr2、Dr3 是调试断点寄存器,而 Dr6、Dr7 是调试控制寄存器,一般的 SEH Handler 会将 Dr0~6 清零,将 Dr7 置 155h 使之前所下断点失效,这种情形在壳中极为常见,关于细节,请参阅有关调试寄存器的文献资料,中英文都有。
Eip 不必多说,如果 SEH Handler 修改了此值,系统就会从其开始继续执行程序,如果直接在其设断会节省很多时间,而盲目在系统中不断返回常常会迷失在系统中,因此――
调试中如果获知指向 Context 的寄存器,那么它的 04h/08h/0Ch/10h/14h/18h 偏移将访问调试寄存器,用尽手段恢复它们吧。
对于利用 SEH Handler 修改流程的程序,见到写入 Context 之 0B8h 偏移的代码,不要犹豫在那里下断,可以省去很多时间进行进一步跟踪。
SEH Hanlder 还有一些特殊的用法,例如:
SehHandler:
xor eax, eax
mov esp, fs:[eax]; 恢复堆栈
pop fs:[eax]; 恢复旧的 SEH Hanlder
jmp somewhere
这种情况将不通过系统而直接继续执行代码。另外 Windows 9x 系列中还可以通过 SEH 技巧夺取 RIng 0 权限直接操作 DrX 寄存器,可以参考 ljtt 《怎样利用SEH技巧进入Ring0级》一文。
(作者linson,未完待续 ):)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!