Skip to content

Commit 26f5f02

Browse files
committed
v1.0 working + tidy up + readme
1 parent c837869 commit 26f5f02

File tree

2 files changed

+9
-46
lines changed

2 files changed

+9
-46
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# NTDLL Integrity Checker
1+
# Usermode rootkit detector
22

33
This project is designed to inspect and compare the NTDLL memory sections of running processes against the disk version of `ntdll.dll` in Windows systems. Its primary goal is to detect potential modifications indicative of usermode rootkits. Since the only way for usermode rootkit to exist is hooking NtResumeThread, or its neighbouring functions during thread creation to achieve persistence, checking ntdll's integrity is a viable way of observing rootkit's presence. Other methods of persistence include patching import table, however it is not reliable, since ntdll does not have an import table, thus leaving the .text section the only candidate for usermode hooks.
44

@@ -7,12 +7,13 @@ This project is designed to inspect and compare the NTDLL memory sections of run
77
- Parses `ntdll.dll` directly from disk to retrieve the `.text` section.
88
- Parses the `.text` section of `ntdll.dll` loaded in each running process's memory.
99
- Compares these sections to identify discrepancies.
10+
- Works for both wow64 and 64bit processes.
1011
- Provides a summary of potentially patched processes, aiding in the detection of usermode rootkits.
1112

1213
## Requirements
1314

1415
- Windows operating system.
15-
- Administrator privileges for process memory inspection.
16+
- (Optional) Administrator privileges for process memory inspection.
1617

1718
## Building
1819

@@ -22,4 +23,10 @@ This project is designed to inspect and compare the NTDLL memory sections of run
2223

2324
2. Compile either via a provided make.bat (gcc toolchain) or on your own with msvc or something.
2425

26+
## Notes
27+
28+
Tested against publicly available usermode rootkits:
29+
30+
- [r77](https://bytecode77.com/)
31+
- [My own one](https://github.com/forentfraps/rootkit-userland), since it does not replicate itself, however it does detect the altered processes
2532

main.c

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -499,42 +499,6 @@ int iterate_processes(unsigned char *stock_text64, int stock_size64,
499499
}
500500
return 0;
501501
}
502-
BOOL SetDebugPrivileges() {
503-
HANDLE hToken = NULL;
504-
TOKEN_PRIVILEGES tokenPrivileges;
505-
506-
if (!OpenProcessToken(GetCurrentProcess(),
507-
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
508-
printf("Failed to open process token. Error: %lu\n", GetLastError());
509-
return FALSE;
510-
}
511-
512-
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME,
513-
&tokenPrivileges.Privileges[0].Luid)) {
514-
printf("Failed to lookup privilege value. Error: %lu\n", GetLastError());
515-
CloseHandle(hToken);
516-
return FALSE;
517-
}
518-
519-
tokenPrivileges.PrivilegeCount = 1;
520-
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
521-
522-
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0,
523-
(PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
524-
printf("Failed to adjust token privileges. Error: %lu\n", GetLastError());
525-
CloseHandle(hToken);
526-
return FALSE;
527-
}
528-
529-
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
530-
printf("The token does not have the specified privilege.\n");
531-
CloseHandle(hToken);
532-
return FALSE;
533-
}
534-
535-
CloseHandle(hToken); // Close the token handle
536-
return TRUE; // Successfully enabled debug privileges
537-
}
538502

539503
BOOL ReadRemoteProcessMemory(DWORD processId, LPCVOID baseAddress,
540504
LPVOID buffer, SIZE_T size) {
@@ -557,20 +521,12 @@ BOOL ReadRemoteProcessMemory(DWORD processId, LPCVOID baseAddress,
557521
CloseHandle(processHandle);
558522
return TRUE;
559523
}
560-
int main1() {
561-
void *buffer = HeapAlloc(GetProcessHeap(), 0, 200);
562-
ReadRemoteProcessMemory(11180, (LPCVOID)0x76f90000, buffer, 200);
563-
}
564-
565524
int main() {
566-
void *virt_text;
567525
void *stock_text32;
568526
void *stock_text64;
569-
int virt_size;
570527
int stock_size32;
571528
int stock_size64;
572529
DWORD base_addr32;
573-
// SetDebugPrivileges();
574530
parse_disk_ntdll64(&stock_text64, &stock_size64);
575531
parse_disk_ntdll32(&stock_text32, &stock_size32, &base_addr32);
576532

0 commit comments

Comments
 (0)