Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@
#define KC_ENABLE_BOOLEAN_OBFUSCATION KC_ENABLE_ALL
#endif

// behavioral config
#ifndef KC_IMPORT_HIDING_LOCK_MODULE_LIST
#define KC_IMPORT_HIDING_LOCK_MODULE_LIST 1
#endif

#ifndef KC_POOL_TAG
#define KC_POOL_TAG 'kcLK'
#endif
Expand Down
91 changes: 21 additions & 70 deletions security/import_hiding.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,14 @@ extern "C" {
#endif

extern LIST_ENTRY PsLoadedModuleList;
#if KC_IMPORT_HIDING_LOCK_MODULE_LIST
extern struct _ERESOURCE PsLoadedModuleResource;
#endif
}
#else
// when ntddk/wdm is included, PsLoadedModuleList still needs declaration
// as it's not in the standard WDK headers
extern "C" {
extern LIST_ENTRY PsLoadedModuleList;
#if KC_IMPORT_HIDING_LOCK_MODULE_LIST
extern struct _ERESOURCE PsLoadedModuleResource;
#endif
}
#endif

Expand Down Expand Up @@ -210,82 +206,37 @@ KC_FORCEINLINE bool is_valid_pe(void* base) {

// walk PsLoadedModuleList for module base by case-insensitive wide-string hash
KC_NOINLINE inline void* find_module_by_hash(uint64_t name_hash) {
#if KC_IMPORT_HIDING_LOCK_MODULE_LIST
bool in_critical = false;
bool resource_acquired = false;
#endif
void* found = nullptr;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); // No PASSIVE_LEVEL no party

__try {
#if KC_IMPORT_HIDING_LOCK_MODULE_LIST
if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
__try {
KeEnterCriticalRegion();
in_critical = true;

ExAcquireResourceSharedLite(&PsLoadedModuleResource, 1);
resource_acquired = true;
} __except (1) {
resource_acquired = false;
if (in_critical) {
KeLeaveCriticalRegion();
in_critical = false;
}
}
}
#endif
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&PsLoadedModuleResource, TRUE);

auto* head = &PsLoadedModuleList;
if (!MmIsAddressValid(head) || !MmIsAddressValid(head->Flink))
goto out;
void* found = nullptr;

for (auto* entry = head->Flink; entry != head; entry = entry->Flink) {
if (!MmIsAddressValid(entry))
break;
auto* head = &PsLoadedModuleList;

auto* mod = reinterpret_cast<PKLDR_DATA_TABLE_ENTRY>(entry);
if (!mod->BaseDllName.Buffer || !mod->BaseDllName.Length)
continue;
if (!MmIsAddressValid(mod->BaseDllName.Buffer))
continue;
for (auto* entry = head->Flink; entry != head; entry = entry->Flink) {
auto* mod = CONTAINING_RECORD(entry, KLDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

size_t wchar_len = static_cast<size_t>(mod->BaseDllName.Length) / sizeof(wchar_t);
if (!wchar_len)
continue;
if (wchar_len > 260)
continue;
if (!mod->BaseDllName.Buffer || !mod->BaseDllName.Length)
continue;

uint64_t h = fnv1a_64_rt_unicode_ci_to_ascii(mod->BaseDllName.Buffer, wchar_len);
if (h == name_hash) {
found = mod->DllBase;
break;
}
}
size_t wchar_len = mod->BaseDllName.Length / sizeof(wchar_t);
if (!wchar_len || wchar_len > 260)
continue;

out:
#if KC_IMPORT_HIDING_LOCK_MODULE_LIST
if (resource_acquired) {
ExReleaseResourceLite(&PsLoadedModuleResource);
resource_acquired = false;
}
if (in_critical) {
KeLeaveCriticalRegion();
in_critical = false;
}
#endif
uint64_t h = fnv1a_64_rt_unicode_ci_to_ascii(mod->BaseDllName.Buffer, wchar_len);

return found;
} __except (1) {
#if KC_IMPORT_HIDING_LOCK_MODULE_LIST
if (resource_acquired) {
ExReleaseResourceLite(&PsLoadedModuleResource);
if (h == name_hash) {
found = mod->DllBase;
break;
}
if (in_critical) {
KeLeaveCriticalRegion();
}
#endif
return nullptr;
}

ExReleaseResourceLite(&PsLoadedModuleResource);
KeLeaveCriticalRegion();

return found;
}

// resolve export from module base by case-insensitive function name hash
Expand Down
2 changes: 2 additions & 0 deletions security/integrity.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ KC_NOINLINE inline bool find_text_section(void* base, uintptr_t& text_va, uint32
}

// fallback: first section with IMAGE_SCN_MEM_EXECUTE
#ifndef IMAGE_SCN_MEM_EXECUTE
constexpr uint32_t IMAGE_SCN_MEM_EXECUTE = 0x20000000;
#endif
for (uint16_t i = 0; i < nt->FileHeader.NumberOfSections; ++i) {
if (section[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) {
text_va = reinterpret_cast<uintptr_t>(base) + section[i].VirtualAddress;
Expand Down