+----------------------------------+
| Pool Rootkit: Goblin v3.0 |
| by Scott |
| 2008-07-03 |
| xscott_at_126[dot]com |
| http://www.phpfav.com |
之前很久就研究了Pool rootkit技术,发现现在这个技术还挺流行。所以公开一下这个版本功能信息。
Goblin v3.0 实际上演变于我原来的NetKCmd(一个验证版本的Rootkit),现在重新进行了编码保证正了其稳定性外,还加入了一些新元素在里面。Goblin v3.0有别于Goblin v2.0功能大而全,Goblin v3.0则注重隐藏,功能相对单一。
功能:
1:复合的内核模块隐藏技术
2:隐藏通讯连接
3:提供CMD命令行环境
4:反向连接,本地NetCat管理
5:以上功能完全由一个驱动文件实现,没有Ring3部分
运行环境:
系统环境:windows 2k-sp4 XP-sp2 2k3-sp2 VISTA-sp0-sp1
硬件环境:支持单核CPU 支持多核CPU
以上环境经历了40天的测试,稳定,完全隐藏于系统之内,对系统性能不产生负面影响。
Tags: 技术文章
经过3天的努力终于搞定了。KMD模式下的驱动电源管理的处理。
为什么要处理?
很多时候我们写硬件的过滤驱动的时候,必然会选择一些DDK内的例子作为框架然后修改增删。这些例子基本上都是WDM模式驱动,都需要自己处理电源和PNP事件。同时WDM的安装也是需要用到INF文件来启动的。这里就要说一下KMD驱动的优势了。灵活,不需要INF安装启动,只要用services API就可以启动关闭了,也不需要处理电源管理。
通过以上的信息,我就会遇到一个问题:有些时候在KMD模式下处理了一些硬件的过滤,那么KMD驱动这时候就暴露了它的不足,在关机,待机等电源模式下的处理问题。如果处理不好,就容易让系统蓝屏,或者卡住。
现在终于解决了,用我的通用Power.h 文件来处理KMD模式的电源管理。谨以此文,以记之。。。
续一个:在做好以上处理后,要处理自己的IOCTL时,需要先处理一个128的IOCTL。切记。。。
Tags: 技术文章
+----------------------------------+
| Verify Syetem Service Table v2.1 |
| by Scott |
| 2008-05-28 |
| xscott_at_126[dot]com |
| http://www.phpfav.com |
USAGE:
VSST OPERATION
Operation:
check Verify system service function (complete)
fix (uncomplete)
下载地址: vsst-v2.1
一 功能如下:
1:显示服务号。
2:显示服务函数名。
3:显示服务静态时入口地址,以及入口指令。
4:显示服务加载后入口地址,以及入口指令。
5:显示真实的内存函数入口指令。
6:智能解析HOOK类型,并且解析HOOK指令。
7:定位HOOK驱动模块的名字。
二 适用系统:CPU : 单/双核CPU (VSST V2.0 增加了对双核CPU的支持)
OS : Windows 2000(ser/pro)-SP4 / XP-SP2 / 2003-SP2 / VISTA
以上环境测试通过。
三 FIX:2008-05-28 V2.1 windows 2000 profreeional 兼容性问题
如有错误,希望通过以下方式告诉我。
EMAIL:xscott_at_126[dot]com
BLOG :http://www.phpfav.com
Tags: 作品发布
/////////////////////////////////////////////////////////////////////////
//
// Module:
// Read physical memory information from registry
// HKLM\HARDWARE\RESOURCEMAP\System Resources\Physical Memory
//
// Author:
// CDrea (CDrea_at_SafeChina[dot]org)
//
// Version:
// 2007-12-24 v0.1
//
/////////////////////////////////////////////////////////////////////////
#include
#include
struct _mi {
LARGE_INTEGER Address;
DWORD Length;
DWORD Reserved;
};
#define MI_LEN sizeof(struct _mi)
typedef struct _phy_mem_info {
DWORD BusCount;
DWORD MemoryRangeCount;
struct _mi* MemInfoPtr;
}PHY_MEM_INFO;
BOOL
GetPhyMemoryInfo(
OUT PHY_MEM_INFO* PhyMemInfo
);
void logo();
int main()
{
PHY_MEM_INFO PhyMemInfo = {0};
LARGE_INTEGER TotalSize = {0};
logo();
if(!GetPhyMemoryInfo(&PhyMemInfo)) return -1;
for(DWORD i = 0; i < PhyMemInfo.MemoryRangeCount; i++)
{
TotalSize.QuadPart += (PhyMemInfo.MemInfoPtr + i)->Length;
}
printf(”Total memory: %d MB\n”, TotalSize.QuadPart / 1024 / 1024);
printf(”Bus count: %d\n”, PhyMemInfo.BusCount);
printf(”Memory ranges:\n”);
for(DWORD i = 0; i < PhyMemInfo.MemoryRangeCount; i++)
{
printf(" 0x%-016I64X Length: 0x%X (%dK)\n",
(PhyMemInfo.MemInfoPtr + i)->Address.QuadPart,
(PhyMemInfo.MemInfoPtr + i)->Length,
(PhyMemInfo.MemInfoPtr + i)->Length / 1024);
}
if(PhyMemInfo.MemInfoPtr != NULL)
free(PhyMemInfo.MemInfoPtr);
return 0;
}
BOOL
GetPhyMemoryInfo(
OUT PHY_MEM_INFO* PhyMemInfo
)
{
HKEY hKey;
int nRet = 0;
nRet = RegOpenKey(HKEY_LOCAL_MACHINE, “Hardware\\ResourceMap\\System Resources\\Physical Memory”, &hKey);
if(nRet != ERROR_SUCCESS)
{
fprintf(stderr, “RegOpenKey() failed. –err: %d\n”, GetLastError());
return FALSE;
}
DWORD Type = 0;
DWORD cbData = 0;
LPBYTE lpData = NULL;
LPBYTE pmrc = NULL;
RegQueryValueEx(hKey, “.Translated”, 0, &Type, NULL, &cbData);
lpData = (LPBYTE)malloc(cbData);
RegQueryValueEx(hKey, “.Translated”, 0, &Type, lpData, &cbData);
if(nRet != ERROR_SUCCESS)
{
fprintf(stderr, “RegQueryValueEx() failed. –err: %d\n”, GetLastError());
return FALSE;
}
DWORD BusCount = *(DWORD*)lpData;
if(BusCount <= 0)
{
fprintf(stderr, "Cannot get valid memory information.\n");
return FALSE;
}
LPBYTE p = lpData + 0x10;
DWORD MemoryRangesCount = 0;
for(DWORD i = 1; i <= BusCount; i++)
{
MemoryRangesCount += *(DWORD*)p;
p = p + 0x8 + i * (*(DWORD*)p) * 0x10;
}
p = lpData + 0x10;
PhyMemInfo->MemInfoPtr = (struct _mi*)malloc(MI_LEN * MemoryRangesCount);
if(PhyMemInfo->MemInfoPtr == NULL)
{
fprintf(stderr, “Not enough memory.\n”);
return FALSE;
}
LPBYTE pmi = NULL;
struct _mi* ptr = PhyMemInfo->MemInfoPtr;
for(DWORD i = 1; i <= BusCount; i++)
{
pmi = p + 0x8;
for(DWORD j = 0; j < *(DWORD*)p; j++)
{
ptr->Address.LowPart = *(DWORD*)pmi;
ptr->Address.HighPart = *(long*)(pmi + 0×4);
ptr->Length = *(DWORD*)(pmi + 0×8);
ptr++;
pmi += MI_LEN;
}
p = p + 0×8 + i * (*(DWORD*)p) * 0×10;
}
PhyMemInfo->BusCount = BusCount;
PhyMemInfo->MemoryRangeCount = MemoryRangesCount;
RegCloseKey(hKey);
free(lpData);
return TRUE;
}
void logo()
{
printf(”+————————————+\n”);
printf(”| Physical Memory Information v0.1 |\n”);
printf(”| Write by CDrea |\n”);
printf(”| CDrea_at_SafeChina[dot]ORG |\n”);
printf(”| 2007-12-24 |\n”);
printf(”| http://www.safechina.org |\n”);
printf(”+————————————+\n\n”);
}
Tags: 代码
一直习惯用T43的Fn+F3关闭显示器,但DELL D630没有提供关闭显示器的热键,于是写了个程序,代码在google上一搜一大堆。
#include <windows.h>
#include <tchar.h>
int
APIENTRY
_tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow
)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
return 0;
}
P.S. 如果喜欢用热键方式关闭显示器,可以给程序在桌面上建立一个快捷方式,之后在“属性”中设置一个“快捷键”即可。
Tags: 代码
最近心理极度烦躁:然后就只能靠写程序来使自己平静。
工程名称:VDISK_PACK (SDK) 虚拟磁盘开发包 v1.0
文件:
vDisk.sys 磁盘驱动
vDisk.dll 提供应用层接口
vADisk.dll 扩展应用接口(未开发,备用)
功能:
1:建立虚拟磁盘(支持NTFS,FAT)
2:虚拟磁盘自动格式化
3:虚拟磁盘管理(丰富的管理接口)
4:同时支持3个虚拟磁盘应用
使用环境:
处理器: 适用于单核处理器,多核处理器
操作系统:windows 2000/xp/2003/vista
测试与稳定性:
1:在NTFS环境下可以建立30G的磁盘,同时读,写速度与正常磁盘相仿
2:同时建立3个虚拟磁盘同时读,写,效果稳定
3:以上测试历时了1个月。
.
.
Write by Scott
.
Tags: 作品发布
+----------------------------------+
| Rootkit: Goblin v2.0 |
| by Scott |
| 2007-09-14 |
| xscott_at_126[dot]com |
| http://www.phpfav.com |
标准的模块化开发,只有一个内核文件。
一 功能:
1:显示目标磁盘驱动器
2:内核 Dir 命令
3:内核 cmd 命令行环境(分强/弱两种模式)
4:隐藏网络端口 (bypass IceSword 1.22)
5:隐藏内核模块 (bypass IceSword 1.22)
6:隐藏注册表 (bypass IceSword 1.22)
7:上传文件并执行
8:下载文件
9:支持正向连接,支持反向连接
10:新增加了友好客户端操作界面,文件管理(上传,下载,删除)均使用“资源管理器”风格
二 适用系统:
操作系统: WIN 2000-SP4 / XP-SP1-SP2 / 2003-SP1-SP2 / VISTA-6000
硬件平台: 支持 单/双 核CPU
以上环境经过历时一个月的测试通过
.
.
Write by Scott
.
Tags: 作品发布
这篇《无题》是为以前我写的两篇文章做个续,纠错,补充。
两篇文章如下:
1:内核时差计算器
http://www.phpfav.com/?p=76
2:Hide Port/Link Bypass IceSword 1.22
http://www.phpfav.com/?p=105
先说 1
以前给两种方法。1:KeQuerySystemTime 这个方法当时就给否了。后来在实际应用中发现 2:__asm RDTSC 这种方法通用性不好。不适合在广泛应用的情况下使用,只能在特定的环境下使用。
所以现在给出稳定,通用性好的一种做法即:利用
NTHALAPI
LARGE_INTEGER
KeQueryPerformanceCounter (
IN PLARGE_INTEGER PerformanceFrequency OPTIONAL
);
现在说 2
其实是对那篇文章的补充,当时忘说了。
老生常谈了,即:端口与进程关联。
// 0x102
typedef struct TCPAddrExEntry {
ULONG tae_ConnState;
ULONG tae_ConnLocalAddress;
ULONG tae_ConnLocalPort;
ULONG tae_ConnRemAddress;
ULONG tae_ConnRemPort;
ULONG pid; // 进程ID
} TCPAddrExEntry;
用 0×102 的 IRP 查询然后得到的返回信息自然就可以关联到进程了。
Tags: 技术文章
解决了一个历史遗留问题。记得去年的时候和CD讨论过 IOCTL_TCP_QUERY_INFORMATION_EX 这个东西的处理,后来就没下文了。
这几天整理代码,索性就把那时候的几个相关代码找出来分析了一下。发现以前的代码有一个逻辑错误导致可以隐藏 XP netstat -an 命令。但是不可以在2003 netstat -an 下隐藏。然后发现处理的时候漏处理了ReqType 0×102 这个类型修正了这个逻辑错误后可以在2003 netstat -an 下隐藏了。
其实本应该到此结束,不过在这个过程中有个了一个偶然的发现,才有了继续做的动力。
先说发现:在XP下 netstat -an 实际上系统只发了一个 0×101 ID IRP进行查询。而在2003上也许是微软对网络版操作系统的加强(个人想法),netstat -an 与在XP截然不同,2003发了两个查询IRP 分别是 0×101 和 0×102,然后对两个IRP返回的数据进行对比分析然后给出显示。以上的发现都是在我自己写的一个截获系统IRP的工具下动态监视后得出的。
然后继续用此工具分析,再参照一些TDI的结构,也就知道了 IceSword 1.22 查隐藏端口的原理,再稍微看一下其操作的层次。一切OK!
既然知道了原理那么绕过便是一个机械化的工作了。到此结束。
Tags: 技术文章
+----------------------------------+
| Verify Syetem Service Table v2.0 |
| by Scott |
| 2007-09-02 |
| xscott_at_126[dot]com |
| http://www.phpfav.com |
+———————————-+
USAGE:
VSST OPERATION
Operation:
check Verify system service function (complete)
fix (uncomplete)
vsst v2.0 点击下载
一 功能如下:
1:显示服务号。
2:显示服务函数名。
3:显示服务静态时入口地址,以及入口指令。
4:显示服务加载后入口地址,以及入口指令。
5:显示真实的内存函数入口指令。
6:智能解析HOOK类型,并且解析HOOK指令。
7:定位HOOK驱动模块的名字。
二 适用系统:CPU : 单/双核CPU (VSST V2.0 增加了对双核CPU的支持)
OS : Windows 2000-SP4 / XP-SP2 / 2003-SP2 / VISTA
以上环境测试通过。
如有错误,希望通过以下方式告诉我。
EMAIL:xscott_at_126[dot]com
BLOG :http://www.phpfav.com
Tags: 作品发布
又这样恍惚了一个月,在命令行下看了一眼瑞星2008的系统文件保护。顺便发布我4月份写的那个fsv。
C:\Utils>fsv check
Verify \FileSystem\FastFat... Loaded.
FatFsdCreate() HOOK Found!
module path: \SystemRoot\system32\drivers\HOOKHELP.sys
memory: 0xFAE76080
file : 0xFAA4BC8A
FatFsdWrite() HOOK Found!
module path: \SystemRoot\system32\drivers\HOOKHELP.sys
memory: 0xFAE760E4
file : 0xFAA44AED
FatFsdSetInformation() HOOK Found!
module path: \SystemRoot\system32\drivers\HOOKHELP.sys
memory: 0xFAE760CB
file : 0xFAA52821
+---------------------[ !!!WARNING!!! ]———————+
| Your file system driver has been modified by some MALWARE |
| Please try “fsv fix” to fix it. |
+———————————————————–+
使用说明:
C:\Utils>fsv
+---------------------------------+
| File System Verify v2.1 |
| by CDrea |
| 2007-04-29 |
| CDrea_at_safechina[dot]org |
| http://www.phpfav.com |
+———————————+
USAGE:
fsv OPERATION [ <file name> ]
Operation:
check Verify file system.
fix Fix file system (may cause BSOD!!).
delete Delete a file.
fdel Force delete a file, including runing exe and dll.
- check 检查系统文件驱动(检查hook和inline hook)
- fix 修复文件系统
- delete 文件删除
- fdel 强行文件删除,可以删除系统中运行的exe和dll
支持Windows 2000/XP/2003/Vista
如果有什么问题请发mail至CDrea_at_safechina[dot]org
点击下载
Tags: 作品发布
一年真的好快。一转眼 5eCur!ty Labs 已经开张一年了。
Tags: 生活
+----------------------------------+
| Verify Syetem Service Table v1.0 |
| by Scott |
| 2007-08-10 |
| xscott_at_126[dot]com |
| http://www.phpfav.com |
+———————————-+
USAGE:
VSST OPERATION
Operation:
check Verify system service function (complete)
fix (uncomplete)
***************************************************************************
下载地址
一 功能如下:
1:显示服务号。
2:显示服务函数名。
3:显示服务静态时入口地址,以及入口指令。
4:显示服务加载后入口地址,以及入口指令。
5:显示真实的内存函数入口指令。
6:智能解析HOOK类型,并且解析HOOK指令。
7:定位HOOK驱动模块的名字。
二 适用系统:CPU: Intel Pentium 1600MHz processor
OS : win 2000-SP4/XP-SP2/2003-SP2/VISTA-6000
以上环境测试通过。
如有错误,希望通过以下方式告诉我。我将不尽感激。
EMAIL:xscott_at_126[dot]com
BLOG :http://www.phpfav.com
三 检测演示:
SERVICE NUMBER: 41
ServiceFunciton: NtCreateKey
File_SDT_Addr: 0x8056F7A9
FILE_VALUE:: 68 C4 00 00 00 68 C0 94 41 00 E8 83 3C
Memory_SDT_Addr: 0x8056F7A9
MEMO_VALUE:: E9 31 6B F3 6D 68 C0 14 4F 80 E8 83 3C
REAL_VALUE:: 68 C4 00 00 00 68 C0 14 4F 80 E8 83 3C
**********************************************************
Warning ! INLINE_HOOK !
jmp [0xEE4A62DF]
At Module: mfehidk.sys
Input ENTER Go On :
SERVICE NUMBER: 52
ServiceFunciton: NtCreateSymbolicLinkObject
File_SDT_Addr: 0×805A1C69
FILE_VALUE:: 6A 2C 68 80 FC 42 00 E8 C6 17 F4 FF 64
Memory_SDT_Addr: 0xF7ADE0DC
MEMO_VALUE:: 6A 2C 68 80 7C 50 80 E8 C6 17 F4 FF 64
REAL_VALUE:: 6A 2C 68 80 7C 50 80 E8 C6 17 F4 FF 64
**********************************************************
Warning ! SSDT_HOOK !
real addr: 0×805A1C69
running addr: 0xF7ADE0DC
At Module: vdiskbus.sys
Input ENTER Go On :
Tags: 作品发布
在《Windows对象(Object)结构》一文中简单的描述了Object的结构,其中一些结构的细节地方尚未提及。
这篇文章中,主要讨论对象管理器(Object Manager)如何组织系统中的各种对象。
与文件系统管理文件的方法类似,Windows对象管理器将系统中的对象按照树状结构进行存储。可以使用www.sysinternals.com的winobj来观察系统中的对象。
既然系统以树状结构存储对象,那就先从组成这棵树数据结构下手,看一下系统是如何将对象组织起来的。
Windows使用OBJECT_DIRECTORY和OBJECT_DIRECTORY_ENTRY结构作为“树干”,将OBJECT_DIRECTORY结构的地址保存到位于Object Header之前的OBJECT_HEADER_NAME_INFO结构中。这些结构的定义如下:
//
// Object Directory Structure
//
#define NUMBER_HASH_BUCKETS 37
#define OBJ_INVALID_SESSION_ID 0xFFFFFFFF
typedef struct _OBJECT_DIRECTORY {
struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[ NUMBER_HASH_BUCKETS ];
EX_PUSH_LOCK Lock;
struct _DEVICE_MAP *DeviceMap;
ULONG SessionId;
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;
//
// Object Directory Entry Structure
//
typedef struct _OBJECT_DIRECTORY_ENTRY {
struct _OBJECT_DIRECTORY_ENTRY *ChainLink;
PVOID Object;
ULONG HashValue;
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_HEADER_NAME_INFO {
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG QueryReferences;
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
首先来看一下OBJECT_DIRECTORY结构,HashBuckets是一个有NUMBER_HASH_BUCKETS项数据的HASH表,类型为OBJECT_DIRECTORY_ENTRY结构指针数组,计算HASH的伪代码如下:
int CalcHash(WCHAR* ws)
{
WcharLength = ws / sizeof( ws[0] );
HashIndex = 0;
while (WcharLength–) {
Wchar = *ws++;
HashIndex += (HashIndex << 1) + (HashIndex >> 1);
if (Wchar < 'a') {
HashIndex += Wchar;
} else if (Wchar > 'z') {
HashIndex += RtlUpcaseUnicodeChar( (WCHAR)Wchar );
} else {
HashIndex += (Wchar - ('a'-'A'));
}
}
HashValue = HashIndex;
HashIndex %= NUMBER_HASH_BUCKETS;
return HashIndex;
}
这段代码的实现可以在ObpLookupDirectoryEntry()中找到(%wrk%\base\ntos\ob\Obdir.c)。
OBJECT_DIRECTORY结构正如它的名字一样——对象目录,对象管理器(Object Manager)将具有各个不同索引值的OBJECT_DIRECTORY_ENTRY结构保存在HashBuckets表中(索引值是这个指针数组的下标,范围从0-NUMBER_HASH_BUCKETS),而将各个具有相同索引值的OBJECT_DIRECTORY_ENTRY结构,依靠OBJECT_DIRECTORY_ENTRY.ChainLink联系在一起,并将每一个对象(Object Body部分)保存在OBJECT_DIRECTORY_ENTRY.Object成员中。
我们将上面的文字描述实例化,最终形成了如下图的结构:

这张图的信息全部来自于kd的输出,这里以“\Driver”为例,利用调试器看一下系统内部对象是如何组织的。
kd> !object \driver
Object: e1005160 Type: (899272c0) Directory
ObjectHeader: e1005148
HandleCount: 0 PointerCount: 117
Directory Object: e1000118 Name: Driver
Hash Address Type Name
---- ------- ---- ----
00 897adc30 Driver Beep
8988df38 Driver NDIS
89885328 Driver KSecDD
01 8979b880 Driver Raspti
89690f38 Driver Mouclass
02 896a4418 Driver TPInput
03 896d79f0 Driver Fips
896a6d10 Driver Kbdclass
...
36 896c0658 Driver Smapint
896e1468 Driver i8042prt
897b04a8 Driver CmBatt
“Object: e1005160”是“\Driver”对象的Object Body部分(OBJECT_DIRECTORY结构);“Type: (899272c0) Directory”表示“\Driver”对象是目录(Directory)类型;“Directory Object: e1000118”表示“\Driver”对象所在父目录(对象)的地址为0xe1000118(“\”目录对象)。
我们可以这样理解这个问题,文件系统会用两个特殊的目录来表示当前目录(“.”)和父目录(“..”),而对于一个目录(Directory)类型的对象,对象管理器使用Object Body部分来记录当前目录(对象)的信息,用OBJECT_HEADER_NAME_INFO的Directory成员保存父目录(对象)的地址。
OBJECT_HEADER_NAME_INFO是位于Object Header之前的一个结构,Directory成员记录了当前对象所在的目录(对象)的地址,Name成员保存对象名。
因此上面输出中的“Directory Object: e1000118”正是“\Driver”对象的OBJECT_HEADER_NAME_INFO.Directory所指向的目录(对象)——对象树的根节点“\”:
kd> dt nt!_object_header_name_info e1005148-0x10
nt!_OBJECT_HEADER_NAME_INFO
+0x000 Directory : 0xe1000118 _OBJECT_DIRECTORY
+0x004 Name : _UNICODE_STRING "Driver"
+0x00c QueryReferences : 1
kd> !object 0xe1000118
Object: e1000118 Type: (899272c0) Directory
ObjectHeader: e1000100
HandleCount: 0 PointerCount: 38
Directory Object: 00000000 Name: \
“\”对象是目录类型,是整个对象数的树根,其OBJECT_HEADER_NAME_INFO.Directory的值为NULL。系统中将其地址保存在nt!ObpRootDirectoryObject中,如果使用“!object poi(nt!ObpRootDirectoryObject)”会得到与“!object 0xe1000118”相同的输出。
继续看“!object \driver”的输出,Hash一列是OBJECT_DIRECTORY.HashBuckets的数组下标(索引值),可以使用“!list ” -t nt!_OBJECT_DIRECTORY_ENTRY.ChainLink -e -x \”dd @$extret l4; !object poi(@$extret+0×4) \” 0xe15849d8 “”来查看具有相同索引值的OBJECT_DIRECTORY_ENTRY结构中的信息;Address一列表示对象地址(Object Body部分),保存在OBJECT_DIRECTORY_ENTRY.Object成员中;Type表示对象类型,可以看到“\Driver”目录(对象)中保存的对象为Driver类型(即Object Body部分使用DRIVER_OBJECT结构);Name是对象的名字,从OBJECT_DIRECTORY.Name中获得。
从上面的分析中可以看出,“!object”实际上是从OBJECT_HEADER以及Object Header之前的几个结构下手,从中取得系统内对象的信息。因此,Windows对象管理器在管理对象的时候,操作的是OBJECT_HEADER与Object Header之前的几个结构,而并不关心Object Body的内容。Object Body之前的部分实际上是一个对象的“隐私”,这部分的“隐私”完全由对象管理器来维护,所以说,对象管理器的核心就是Object Body之前的这些结构,并利用ObXxx例程来对这些结构进行操作,从而实现对象管理的能力。
—
by CDrea
2007-07-09
CDrea_at_safechina[dot]org
http://www.safechina.org
http://www.phpfav.com
Tags: 技术文章
Windows系统的各种资源以对象(Object)的形式来组织,例如File Object, Driver Object, Device Object等等,但实际上这些所谓的“对象”在系统的对象管理器(Object Manager)看来只是完整对象的一个部分——对象实体(Object Body)。Windows XP中有31种不同类型的对象,Object Body反映了某一类型对象的特征信息,例如,文件对象使用FILE_OBJECT结构描述、驱动对象使用DRIVER_OBJECT结构描述、DEVICE_OBJECT用于描述设备对象等等。而各种Object的共有的信息(例如,对象类型、对象的引用计数、句柄数等信息)保存在OBJECT_HEADER与其他的几个结构中。换而言之,在对象管理器内部,不同类型的对象具有相同的Object Header,但Object Body部分却是不同的。
先放上一张Windows Object完整的结构图,其中OBJECT_HEADER取自Windows XP SP2 英文版。
+----------------------------------------------------------------+
+------->| ( OBJECT_HEADER_QUOTA_INFO ) |
| +---->| ( OBJECT_HEADER_HANDLE_INFO ) |
| | +->| ( OBJECT_HEADER_NAME_INFO ) |
| | | | ( OBJECT_HEADER_CREATOR_INFO ) |
| | | +------------------------[ Object Header ]———————–+
| | | | nt!_OBJECT_HEADER |
| | | | +0×000 PointerCount : Int4B |
| | | | +0×004 HandleCount : Int4B |
| | | | +0×004 NextToFree : Ptr32 Void |
| | | | +0×008 Type : Ptr32 _OBJECT_TYPE |
| | +–| +0×00c NameInfoOffset : UChar |
| +—–| +0×00d HandleInfoOffset : UChar |
+——–| +0×00e QuotaInfoOffset : UChar |
| +0×00f Flags : UChar |
| +0×010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION |
| +0×010 QuotaBlockCharged : Ptr32 Void |
| +0×014 SecurityDescriptor : Ptr32 Void |
| +0×018 Body : _QUAD |
+————————-[ Object Body ]————————+
| OBJECT_DIRECTORY, DRIVER_OBJECT, DEVICE_OBJECT, FILE_OBJECT… |
+—————————————————————-+
一个对象由三部分组成,在Object Header之前是一段变长的区域,由四个独立的结构体组成:
typedef struct _OBJECT_HEADER_QUOTA_INFO {
ULONG PagedPoolCharge;
ULONG NonPagedPoolCharge;
ULONG SecurityDescriptorCharge;
PEPROCESS ExclusiveProcess;
#ifdef _WIN64
ULONG64 Reserved; // Win64 requires these structures to be 16 byte aligned.
#endif
} OBJECT_HEADER_QUOTA_INFO, *POBJECT_HEADER_QUOTA_INFO;
typedef struct _OBJECT_HEADER_HANDLE_INFO {
union {
POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase;
OBJECT_HANDLE_COUNT_ENTRY SingleEntry;
};
} OBJECT_HEADER_HANDLE_INFO, *POBJECT_HEADER_HANDLE_INFO;
// begin_ntosp
typedef struct _OBJECT_HEADER_NAME_INFO {
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG QueryReferences;
#if DBG
ULONG Reserved2;
LONG DbgDereferenceCount;
#ifdef _WIN64
ULONG64 Reserved3; // Win64 requires these structures to be 16 byte aligned.
#endif
#endif
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
// end_ntosp
typedef struct _OBJECT_HEADER_CREATOR_INFO {
LIST_ENTRY TypeList;
HANDLE CreatorUniqueProcess;
USHORT CreatorBackTraceIndex;
USHORT Reserved;
} OBJECT_HEADER_CREATOR_INFO, *POBJECT_HEADER_CREATOR_INFO;
一个对象可以包含全部四个结构,也可能只包含其中的某个,因此这段区域是变长的。
之后是OBJECT_HEADER结构,NameInfoOffset、HandleInfoOffset、QuotaInfoOffset分别为OBJECT_HEADER到OBJECT_HEADER_NAME_INFO、OBJECT_HEADER_HANDLE_INFO、OBJECT_HEADER_QUOTA_INFO这三个结构的偏移。
WinDBG的“!object”命令可以显示对象的信息:
kd> !object \Driver\Disk
Object: 8985da08 Type: (898df3b0) Driver
ObjectHeader: 8985d9f0
HandleCount: 0 PointerCount: 6
Directory Object: e1005160 Name: Disk
继续看一下OBJECT_HEADER结构的信息:
kd> dt nt!_object_header 8985d9f0
nt!_OBJECT_HEADER
+0x000 PointerCount : 6
+0x004 HandleCount : 0
+0x004 NextToFree : (null)
+0x008 Type : 0x898df3b0 _OBJECT_TYPE
+0x00c NameInfoOffset : 0x10 ''
+0x00d HandleInfoOffset : 0 ''
+0x00e QuotaInfoOffset : 0 ''
+0x00f Flags : 0x32 '2'
+0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x00000001
+0x014 SecurityDescriptor : 0xe100c843
+0x018 Body : _QUAD
在NameInfoOffset中指出OBJECT_HEADER_NAME_INFO的便宜量为0×10,它的地址为OBJECT_HEADER - OBJECT_HEADER.NameInfoOffset,即0×8985d9f0-0×10,继续来看:
kd> dt nt!_object_header_name_info 8985d9f0-0x10
nt!_OBJECT_HEADER_NAME_INFO
+0x000 Directory : 0xe1005160 _OBJECT_DIRECTORY
+0x004 Name : _UNICODE_STRING "Disk"
+0x00c QueryReferences : 1
第三部分就是对象的实体部分(Object Body),根据对象类型的不同,这部分的结构也不相同。日常使用的DRIVER_OBJECT、DEVICE_OBJECT、FILE_OBJECT等等都是Object Body结构,继续回头看一下!object \Driver\Disk的输出,Object: 8985da08是Object Body部分——DRIVER_OBJECT结构。
kd> dt nt!_driver_object 8985da08
nt!_DRIVER_OBJECT
+0x000 Type : 4
+0x002 Size : 168
+0x004 DeviceObject : 0x89900c68 _DEVICE_OBJECT
+0x008 Flags : 0x12
+0x00c DriverStart : 0xf7627000
+0x010 DriverSize : 0x8e00
+0x014 DriverSection : 0x89927a70
+0x018 DriverExtension : 0x8985dab0 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\Driver\Disk"
+0x024 HardwareDatabase : 0x8068db10 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0xf762e8ab disk!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : 0xf763e53a CLASSPNP!ClassUnload+0
+0x038 MajorFunction : [28] 0xf763dc30 CLASSPNP!ClassCreateClose+0
kd> !drvobj 8985da08
Driver object (8985da08) is for:
\Driver\Disk
Driver Extension List: (id , addr)
(f763e3be 8985d8f0)
Device Object list:
89900c68 89896c68 8985ec68 8985cab8
现在有这样一个问题,我们经常使用Object Body的结构,但是要访问OBJECT_HEADER该如何做呢?
OBJECT_HEADER的大小为0×18字节,因此Object Body = OBJECT_HEADER + 0×18,但是0×18是个硬编码值,如果OBJECT_HEADER在以后的系统中发生了变化,显然用这个0×18是不可靠的。
OBJECT_HEADER结构中有一个Body成员,如果执行“dt nt!_OBJECT_HEADER -b”会有以下的输出:
kd> dt nt!_OBJECT_HEADER -b
+0x000 PointerCount : Int4B
+0x004 HandleCount : Int4B
+0x004 NextToFree : Ptr32
+0x008 Type : Ptr32
+0x00c NameInfoOffset : UChar
+0x00d HandleInfoOffset : UChar
+0x00e QuotaInfoOffset : UChar
+0x00f Flags : UChar
+0x010 ObjectCreateInfo : Ptr32
+0x010 QuotaBlockCharged : Ptr32
+0x014 SecurityDescriptor : Ptr32
+0x018 Body : _QUAD
+0×000 DoNotUseThisField : Float
注意斜体字部分。Body成员在OBJECT_HEADER结构中的偏移量实际上就是Object Body到OBJECT_HEADER的偏移量(0×18),它只是作为定位偏移量来使用,因此会有“Do Not Use This Field”的提示。
在WRK的代码中定义了一个宏函数(见 %wrk%\base\ntos\inc\ob.h),用于从Object Body访问OBJECT_HEADER结构。
#define OBJECT_TO_OBJECT_HEADER( o ) \
CONTAINING_RECORD( (o), OBJECT_HEADER, Body )
//
// Calculate the address of the base of the structure given its type, and an
// address of a field within the structure.
//
#ifndef CONTAINING_RECORD
#define CONTAINING_RECORD(address, type, field) \
((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
#endif
利用OBJECT_TO_OBJECT_HEADER()传递一个Object Body的地址给它(例如,Disk.sys的DriverObject),就可以轻松的得到这个对象的OBJECT_HEADER结构。
—
by CDrea
2007-07-04
CDrea_at_safechina[dot]org
http://www.safechina.org
http://www.phpfav.com
Tags: 技术文章
很久没有写代码了,最近简单的看了一下disk相关的东西,写了段代码share一下。
先用livekd看一下Disk.sys DriverObject的一些信息:
kd> !drvobj \driver\disk
Driver object (89885a08) is for:
\Driver\Disk
Driver Extension List: (id , addr)
(f763e3be 898858f0)
Device Object list:
8985ec68 8987fc68 8989ac68 89818ab8
然后看下这四个DeviceObject,分区数和硬盘数量不同,Device的数量也不同,我的机器只有三个分区,一块硬盘
kd> !devobj 8985ec68
Device object (8985ec68) is for:
DP(3)0×700a41e00-0xba11e0200+3 \Driver\Disk DriverObject 89885a08
Current Irp 00000000 RefCount 0 Type 00000007 Flags 000020d0
Vpb 89861b38 Dacl e1555b1c DevExt 8985ed20 DevObjExt 8985efd0 Dope 8989bad8
ExtensionFlags (0000000000)
Device queue is not busy.
kd> !devobj 8987fc68
Device object (8987fc68) is for:
DP(2)0×2002f3e00-0×500746200+2 \Driver\Disk DriverObject 89885a08
Current Irp 00000000 RefCount 0 Type 00000007 Flags 000020d0
Vpb 89862d78 Dacl e1555b1c DevExt 8987fd20 DevObjExt 8987ffd0 Dope 899260e8
ExtensionFlags (0000000000)
Device queue is not busy.
kd> !devobj 8989ac68
Device object (8989ac68) is for:
DP(1)0×7e00-0×2002e4200+1 \Driver\Disk DriverObject 89885a08
Current Irp 00000000 RefCount 0 Type 00000007 Flags 000000d0
Vpb 89886b38 Dacl e1555b1c DevExt 8989ad20 DevObjExt 8989afd0 Dope 899021a8
ExtensionFlags (0000000000)
Device queue is not busy.
kd> !devobj 89818ab8
Device object (89818ab8) is for:
DR0 \Driver\Disk DriverObject 89885a08
Current Irp 00000000 RefCount 0 Type 00000007 Flags 00000050
Vpb 89880008 Dacl e1555b1c DevExt 89818b70 DevObjExt 89818fd0 Dope 8985fbc8
ExtensionFlags (0000000000)
AttachedDevice (Upper) 89884a18*** ERROR: Module load completed but symbols could not be loaded for Apsx86.sys
\Driver\Shockprf
AttachedTo (Lower) 8989a9e8 \Driver\ACPI
Device queue is not busy.
ok,可以用下面的代码取出想要的DeviceObject
PDEVICE_OBJECT
GetDiskDeviceObject(
VOID
)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING usDiskName;
PDRIVER_OBJECT pDiskDrvObj = NULL;
PDEVICE_OBJECT pDiskDevObj = NULL;
DWORD dwLength = 0;
POBJECT_NAME_INFORMATION poni = NULL;
poni = poni;
RtlInitUnicodeString(&usDiskName, L"\\Driver\\Disk");
status = ObReferenceObjectByName(
&usDiskName,
0x40,
0,
0,
*IoDriverObjectType,
0,
NULL,
&pDiskDrvObj
);
if(!NT_SUCCESS(status))
{
KdPrint(("[dsv] ObReferenceObjectByName() failed.\n”));
return NULL;
}
pDiskDevObj = pDiskDrvObj->DeviceObject;
if(pDiskDevObj == NULL)
{
KdPrint((”[dsv] Disk DeviceObject is NULL.\n”));
ObDereferenceObject(pDiskDrvObj);
return NULL;
}
while(pDiskDevObj != NULL)
{
if(pDiskDevObj->DeviceType != FILE_DEVICE_DISK)
{
KdPrint((”[dsv] DeviceObject is NOT for Disk.\n”));
pDiskDevObj = pDiskDevObj->NextDevice;
continue;
}
if( !(pDiskDevObj->Flags & DO_DEVICE_HAS_NAME) )
{
KdPrint((”[dsv] DeviceObject DO NOT has a name.\n”));
pDiskDevObj = pDiskDevObj->NextDevice;
continue;
}
status = ObQueryNameString(pDiskDevObj, poni, 0, &dwLength);
if(STATUS_INFO_LENGTH_MISMATCH == status)
{
poni = (POBJECT_NAME_INFORMATION) np_malloc(dwLength);
if(NULL == poni)
{
KdPrint((”[dsv] np_malloc() failed.\n”));
ObDereferenceObject(pDiskDrvObj);
return NULL;
}
status = ObQueryNameString(pDiskDevObj, poni, dwLength, &dwLength);
if(!NT_SUCCESS(status))
{
KdPrint((”[dsv] ObQueryNameString with length: %d failed.\n”, dwLength));
free(poni);
ObDereferenceObject(pDiskDrvObj);
return NULL;
}
}
else if( !NT_SUCCESS(status) )
{
KdPrint((”[dsv] ObQueryNameString() failed.\n”));
ObDereferenceObject(pDiskDrvObj);
return NULL;
}
else
{
; // Nothing.
}
KdPrint((”[dsv] %S\n”, poni->Name.Buffer));
//
// TODO: Add code here.
//
free(poni);
if(pDiskDevObj->NextDevice == NULL) break;
pDiskDevObj = pDiskDevObj->NextDevice;
}
ObDereferenceObject(pDiskDrvObj);
return pDiskDevObj;
}
还有两个例程的声明,如果装了ifs就不需要声明ObQueryNameString()了,写在下面(看我服务多周到^^)
NTSTATUS
ObQueryNameString(
IN PVOID Object,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength
);
ObReferenceObjectByName(
IN PUNICODE_STRING ObjectPath,
IN ULONG Attributes,
IN PACCESS_STATE PassedAccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID *ObjectPtr
);
Tags: 代码
- Specter v0.1
Specter是一个检查rootkit隐藏文件与隐藏端口的工具。
+---------------------------------+
| Specter V-0.1 |
| By Scott |
| 2006-08-30 |
| xscott_at_126[dot]com |
| http://www.phpfav.com |
+———————————+
USAGE:
Specter OPERATION
Operation:
-F <dir> Verify hide hile
-PP Verify hide port(testing)
********************************************************
这个也是一个老工具了。
修改了一下数据输出和之前BUG,但是功能没有加强。
一 功能如下:
-F <目录名> 检测隐藏文件。
-PP 检测隐藏端口。但是此功能的输出不同于 NETSTAT -AN 命令。列出内核态和用户态两类信息。
偏重于对一些特殊端口的检测。
在以后的版本中会逐步细化此功能。
二 适用系统:win 2000/XP/2003 下测试通过。(2000下的 -PP 显示可能出现重复项属于正常现象)
如有错误和意见,希望通过以下方式告诉我。我将不尽感激。
EMAIL:xscott_at_126[dot]com
BLOG :http://www.phpfav.com
三 检测演示:
N:\Specter\Release>specter -f ..
directory dump:
------------------------START !
.
..
SpecterO
TEST
SpecterO.rar
Release
------------------------INFO !
NO HIDE FILE ! FileNum : 6
------------------------END !
N:\Specter\Release>specter -pp
PID Name Protocol IP Address Port
IOCTL: 00210012
4 [System] Tcp 0.0.0.0 135
IOCTL: 00210012
4 [System] RawIp 0.0.0.0 0
IOCTL: 00210012
4 [System] RawIp 0.0.0.0 0
IOCTL: 00210012
4 [System] Udp 0.0.0.0 500
IOCTL: 00210012
4 [System] Udp 0.0.0.0 4500
IOCTL: 00210012
504 lsass.exe Udp 0.0.0.0 500
C:\WINDOWS\system32\lsass.exe
IOCTL: 00210012
504 lsass.exe Udp 0.0.0.0 4500
C:\WINDOWS\system32\lsass.exe
IOCTL: 00210012
504 lsass.exe RawIp 0.0.0.0 0
C:\WINDOWS\system32\lsass.exe
IOCTL: 00210012
716 svchost.exe Tcp 0.0.0.0 135
C:\WINDOWS\system32\svchost.exe
MD5: 997cc6224584a95285465b13295a6cd0
点击下载
Tags: 作品发布
Rootkit : Goblin v1.0
标准的模块化开发,可以在短时间内拼装出来带有各种功能的RK。
只有一个内核文件(Goblin.sys)。
演示视频:
http://www.phpfav.com/uploads/scott/rk_goblin.zip
技术指标:
1:使用平台:
OS: WIN 2000-SP4 / XP-SP1-SP2 / 2003-SP1-SP2 / VISTA-6000
2:文件传输:支持文件回传。
3:网络通讯:支持正/反连接两种模块。
4:命令行:完全的内核模式命令行,与用户模式CMD执行效果一样。
5:网络连接隐藏:两套模块分别对应 VISTA 和 2K/XP/2K3。
(2K/XP/2K3下开端口,bypass ICESWORD DARKSKY ”netstat -an”)
(VISTA下连接,bypass “netstat -an”)
6:隐藏文件:ICESWORD DARKSKY 双开隐藏。
Scott>NewG
2007006021
Tags: 作品发布
原文地址:
http://www.gidforums.com/t-3328.html
#include <stdio.h>
#include <basetsd.h>/* required typedef __int64 for gcc */
typedef char TCHAR;
#define TEXT(x) x
unsigned __int64 atou64(const TCHAR *s) ;
int main()
{
unsigned __int64 value;
TCHAR *test = "1234567890123456789";
printf("in main(): test = <%s>\n", test);
printf("sizeof(__int64) = %d\n", sizeof(__int64));
value = atou64(test);
printf("value using I64d: %I64d\n", value); /* for Borland BCC or Microsoft VC++ */
printf("value using Ld: %Ld\n", value); /* for Borland BCC */
printf("value using lld: %lld\n", value); /* for gcc */
printf("value using I64x: %016I64x(hex)\n", value);/* for Borland BCC or Microsoft VC++ */
printf("value using Lx: %016Lx(hex)\n", value);/* for Borland BCC */
printf("value using llx: %016llx(hex)\n", value); /* for gcc */
return 0;
}
unsigned __int64 atou64(const TCHAR *s)
{
const unsigned __int64 max64 = (unsigned __int64)0-1;
unsigned __int64 v = 0;
int digit;
while (*s>=TEXT('0') && *s<=TEXT('9'))
{
digit = *s++ - TEXT('0');
if (v > (max64-digit)/10)
return 0; /* overflow */
v = 10*v + digit;
}
return v;
}
Tags: 技术文章
前些时候就想写这个东西。但是一直在思考,不知道怎么入手。
今天实践了一下,发现之前的思路错了。换个思路OK :)
主要功能:
1:记录内核里面任意两个事件的发生的时间差。并暂时保存在内核供以后使用。
2:精确度 百万分之一秒。
实现方法:
1:KeQuerySystemTime
2:__asm RDTSC
最开始的时候使用第一种发现精度不高,后来选择用第二种,效果非常不错。
Scott.MyTimer
200700613
Tags: 技术文章