X64环境遍历32位进程的模块驱动代码
typedef struct _PEB_LDR_DATA
{
ULONG Length;
ULONG Initialized;
PVOID64 SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID64 EntryInProgress;
ULONG64 ShutdownInProgress;
PVOID64 ShutdownThreadId;
}PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY64 InLoadOrderLinks;
LIST_ENTRY64 InMemoryOrderLinks;
LIST_ENTRY64 InInitializationOrderLinks;
PVOID64 DllBase;
PVOID64 EntryPoint;
ULONG64 SizeOfImage;
UNICODE_STRING64 FullDllName;
UNICODE_STRING64 BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union {
LIST_ENTRY64 HashLinks;
struct {
PVOID64 SectionPointer;
ULONG64 CheckSum;
};
};
union {
struct {
ULONG TimeDateStamp;
};
struct {
PVOID64 LoadedImports;
};
};
ULONG64 * EntryPointActivationContext;
PVOID64 PatchInformation;
LIST_ENTRY64 ForwarderLinks;
LIST_ENTRY64 ServiceTagLinks;
LIST_ENTRY64 StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
//枚举进程并返回进程对象
PEPROCESS EnumProcessALL(char *ProcessName)//通过进程对象的对向链表遍历进程,缺点是进程名只能取十五个非中文字符
{
CHAR TProcessName = { 0 };
CHAR CProcessName = { 0 };
RtlZeroMemory(TProcessName, 32);
memcpy(TProcessName, ProcessName, strlen(ProcessName));//一般传进来的进程名不超过32个字符
_strupr(TProcessName); //转换成大写
PEPROCESS process;
PLIST_ENTRY64 plist, plist1;
process = PsGetCurrentProcess();
plist1 = plist = *(PULONG64)((ULONG64)process + 0x188);
do
{
process = (ULONG64)plist1 - 0x188;
RtlZeroMemory(CProcessName, 16);
memcpy(CProcessName, (char*)process + 0x2e0, 16);//一般传进来的进程名不超过32个字符
_strupr(CProcessName);
if (strstr(CProcessName, TProcessName) != 0 && *(ULONG64*)((ULONG64)process + 0x200)!=0)//句柄表中有值才是活的进程,句柄表中无值是同名的死进程
{
return process;
}
//进程对象从链表中摘除
//((PLIST_ENTRY64)(plist1->Flink))->Blink = plist1->Blink;//让前一个节点的后指针指向我的后一个节点,抹hashlinks
//((PLIST_ENTRY64)(plist1->Blink))->Flink = plist1->Flink;//让后一个节点的前指针指向我的前一个节点
//64位KdPrint 输出十进制用%ld,输出十六进制%p
//KdPrint(("count %ld -- process name is %15s --process id is %ld\n", count, (char*)process + 0x2e0, *(ULONG64*)((ULONG64)process + 0x180)));
plist1 = plist1->Blink;
} while (plist1 != plist);
return 0;
}WCHAR removeName = { 0 };
PEPROCESS pebprocess=0;
VOID HideDLLByPEBandNThash()//遍历进程用户层模块by PEB
{
pebprocess = EnumProcessALL("dnf");
if (pebprocess == NULL)
{
KdPrint(("dnf process is null \n"));
return;
}
PPEB processPEB=0;
PPEB_LDR_DATApldr_data, pldr_dataT;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PLIST_ENTRY plistLDR, plistLDR1;
PLDR_DATA_TABLE_ENTRY ldr_table_entry;
UNICODE_STRING KeattachProce;
UNICODE_STRING KeDetachProce;
PIMAGE_DOS_HEADER pimage_dos_header;
PIMAGE_NT_HEADERS pimage_nt_header;
MyKeAttachProcess((PKPROCESS)pebprocess);//附加到我们要摘链的用户层进程
processPEB = *(ULONG64*)((ULONG64)pebprocess + 0x338);//取得PEB
if (processPEB==0)
{
KdPrint(("peb is null \n"));
MyKeDetachProcess(pebprocess);
return;
}
KdPrint(("X64peb is %x\n", processPEB));
pldr_data = *(ULONG64*)((ULONG64)processPEB + 0x18);//取得_PEB_LDR_DATA
InLoadOrderModuleList = pldr_data->InLoadOrderModuleList;//从_PEB_LDR_DATA取得按加载顺序组织的模块链表
InMemoryOrderModuleList = pldr_data->InMemoryOrderModuleList;//从_PEB_LDR_DATA取得按内存顺序组织的模块链表
InInitializationOrderModuleList = pldr_data->InInitializationOrderModuleList;
/**********先处理x64NT模块中的那份HASH表,此表里面保存的是进程所有已加载模块******/
PLIST_ENTRY pNThash, pnt;
PLDR_DATA_TABLE_ENTRY pNTHashTalbeList;
plistLDR = InLoadOrderModuleList.Blink;
plistLDR1 = plistLDR;
do
{
ldr_table_entry = plistLDR;
memset(removeName, 0, 256 * 2);
RtlCopyMemory(removeName, ldr_table_entry->FullDllName.Buffer, ldr_table_entry->FullDllName.Length);
_wcsupr(removeName);
if (wcsstr(removeName, L"NTDLL") != 0 )//通过PEB遍历模块,如果找到NT模块就处理里面的HASHTABLE
{
//64位WIN7环境下syswow64目录下的NT模块基址加偏移0x13A940就是那份HASH数组的地址
pNThash = (PLIST_ENTRY)((ULONG64)ldr_table_entry->DllBase + 0x13A940);//在NTDLL里搜字符串LdrpHashTable可以定位此数组地址
KdPrint(("X64NT base is %p--hashtable is %p\n", ldr_table_entry->DllBase, pNThash));
//nt模块里的HASHtable是个数组,该数组有32个成员,每个成员是LIST_ENTRY,
//每个(LIST_ENTRY)双向链表维护了一组哈希值相同的模块
//每个进程中的NT基址是相同的,但是这个hashtalbe是和进程相关的,
//也就是说每一个进程有一份独立的hashtalbe
for (ULONG64 i = 0; i < 32; i++, pNThash++)
{
//如果数组中某个(LIST_ENTRY)双向链表成员是空,那么该元素的Blink和Flink的值就是LIST_ENTRY的地址
if (pNThash->Blink != pNThash)
{
pnt = pNThash->Blink;
do
{
pNTHashTalbeList = (ULONG64)pnt - 0x70;//X64 WIN7环境下hashlinks在_LDR_DATA_TABLE_ENTRY中的偏移是0x70
//memset(removeName, 0, 256 * 2);
if (MmIsAddressValid(pNTHashTalbeList->FullDllName.Buffer))
{
//RtlCopyMemory(removeName, pNTHashTalbeList->FullDllName.Buffer, pNTHashTalbeList->FullDllName.Length);
//_wcsupr(removeName);
//if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)
//{
// KdPrint(("find AACD IN NTDLL HASHTABLE AND REMOVE\n"));
// //pnt->Flink->Blink = pnt->Blink;//让前一个节点的后指针指向我的后一个节点,抹hashlinks
// //pnt->Blink->Flink = pnt->Flink;//让后一个节点的前指针指向我的前一个节点
//}
KdPrint(("X64nt hash index %d--dll base is %x-size %x--name %wZ\n", i, pNTHashTalbeList->DllBase, pNTHashTalbeList->SizeOfImage, &pNTHashTalbeList->FullDllName));
}
pnt = pnt->Blink;
} while (pnt != pNThash);//如果某个成员有值就循环遍历
}
}
break;
}
plistLDR = plistLDR->Blink;
} while (plistLDR != plistLDR1);
/*****************遍历x64PEB LDR第一个链表并将指定模块摘链******************************/
plistLDR = InLoadOrderModuleList.Blink;
plistLDR1 = plistLDR;
ULONG64 count = 0;
do
{
count = count + 1;
ldr_table_entry = plistLDR;
//memset(removeName, 0, 256 * 2);
//RtlCopyMemory(removeName, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.Length);
//_wcsupr(removeName);
//if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)//如果是我们要摘链的模块就进行摘链
//{
// KdPrint(("find and remove"));
// pimage_dos_header = ldr_table_entry->DllBase;
// KdPrint(("e_magic is %s\n", &pimage_dos_header->e_magic));
// PageProtectOff();
// //pimage_dos_header->e_magic= "0x1234";
// pimage_nt_header = pimage_dos_header->e_lfanew + (ULONG64)ldr_table_entry->DllBase;
// ULONG64 sizeheader = pimage_nt_header->OptionalHeader.SizeOfHeaders;
// KdPrint(("size of header is %d\n", sizeheader));
// memset(pimage_dos_header, 0, sizeheader);//整个PE头全部清零
// //pimage_nt_header->Signature = "0x87654321";
// PageProtectOn();
// plistLDR->Flink->Blink = plistLDR->Blink;//让前一个节点的后指针指向我的后一个节点
// plistLDR->Blink->Flink = plistLDR->Flink;//让后一个节点的前指针指向我的前一个节点
// break;
//}
KdPrint(("X64 LDR one index %d--base is %x--size %x--file name is %wZ\n",count, ldr_table_entry->DllBase, ldr_table_entry->SizeOfImage, &ldr_table_entry->FullDllName));
plistLDR = plistLDR->Blink;
} while (plistLDR != plistLDR1);
/*****************遍历x64PEB LDR第二个链表并将指定模块摘链***************************/
plistLDR = InMemoryOrderModuleList.Blink;
plistLDR1 = plistLDR;
count = 0;
do
{
count = count + 1;
ldr_table_entry = (ULONG64)plistLDR - 0x10;
//memset(removeName, 0, 128 * 2);
//RtlCopyMemory(removeName, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.Length);
//_wcsupr(removeName);
//if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)//如果是我们要摘链的模块就进行摘链
//{
// KdPrint(("find and remove"));
// plistLDR->Flink->Blink = plistLDR->Blink;//让前一个节点的后指针指向我的后一个节点
// plistLDR->Blink->Flink = plistLDR->Flink;//让后一个节点的前指针指向我的前一个节点
// break;
//}
KdPrint(("X64 LDR two index %d--base is %x--size %x--file name is %wZ\n", count, ldr_table_entry->DllBase, ldr_table_entry->SizeOfImage, &ldr_table_entry->FullDllName));
plistLDR = plistLDR->Blink;
} while (plistLDR1 != plistLDR);
/*****************遍历x64PEB LDR第三个链表并将指定模块摘链***************************/
plistLDR = InInitializationOrderModuleList.Blink;
plistLDR1 = plistLDR;
count = 0;
do
{
count = count + 1;
ldr_table_entry = (ULONG64)plistLDR - 0x20;
//memset(removeName, 0, 128 * 2);
//RtlCopyMemory(removeName, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.Length);
//_wcsupr(removeName);
//if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)//如果是我们要摘链的模块就进行摘链
//{
// KdPrint(("find and remove"));
// plistLDR->Flink->Blink = plistLDR->Blink;//让前一个节点的后指针指向我的后一个节点
// plistLDR->Blink->Flink = plistLDR->Flink;//让后一个节点的前指针指向我的前一个节点
// break;
//}
KdPrint(("X64 LDRthree index %d--base is %x--size %x--file name is %wZ\n", count, ldr_table_entry->DllBase, ldr_table_entry->SizeOfImage, &ldr_table_entry->FullDllName));
plistLDR = plistLDR->Blink;
} while (plistLDR1 != plistLDR);
/*****************x64PEB三个链表指定模块摘链完毕***************************/
//////开始遍历x64环境中的 PEB32三个链表中的模块,X64平台中的32位程序有两个PEB,一个里面保存了X64模块,一个里面保存了X86模块
ULONG processPEB32=0;
PPEB_LDR_DATA32pldr_data32, pldr_dataT32;
LIST_ENTRY32 InLoadOrderModuleList32;
LIST_ENTRY32 InMemoryOrderModuleList32;
LIST_ENTRY32 InInitializationOrderModuleList32;
PLIST_ENTRY32 plistLDR32, plistLDR132;
PLDR_DATA_TABLE_ENTRY32 ldr_table_entry32;
processPEB32 = *(ULONG*)((ULONG64)pebprocess + 0x320);//取得PEB32 //process是ulong64类型
if (processPEB32==0)
{
KdPrint(("processPEB32 if null \n"));
MyKeDetachProcess(pebprocess);
return;
}
KdPrint(("wow64peb is %x\n", processPEB32));
pldr_data32 = *(ULONG*)((ULONG)processPEB32 + 0xc);//取得_PEB_LDR_DATA
InLoadOrderModuleList32 = pldr_data32->InLoadOrderModuleList;//从_PEB_LDR_DATA取得按加载顺序组织的模块链表
InMemoryOrderModuleList32 = pldr_data32->InMemoryOrderModuleList;//从_PEB_LDR_DATA取得按内存顺序组织的模块链表
InInitializationOrderModuleList32 = pldr_data32->InInitializationOrderModuleList;
/**********先处理x64NT32模块中的那份HASH表,此表里面保存的是进程所有已加载的32位模块******/
PLIST_ENTRY32 pNThash32, pnt32;
PLDR_DATA_TABLE_ENTRY32 pNTHashTalbeList32;
plistLDR32 = InLoadOrderModuleList32.Blink;
plistLDR132 = plistLDR32;
do
{
ldr_table_entry32 = plistLDR32;
memset(removeName, 0, 256 * 2);
RtlCopyMemory(removeName, ldr_table_entry32->FullDllName.Buffer, ldr_table_entry32->FullDllName.Length);
_wcsupr(removeName);
if (wcsstr(removeName, L"NTDLL") != 0)//通过PEB遍历模块,如果找到NT模块就处理里面的HASHTABLE
{
//64位WIN7环境下syswow64目录下的NT模块基址加偏移0x104800就是那份HASH数组的地址
pNThash32 = (PLIST_ENTRY32)((ULONG)ldr_table_entry32->DllBase + 0x104800);//在NTDLL里搜字符串LdrpHashTable可以定位此数组地址
KdPrint(("NT base is %x--hashtable is %x\n", ldr_table_entry32->DllBase, pNThash32));
//nt模块里的HASHtable是个数组,该数组有32个成员,每个成员是LIST_ENTRY,
//每个(LIST_ENTRY)双向链表维护了一组哈希值相同的模块
//每个进程中的NT基址是相同的,但是这个hashtalbe是和进程相关的,
//也就是说每一个进程有一份独立的hashtalbe
for (ULONG i = 0; i < 32; i++, pNThash32++)
{
//如果数组中某个(LIST_ENTRY)双向链表成员是空,那么该元素的Blink和Flink的值就是LIST_ENTRY的地址
if (pNThash32->Blink != pNThash32)
{
pnt32 = pNThash32->Blink;
do
{
pNTHashTalbeList32 = (ULONG)pnt32 - 0x3C;
if (MmIsAddressValid(pNTHashTalbeList32->FullDllName.Buffer))
{
KdPrint(("wow64 nt hush index %d--dll base is %x -size %x --name %S\n", i, pNTHashTalbeList32->DllBase, pNTHashTalbeList32->SizeOfImage,pNTHashTalbeList32->FullDllName.Buffer));
}
pnt32 = pnt32->Blink;
} while (pnt32 != pNThash32);//如果某个成员有值就循环遍历
}
}
break;
}
plistLDR32 = plistLDR32->Blink;
} while (plistLDR32 != plistLDR132);
/*****************遍历x64 PEB32 LDR第一个链表并将指定模块摘链******************************/
plistLDR32 = InLoadOrderModuleList32.Blink;
plistLDR132 = plistLDR32;
count = 0;
do
{
count = count + 1;
ldr_table_entry32 = plistLDR32;
KdPrint(("wow64 LDR one index %d--base is %x--size %x--file name is %ws\n", count, ldr_table_entry32->DllBase, ldr_table_entry32->SizeOfImage, ldr_table_entry32->FullDllName.Buffer));
plistLDR32 = plistLDR32->Blink;
} while (plistLDR32 != plistLDR132);
/*****************遍历x64 PEB32 LDR第二个链表并将指定模块摘链***************************/
plistLDR32 = InMemoryOrderModuleList32.Blink;
plistLDR132 = plistLDR32;
count = 0;
do
{
count = count + 1;
ldr_table_entry32 = (ULONG)plistLDR32 - 8;
KdPrint(("wow64 LDR two index %d--base is %x--size %x--file name is %S\n", count, ldr_table_entry32->DllBase, ldr_table_entry32->SizeOfImage, ldr_table_entry32->FullDllName.Buffer));
plistLDR32 = plistLDR32->Blink;
} while (plistLDR132 != plistLDR32);
/*****************遍历x64 PEB32 LDR第三个链表并将指定模块摘链***************************/
plistLDR32 = InInitializationOrderModuleList32.Blink;
plistLDR132 = plistLDR32;
count = 0;
do
{
count = count + 1;
ldr_table_entry32 = (ULONG)plistLDR32 - 0x10;
KdPrint(("wow64 LDR three index %d--base is %x--size %x--file name is %ws\n", count, ldr_table_entry32->DllBase, ldr_table_entry32->SizeOfImage, ldr_table_entry32->FullDllName.Buffer));
plistLDR32 = plistLDR32->Blink;
} while (plistLDR132 != plistLDR32);
MyKeDetachProcess(pebprocess);
}
页:
[1]