📄 01 intro.txt
字号:
ExceptionCode是Windows NT的异常代号。异常在NTSTATUS.H文件中被描述为STATUX_xxxxxx: ExceptionAddres - 发生异常的地址。
第三个参数是指向CONTEXT结构体的指针。
typedef struct _CONTEXT
{
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
:.
DWORD Esp;
DWORD SegSs;
} CONTEXT;
这个结构体定义于WINNT.H文件。其意义是不言而喻的,这里就不全写了。函数返回下面枚举类型值中的一个:
typedef enum _EXCEPTION_DISPOSITION {
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
ExceptionFlags定义了下面的位标志:
#define EH_NONCONTINUABLE 1
#define EH_UNWINDING 2
#define EH_EXIT_UNWIND 4
#define EH_STACK_INVALID 8
#define EH_NESTED_CALL 0x10
在发生异常时,控制传递到ntoskrnl.exe中相应的处理程序。例如,如果试图下面这段代码:
mov eax,80100000h
mov dword ptr [eax],0
这会引发异常0e,控制传递向处理程序KiTrap0E,堆栈中错误号为07(试图在用户模式下向内核写入。该页位于内存中,因为线性地址80100000h是内核加载的起始地址)。之后,控制传递到ntdll.dll,在这里解析线程的TEB并顺次执行链表中所有的处理程序,直到某个函数的返回代号不是ExceptionContinueSearch。在此之后,再次调用链表中的所有处理函数,直到找到某个函数,但这次用的是另外一个代号ExceptionCode(STATUS_UNWIND)并在ExceptionFlags设置位EH_UNWINDINGS。这个标志用于异常处理,进行堆栈的清除和其它必要的工作。如果没有一个处理程序能处理,则就来到链表中最后一个处理程序,由Win32子系统建立的处理程序。这个处理程序是如何被建立的以及建立在哪里在以后研究CreateProcessW函数时会讲到。关于异常处理的完整介绍可以从MSDN获得,因为在反汇编源代码中所得到的是扩大化了的异常处理机制(更高层次的机制)。
04. 进程控制域(PROCESSOR CONTROL REGION)
===========================================================
当线程在内核模式下执行时,在FS寄存器中加载的是选择子30,用于寻址PCR结构体(基址0xFFDFF000,界限0x00001FFF)。在NTDDK.H中远没有描述结构体所有的成员,只是其中不多的部分。为了说明PCR中的成分信息,这里列出用于i386的结构体(Windows NT 4.0)
typedef struct _KPCR { // Size: 0xB10
/*000*/ NT_TIB NtTib;
/*01C*/ struct _KPCR* SelfPcr;
/*020*/ struct _KPRCB* Prcb; // Current PCB
/*024*/ KIRQL Irql; // Current IRQL
/*028*/ ULONG IRR;
/*02C*/ ULONG IrrActive;
/*030*/ ULONG IDR;
/*034*/ ULONG Reserved2;
/*038*/ struct _KIDTENTRY* ULONG IDT;
/*03C*/ struct _KGDTENTRY* GDT;
/*040*/ struct _KTSS* TSS;
/*044*/ USHORT MajorVersion; // 1
/*046*/ USHORT MinorVersion; // 1
/*048*/ KAFFINITY SetMember;
/*04C*/ ULONG StallScaleFactor;
/*050*/ UCHAR DebugActive;
/*051*/ UCHAR Number;
// End of official portion of KPCR
/*052*/ BOOLEAN VdmAlert;
/*053*/ UCHAR Reserved;
/*054*/ UCHAR KernelReserved[0x90-0x54];
/*090*/ ULONG SecondLevelCacheSize;
/*094*/ UCHAR HalReserved[0xD4-0x94];
/*0D4*/ ULONG InterruptMode;
/*0D8*/ ULONG Spare1;
/*0DC*/ UCHAR KernelReserved2[0x120-0xDC];
// Note that current thread is at offset 0x124 (pointer to KTHREAD)
// This essentially means that the 1st PRCB must match the active CPU
/*120*/ UCHAR PrcbData[0xB10-0x120]; // PCBs for all CPUs supported
} KPCR, *PKPCR;
PCR包含着指向PCRB(Processor Control Region)的指针,但实际上,PCRB位于PCR的偏移0x120处,并且所有的向PCRB域的转换都是相对于PCR的起点的。在WINNT.H中描述了PCRB结构体。这里给出整个结构体(Windows NT 4.0):
// 0x120 from KPCR
typedef struct _KPRCB {
/*000*/ USHORT MinorVersion;
/*002*/ USHORT MajorVersion;
/*004*/ struct _KTHREAD *CurrentThread;
/*008*/ struct _KTHREAD *NextThread;
/*00c*/ struct _KTHREAD *IdleThread;
/*010*/ CCHAR Number;
/*011*/ CCHAR Reserved;
/*012*/ USHORT BuildType;
/*014*/ KAFFINITY SetMember;
/*015*/ struct _RESTART_BLOCK *RestartBlock;
/*018*/ CCHAR CpuType;
/*019*/ CCHAR CpuID;
/*01A*/ CCHAR CpuStep;
/*01C*/ KPROCESSOR_STATE ProcessorState;
/*13C*/ CCHAR KernelReserved[0x40];
/*17C*/ CCHAR HalReserved[0x40];
/*1BC*/ ULONG NpxThread;
/*1C0*/ ULONG InterruptCount;
/*1C4*/ ULONG KernelTime;
/*1C8*/ ULONG UserTime;
/*1CC*/ ULONG DpcTime;
/*1D0*/ ULONG InterruptTime;
/*1D4*/ ULONG ApcBypassCount;
/*1D8*/ ULONG DpcBypassCount;
/*1DC*/ ULONG AdjustDpcThreshold;
/*1E0*/ UCHAR Spare2[0x14];
/*1F4*/ ULONG64 ThreadStartCount;
/*1FC*/ SINGLE_LIST_ENTRY FsRtlFreeSharedLockList;
/*200*/ SINGLE_LIST_ENTRY FsRtlFreeExclusiveLockList;
/*204*/ ULONG CcFastReadNoWait;
/*208*/ ULONG CcFastReadWait;
/*20C*/ ULONG CcFastReadNotPossible;
/*210*/ ULONG CcCopyReadNoWait;
/*214*/ ULONG CcCopyReadWait;
/*218*/ ULONG CcCopyReadNoWaitMiss;
/*21C*/ ULONG KeAlignmentFixupCount;
/*220*/ ULONG KeContextSwitches;
/*224*/ ULONG KeDcacheFlushCount;
/*228*/ ULONG KeExceptionDispatchCount;
/*22C*/ ULONG KeFirstLevelTbFills;
/*230*/ ULONG KeFloatingEmulationCount;
/*234*/ ULONG KeIcacheFlushCount;
/*238*/ ULONG KeSecondLevelTbFills;
/*23C*/ ULONG KeSystemCalls;
/*240*/ SINGLE_LIST_ENTRY FsRtlFreeWaitingLockList;
/*244*/ SINGLE_LIST_ENTRY FsRtlFreeLockTreeNodeList
/*248*/ CCHAR ReservedCounter[0x18];
/*260*/ PVOID SmallIrpFreeEntry;
/*264*/ PVOID LargeIrpFreeEntry;
/*268*/ PVOID MdlFreeEntry
/*26C*/ PVOID CreateInfoFreeEntry;
/*270*/ PVOID NameBufferFreeEntry
/*274*/ PVOID SharedCacheMapEntry
/*278*/ CCHAR CachePad0[8];
/*280*/ CCHAR ReservedPad[0x200];
/*480*/ CCHAR CurrentPacket[0xc];
/*48C*/ ULONG TargetSet;
/*490*/ PVOID WorkerRoutine;
/*494*/ ULONG IpiFrozen;
/*498*/ CCHAR CachePad1[0x8];
/*4A0*/ ULONG RequestSummary;
/*4A4*/ ULONG SignalDone;
/*4A8*/ ULONG ReverseStall;
/*4AC*/ ULONG IpiFrame;
/*4B0*/ CCHAR CachePad2[0x10];
/*4C0*/ ULONG DpcInterruptRequested;
/*4C4*/ CCHAR CachePad3 [0xc];
/*4D0*/ ULONG MaximumDpcQueueDepth;
/*4D4*/ ULONG MinimumDpcRate;
/*4D8*/ CCHAR CachePad4[0x8];
/*4E0*/ LIST_ENTRY DpcListHead;
/*4E8*/ ULONG DpcQueueDepth;
/*4EC*/ ULONG DpcRoutineActive;
/*4F0*/ ULONG DpcCount;
/*4F4*/ ULONG DpcLastCount;
/*4F8*/ ULONG DpcRequestRate;
/*4FC*/ CCHAR KernelReserved2[0x2c];
/*528*/ ULONG DpcLock;
/*52C*/ CCHAR SkipTick;
/*52D*/ CCHAR VendorString[0xf];
/*53C*/ ULONG MHz;
/*540*/ ULONG64 FeatureBits;
/*548*/ ULONG64 UpdateSignature;
/*550*/ ULONG QuantumEnd;
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
PCRB中最有用的就是指向当前线程的指针(KTHREAD结构体)。通常内核代码以以下代码取得此指针:
MOV REG, FS:[124h].
---------------------------------------------------------------------------
(c)Gloomy aka Peter Kosyh, Melancholy Coding'2001
http://gloomy.cjb.net
mailto:gl00my@mail.ru
董岩 译
http://greatdong.blog.edu.cn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -