通行证: 用户 密码 域名空间  下载中心 社区论坛 信息公告 MY小屋
联系我们
设为首页
加入收藏

 

QQ,ASP,PHP,JSP,XML,SQL,.Net,编程 程序 网页图象 建站经验 私服
首页 | 新闻资讯 | 编程开发 | 网页设计 | 图形图象 | 网络媒体 | 网站模板 | 数 据 库 | 投稿
论坛 | 操作系统 | 系统优化 | 网络安全 | 黑客技术 | 硬件学堂 | 硬件报价 | 服 务 器 | 地图
专题 | 应用软件 | 聊天通讯 | Q Q 专栏 | 建站经验 | 在线工具 | 站长Club | 注 册 表 | 旧版
社会 | 游戏娱乐 | 设计欣赏 | 疑难解答 | 社区论坛 | 韩国素材 | 素材图库 | 广告服务 | 服务
当前位置:首页>>编程开发>>VC编程>>正文 新版上线![旧版]
注:打开慢时请稍等

Windows NT/2000内部数据结构探究

http://www.iyit.net  日期:2006-5-23 11:35:54  来源:本站整理转载   点击:
参加讨论Windows NT/2000内部数据结构探究
WebCrazy(tsu00@263.net)
注:本文最初见于www.nsfocus.com

WINDOWS系统隐含了不少内部数据结构,其记录着与系统相关的所有重要信息如线程、进程、内核调用等等,具体如Windows NT/2000模块ntoskrnl.exe中的NtBuildNumber与KeServiceDescriptorTable等(用SoftICE或Visual Studio所带的Dependency Walker之类的可以看到),前者只是指出当前Windows的Build号(如SoftICE下可用dw命令查出我的机器中为0893h 即十进制2195);后者是指向如下数据结构的指针:
struct _ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
}ServiceDescriptorTableEntry

其典型应用为Mark Russinovich与Bryce Cogswell的Regmon,具体可以参阅www.sysinternals.com.
本文仅在Intel i386的Windows 2000 Server(Build 2195)中对TEB(Thread Environment Block)作初步介绍.
TEB在Windows 9x系列中称为TIB(Thread Information Block),她纪录着线程的重要信息,每一个线程对应一个TEB结构。其格式如下(摘自Matt Pietrek的Under the Hood专栏-MSJ 1996):
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;

   在Windows 2000 DDK中定义为:
typedef struct _NT_TIB
{
struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
PVOID StackBase;
PVOID StackLimit;
PVOID SubSystemTib;
union {
PVOID FiberData;
ULONG Version;
};
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self;
} NT_TIB;

庆幸的是,Windows在调入进程,创建线程时,操作系统均会为每个线程分配TEB,而且都将FS段选择器(i386)指向当前线程的TEB数据(单CPU机器在任何时刻系统中只有一条线程在执行),这就为我们提供了存取TEB数据的途径。实际上Windows都是通过这种方法来为你的应用程序提供信息的,让我们来看一个例子吧!大家都知道用GetCurrentThreadID API来获得当前线程ID的,其在Kernel32.dll是如下实现的:

GetCurrentThreadID:
mov eax, FS:[00000018] ; 18h Linear address of TIB structure(TIB结构线性地址)
mov eax, [eax+24] ; 24h ThreadID
ret ; 将EAX中的值返回给调用者

由于TEB结构过于庞大,我现在只来谈谈偏移量为00h的struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList,并结合CIH 1.3源码来说说它具体用处。ExceptionList主要用于处理SEH(Structured Exception Handling)的。如果你连C语言中新增的_try,_except与_finally也不熟悉的话,建议请先看看Jeffery Richter的<<Advanced Windows NT>>或之类的。

   首先让我们来看看_EXCEPTION_REGISTRATION_RECORD结构,在CRT(C++ RunTime library)源码中它如下定义:

// Exsup.INC ---Microsoft Visual C++ CRT 源文件

_EXCEPTION_REGISTRATION struc
prev dd ?
handler dd ?
_EXCEPTION_REGISTRATION ends

其中prev是指向前一_EXCEPTION_REGISTRATION的指针,形成一链状结构,这样才会在EXCPT.H中有EXCEPTION_CONTINUE_SEARCH这样的定义(参阅&t;<Advanced Windows NT>>);handler指向异常处理代码。

CIH正是利用了这一机制,将handler指向它自己程序中。在它入口处有如下代码:

.
.
.

; *********************************************************
; * Ring3 Virus Game Initial Program *
; *********************************************************

MyVirusStart: ; Ring3代码入口点
push ebp

; *************************************
; * Let's Modify Structured Exception *
; * Handing, Prevent Exception Error *
; * Occurrence, Especially in NT. *
; *************************************

lea eax, [esp-04h*2] ;在栈中分配8字节存放_EXCEPTION_REGISTRATION结构
                     ;相当于C中基于栈的数据,即局部变量(C编译器中完成)
;这样EAX即指向_EXCEPTION_REGISTRATION的指针,但此时
                      ;_EXCEPTION_REGISTRATION结构未初始化
;具体实现机制可翻阅编译原理书籍和Matt Pietrek大师文章


xor ebx, ebx ;0->EBX
xchg eax, fs:[ebx] ;FS:[0]<->EAX ;此时EAX存放的是原来异常处理代码,FS:[0]指向TEB中
                    ;ExceptionList(FS指向TEB,ExceptionList偏移为0,即FS:[0])

call @0
@0:
pop ebx ;此三行计算代码入口,此时ebx就是@0的地址
lea ecx, StopToRunVirusCode-@0[ebx] ;将ecx指向自己内部代码处
push ecx ;填充_EXCEPTION_REGISTRATION结构的handler
                     ;在发生异常时,操作系统会自动调用,此时为CIH代码

