您的位置:首页 > 其它

Winpcap分析 -- getAdaptersList

2010-02-06 13:18 183 查看
getAdaptersList:
这个函数主要的逻辑是读取注册表的数据

打开SYSTEM//CurrentControlSet//Control//Class//{4D36E972-E325-11CE-BFC1-08002BE10318}键项



InitializeObjectAttributes(&objAttrs, &AdapterListKey,

OBJ_CASE_INSENSITIVE, NULL, NULL);

status = ZwOpenKey(&keyHandle,
KEY_READ, &objAttrs);

说明:InitializeObjectAttributes和ZwOpenKey的wdk描述,请参考:

http://blog.csdn.net/huang_shao_bin/archive/2010/02/06/5294008.aspx

http://blog.csdn.net/huang_shao_bin/archive/2010/02/06/5294014.aspx

参数:

objAttrs:需要初始化的一个对象,主要为了调用ZwOpenKey提供数据

AdapterListKey:注册表键项值,需要打开的注册表的键项值,也即上面出现的字符串

对大小写不敏感所以需要指定OBJ_CASE_INSENSITIVE标志

后面的参数主要是用于路径对象的跟目录和安全描述符,这里不需要

相关数据:



根据打开的键值句柄,遍历所有子项,再获取每个子项下的Linkage子项,在Linkage子项中查找Export键值的值





遍历所有子项

while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)

说明:ZwEnumerateKey的wdk描述,请参考:

http://blog.csdn.net/huang_shao_bin/archive/2010/02/06/5294018.aspx

参数:

keyHandle:ZwOpenKey返回的句柄

i:需要获得的子键的索引,从0开始不断的计数,直到找不到为止

KeyBasicInformation:是一个枚举类型KEY_INFORMATION_CLASS,说明需要获取哪些信息,这里只获得基本信息就可以

AdapInfo:根据KEY_INFORMATION_CLASS类型定义不用的数据结构来接收函数返回的信息

sizeof(AdapInfo):接收数据的buffer的大小

resultLength:返回接收buffer需要的长度或者实际返回数据内容的长度,具体请参考wdk文档

相关数据:



打开Linkage子项

RtlCopyMemory(ExportKeyName,

ExportKeyPrefix,

ExportKeyPrefixSize);

RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,

tInfo->Name,

tInfo->NameLength+2);

RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,

LinkageKeyPrefix,

LinkageKeyPrefixSize);

RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);

InitializeObjectAttributes(&objAttrs, &AdapterKeyName,

OBJ_CASE_INSENSITIVE, NULL, NULL);

status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);

查询Export键值的信息

status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,

KeyValuePartialInformation, &valueInfo,

sizeof(valueInfo), &resultLength);

说明:ZwQueryValueKey的wdk描述,请参考:

http://blog.csdn.net/huang_shao_bin/archive/2010/02/06/5294020.aspx

参数:基本参数和ZwEnumerateKey类似,详细请参考wdk文档

计算数据大小,并重新分配内存进行查询

ULONG valueInfoLength = valueInfo.DataLength +
FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);

PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION)
ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');

if (valueInfoP != NULL) {

status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,

KeyValuePartialInformation,

valueInfoP,

valueInfoLength, &resultLength);

说明:

valueInfo.DataLength :Export键值的数据长度

FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
Data[0]):获得Data[0]成员在KEY_VALUE_PARTIAL_INFORMATION结构中的偏移

上述两项加起来就是总长度,然后重新查询Export键值信息,就可以通过valueInfoP->Data获得键值的数据

对上述的操作进行循环,就可以获得所有数据,下面来看看循环中的一些内存分配和长度计算

if( BufPos + valueInfoP->DataLength > BufLen ) {

// double the buffer size

PWCHAR DeviceNames2 = (PWCHAR)
ExAllocatePoolWithTag(PagedPool, BufLen

<< 1, '0PWA');

if( DeviceNames2 ) {

RtlCopyMemory((PCHAR)DeviceNames2,
(PCHAR)DeviceNames, BufLen);

BufLen
<<= 1;

ExFreePool(DeviceNames);

DeviceNames = DeviceNames2;

}

}

if( BufPos + valueInfoP->DataLength < BufLen ) {

RtlCopyMemory((PCHAR)DeviceNames+BufPos,

valueInfoP->Data,

valueInfoP->DataLength);

BufPos+=valueInfoP->DataLength-2;

}

// terminate the buffer

DeviceNames[BufPos/2]=0;

DeviceNames[BufPos/2+1]=0;

BufLen 是UINT型数据,初始值是4096

当buffer用完的时候,是通过移位来增加buffer长度,并重新分配一块新的内存区域

通过拷贝内存把原来数据拷贝到新的内存区域中

释放原来的内存区域

重新给指针赋值,指向新的内存区域

关于BufPos+=valueInfoP->DataLength-2,本人不知道原因,但是通过windbg查看,valueInfoP->DataLength-2的长度刚好就是最后一个字符的长度再往后2个字符,刚好配合后面的置0操作。也就是说valueInfoP->DataLength是数据的实际长度再加上4个字节的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: