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个字节的。
这个函数主要的逻辑是读取注册表的数据
打开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个字节的。
相关文章推荐
- PostgreSQL 的 target_list分析(六)
- *Delphi容器类之---TList、TStringList、TObjectList,以及一个例程的代码分析
- Winpcap原理分析
- linux 内核分析之list_head
- 自己实现LinkedList集合add,get,remove
- 深入源码分析Map与List的关系
- list链表分析(一)ngx_list
- Android getReadableDatabase() 和 getWritableDatabase()分析对比
- 集合List和ArrayList等实现类的底层原理分析
- Linux内核中LIST_HEAD分析
- list 、set 、map 粗浅性能对比分析
- tomcat源码分析之getParameter(String)与getQueryString()
- php中file_get_contents与curl性能比较分析
- linux内存管理--分配内存页(快速) get_page_from_freelist
- How to get projects list in eclipse
- java集合框架03--LinkedList和源码分析
- 分析分配控制列表 distribute-list
- PHP 发送GET 和 POST数据的方法分析
- java LinkedList源码分析
- c语言可变参数va_list,va_start用法与分析