push eax ;EAX为原来异常处理代码
;填充_EXCEPTION_REGISTRATION结构的prev

.
.
.

这其后CIH调用int 3使系统发生异常,仍能进入自已的代码,这可从CIH源代码中的如下注释得到证实:

; *************************************
; * Generate Exception to Get Ring0 *
; *************************************

int HookExceptionNumber ; GenerateException
   HookExceptionNumber定义为3,此段代码会产生异常,具体请参阅CIH源代码。

因为如上代码比较抽象,我特意将它稍加修改,以便于理解(PE格式可直接在Windows下执行):

// TestCIH.C 有任何问题联系tsu00@263.net

#include <windows.h>
#include <stdio.h>


EXCEPTION_DISPOSITION __cdecl _except_handler(  //异常处理程序段               
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext )
{
printf( "CIH Run Here...\n" );
exit(0); //由于堆栈已被程序打乱,有兴趣的可以自己将它恢复,这儿我只简单的退出
}

void main(void)
{
_asm
{
push ebp

mov eax, esp
sub eax, 8         //这两行相当于lea eax, [esp-04h*2]
xor ebx, ebx
xchg eax, fs:[ebx]

call next
   next:
pop ebx //这三行在这没实在意义,只是为了与CIH对比

lea ecx, _except_handler  //将_except_handler设为异常处理入口
push ecx

push eax
}

_asm
{
mov eax,0
mov [eax],0    //发生STATUS_ACCESS_VIOLATION异常让操作系统调用_except_handler
}
}

_except_handler回调函数原形可参阅EXCPT.H 
在main函数中第一个_asm段与前面讨论的CIH代码基本一致,而第二个_asm段则试图写系统保留内存地址,发生异常。
使用Visual C++如下编译:
c:>Cl testCIH.c
c:>testCIH
CIH Run Here...
在Windows 2000中,运行此段代码时,出现异常后操作系统将控制权交给_except_handler执行,这样CIH代码在NT/2000环境下在系统修改被其保护的内存地址时(IDT区域),不至于出现非法操作等提示,以达到保护自己的目的!

我总觉得了解系统安全,首先必须对这个系统有足够的了解,就像了解CIH病毒一样,而目前国内在这方面的资料可真谓少之又少,本文仅在这方面说出我自己的一些切身实践,错误之处,在所难免。如果您有任何发现,如果您对这方面有比较有兴趣,请联系tsu00@263.net.

最后很感谢绿盟高手的指点与帮助!

参考文献:

1.Jeffrey Richter <<Advanced Windows NT>>
2.Matt Pietrek <<A Crash Course on the Depths of Win32 Structured Exception Handling>>
3.CIH 1.3源代码

编辑:黑鹰 [发送给好友] [打印本页] [关闭窗口] [返回顶部]
上一篇:Windows 2000 System Services列表
下一篇:游戏修改器
转载请注明来源:www.iyit.net
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。

 相关文章
使用Windows NT 的安全性 精通Windows的安全API windows编程通用的Win32类型和常见的结
修改Windows2000的开机屏幕 Windows 2000下直接读写磁盘扇区 初探WINDOWS下IME编程
VC学习:Windows CE下的串口通讯类 一个对Winsock完成端口模型封装的类 Windows可执行文件简述(二)
Windows可执行文件简述(一) Windows网络编程经典入门 Windows 2000下直接读写磁盘扇区
WinAMP插件DIY 对MFC封装Windows通讯API的研究 利用Win32的网络函数创建一个网络浏览器
用Win32 API实现串行通信 用VC++和Winsock实现与HTTP服务器通话 Windows Socket API 使用经验
如何制作Windows自定义边框的对话框 Windows程序工作原理 Win32程序函数调用时堆栈变化情况分析
Windows 2000 System Services列表 再谈Windows NT/2000内部数据结构 再谈Windows NT/2000环境切换
最新更新 热点排行 推荐新闻
用VC++自制王码五笔输入法安装包 
在线资源指导
实用组件介绍
如何以最佳方式购买组件
ActiveX和OCX组件资源
用VC++自制王码五笔输入法安装包 
在线资源指导
实用组件介绍
如何以最佳方式购买组件
ActiveX和OCX组件资源
建立安装程序
收 集 文 件
理解各种打包类型
打包应用程序
向应用程序增加基于HTML的帮助
VC++实现对远程计算机屏幕的监视
用VC++6.0的Sockets API实现一个聊天室
多线程技术在VC++串口通信程序中的应用
用VC++制作一个简单的局域网消息发送工
用VC 6.0实现串行通信的三种方法
优秀公益广告作品欣赏(8)
java数据类型转换
Windows XP专业版IIS连接数的更改
新开放QQ免费挂级网站
优秀公益广告作品欣赏(7)
免费在QQ上看在线电影电视听音乐
WEB服务器配置全攻略(三)
QQ珊瑚虫外挂4.0版本发布!
免费把QQ炫铃设为本机QQ的系统提示音
Office2007简体中文版浮出水面 美图抢
微软将在华推分期付款,充值卡PC 可低价
 AMD处理器AM2测试 风扇竟运行7分钟
exeplorer.exe错误的问题的总结、解决
ASP.NET 2.0 中的异步页功能应用
硬盘坏道修复及数据恢复宝典
免费登录搜索引擎入口大全
搜索引擎注册九大秘法
小心摄像头成为黑客偷窥你的眼睛
内存混插常见问题和解决方法
Office2007简体中文版浮出水面 美图抢
 友情链接
设置首 页 - 版权声明 - 广告服务 - 关于我们 - 联系我们 - 友情连接
Copyrights © 2004-2006 iYiT.Net All Rights Reserved.
网站合作、广告联系QQ:147007642、466949678
易特网络技术 点击这里给我发消息