看流星社区

 找回密码
 注册账号
查看: 3280|回复: 0

X64环境遍历32位进程的模块驱动代码

[复制链接]

该用户从未签到

发表于 2018-2-28 11:20:32 | 显示全部楼层 |阅读模式
  1. typedef struct _PEB_LDR_DATA
  2. {
  3.         ULONG Length;
  4.         ULONG Initialized;
  5.         PVOID64 SsHandle;
  6.         LIST_ENTRY InLoadOrderModuleList;
  7.         LIST_ENTRY InMemoryOrderModuleList;
  8.         LIST_ENTRY InInitializationOrderModuleList;
  9.         PVOID64 EntryInProgress;
  10.         ULONG64 ShutdownInProgress;
  11.         PVOID64 ShutdownThreadId;
  12. }PEB_LDR_DATA, *PPEB_LDR_DATA;

  13. typedef struct _LDR_DATA_TABLE_ENTRY {
  14.         LIST_ENTRY64 InLoadOrderLinks;
  15.         LIST_ENTRY64 InMemoryOrderLinks;
  16.         LIST_ENTRY64 InInitializationOrderLinks;
  17.         PVOID64 DllBase;
  18.         PVOID64 EntryPoint;
  19.         ULONG64 SizeOfImage;
  20.         UNICODE_STRING64 FullDllName;
  21.         UNICODE_STRING64 BaseDllName;
  22.         ULONG Flags;
  23.         USHORT LoadCount;
  24.         USHORT TlsIndex;
  25.         union {
  26.                 LIST_ENTRY64 HashLinks;
  27.                 struct {
  28.                         PVOID64 SectionPointer;
  29.                         ULONG64 CheckSum;
  30.                 };
  31.         };
  32.         union {
  33.                 struct {
  34.                         ULONG TimeDateStamp;
  35.                 };
  36.                 struct {
  37.                         PVOID64 LoadedImports;
  38.                 };
  39.         };
  40.         ULONG64 * EntryPointActivationContext;
  41.         PVOID64 PatchInformation;
  42.         LIST_ENTRY64 ForwarderLinks;
  43.         LIST_ENTRY64 ServiceTagLinks;
  44.         LIST_ENTRY64 StaticLinks;
  45. } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
复制代码

  1. //枚举进程并返回进程对象
  2. PEPROCESS EnumProcessALL(char *ProcessName)//通过进程对象的对向链表遍历进程,缺点是进程名只能取十五个非中文字符
  3. {
  4.         CHAR TProcessName[32] = { 0 };
  5.         CHAR CProcessName[16] = { 0 };
  6.         RtlZeroMemory(TProcessName, 32);
  7.         memcpy(TProcessName, ProcessName, strlen(ProcessName));//一般传进来的进程名不超过32个字符
  8.         _strupr(TProcessName); //转换成大写

  9.         PEPROCESS process;
  10.         PLIST_ENTRY64 plist, plist1;
  11.         process = PsGetCurrentProcess();
  12.         plist1 = plist = *(PULONG64)((ULONG64)process + 0x188);

  13.         do
  14.         {
  15.                 process = (ULONG64)plist1 - 0x188;
  16.                 RtlZeroMemory(CProcessName, 16);
  17.                 memcpy(CProcessName, (char*)process + 0x2e0, 16);//一般传进来的进程名不超过32个字符
  18.                 _strupr(CProcessName);
  19.                 if (strstr(CProcessName, TProcessName) != 0 && *(ULONG64*)((ULONG64)process + 0x200)!=0)//句柄表中有值才是活的进程,句柄表中无值是同名的死进程
  20.                 {
  21.                         return process;
  22.                 }
  23.             //进程对象从链表中摘除
  24.             //((PLIST_ENTRY64)(plist1->Flink))->Blink = plist1->Blink;//让前一个节点的后指针指向我的后一个节点,抹hashlinks
  25.                 //((PLIST_ENTRY64)(plist1->Blink))->Flink = plist1->Flink;//让后一个节点的前指针指向我的前一个节点
  26.                 //64位KdPrint 输出十进制用%ld,输出十六进制%p
  27.                 //KdPrint(("count %ld -- process name is %15s --process id is %ld\n", count, (char*)process + 0x2e0, *(ULONG64*)((ULONG64)process + 0x180)));
  28.                 plist1 = plist1->Blink;
  29.         } while (plist1 != plist);
  30.         return 0;
  31. }
