diff --git a/KernelLibrary/HashTable.cpp b/KernelLibrary/HashTable.cpp index cee99c5..34e9154 100644 --- a/KernelLibrary/HashTable.cpp +++ b/KernelLibrary/HashTable.cpp @@ -38,12 +38,12 @@ UINT32 HashTableGetBucketIndex(UINT32 bucketCount, UINT64 key) { return (bucketCount - 1) & HashUlongPtr(key); } -UINT32 HashTableInsert(PHASH_TABLE Hash, PSINGLE_LIST_ENTRY pListEntry) { +UINT32 HashTableInsert(PHASH_TABLE Hash, PHASH_BUCKET Entry) { UINT32 count = (Hash->BucketCount >> 5) & 0x7FFFFFF; - PHASH_ENTRY pEntry = CONTAINING_RECORD(pListEntry, HASH_ENTRY, Link); - UINT64 key = (ULONGLONG(-1) << (Hash->BucketCount & 0x1F)) & pEntry->HashVaue; + UINT64 key = (ULONGLONG(-1) << (Hash->BucketCount & 0x1F)) & Entry->HashValue; UINT32 idx = HashTableGetBucketIndex(count, key); - PushEntryList((PSINGLE_LIST_ENTRY)&Hash->Buckets[idx], pListEntry); + + PushEntryList(&Hash->Buckets[idx], (PSINGLE_LIST_ENTRY)Entry); count = Hash->ItemCount + 1; Hash->ItemCount = count; return count; @@ -63,7 +63,7 @@ UINT32 GetHighestBitIndex(UINT32 value) { } void HashTableInitialize(PHASH_TABLE Hash, UINT32 Flags, - UINT32 BucketCount, PHASH_BUCKET Buckets) { + UINT32 BucketCount, PSINGLE_LIST_ENTRY Buckets) { UINT32 count = RoundToPowerOfTwo(BucketCount, FALSE); if (count > 0x4000000) count = 0x4000000; @@ -71,11 +71,11 @@ void HashTableInitialize(PHASH_TABLE Hash, UINT32 Flags, Hash->BucketCount = (count << 5) | Hash->BucketCount & 0x1F; Hash->Buckets = Buckets; Hash->BucketCount = Flags & 0x1F | Hash->BucketCount & 0xFFFFFFE0; - PHASH_BUCKET p = Buckets; - PHASH_BUCKET pEnd = &Buckets[count]; + PSINGLE_LIST_ENTRY p = Buckets; + PHASH_BUCKET pEnd = (PHASH_BUCKET)&Buckets[count]; if (p) { - while (p < pEnd) { - p->Hash = ((ULONG_PTR)Hash | 1); + while ((PHASH_BUCKET)p < pEnd) { + ((PHASH_BUCKET)(p))->Hash = ((ULONG_PTR)Hash | 1); p++; } } @@ -102,7 +102,7 @@ UINT32 RoundToPowerOfTwo(UINT32 value, BOOLEAN roundUpToNext){ } PHASH_BUCKET HashTableCleanup(PHASH_TABLE Hash) { - return Hash->Buckets; + return (PHASH_BUCKET)Hash->Buckets; } PHASH_BUCKET HashTableFindNext(PHASH_TABLE Hash, UINT64 Key, PHASH_BUCKET Bucket) { @@ -119,16 +119,16 @@ PHASH_BUCKET HashTableFindNext(PHASH_TABLE Hash, UINT64 Key, PHASH_BUCKET Bucket if (count == 0) return NULL; UINT32 idx = HashTableGetBucketIndex(count, k); - pBucket = &Hash->Buckets[idx]; + pBucket = (PHASH_BUCKET)&Hash->Buckets[idx]; } + for (bLastLink = HashBucketLastLink(pBucket); !bLastLink; bLastLink = HashBucketLastLink(pBucket)) { - PHASH_ENTRY pEntry = CONTAINING_RECORD(pBucket, HASH_ENTRY, Link); - if (k == (value & pEntry->HashVaue)) { - return (PHASH_BUCKET)pBucket->Hash; + if (k == (value & ((PHASH_BUCKET)(pBucket->Link.Next))->HashValue)) { + return (PHASH_BUCKET)pBucket->Link.Next; } - pBucket = (PHASH_BUCKET)pBucket->Hash; + pBucket = (PHASH_BUCKET)pBucket->Link.Next; } return NULL; } @@ -141,45 +141,44 @@ PHASH_TABLE HashTableGetTable(PHASH_BUCKET HashEntry) { for (bLastLink = HashBucketLastLink(pBucket); !bLastLink; bLastLink = HashBucketLastLink(pBucket)) { - pEntry = (PHASH_BUCKET)pBucket->Link; + pEntry = (PHASH_BUCKET)(pBucket->Link.Next); } pHash = (PHASH_TABLE)(pBucket->Hash & ~1ull); pEntry = NULL; do { - PHASH_ENTRY pHashEntry = CONTAINING_RECORD(pBucket, HASH_ENTRY, Link); - pEntry = HashTableFindNext(pHash, pHashEntry->HashVaue, pEntry); + pEntry = HashTableFindNext(pHash, HashEntry->HashValue, pEntry); } while (pEntry && pEntry != HashEntry); return pHash; } PHASH_BUCKET HashTableChangeTable(PHASH_TABLE Hash, ULONG size, - PHASH_BUCKET pBuckets) { + PSINGLE_LIST_ENTRY pBuckets) { PHASH_BUCKET pOldBuckets = NULL; UINT32 count = RoundToPowerOfTwo(size, FALSE); if (count > 0x4000000) count = 0x4000000; - PHASH_BUCKET p = pBuckets; - PHASH_BUCKET pEnd = &pBuckets[count]; - for (; p < pEnd; ++p) { - p->Hash = (ULONG_PTR)Hash | 1; + PSINGLE_LIST_ENTRY p = pBuckets; + PHASH_BUCKET pEnd = (PHASH_BUCKET)&pBuckets[count]; + for (; p < (PSINGLE_LIST_ENTRY)pEnd; ++p) { + ((PHASH_BUCKET)(p))->Hash = (ULONG_PTR)Hash | 1; } UINT64 value = ULONGLONG(-1) << (Hash->BucketCount & 0x1F); UINT32 bucketCount = (Hash->BucketCount >> 5) & 0x7FFFFFF; for (UINT32 j = 0; j < bucketCount; ++j) { - PHASH_BUCKET pBucket = &Hash->Buckets[j]; + PHASH_BUCKET pBucket = (PHASH_BUCKET)&Hash->Buckets[j]; while (!HashBucketLastLink(pBucket)) { - p = pBucket; - PHASH_ENTRY pEntry = CONTAINING_RECORD(p, HASH_ENTRY, Link); - UINT32 idx = HashTableGetBucketIndex(bucketCount, value & pEntry->HashVaue); - PushEntryList((PSINGLE_LIST_ENTRY)&pBuckets[idx], p->Link); + PHASH_ENTRY pEntry = (PHASH_ENTRY)pBucket->Link.Next; + pBucket->Link.Next = pBucket->Link.Next->Next; + UINT32 idx = HashTableGetBucketIndex(bucketCount, value & pEntry->HashValue); + PushEntryList((PSINGLE_LIST_ENTRY)&pBuckets[idx], (PSINGLE_LIST_ENTRY)&p->Next); } } - pOldBuckets = Hash->Buckets; - Hash->Buckets = pBuckets; + pOldBuckets = (PHASH_BUCKET)Hash->Buckets; + Hash->Buckets = (PSINGLE_LIST_ENTRY)pBuckets; Hash->BucketCount = (count << 5) | Hash->BucketCount & 0x1F; return pOldBuckets; @@ -189,7 +188,7 @@ PHASH_TABLE_ITERATOR HashTableIterInit(PHASH_TABLE_ITERATOR Iterator, PHASH_TABLE Hash) { RtlZeroMemory(Iterator, sizeof(HASH_TABLE_ITERATOR)); Iterator->Hash = Hash; - Iterator->Bucket = Hash->Buckets; + Iterator->Bucket = (PHASH_BUCKET)Hash->Buckets; Iterator->HashEntry = Iterator->Bucket; return Iterator; } @@ -197,28 +196,32 @@ PHASH_TABLE_ITERATOR HashTableIterInit(PHASH_TABLE_ITERATOR Iterator, PHASH_BUCKET HashTableIterGetNext(PHASH_TABLE_ITERATOR Iterator) { PHASH_BUCKET HashEntry = Iterator->HashEntry; UINT32 count = 0; + if (!HashEntry || HashBucketLastLink(HashEntry)) { + // 这个分支完全没有走过 直接就g了 相当于连链表的大小都没判断过 PHASH_TABLE Hash = Iterator->Hash; - + PSINGLE_LIST_ENTRY pBucket = (PSINGLE_LIST_ENTRY)&Iterator->Bucket->HashValue; + count = (Hash->BucketCount >> 5) & 0x7FFFFFF; - PHASH_BUCKET pBucket = Iterator->Bucket; - PHASH_BUCKET pEnd = &Hash->Buckets[count]; + PHASH_BUCKET pEnd = (PHASH_BUCKET)&Hash->Buckets[count]; while (TRUE) { - if (pBucket >= pEnd) + if (pBucket >= (PSINGLE_LIST_ENTRY)pEnd) return NULL; - if (!HashBucketLastLink(pBucket)) + if (!HashBucketLastLink((PHASH_BUCKET)pBucket)) break; - pBucket = (PHASH_BUCKET)pBucket->Link->Next; + pBucket++; } - PHASH_BUCKET pHashEntry = (PHASH_BUCKET)pBucket->Hash; - count = (Iterator->Bucket - Iterator->Hash->Buckets) >> 3; - Iterator->Bucket = pBucket; + PHASH_BUCKET pHashEntry = (PHASH_BUCKET)pBucket->Next; + Iterator->Bucket = (PHASH_BUCKET)pBucket; Iterator->HashEntry = pHashEntry; return pHashEntry; } else { - count = (Iterator->Bucket - Iterator->Hash->Buckets) >> 3; + // 一直走的这 一直顺着链表往下遍历 很有可能是过程里面 有成员被移除了。数据不一致,我和他不同步,嗯 你们不同步啊 + // 这方法都没法让别人遍历了,真好。有因为可以try catch估计问题不大 多写几个判断就行了。啥判断啊,你又没法影响wdfilter MmCopyVirtualMemory 然后 MmIsValid把 估计不会蓝 + // 不好控制,今天就这样吧?ok + Iterator->HashEntry = (PHASH_BUCKET)HashEntry->Link.Next; return Iterator->HashEntry; } } @@ -229,16 +232,15 @@ PHASH_BUCKET HashTableIterRemove(PHASH_TABLE_ITERATOR Iterator) { PHASH_BUCKET pBucket = Iterator->Bucket; BOOLEAN bLastLink = FALSE; - for (bLastLink = HashBucketLastLink(pBucket); !bLastLink; - bLastLink = HashBucketLastLink(pBucket)) { - PHASH_BUCKET p = (PHASH_BUCKET)pBucket->Hash; - if (p == pHashEntry) { + for (bLastLink = HashBucketLastLink(pBucket); !bLastLink; bLastLink = HashBucketLastLink(pBucket)) { + if (pBucket == pHashEntry) { + pBucket->Hash = pHashEntry->Hash; --Iterator->Hash->ItemCount; - p->Link->Next = pHashEntry->Link->Next; - pHashEntry->Link->Next = (PSINGLE_LIST_ENTRY)((ULONG_PTR)pHashEntry->Link->Next | 0x8000000000000002); - Iterator->HashEntry = p; + pHashEntry->Hash |= 0x8000000000000002ui64; + Iterator->HashEntry = pBucket; return pHashEntry; } + pBucket = (PHASH_BUCKET)pBucket->Link.Next; } return NULL; diff --git a/KernelLibrary/HashTable.h b/KernelLibrary/HashTable.h index 684f3e1..a151a79 100644 --- a/KernelLibrary/HashTable.h +++ b/KernelLibrary/HashTable.h @@ -2,20 +2,21 @@ typedef struct _HASH_ENTRY { SINGLE_LIST_ENTRY Link; - ULONG_PTR HashVaue; + ULONG_PTR HashValue; }HASH_ENTRY, * PHASH_ENTRY; typedef struct _HASH_BUCKET { union { ULONG_PTR Hash; - PSINGLE_LIST_ENTRY Link; + SINGLE_LIST_ENTRY Link; }; + UINT64 HashValue; }HASH_BUCKET,*PHASH_BUCKET; typedef struct _HASH_TABLE { UINT32 ItemCount; UINT32 BucketCount; - PHASH_BUCKET Buckets; + PSINGLE_LIST_ENTRY Buckets; }HASH_TABLE,*PHASH_TABLE; typedef struct _HASH_TABLE_ITERATOR { @@ -37,12 +38,12 @@ UINT64 HashUStringUpcase(PWCH pBuffer, int len); UINT32 HashTableGetBucketIndex(UINT32 bucketCount, UINT64 key); -UINT32 HashTableInsert(PHASH_TABLE Hash, PSINGLE_LIST_ENTRY pListEntry); +UINT32 HashTableInsert(PHASH_TABLE Hash, PHASH_BUCKET pBucket); BOOLEAN HashBucketLastLink(PHASH_BUCKET bucket); void HashTableInitialize(PHASH_TABLE Hash, UINT32 Flags, - UINT32 BucketCount, PHASH_BUCKET Buckets); + UINT32 BucketCount, PSINGLE_LIST_ENTRY Buckets); UINT32 GetHighestBitIndex(UINT32 value); @@ -53,7 +54,7 @@ BOOLEAN IsPowerOfTwo(UINT32 x); PHASH_BUCKET HashTableCleanup(PHASH_TABLE Hash); PHASH_BUCKET HashTableFindNext(PHASH_TABLE Hash, UINT64 Key, PHASH_BUCKET Bucket); PHASH_TABLE HashTableGetTable(PHASH_BUCKET HashEntry); -PHASH_BUCKET HashTableChangeTable(PHASH_TABLE Hash, ULONG size, PHASH_BUCKET pBucket); +PHASH_BUCKET HashTableChangeTable(PHASH_TABLE Hash, ULONG size, PSINGLE_LIST_ENTRY pBucket); PHASH_TABLE_ITERATOR HashTableIterInit(PHASH_TABLE_ITERATOR Iterator, PHASH_TABLE Hash); PHASH_BUCKET HashTableIterGetNext(PHASH_TABLE_ITERATOR Iterator); PHASH_BUCKET HashTableIterRemove(PHASH_TABLE_ITERATOR Iterator); \ No newline at end of file diff --git a/Test/test.cpp b/Test/test.cpp index 723126e..2927ee0 100644 --- a/Test/test.cpp +++ b/Test/test.cpp @@ -18,11 +18,16 @@ PUCHAR g_pAddr = (PUCHAR)0xfffff96000082744; HASH_TABLE g_Table; -struct FullItem { - ULONG_PTR Value; - HASH_ENTRY Entry; + +struct FZG +{ + int height; + int age; + HASH_BUCKET bucket; + char* name; }; + extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { @@ -31,45 +36,66 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { HashTableInitialize(&g_Table, 0, 0, nullptr); - PHASH_BUCKET pBuckets = (PHASH_BUCKET)ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'tset'); + + int AllocCount = 100; + + + PHASH_BUCKET pBuckets = (PHASH_BUCKET)ExAllocatePoolWithTag(PagedPool, AllocCount * sizeof(PSINGLE_LIST_ENTRY), 'tset'); if (!pBuckets) { return STATUS_INSUFFICIENT_RESOURCES; } - HashTableChangeTable(&g_Table, PAGE_SIZE / sizeof(SINGLE_LIST_ENTRY), pBuckets); + HashTableChangeTable(&g_Table, AllocCount, (PSINGLE_LIST_ENTRY)pBuckets); do { - auto item = (FullItem*)ExAllocatePoolWithTag(PagedPool, sizeof(FullItem), 'meti'); - if (!item) - break; + auto item = (FZG*)ExAllocatePoolWithTag(PagedPool, sizeof(FZG), 'meti'); + auto item2 = (FZG*)ExAllocatePoolWithTag(PagedPool, sizeof(FZG), 'meti'); + RtlZeroMemory(item, sizeof(FZG)); + RtlZeroMemory(item2, sizeof(FZG)); - RtlZeroMemory(item, sizeof(FullItem)); + - UINT64 value = 0x1000; - UINT64 key = HashUlongPtr(value); - item->Entry.HashVaue = key; - item->Value = 0x7fff0; + item->age = 18; + item->height = 183; + item->name = "ShuaiGeZengZhenDeShuai"; + UINT64 hash = HashUlongPtr((UINT64)item->name); + item->bucket.HashValue = hash; + + item2->age = 19; + item2->height = 182; + item2->name = "ShuaiGeCunZhenDeShuai"; + UINT64 hash2 = HashUlongPtr((UINT64)item2->name); + item2->bucket.HashValue = hash2; - - HashTableInsert(&g_Table, &item->Entry.Link); + + HashTableInsert(&g_Table, &item->bucket); + HashTableInsert(&g_Table, &item2->bucket); PHASH_BUCKET pBucket = NULL; - FullItem* pData = NULL; - pBucket = HashTableFindNext(&g_Table, key, pBucket); - if (pBucket != NULL) { - pData = CONTAINING_RECORD(pBucket, FullItem, Entry); - KdPrint(("Value: %p\n", pData->Value)); + while (TRUE) { + pBucket = HashTableFindNext(&g_Table, hash, pBucket); + if (!pBucket) { + KdPrint(("Not Found!")); + break; + } + + FZG* result = CONTAINING_RECORD(pBucket, FZG, bucket); + KdPrint(("%d %d %s", result->age, result->height, result->name)); } - HASH_TABLE_ITERATOR iter; - HashTableIterInit(&iter, &g_Table); - while (HashTableIterGetNext(&iter)) { - pData = CONTAINING_RECORD(iter.Bucket, FullItem, Entry); - HashTableIterRemove(&iter); - KdPrint(("Value: %p\n", pData->Value)); - ExFreePoolWithTag(pData, 'meti'); - } + DbgBreakPoint(); + HASH_TABLE_ITERATOR Iterator; + HashTableIterInit(&Iterator, &g_Table); + while (HashTableIterGetNext(&Iterator)) + { + FZG* result = CONTAINING_RECORD(Iterator.HashEntry, FZG, bucket); + KdPrint(("result %p", result)); + HashTableIterRemove(&Iterator); + //KdPrint(("Iterator %d %d %s", result->age, result->height, result->name)); + //ExFreePoolWithTag(result, 'meti'); + + } } while (FALSE); @@ -79,6 +105,22 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { ExFreePoolWithTag(p, 'tset'); } + DbgBreakPoint(); + HASH_TABLE_ITERATOR iter; + HashTableIterInit(&iter, (PHASH_TABLE)(0xfffff80510af0000 + 0x20AF0)); + while (HashTableIterGetNext(&iter)) + { + KdPrint(("result %p", iter.HashEntry)); + HashTableIterRemove(&iter); + } + // 好像不是test.sys蓝的,肯定必现,你没结构体大小 不好验证。 + // 没问题吧???? 每 怎么验证正确性:) 结构体 你需要它的结构体大小 还有bucket所在的位置 + // // -0x10 + 0x30 = name 你试一下继续下个段 + // 不看以下新版本的吗 一样 + // 代码要动吗 不动 断点断了以后 给我操作 我看看 // 结构体没对上 -0x10 + 0x30不对 // 确实是+0x38 我刚刚看错了 意思就是遍历对了 + // 按错了 md 重新来一下 我看看为什么蓝屏 这个iter貌似是要配合Remove一起用的 + // 这样试试?这样我估计会蓝 因为毕竟你是在遍历别人的链表 是没有锁的 别人在你遍历的过程里面 删一个你就炸了 还有可能是这个原因。 + return STATUS_SUCCESS; }