复制代码
  1. WCHAR removeName[256] = { 0 };
  2. PEPROCESS pebprocess=0;
  3. VOID HideDLLByPEBandNThash()//遍历进程用户层模块by PEB
  4. {
  5.         pebprocess = EnumProcessALL("dnf");
  6.         if (pebprocess == NULL)
  7.         {
  8.                 KdPrint(("dnf process is null \n"));
  9.                 return;
  10.         }
  11.         PPEB processPEB=0;
  12.         PPEB_LDR_DATA  pldr_data, pldr_dataT;
  13.         LIST_ENTRY InLoadOrderModuleList;
  14.         LIST_ENTRY InMemoryOrderModuleList;
  15.         LIST_ENTRY InInitializationOrderModuleList;
  16.         PLIST_ENTRY plistLDR, plistLDR1;
  17.         PLDR_DATA_TABLE_ENTRY ldr_table_entry;
  18.         UNICODE_STRING KeattachProce;
  19.         UNICODE_STRING KeDetachProce;
  20.         PIMAGE_DOS_HEADER pimage_dos_header;
  21.         PIMAGE_NT_HEADERS pimage_nt_header;

  22.         MyKeAttachProcess((PKPROCESS)pebprocess);//附加到我们要摘链的用户层进程
  23.         processPEB = *(ULONG64*)((ULONG64)pebprocess + 0x338);//取得PEB
  24.         if (processPEB==0)
  25.         {
  26.                 KdPrint(("peb is null \n"));
  27.                 MyKeDetachProcess(pebprocess);
  28.                 return;
  29.         }
  30.         KdPrint(("X64peb is %x\n", processPEB));
  31.         pldr_data = *(ULONG64*)((ULONG64)processPEB + 0x18);//取得_PEB_LDR_DATA
  32.         InLoadOrderModuleList = pldr_data->InLoadOrderModuleList;//从_PEB_LDR_DATA取得按加载顺序组织的模块链表
  33.         InMemoryOrderModuleList = pldr_data->InMemoryOrderModuleList;//从_PEB_LDR_DATA取得按内存顺序组织的模块链表
  34.         InInitializationOrderModuleList = pldr_data->InInitializationOrderModuleList;
  35.         /**********先处理x64NT模块中的那份HASH表,此表里面保存的是进程所有已加载模块******/
  36.         PLIST_ENTRY pNThash, pnt;
  37.         PLDR_DATA_TABLE_ENTRY pNTHashTalbeList;
  38.         plistLDR = InLoadOrderModuleList.Blink;
  39.         plistLDR1 = plistLDR;
  40.         do
  41.         {
  42.                 ldr_table_entry = plistLDR;
  43.                 memset(removeName, 0, 256 * 2);
  44.                 RtlCopyMemory(removeName, ldr_table_entry->FullDllName.Buffer, ldr_table_entry->FullDllName.Length);
  45.                 _wcsupr(removeName);
  46.                 if (wcsstr(removeName, L"NTDLL") != 0 )//通过PEB遍历模块,如果找到NT模块就处理里面的HASHTABLE
  47.                 {
  48.                         //64位WIN7环境下syswow64目录下的NT模块基址加偏移0x13A940就是那份HASH数组的地址
  49.                         pNThash = (PLIST_ENTRY)((ULONG64)ldr_table_entry->DllBase + 0x13A940);//在NTDLL里搜字符串LdrpHashTable可以定位此数组地址
  50.                         KdPrint(("X64NT base is %p--hashtable is %p\n", ldr_table_entry->DllBase, pNThash));
  51.                         //nt模块里的HASHtable是个数组,该数组有32个成员,每个成员是LIST_ENTRY,
  52.                         //每个(LIST_ENTRY)双向链表维护了一组哈希值相同的模块
  53.                         //每个进程中的NT基址是相同的,但是这个hashtalbe是和进程相关的,
  54.                         //也就是说每一个进程有一份独立的hashtalbe
  55.                         for (ULONG64 i = 0; i < 32; i++, pNThash++)
  56.                         {
  57.                                 //如果数组中某个(LIST_ENTRY)双向链表成员是空,那么该元素的Blink和Flink的值就是LIST_ENTRY的地址
  58.                                 if (pNThash->Blink != pNThash)
  59.                                 {
  60.                                         pnt = pNThash->Blink;
  61.                                         do
  62.                                         {
  63.                                                 pNTHashTalbeList = (ULONG64)pnt - 0x70;//X64 WIN7环境下hashlinks在_LDR_DATA_TABLE_ENTRY中的偏移是0x70
  64.                                                 //memset(removeName, 0, 256 * 2);
  65.                                                 if (MmIsAddressValid(pNTHashTalbeList->FullDllName.Buffer))
  66.                                                 {
  67.                                                         //RtlCopyMemory(removeName, pNTHashTalbeList->FullDllName.Buffer, pNTHashTalbeList->FullDllName.Length);
  68.                                                         //_wcsupr(removeName);
  69.                                                         //if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)
  70.                                                         //{
  71.                                                         //        KdPrint(("find AACD IN NTDLL HASHTABLE AND REMOVE\n"));
  72.                                                         //        //pnt->Flink->Blink = pnt->Blink;//让前一个节点的后指针指向我的后一个节点,抹hashlinks
  73.                                                         //        //pnt->Blink->Flink = pnt->Flink;//让后一个节点的前指针指向我的前一个节点
  74.                                                         //}
  75.                                                         KdPrint(("X64nt hash index %d--dll base is %x  -size %x--name %wZ\n", i, pNTHashTalbeList->DllBase, pNTHashTalbeList->SizeOfImage, &pNTHashTalbeList->FullDllName));
  76.                                                 }
  77.                                                 pnt = pnt->Blink;
  78.                                         } while (pnt != pNThash);//如果某个成员有值就循环遍历
  79.                                 }
  80.                         }
  81.                         break;
  82.                 }
  83.                 plistLDR = plistLDR->Blink;
  84.         } while (plistLDR != plistLDR1);

  85.         /*****************遍历x64PEB LDR第一个链表并将指定模块摘链******************************/
  86.         plistLDR = InLoadOrderModuleList.Blink;
  87.         plistLDR1 = plistLDR;
  88.         ULONG64 count = 0;
  89.         do
  90.         {
  91.                 count = count + 1;
  92.                 ldr_table_entry = plistLDR;
  93.                 //memset(removeName, 0, 256 * 2);
  94.                 //RtlCopyMemory(removeName, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.Length);
  95.                 //_wcsupr(removeName);
  96.                 //if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)//如果是我们要摘链的模块就进行摘链
  97.                 //{
  98.                 //        KdPrint(("find and remove"));
  99.                 //        pimage_dos_header = ldr_table_entry->DllBase;
  100.                 //        KdPrint(("e_magic is %s\n", &pimage_dos_header->e_magic));
  101.                 //        PageProtectOff();
  102.                 //        //pimage_dos_header->e_magic= "0x1234";
  103.                 //        pimage_nt_header = pimage_dos_header->e_lfanew + (ULONG64)ldr_table_entry->DllBase;
  104.                 //        ULONG64 sizeheader = pimage_nt_header->OptionalHeader.SizeOfHeaders;
  105.                 //        KdPrint(("size of header is %d\n", sizeheader));
  106.                 //        memset(pimage_dos_header, 0, sizeheader);//整个PE头全部清零
  107.                 //        //pimage_nt_header->Signature = "0x87654321";
  108.                 //        PageProtectOn();
  109.                 //        plistLDR->Flink->Blink = plistLDR->Blink;//让前一个节点的后指针指向我的后一个节点
  110.                 //        plistLDR->Blink->Flink = plistLDR->Flink;//让后一个节点的前指针指向我的前一个节点
  111.                 //        break;
  112.                 //}
  113.                 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));
  114.                 plistLDR = plistLDR->Blink;
  115.         } while (plistLDR != plistLDR1);
  116.         /*****************遍历x64PEB LDR第二个链表并将指定模块摘链***************************/
  117.         plistLDR = InMemoryOrderModuleList.Blink;
  118.         plistLDR1 = plistLDR;
  119.         count = 0;
  120.         do
  121.         {
  122.                 count = count + 1;
  123.                 ldr_table_entry = (ULONG64)plistLDR - 0x10;
  124.                 //memset(removeName, 0, 128 * 2);
  125.                 //RtlCopyMemory(removeName, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.Length);
  126.                 //_wcsupr(removeName);
  127.                 //if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)//如果是我们要摘链的模块就进行摘链
  128.                 //{
  129.                 //        KdPrint(("find and remove"));
  130.                 //        plistLDR->Flink->Blink = plistLDR->Blink;//让前一个节点的后指针指向我的后一个节点
  131.                 //        plistLDR->Blink->Flink = plistLDR->Flink;//让后一个节点的前指针指向我的前一个节点
  132.                 //        break;
  133.                 //}
  134.                 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));
  135.                 plistLDR = plistLDR->Blink;
  136.         } while (plistLDR1 != plistLDR);
  137.         /*****************遍历x64PEB LDR第三个链表并将指定模块摘链***************************/
  138.         plistLDR = InInitializationOrderModuleList.Blink;
  139.         plistLDR1 = plistLDR;
  140.         count = 0;
  141.         do
  142.         {
  143.                 count = count + 1;
  144.                 ldr_table_entry = (ULONG64)plistLDR - 0x20;
  145.                 //memset(removeName, 0, 128 * 2);
  146.                 //RtlCopyMemory(removeName, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.Length);
  147.                 //_wcsupr(removeName);
  148.                 //if (wcsstr(removeName, L"AACD") != 0 || wcsstr(removeName, L"ABCD") != 0 || wcsstr(removeName, L"ACCD") != 0)//如果是我们要摘链的模块就进行摘链
  149.                 //{
  150.                 //        KdPrint(("find and remove"));
  151.                 //        plistLDR->Flink->Blink = plistLDR->Blink;//让前一个节点的后指针指向我的后一个节点
  152.                 //        plistLDR->Blink->Flink = plistLDR->Flink;//让后一个节点的前指针指向我的前一个节点
  153.                 //        break;
  154.                 //}
  155.                 KdPrint(("X64 LDR  three 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));
  156.                 plistLDR = plistLDR->Blink;
  157.         } while (plistLDR1 != plistLDR);
  158.         /*****************x64PEB三个链表指定模块摘链完毕***************************/

  159.         //////开始遍历x64环境中的 PEB32三个链表中的模块,X64平台中的32位程序有两个PEB,一个里面保存了X64模块,一个里面保存了X86模块
  160.         ULONG processPEB32=0;
  161.         PPEB_LDR_DATA32  pldr_data32, pldr_dataT32;
  162.         LIST_ENTRY32 InLoadOrderModuleList32;
  163.         LIST_ENTRY32 InMemoryOrderModuleList32;
  164.         LIST_ENTRY32 InInitializationOrderModuleList32;
  165.         PLIST_ENTRY32 plistLDR32, plistLDR132;
  166.         PLDR_DATA_TABLE_ENTRY32 ldr_table_entry32;

  167.         processPEB32 = *(ULONG*)((ULONG64)pebprocess + 0x320);//取得PEB32 //process是ulong64类型
  168.         if (processPEB32==0)
  169.         {
  170.                 KdPrint(("processPEB32 if null \n"));
  171.                 MyKeDetachProcess(pebprocess);
  172.                 return;
  173.         }
  174.         KdPrint(("wow64peb is %x\n", processPEB32));
  175.         pldr_data32 = *(ULONG*)((ULONG)processPEB32 + 0xc);//取得_PEB_LDR_DATA
  176.         InLoadOrderModuleList32 = pldr_data32->InLoadOrderModuleList;//从_PEB_LDR_DATA取得按加载顺序组织的模块链表
  177.         InMemoryOrderModuleList32 = pldr_data32->InMemoryOrderModuleList;//从_PEB_LDR_DATA取得按内存顺序组织的模块链表
  178.         InInitializationOrderModuleList32 = pldr_data32->InInitializationOrderModuleList;
  179.         /**********先处理x64NT32模块中的那份HASH表,此表里面保存的是进程所有已加载的32位模块******/
  180.         PLIST_ENTRY32 pNThash32, pnt32;
  181.         PLDR_DATA_TABLE_ENTRY32 pNTHashTalbeList32;
  182.         plistLDR32 = InLoadOrderModuleList32.Blink;
  183.         plistLDR132 = plistLDR32;
  184.         do
  185.         {
  186.                 ldr_table_entry32 = plistLDR32;
  187.                 memset(removeName, 0, 256 * 2);
  188.                 RtlCopyMemory(removeName, ldr_table_entry32->FullDllName.Buffer, ldr_table_entry32->FullDllName.Length);
  189.                 _wcsupr(removeName);
  190.                 if (wcsstr(removeName, L"NTDLL") != 0)//通过PEB遍历模块,如果找到NT模块就处理里面的HASHTABLE
  191.                 {
  192.                         //64位WIN7环境下syswow64目录下的NT模块基址加偏移0x104800就是那份HASH数组的地址
  193.                         pNThash32 = (PLIST_ENTRY32)((ULONG)ldr_table_entry32->DllBase + 0x104800);//在NTDLL里搜字符串LdrpHashTable可以定位此数组地址
  194.                         KdPrint(("NT base is %x--hashtable is %x\n", ldr_table_entry32->DllBase, pNThash32));
  195.                         //nt模块里的HASHtable是个数组,该数组有32个成员,每个成员是LIST_ENTRY,
  196.                         //每个(LIST_ENTRY)双向链表维护了一组哈希值相同的模块
  197.                         //每个进程中的NT基址是相同的,但是这个hashtalbe是和进程相关的,
  198.                         //也就是说每一个进程有一份独立的hashtalbe
  199.                         for (ULONG i = 0; i < 32; i++, pNThash32++)
  200.                         {
  201.                                 //如果数组中某个(LIST_ENTRY)双向链表成员是空,那么该元素的Blink和Flink的值就是LIST_ENTRY的地址
  202.                                 if (pNThash32->Blink != pNThash32)
  203.                                 {
  204.                                         pnt32 = pNThash32->Blink;
  205.                                         do
  206.                                         {
  207.                                                 pNTHashTalbeList32 = (ULONG)pnt32 - 0x3C;
  208.                                                 if (MmIsAddressValid(pNTHashTalbeList32->FullDllName.Buffer))
  209.                                                 {
  210.                                                         KdPrint(("wow64 nt hush index %d--dll base is %x -size %x --name %S\n", i, pNTHashTalbeList32->DllBase, pNTHashTalbeList32->SizeOfImage,pNTHashTalbeList32->FullDllName.Buffer));
  211.                                                 }
  212.                                                 pnt32 = pnt32->Blink;
  213.                                         } while (pnt32 != pNThash32);//如果某个成员有值就循环遍历
  214.                                 }
  215.                         }
  216.                         break;
  217.                 }
  218.                 plistLDR32 = plistLDR32->Blink;
  219.         } while (plistLDR32 != plistLDR132);

  220.         /*****************遍历x64 PEB32 LDR第一个链表并将指定模块摘链******************************/
  221.         plistLDR32 = InLoadOrderModuleList32.Blink;
  222.         plistLDR132 = plistLDR32;
  223.     count = 0;
  224.         do
  225.         {
  226.                 count = count + 1;
  227.                 ldr_table_entry32 = plistLDR32;
  228.                 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));
  229.                 plistLDR32 = plistLDR32->Blink;
  230.         } while (plistLDR32 != plistLDR132);
  231.         /*****************遍历x64 PEB32 LDR第二个链表并将指定模块摘链***************************/
  232.         plistLDR32 = InMemoryOrderModuleList32.Blink;
  233.         plistLDR132 = plistLDR32;
  234.         count = 0;
  235.         do
  236.         {
  237.                 count = count + 1;
  238.                 ldr_table_entry32 = (ULONG)plistLDR32 - 8;
  239.                 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));
  240.                 plistLDR32 = plistLDR32->Blink;
  241.         } while (plistLDR132 != plistLDR32);
  242.         /*****************遍历x64 PEB32 LDR第三个链表并将指定模块摘链***************************/
  243.         plistLDR32 = InInitializationOrderModuleList32.Blink;
  244.         plistLDR132 = plistLDR32;
  245.         count = 0;
  246.         do
  247.         {
  248.                 count = count + 1;
  249.                 ldr_table_entry32 = (ULONG)plistLDR32 - 0x10;
  250.                 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));
  251.                 plistLDR32 = plistLDR32->Blink;
  252.         } while (plistLDR132 != plistLDR32);
  253.         MyKeDetachProcess(pebprocess);
  254. }
复制代码

点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-23 20:33

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表