是由获得进程模块而引发的一系列的问题,首先,在ring3层下枚举进程模块有ToolHelp,Psapi,还可以通过在ntdll中获得ZwQuerySystemInformation的函数地址来枚举,其中ZwQueryInformationProcess相当于是调用系统服务函数,其内部实现就是遍历PEB中的Moudle链表,

kd> dt _PEB

+0x00c Ldr              : Ptr32 _PEB_LDR_DATA

kd> dt _PEB_LDR_DATA

nt!_PEB_LDR_DATA

+0x000 Length           : Uint4B

+0x004 Initialized         : UChar

+0x008 SsHandle         : Ptr32 Void

+0x00c InLoadOrderModuleList : _LIST_ENTRY        //按模块的加载顺序

+0x014 InMemoryOrderModuleList : _LIST_ENTRY     //按模块在内存中的地址顺序

+0x01c InInitializationOrderModuleList : _LIST_ENTRY  //按初始化顺序

+0x024 EntryInProgress  : Ptr32 Void

+0x028 ShutdownInProgress : UChar

+0x02c ShutdownThreadId : Ptr32 Void

整个链的结构就是下面这张图

  1. typedef struct _PEB_LDR_DATA32 //xp sp3 x86
  2. {
  3. ULONG Length;      0x00
  4. BOOLEAN Initialized;    0x04
  5. HANDLE SsHandle;    0x08
  6. LIST_ENTRY InLoadOrderModuleList;    0x0c //按模块的加载顺序
  7. LIST_ENTRY InMemoryOrderModuleList;      0x14 //按模块在内存中的地址顺序
  8. LIST_ENTRY InInitializationOrderModuleList; 0x1c //按初始化顺序
  9. PVOID EntryInProgress; 0x24
  10. } PEB_LDR_DATA32, *PPEB_LDR_DATA32;
  11.  
  12. typedef struct _PEB_LDR_DATA64 //win7 sp1 x64
  13. {
  14. ULONG Length;
  15. BOOLEAN Initialized;
  16. HANDLE SsHandle;
  17. LIST_ENTRY64 InLoadOrderModuleList;
  18. LIST_ENTRY64 InMemoryOrderModuleList;
  19. LIST_ENTRY64 InInitializationOrderModuleList;
  20. PVOID EntryInProgress;
  21. BOOLEAN ShutdownInProgress;
  22. PVOID ShutdownThreadId;
  23. } PEB_LDR_DATA64, *PPEB_LDR_DATA64;
  24.  
  25. 图中所示的_LDR_MOUDLE的结构如下:
  26. typedef struct _LDR_DATA_TABLE_ENTRY32 { //xp sp3 x86
  27. LIST_ENTRY InLoadOrderLinks;
  28. LIST_ENTRY InMemoryOrderLinks;
  29. LIST_ENTRY InInitializationOrderLinks;
  30. PVOID DllBase;
  31. PVOID EntryPoint;
  32. ULONG SizeOfImage;
  33. UNICODE_STRING FullDllName;
  34. UNICODE_STRING BaseDllName;
  35. ULONG Flags;
  36. USHORT LoadCount;
  37. USHORT TlsIndex;
  38. union {
  39. LIST_ENTRY HashLinks;
  40. struct {
  41. PVOID SectionPointer;
  42. ULONG CheckSum;
  43. };
  44. };
  45. union {
  46. struct {
  47. ULONG TimeDateStamp;
  48. };
  49. struct {
  50. PVOID LoadedImports;
  51. };
  52. };
  53. } LDR_DATA_TABLE_ENTRY32,*PLDR_DATA_TABLE_ENTRY32;
  54.  
  55. typedef struct _LDR_DATA_TABLE_ENTRY64 //win7 sp1 x64
  56. {
  57. LIST_ENTRY64 InLoadOrderLinks;
  58. LIST_ENTRY64 InMemoryOrderLinks;
  59. LIST_ENTRY64 InInitializationOrderLinks;
  60. PVOID DllBase;
  61. PVOID EntryPoint;
  62. ULONG SizeOfImage;
  63. UNICODE_STRING FullDllName;
  64. UNICODE_STRING BaseDllName;
  65. ULONG Flags;
  66. USHORT LoadCount;
  67. USHORT TlsIndex;
  68. PVOID SectionPointer;
  69. ULONG CheckSum;
  70. PVOID LoadedImports;
  71. PVOID EntryPointActivationContext;
  72. PVOID PatchInformation;
  73. LIST_ENTRY64 ForwarderLinks;
  74. LIST_ENTRY64 ServiceTagLinks;
  75. LIST_ENTRY64 StaticLinks;
  76. PVOID ContextInformation;
  77. ULONG64 OriginalBase;
  78. LARGE_INTEGER LoadTime;
  79. } LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;

很清晰的结构,只要遍历链表就能获得所有的模块的信息,具体的代码就不给出了。问题产生了,就像利用ActiveList来遍历进程一样,存在被断链的可能,如果被断链了,遍历Ldr的方法就失效了,模块也就被隐藏了。

那针对断链的隐藏进程有没有好的方法呢,答案是肯定的,这就利用到了进程中的内存管理。

我们知道Windows对于可执行映像都是采用内存映射文件的方式,而映射区对象(SectioinObject)中会存有与之关联的FileObject的指针,而文件对象中的域

+0x030 FileName         : _UNICODE_STRING

存放的就是整个映像文件的路径,所以我们可以来暴力搜索进程内存来得到进程模块,这里我们可以借助一个SSDT的函数,NtQueryVirtualMemory() 来枚举进程空间内的所有内存的信息,怎么获得NtQueryVirtualMemory函数地址我就不赘述了,

函数原型:

  1. typedef NTSTATUS
  2. (*pfnNtQueryVirtualMemory)(HANDLE ProcessHandle,PVOID BaseAddress,
  3. MEMORY_INFORMATION_CLASS MemoryInformationClass,
  4. PVOID MemoryInformation,
  5. SIZE_T MemoryInformationLength,
  6. PSIZE_T ReturnLength);

其中的MEMORY_INFORMATION_CLASS 是一个枚举量,来表示查询的是哪种信息

Wrk中搜的枚举类型

  1. typedef enum _MEMORY_INFORMATION_CLASS {
  2. MemoryBasicInformation
  3. #if DEVL
  4. ,MemoryWorkingSetInformation
  5. #endif
  6. ,MemoryMappedFilenameInformation
  7. ,MemoryRegionInformation
  8. ,MemoryWorkingSetExInformation
  9. } MEMORY_INFORMATION_CLASS;

而我自己一般用的就是下面的简化版

  1. typedef enum _MEMORY_INFORMATION_CLASS
  2. {
  3. MemoryBasicInformation, //内存基本信息
  4. MemoryWorkingSetList,
  5. MemorySectionName //内存映射文件名信息
  6. }MEMORY_INFORMATION_CLASS;

当我们使用MemoryBasicInformation 来查询时,MemoryInformation结构如下

  1. typedef struct _MEMORY_BASIC_INFORMATION {
  2. PVOID BaseAddress; //查询内存块所占的第一个页面基地址
  3. PVOID AllocationBase; //内存块所占的第一块区域基地址,小于等于BaseAddress,
  4. DWORD AllocationProtect; //区域被初次保留时赋予的保护属性
  5. SIZE_T RegionSize; //从BaseAddress开始,具有相同属性的页面的大小,
  6. DWORD State; //页面的状态,有三种可能值MEM_COMMIT、MEM_FREE和MEM_RESERVE
  7. DWORD Protect; //页面的属性,其可能的取值与AllocationProtect相同
  8. DWORD Type; //该内存块的类型,有三种可能值:MEM_IMAGE、MEM_MAPPED和MEM_PRIVATE
  9. } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

State指示虚拟内存的状态
MEM_COMMIT    指明已分配物理内存或者系统页文件。
MEM_RESERVE   指明页面被保留,但是没有分配任何物理内存。
MEM_FREE         空闲状态。该区域的虚拟地址没有分配任务物理内存

Type是指示物理存储器的类型

MEM_IMAGE   指明该区域的虚拟地址原先受内存映射的映像文件(如.exe或DLL文件)的支持,但也许不再受映像文件的支持。
         例如,当写入模块映像中的全局变量时,“写入时拷贝”的机制将由页文件来支持特定的页面,而不是受原始映像文件的支持。
MEM_MAPPED   该区域的虚拟地址原先是受内存映射的数据文件的支持,但也许不再受数据文件的支持。
         例如,数据文件可以使用“写入时拷贝”的保护属性来映射。对文件的任何写入操作都将导致页文件而不是原始数据支持特定的页面。
MEM_PRIVATE   指明该内存区域是私有的。不被其他进程共享。

用MemorySectionName 查询时MemoryInformation结构如下

  1. typedef struct _MEMORY_SECTION_NAME {
  2. UNICODE_STRING Name;
  3. WCHAR Buffer[_MAX_OBJECT_NAME];
  4. }MEMORY_SECTION_NAME,*PMEMORY_SECTION_NAME;

下面给出主要代码,思路就是调用NtQueryVirtualMemory来暴力遍历进程的所有内存

  1. NTSTATUS EnumMoudleByNtQueryVirtualMemory(ULONG ProcessId)
  2. {
  3. NTSTATUS Status;
  4. PEPROCESS EProcess = NULL;
  5. HANDLE hProcess = NULL;
  6. ULONG_PTR HighUserAddress = ;
  7. ULONG ulRet = ;
  8. #ifdef _WIN64
  9. HighUserAddress = 0x80000000000;
  10. #else
  11. HighUserAddress = 0x80000000;
  12. #endif
  13.  
  14. if (ProcessId)
  15. {
  16. Status = PsLookupProcessByProcessId((HANDLE)ProcessId, &EProcess);
  17. if (!NT_SUCCESS(Status))
  18. {
  19. return Status;
  20. }
  21. }
  22. if (IsRealProcess(EProcess)) //判断是否为僵尸进程,我只是判断了对象类型和句柄表是否存在
  23. {
  24. ObfDereferenceObject(EProcess);
  25. Status = ObOpenObjectByPointer(EProcess,
  26. OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
  27. NULL,
  28. GENERIC_ALL,
  29. *PsProcessType,
  30. KernelMode,
  31. &hProcess
  32. );
  33. if (NT_SUCCESS(Status))
  34. {
  35. ULONG_PTR ulBase = ;
  36. //改变PreviousMode
  37. PETHREAD EThread = PsGetCurrentThread();
  38. CHAR PreMode = ChangePreMode(EThread); //KernelMode
  39. do
  40. {
  41. MEMORY_BASIC_INFORMATION mbi = {};
  42. Status = NtQueryVirtualMemory(hProcess,
  43. (PVOID)ulBase,
  44. MemoryBasicInformation,
  45. &mbi,
  46. sizeof(MEMORY_BASIC_INFORMATION),
  47. &ulRet);
  48. if (NT_SUCCESS(Status))
  49. {
  50. //如果是Image 再查询SectionName,即FileObject Name
  51. if (mbi.Type==MEM_IMAGE)
  52. {
  53. MEMORY_SECTION_NAME msn = {};
  54. Status = NtQueryVirtualMemory(hProcess,
  55. (PVOID)ulBase,
  56. MemorySectionName,
  57. &msn,
  58. sizeof(MEMORY_SECTION_NAME),
  59. &ulRet);
  60. if (NT_SUCCESS(Status))
  61. {
  62. UNICODE_STRING DosName;
  63. DbgPrint("SectionName:%wZ\r\n",&(msn.SectionFileName));
  64. // DbgPrint("MoudleName:%S\r\n",msn.SectionFileName);
  65. RtlVolumeDeviceToDosName_(&(msn.SectionFileName),&DosName);
  66. DbgPrint("SectionName:%wZ\r\n",&(DosName));
  67. }
  68. }
  69. ulBase += mbi.RegionSize;
  70. }
  71. else ulBase += PAGE_SIZE;
  72. } while (ulBase < (ULONG_PTR)HighUserAddress);
  73. NtClose(hProcess);
  74. RecoverPreMode(EThread,PreMode);
  75. }
  76. }
  77. return Status;
  78. }

然后我们进一步探索NtQueryVirtualMemory的内部实现原理,先重点关注NtQueryVirtualMemory关于MemorySectionName==2 方式的处理流程,这里只以Win7 x86 Sp1为例列出我们要用到的几个结构,如果对于Windows 底层的内存管理想要深入了解,可以阅读《Windows内核原理及实现》和《Windows内核情景分析》中内存管理的相关章节。

我们可以看到EProcess进程体的VadRoot

  1. kd> dt _eprocess
  2. +0x278 VadRoot : _MM_AVL_TABLE
  1. kd> dt _MMADDRESS_NODE
  2. nt!_MMADDRESS_NODE
  3. +0x000 u1 : <unnamed-tag>
  4. +0x004 LeftChild : Ptr32 _MMADDRESS_NODE
  5. +0x008 RightChild : Ptr32 _MMADDRESS_NODE
  6. +0x00c StartingVpn : Uint4B
  7. +0x010 EndingVpn : Uint4B

可以看到Win 7Sp1 下的两种结构非常简单,提供不了太多有效的信息,我们再来看看xp sp3下的结构

  1. kd> dt _eprocess
  2. +0x11c VadRoot : Ptr32 Void

只是一个32位的指针,但是我们知道这个指针是指向_MMVAD结构,形成一颗二叉树结构

  1. kd> dt _mmvad
  2. nt!_MMVAD
  3. +0x000 StartingVpn : Uint4B
  4. +0x004 EndingVpn : Uint4B
  5. +0x008 Parent : Ptr32 _MMVAD
  6. +0x00c LeftChild : Ptr32 _MMVAD
  7. +0x010 RightChild : Ptr32 _MMVAD
  8. +0x014 u : __unnamed
  9. +0x018 ControlArea : Ptr32 _CONTROL_AREA
  10. +0x01c FirstPrototypePte : Ptr32 _MMPTE
  11. +0x020 LastContiguousPte : Ptr32 _MMPTE
  12. +0x024 u2 : __unnamed

然后尝试着在Win 7下输入 dt _MMVAD

  1. kd> dt _mmvad
  2. nt!_MMVAD
  3. +0x000 StartingVpn : Uint4B
  4. +0x004 EndingVpn : Uint4B
  5. +0x008 Parent : Ptr32 _MMVAD
  6. +0x00c LeftChild : Ptr32 _MMVAD
  7. +0x010 RightChild : Ptr32 _MMVAD
  8. +0x014 u : __unnamed
  9. +0x018 ControlArea : Ptr32 _CONTROL_AREA
  10. +0x01c FirstPrototypePte : Ptr32 _MMPTE
  11. +0x020 LastContiguousPte : Ptr32 _MMPTE
  12. +0x024 u2 : __unnamed

对比两个结构,发现了什么,没错,_MMADRESS_NODE只是_MMVAD结构体的前一部分,真正的内存块的节点还是_MMVAD结构

我们可以以calc.exe为例来体验一下整个流程 Win7 x86 sp1

  1. kd> !process
  2. **** NT ACTIVE PROCESS DUMP ****
  3. PROCESS 87b73cf8 SessionId: Cid: 0dd8 Peb: 7ffdf000 ParentCid: 07f4
  4. DirBase: 7f3455e0 ObjectTable: HandleCount: .
  5. Image: calc.exe
  1. kd> dt _eprocess 87b73cf8
  2. +0x278 VadRoot : _MM_AVL_TABLE
  1. kd> dt _MM_AVL_TABLE 87b73cf8+0x278
  2. nt!_MM_AVL_TABLE
  3. +0x000 BalancedRoot : _MMADDRESS_NODE
  4. +0x014 DepthOfTree : 0y01001 (0x9)
  5. +0x014 Unused : 0y000
  6. +0x014 NumberGenericTableElements : 0y000000000000000010011111 (0x9f)
  7. +0x018 NodeHint : 0x876c4ec8 Void
  8. +0x01c NodeFreeHint : (null)
  1. kd> dt _MMADDRESS_NODE 87b73cf8+0x278
  2. nt!_MMADDRESS_NODE
  3. +0x000 u1 : <unnamed-tag>
  4. +0x004 LeftChild : (null)
  5. +0x008 RightChild : 0x87c327e0 _MMADDRESS_NODE
  6. +0x00c StartingVpn :
  7. +0x010 EndingVpn :

注意Win 7下的根结点只利用了右子树,想当与跟节点的右子树才是真正意义上的AVL树的根节点,继续跟入:

  1. kd> dt _MMVAD 0x87c327e0
  2. nt!_MMVAD
  3. +0x000 u1 : <unnamed-tag>
  4. +0x004 LeftChild : 0x87ac3248 _MMVAD
  5. +0x008 RightChild : 0x87c2b3b8 _MMVAD
  6. +0x00c StartingVpn : 0xd80
  7. +0x010 EndingVpn : 0xe3f
  8. +0x014 u : <unnamed-tag>
  9. +0x018 PushLock : _EX_PUSH_LOCK
  10. +0x01c u5 : <unnamed-tag>
  11. +0x020 u2 : <unnamed-tag>
  12. +0x024 Subsection : 0x880a3410 _SUBSECTION //我们接下来要跟的就是这个结构
  13. +0x024 MappedSubsection : 0x880a3410 _MSUBSECTION
  14. +0x028 FirstPrototypePte : 0x961b69c8 _MMPTE
  15. +0x02c LastContiguousPte : 0xfffffffc _MMPTE
  16. +0x030 ViewLinks : _LIST_ENTRY [ 0x880a3408 - 0x880a3408 ]
  17. +0x038 VadsProcess : 0x87b73cf9 _EPROCESS
  1. kd> dt _SUBSECTION 0x880a3410
  2. nt!_SUBSECTION
  3. +0x000 ControlArea : 0x880a33c0 _CONTROL_AREA //跟这个结构
  4. +0x004 SubsectionBase : 0x961b69c8 _MMPTE
  5. +0x008 NextSubsection : 0x880a3430 _SUBSECTION
  6. +0x00c PtesInSubsection :
  7. +0x010 UnusedPtes :
  8. +0x010 GlobalPerSessionHead : (null)
  9. +0x014 u : <unnamed-tag>
  10. +0x018 StartingSector :
  11. +0x01c NumberOfFullSectors :
  1. kd> dt _CONTROL_AREA 0x880a33c0
  2. nt!_CONTROL_AREA
  3. +0x000 Segment : 0x961b6998 _SEGMENT
  4. +0x004 DereferenceList : _LIST_ENTRY [ 0x0 - 0x880d7104 ]
  5. +0x00c NumberOfSectionReferences :
  6. +0x010 NumberOfPfnReferences : 0x86
  7. +0x014 NumberOfMappedViews :
  8. +0x018 NumberOfUserReferences :
  9. +0x01c u : <unnamed-tag>
  10. +0x020 FlushInProgressCount :
  11. +0x024 FilePointer : _EX_FAST_REF //关联的文件对象就在这个结构里面了
  12. +0x028 ControlAreaLock : 0n0
  13. +0x02c ModifiedWriteCount :
  14. +0x02c StartingFrame :
  15. +0x030 WaitingForDeletion : (null)
  16. +0x034 u2 : <unnamed-tag>
  17. +0x040 LockedPages : 0n1
  18. +0x048 ViewList : _LIST_ENTRY [ 0x87c32810 - 0x87c32810 ]
  1. kd> dt _EX_FAST_REF 0x880a33c0+0x24
  2. nt!_EX_FAST_REF
  3. +0x000 Object : 0x880a1b43 Void //关联的文件对象
  4. +0x000 RefCnt : 0y011
  5. +0x000 Value : 0x880a1b43

注意,这里关联的文件对象要&0x0FFFFFFF8(最后三位清零)才是正真的文件对象

  1. kd> !object 0x880a1b43&0x0fffffff8
  2. Object: 880a1b40 Type: (863ff650) File
  3. ObjectHeader: 880a1b28 (new version)
  4. HandleCount: PointerCount:
  5. Directory Object: Name: \Windows\System32\calc.exe {HarddiskVolume1} //文件对象名,完整路径

了解了这些结构体之后,再看NtQueryVirtualMemory函数关于MemorySectionName的处理流程,贴出ida分析的过程,只分析了我们关注的MemorySectionName的方式,wrk中也有源码

  1. PAGE:0063F242 ; NTSTATUS __stdcall NtQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, ULONG MemoryInformationLength, PULONG ReturnLength)
  2. PAGE:0063F242 _NtQueryVirtualMemory@24 proc near
  3. PAGE:0063F242 ; DATA XREF: .text:0045CB68o
  4. PAGE:0063F242
  5. PAGE:0063F242 var_7C= dword ptr -7Ch
  6. PAGE:0063F242 var_78= dword ptr -78h
  7. PAGE:0063F242 var_74= dword ptr -74h
  8. PAGE:0063F242 var_70= dword ptr -70h
  9. PAGE:0063F242 var_64= dword ptr -64h
  10. PAGE:0063F242 ApcState= dword ptr -60h
  11. PAGE:0063F242 var_48= dword ptr -48h
  12. PAGE:0063F242 var_44= dword ptr -44h
  13. PAGE:0063F242 var_40= dword ptr -40h
  14. PAGE:0063F242 var_3C= dword ptr -3Ch
  15. PAGE:0063F242 var_38= dword ptr -38h
  16. PAGE:0063F242 Object= dword ptr -34h
  17. PAGE:0063F242 AccessMode= byte ptr -30h
  18. PAGE:0063F242 var_2C= dword ptr -2Ch
  19. PAGE:0063F242 var_28= dword ptr -28h
  20. PAGE:0063F242 var_24= dword ptr -24h
  21. PAGE:0063F242 EProcess= dword ptr -20h
  22. PAGE:0063F242 var_1C??Attached= dword ptr -1Ch
  23. PAGE:0063F242 ms_exc= CPPEH_RECORD ptr -18h
  24. PAGE:0063F242 ProcessHandle= dword ptr
  25. PAGE:0063F242 BaseAddress= dword ptr 0Ch
  26. PAGE:0063F242 MemoryInformationClass= dword ptr 10h
  27. PAGE:0063F242 MemoryInformation= dword ptr 14h
  28. PAGE:0063F242 MemoryInformationLength= dword ptr 18h
  29. PAGE:0063F242 ReturnLength= dword ptr 1Ch
  30. PAGE:0063F242
  31. PAGE:0063F242 6A 6C push 6Ch
  32. PAGE:0063F244 0F push offset stru_450F18
  33. PAGE:0063F249 E8 D2 4F E1 FF call __SEH_prolog4
  34. PAGE:0063F24E F6 xor esi, esi
  35. PAGE:0063F250 E4 mov [ebp+var_1C??Attached], esi
  36. PAGE:0063F253 DC mov [ebp+var_24], esi
  37. PAGE:0063F256 8B mov eax, [ebp+MemoryInformationClass]
  38. PAGE:0063F259 2B C6 sub eax, esi ; Handler MemoryBasicInformation
  39. PAGE:0063F25B jz short Handler_MemoryBasicInformation
  40. PAGE:0063F25D dec eax ; Handler MemoryWorkingSetList
  41. PAGE:0063F25E 1F jz short Handler_MemoryWorkingSetList
  42. PAGE:0063F260 dec eax
  43. PAGE:0063F261 jz short loc_63F295 ; Handler_MemoryMappedFilenameInformation
  44. PAGE:0063F263 dec eax
  45. PAGE:0063F264 jz short loc_63F279
  46. PAGE:0063F266 dec eax
  47. PAGE:0063F267 0A jz short loc_63F273
  48. PAGE:0063F269 B8 C0 mov eax, 0C0000003h
  49. PAGE:0063F26E E9 D6 jmp loc_63F949
  50. PAGE:0063F273 ; ---------------------------------------------------------------------------
  51. PAGE:0063F273
  52. PAGE:0063F273 loc_63F273: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+25j
  53. PAGE:0063F273 7D cmp [ebp+MemoryInformationLength],
  54. PAGE:0063F277 EB jmp short loc_63F289
  55. PAGE:0063F279 ; ---------------------------------------------------------------------------
  56. PAGE:0063F279
  57. PAGE:0063F279 loc_63F279: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+22j
  58. PAGE:0063F279 7D cmp [ebp+MemoryInformationLength], 10h
  59. PAGE:0063F27D EB 0A jmp short loc_63F289
  60. PAGE:0063F27F ; ---------------------------------------------------------------------------
  61. PAGE:0063F27F
  62. PAGE:0063F27F Handler_MemoryWorkingSetList: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+1Cj
  63. PAGE:0063F27F 7D cmp [ebp+MemoryInformationLength],
  64. PAGE:0063F283 EB jmp short loc_63F289
  65. PAGE:0063F285 ; ---------------------------------------------------------------------------
  66. PAGE:0063F285
  67. PAGE:0063F285 Handler_MemoryBasicInformation:
  68. PAGE:0063F285 ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+19j
  69. PAGE:0063F285 7D 1C cmp [ebp+MemoryInformationLength], 1Ch
  70. PAGE:0063F289
  71. PAGE:0063F289 loc_63F289: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+35j
  72. PAGE:0063F289 ; NtQueryVirtualMemory(x,x,x,x,x,x)+3Bj
  73. PAGE:0063F289 ; NtQueryVirtualMemory(x,x,x,x,x,x)+41j
  74. PAGE:0063F289 0A jnb short loc_63F295
  75. PAGE:0063F28B B8 C0 mov eax, 0C0000004h
  76. PAGE:0063F290 E9 B4 jmp loc_63F949
  77. PAGE:0063F295 ; ---------------------------------------------------------------------------
  78. PAGE:0063F295
  79. PAGE:0063F295 loc_63F295: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+1Fj
  80. PAGE:0063F295 ; NtQueryVirtualMemory(x,x,x,x,x,x):loc_63F289j
  81. PAGE:0063F295 8B 1D +mov ebx, large fs:124h ; Handler_MemoryMappedFilenameInformation
  82. PAGE:0063F29C 8A 3A mov al, [ebx+13Ah] ; FS寄存器指向当前CPUKPCR KPCR+0x124指向当前线程对象
  83. PAGE:0063F29C ; +0x13A获取先前的调用模式<KernelMode/UserMode>
  84. PAGE:0063F2A2 D0 mov [ebp+AccessMode], al
  85. PAGE:0063F2A5 C0 test al, al ; KernelMode=0,UserMode=1
  86. PAGE:0063F2A7 jz short loc_63F2F9
  87. PAGE:0063F2A9 FC mov [ebp+ms_exc.registration.TryLevel], esi ; 很明显的异常处理,与我们分析无关,忽略
  88. PAGE:0063F2AC 6A push ; Alignment
  89. PAGE:0063F2AC ; UserMode
  90. PAGE:0063F2AE FF push [ebp+MemoryInformationLength] ; Length
  91. PAGE:0063F2B1 8B 7D mov edi, [ebp+MemoryInformation]
  92. PAGE:0063F2B4 push edi ; Address
  93. PAGE:0063F2B5 E8 B3 E0 FB FF call _ProbeForWrite@12 ; 查看用户态内存是否可写
  94. PAGE:0063F2BA 8B 4D 1C mov ecx, [ebp+ReturnLength]
  95. PAGE:0063F2BD 3B CE cmp ecx, esi ; 此时的esi=0,即比较ReturnLength是否为0
  96. PAGE:0063F2BF 0F jz short loc_63F2D0 ; ReturnLength==0则跳转
  97. PAGE:0063F2C1 A1 mov eax, ds:_MmUserProbeAddress ; 检查此地址是否高于用户边界地址,
  98. PAGE:0063F2C1 ; _MmUserProbeAddress == 7fff0000
  99. PAGE:0063F2C6 3B C8 cmp ecx, eax
  100. PAGE:0063F2C8 jb short loc_63F2CC ; 低于的话则跳转,正常来讲一定会跳
  101. PAGE:0063F2CA 8B C8 mov ecx, eax ; 异常处理,忽略
  102. PAGE:0063F2CC
  103. PAGE:0063F2CC loc_63F2CC: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+86j
  104. PAGE:0063F2CC 8B mov eax, [ecx]
  105. PAGE:0063F2CE mov [ecx], eax
  106. PAGE:0063F2D0
  107. PAGE:0063F2D0 loc_63F2D0: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+7Dj
  108. PAGE:0063F2D0 C7 FC FE FF FF+mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh ; 很明显的SEH处理,
  109. PAGE:0063F2D0 FF ; 改变TryLevel,忽略
  110. PAGE:0063F2D7 EB jmp short loc_63F2FC ; 一般参数没问题,直接跳转
  111. PAGE:0063F2D9 ; ---------------------------------------------------------------------------
  112. PAGE:0063F2D9
  113. PAGE:0063F2D9 loc_63F2D9: ; DATA XREF: .text:stru_450F18o
  114. PAGE:0063F2D9 8B EC mov eax, [ebp+ms_exc.exc_ptr] ; 很明显,如果参数有问题,就直接返回了
  115. PAGE:0063F2DC 8B mov eax, [eax]
  116. PAGE:0063F2DE 8B mov eax, [eax]
  117. PAGE:0063F2E0 D4 mov [ebp+var_2C], eax
  118. PAGE:0063F2E3 C0 xor eax, eax
  119. PAGE:0063F2E5 inc eax
  120. PAGE:0063F2E6 C3 retn
  121. PAGE:0063F2E7 ; ---------------------------------------------------------------------------
  122. PAGE:0063F2E7
  123. PAGE:0063F2E7 loc_63F2E7: ; DATA XREF: .text:stru_450F18o
  124. PAGE:0063F2E7 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 0 for function 63F242
  125. PAGE:0063F2EA 8B D4 mov eax, [ebp+var_2C]
  126. PAGE:0063F2ED
  127. PAGE:0063F2ED loc_63F2ED: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+3DBj
  128. PAGE:0063F2ED ; NtQueryVirtualMemory(x,x,x,x,x,x)+55Bj
  129. PAGE:0063F2ED ; NtQueryVirtualMemory(x,x,x,x,x,x)+620j
  130. PAGE:0063F2ED C7 FC FE FF FF+mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  131. PAGE:0063F2F4 E9 jmp loc_63F949
  132. PAGE:0063F2F9 ; ---------------------------------------------------------------------------
  133. PAGE:0063F2F9
  134. PAGE:0063F2F9 loc_63F2F9: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+65j
  135. PAGE:0063F2F9 8B 7D mov edi, [ebp+MemoryInformation] ; KernelMode
  136. PAGE:0063F2FC
  137. PAGE:0063F2FC loc_63F2FC: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+95j
  138. PAGE:0063F2FC 8B 0C mov eax, [ebp+BaseAddress] ; 还是参数的校验,我们要查询的虚拟地址
  139. PAGE:0063F2FF 8B 0D FC mov ecx, ds:_MmHighestUserAddress ; MmHighestUserAddress==0x7ffeffff
  140. PAGE:0063F2FF ; (这是用户空间可以访问的最高地址,
  141. PAGE:0063F2FF ; 逻辑上的而已,上面还有个64K的禁区(飞地)就到内核空间了)
  142. PAGE:0063F305 3B C1 cmp eax, ecx
  143. PAGE:0063F307 0A jbe short loc_63F313
  144. PAGE:0063F309 B8 0D C0 mov eax, 0C000000Dh ; Status的返回值 STATUS_INVALID_PARAMETER(参数无效)
  145. PAGE:0063F30E E9 jmp loc_63F949 ; 返回
  146. PAGE:0063F313 ; ---------------------------------------------------------------------------
  147. PAGE:0063F313
  148. PAGE:0063F313 loc_63F313: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+C5j
  149. PAGE:0063F313 8D B1 FF FF lea esi, [ecx-10000h] ; esi==0x7ffdffff
  150. PAGE:0063F319 D8 mov [ebp+var_28], esi ; 保存允许查询的最高地址,作为查询的虚拟地址的终结点
  151. PAGE:0063F31C BA F0 FF FF mov edx, 0FFFFF000h
  152. PAGE:0063F321 3B C6 cmp eax, esi ; 判断查询的虚拟地址是否高于终结点
  153. PAGE:0063F323 0F A6 ja loc_63F8CF ; 高于,跳转,等会再看具体处理
  154. PAGE:0063F329 mov [ebp+MemoryInformation], eax ; 将地址保存
  155. PAGE:0063F32C and [ebp+MemoryInformation], edx ; edi==0FFFFF000h 取整得到虚拟地址的内存页首地址
  156. PAGE:0063F32F 7D FE+cmp [ebp+MemoryInformation], 7FFE0000h ; 判断地址是否大于SharedUserData
  157. PAGE:0063F32F 7F ; 也就是说SharedUserData为最后一个合法的用户边界
  158. PAGE:0063F336 0F jz loc_63F8CF
  159. PAGE:0063F33C 7D FF cmp [ebp+ProcessHandle], 0FFFFFFFFh
  160. PAGE:0063F340 jnz short loc_63F34A ; 不是本身的进程就跳转
  161. PAGE:0063F342 8B mov esi, [ebx+50h] ; ebx为线程对象,+0x50就为进程对象
  162. PAGE:0063F345 E0 mov [ebp+EProcess], esi
  163. PAGE:0063F348 EB 2A jmp short loc_63F374
  164. PAGE:0063F34A ; ---------------------------------------------------------------------------
  165. PAGE:0063F34A
  166. PAGE:0063F34A loc_63F34A: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+FEj
  167. PAGE:0063F34A 6A push ; HandleInformation
  168. PAGE:0063F34C 8D CC lea eax, [ebp+Object]
  169. PAGE:0063F34F push eax ; Object
  170. PAGE:0063F350 FF D0 push dword ptr [ebp+AccessMode] ; AccessMode
  171. PAGE:0063F353 FF 2C push ds:_PsProcessType ; ObjectType
  172. PAGE:0063F359 push 400h ; DesiredAccess
  173. PAGE:0063F35E FF push [ebp+ProcessHandle] ; Handle
  174. PAGE:0063F361 E8 F6 D0 FB FF call _ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)
  175. PAGE:0063F366 8B CC mov esi, [ebp+Object]
  176. PAGE:0063F369 E0 mov [ebp+EProcess], esi
  177. PAGE:0063F36C C0 test eax, eax
  178. PAGE:0063F36E 0F 8C D5 jl loc_63F949
  179. PAGE:0063F374
  180. PAGE:0063F374 loc_63F374: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+106j
  181. PAGE:0063F374 7D cmp [ebp+MemoryInformationClass], ; MemoryRegionInformation方式查询
  182. PAGE:0063F378 4D jnz short loc_63F3C7
  183. PAGE:0063F37A push esi
  184. PAGE:0063F37B 8B 5D mov ebx, [ebp+MemoryInformationLength]
  185. PAGE:0063F37E push ebx
  186. PAGE:0063F37F 8B CF mov ecx, edi
  187. PAGE:0063F381 E8 FF B8 DE FF call _MiGetWorkingSetInfoList@12 ; MiGetWorkingSetInfoList(x,x,x)
  188. PAGE:0063F386 8B F8 mov edi, eax
  189. PAGE:0063F388 7D FF cmp [ebp+ProcessHandle], 0FFFFFFFFh
  190. PAGE:0063F38C jz short loc_63F395
  191. PAGE:0063F38E 8B CE mov ecx, esi ; Object
  192. PAGE:0063F390 E8 E1 FF call @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
  193. PAGE:0063F395
  194. PAGE:0063F395 loc_63F395: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+14Aj
  195. PAGE:0063F395 FF test edi, edi
  196. PAGE:0063F397 7D jge short loc_63F3A0
  197. PAGE:0063F399 8B C7 mov eax, edi
  198. PAGE:0063F39B E9 A9 jmp loc_63F949
  199. PAGE:0063F3A0 ; ---------------------------------------------------------------------------
  200. PAGE:0063F3A0
  201. PAGE:0063F3A0 loc_63F3A0: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+155j
  202. PAGE:0063F3A0 C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  203. PAGE:0063F3A7 8B 1C mov eax, [ebp+ReturnLength]
  204. PAGE:0063F3AA C0 test eax, eax
  205. PAGE:0063F3AC 0B jz short loc_63F3B9
  206. PAGE:0063F3AE mov [eax], ebx
  207. PAGE:0063F3B0 EB jmp short loc_63F3B9
  208. PAGE:0063F3B2 ; ---------------------------------------------------------------------------
  209. PAGE:0063F3B2
  210. PAGE:0063F3B2 loc_63F3B2: ; DATA XREF: .text:stru_450F18o
  211. PAGE:0063F3B2 C0 xor eax, eax ; Exception filter 2 for function 63F242
  212. PAGE:0063F3B4 inc eax
  213. PAGE:0063F3B5 C3 retn
  214. PAGE:0063F3B6 ; ---------------------------------------------------------------------------
  215. PAGE:0063F3B6
  216. PAGE:0063F3B6 loc_63F3B6: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x):loc_63F40Ej
  217. PAGE:0063F3B6 ; DATA XREF: .text:stru_450F18o
  218. PAGE:0063F3B6 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 2 for function 63F242
  219. PAGE:0063F3B9
  220. PAGE:0063F3B9 loc_63F3B9: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+16Aj
  221. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+16Ej
  222. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+1B9j
  223. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+1C6j
  224. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x):loc_63F5EEj
  225. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+3B8j
  226. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+3D2j
  227. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+52Cj
  228. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+538j
  229. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+552j
  230. PAGE:0063F3B9 ; NtQueryVirtualMemory(x,x,x,x,x,x)+617j
  231. PAGE:0063F3B9 C7 FC FE FF FF+mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  232. PAGE:0063F3C0 C0 xor eax, eax
  233. PAGE:0063F3C2 E9 jmp loc_63F949
  234. PAGE:0063F3C7 ; ---------------------------------------------------------------------------
  235. PAGE:0063F3C7
  236. PAGE:0063F3C7 loc_63F3C7: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+136j
  237. PAGE:0063F3C7 7D cmp [ebp+MemoryInformationClass],
  238. PAGE:0063F3CB jnz short loc_63F410
  239. PAGE:0063F3CD push esi ; BugCheckParameter1
  240. PAGE:0063F3CE FF push [ebp+MemoryInformationLength] ; int
  241. PAGE:0063F3D1 8B CF mov ecx, edi
  242. PAGE:0063F3D3 E8 A3 E7 FF call _MiGetWorkingSetInfo@12 ; MiGetWorkingSetInfo(x,x,x)
  243. PAGE:0063F3D8 8B D8 mov ebx, eax
  244. PAGE:0063F3DA 7D FF cmp [ebp+ProcessHandle], 0FFFFFFFFh
  245. PAGE:0063F3DE jz short loc_63F3E7
  246. PAGE:0063F3E0 8B CE mov ecx, esi ; Object
  247. PAGE:0063F3E2 E8 E1 FF call @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
  248. PAGE:0063F3E7
  249. PAGE:0063F3E7 loc_63F3E7: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+19Cj
  250. PAGE:0063F3E7 DB test ebx, ebx
  251. PAGE:0063F3E9 0F 8C jl loc_63F947
  252. PAGE:0063F3EF C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  253. PAGE:0063F3F6 8B 1C mov eax, [ebp+ReturnLength]
  254. PAGE:0063F3F9 C0 test eax, eax
  255. PAGE:0063F3FB BC jz short loc_63F3B9
  256. PAGE:0063F3FD 8B 0F mov ecx, [edi]
  257. PAGE:0063F3FF 8D 0C 8D +lea ecx, ds:[ecx*]
  258. PAGE:0063F406 mov [eax], ecx
  259. PAGE:0063F408 EB AF jmp short loc_63F3B9
  260. PAGE:0063F40A ; ---------------------------------------------------------------------------
  261. PAGE:0063F40A
  262. PAGE:0063F40A loc_63F40A: ; DATA XREF: .text:stru_450F18o
  263. PAGE:0063F40A C0 xor eax, eax ; Exception filter 3 for function 63F242
  264. PAGE:0063F40C inc eax
  265. PAGE:0063F40D C3 retn
  266. PAGE:0063F40E ; ---------------------------------------------------------------------------
  267. PAGE:0063F40E
  268. PAGE:0063F40E loc_63F40E: ; DATA XREF: .text:stru_450F18o
  269. PAGE:0063F40E EB A6 jmp short loc_63F3B6 ; Exception handler 3 for function 63F242
  270. PAGE:0063F410 ; ---------------------------------------------------------------------------
  271. PAGE:0063F410
  272. PAGE:0063F410 loc_63F410: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+189j
  273. PAGE:0063F410 7D FF cmp [ebp+ProcessHandle], 0FFFFFFFFh
  274. PAGE:0063F414 jz short loc_63F427 ; 如果不是自己进程本身就靠挂到其他进程空间
  275. PAGE:0063F416 8D A0 lea eax, [ebp+ApcState]
  276. PAGE:0063F419 push eax ; ApcState
  277. PAGE:0063F41A push esi ; Process
  278. PAGE:0063F41B E8 7A E2 FF call _KeStackAttachProcess@8 ; KeStackAttachProcess(x,x)
  279. PAGE:0063F420 C7 E4 +mov [ebp+var_1C??Attached],
  280. PAGE:0063F427
  281. PAGE:0063F427 loc_63F427: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+1D2j
  282. PAGE:0063F427 FF 8B +dec word ptr [ebx+86h] ; ????
  283. PAGE:0063F42E 8D lea eax, [esi+100h] ; +0x100 AddressCreationLock : _EX_PUSH_LOCK
  284. PAGE:0063F42E ; 获取进程的地址空间锁,因为涉及到遍历地址空间,
  285. PAGE:0063F42E ; 就不可以在遍历的时候地址空间发生变化
  286. PAGE:0063F434 6A push 11h
  287. PAGE:0063F436 pop ecx ; ???应该是原子锁的问题,不是很清楚
  288. PAGE:0063F437 8B D0 mov edx, eax
  289. PAGE:0063F439 C0 xor eax, eax
  290. PAGE:0063F43B F0 0F B1 0A lock cmpxchg [edx], ecx
  291. PAGE:0063F43F C0 test eax, eax
  292. PAGE:0063F441 0B jz short loc_63F44E
  293. PAGE:0063F443 8D 8E lea ecx, [esi+100h]
  294. PAGE:0063F449 E8 C7 E4 FF call @ExfAcquirePushLockShared@4 ; ExfAcquirePushLockShared(x)
  295. PAGE:0063F44E
  296. PAGE:0063F44E loc_63F44E: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+1FFj
  297. PAGE:0063F44E 8B +or byte ptr [ebx+289h], ; ???
  298. PAGE:0063F44E ; +0x289 OwnsSessionWorkingSetShared : Pos 0, 1 Bit
  299. PAGE:0063F44E ; +0x289 OwnsProcessAddressSpaceExclusive : Pos 1, 1 Bit
  300. PAGE:0063F44E ; +0x289 OwnsProcessAddressSpaceShared : Pos 2, 1 Bit
  301. PAGE:0063F44E ; +0x289 SuppressSymbolLoad : Pos 3, 1 Bit
  302. PAGE:0063F44E ; +0x289 Prefetching : Pos 4, 1 Bit
  303. PAGE:0063F44E ; +0x289 OwnsDynamicMemoryShared : Pos 5, 1 Bit
  304. PAGE:0063F44E ; +0x289 OwnsChangeControlAreaExclusive : Pos 6, 1 Bit
  305. PAGE:0063F44E ; +0x289 OwnsChangeControlAreaShared : Pos 7, 1 Bi
  306. PAGE:0063F455 F6 +test byte ptr [esi+270h], 20h ; ???判断此进程的空间是否准备删除,EPROCESS->VmDeleted,如果删除就返回了
  307. PAGE:0063F455 ; +0x270 Flags : Uint4B
  308. PAGE:0063F455 ; +0x270 CreateReported : Pos 0, 1 Bit
  309. PAGE:0063F455 ; +0x270 NoDebugInherit : Pos 1, 1 Bit
  310. PAGE:0063F455 ; +0x270 ProcessExiting : Pos 2, 1 Bit
  311. PAGE:0063F455 ; +0x270 ProcessDelete : Pos 3, 1 Bit
  312. PAGE:0063F455 ; +0x270 Wow64SplitPages : Pos 4, 1 Bit
  313. PAGE:0063F455 ; +0x270 VmDeleted : Pos 5, 1 Bit
  314. PAGE:0063F455 ; +0x270 OutswapEnabled : Pos 6, 1 Bit
  315. PAGE:0063F455 ; +0x270 Outswapped : Pos 7, 1 Bit
  316. PAGE:0063F455 ; +0x270 ForkFailed : Pos 8, 1 Bit
  317. PAGE:0063F455 ; +0x270 Wow64VaSpace4Gb : Pos 9, 1 Bit
  318. PAGE:0063F455 ; +0x270 AddressSpaceInitialized : Pos 10, 2 Bits
  319. PAGE:0063F455 ; +0x270 SetTimerResolution : Pos 12, 1 Bit
  320. PAGE:0063F455 ; +0x270 BreakOnTermination : Pos 13, 1 Bit
  321. PAGE:0063F455 ; +0x270 DeprioritizeViews : Pos 14, 1 Bit
  322. PAGE:0063F455 ; +0x270 WriteWatch : Pos 15, 1 Bit
  323. PAGE:0063F455 ; +0x270 ProcessInSession : Pos 16, 1 Bit
  324. PAGE:0063F455 ; +0x270 OverrideAddressSpace : Pos 17, 1 Bit
  325. PAGE:0063F455 ; +0x270 HasAddressSpace : Pos 18, 1 Bit
  326. PAGE:0063F455 ; +0x270 LaunchPrefetched : Pos 19, 1 Bit
  327. PAGE:0063F455 ; +0x270 InjectInpageErrors : Pos 20, 1 Bit
  328. PAGE:0063F455 ; +0x270 VmTopDown : Pos 21, 1 Bit
  329. PAGE:0063F455 ; +0x2
  330. PAGE:0063F45C jz short loc_63F4C5 ; 正常流程跳转
  331. PAGE:0063F45E C9 xor ecx, ecx ; 肯定是如果准备删除了这里会需要处理资源
  332. PAGE:0063F460 8D lea eax, [esi+100h]
  333. PAGE:0063F466 8B D0 mov edx, eax
  334. PAGE:0063F468 6A push 11h
  335. PAGE:0063F46A pop eax
  336. PAGE:0063F46B F0 0F B1 0A lock cmpxchg [edx], ecx
  337. PAGE:0063F46F F8 cmp eax, 11h
  338. PAGE:0063F472 0B jz short loc_63F47F
  339. PAGE:0063F474 8D 8E lea ecx, [esi+100h]
  340. PAGE:0063F47A E8 7B E4 FF call @ExfReleasePushLockShared@4 ; //释放锁
  341. PAGE:0063F47F
  342. PAGE:0063F47F loc_63F47F: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+230j
  343. PAGE:0063F47F A3 +and byte ptr [ebx+289h], 0FBh
  344. PAGE:0063F486 FF +inc word ptr [ebx+86h]
  345. PAGE:0063F48D 0F B7 +movzx eax, word ptr [ebx+86h]
  346. PAGE:0063F494 C0 test ax, ax
  347. PAGE:0063F497 0C jnz short loc_63F4A5
  348. PAGE:0063F499 C3 add ebx, 40h
  349. PAGE:0063F49C 1B cmp [ebx], ebx
  350. PAGE:0063F49E jz short loc_63F4A5
  351. PAGE:0063F4A0 E8 D2 DE DE FF call _KiCheckForKernelApcDelivery@0 ; KiCheckForKernelApcDelivery()
  352. PAGE:0063F4A5
  353. PAGE:0063F4A5 loc_63F4A5: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+255j
  354. PAGE:0063F4A5 ; NtQueryVirtualMemory(x,x,x,x,x,x)+25Cj
  355. PAGE:0063F4A5 F6 E4 test byte ptr [ebp+var_1C??Attached],
  356. PAGE:0063F4A9 jz short loc_63F4BB
  357. PAGE:0063F4AB 8D A0 lea eax, [ebp+ApcState]
  358. PAGE:0063F4AE push eax
  359. PAGE:0063F4AF E8 9E E2 FF call _KeUnstackDetachProcess@4 ; KeUnstackDetachProcess(x)
  360. PAGE:0063F4B4 8B CE mov ecx, esi ; Object
  361. PAGE:0063F4B6 E8 6F E1 FF call @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
  362. PAGE:0063F4BB
  363. PAGE:0063F4BB loc_63F4BB: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+267j
  364. PAGE:0063F4BB B8 0A C0 mov eax, 0C000010Ah ; STATUS_PROCESS_IS_TERMINATING
  365. PAGE:0063F4C0 E9 jmp loc_63F949
  366. PAGE:0063F4C5 ; ---------------------------------------------------------------------------
  367. PAGE:0063F4C5
  368. PAGE:0063F4C5 loc_63F4C5: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+21Aj
  369. PAGE:0063F4C5 F7 8C +test dword ptr [esi+28Ch], 0FFFFFF00h ; esi==Process
  370. PAGE:0063F4C5 FF FF FF ; +0x28c实际+0x014 NumberGenericTableElements : Pos 8, 24 Bits
  371. PAGE:0063F4C5 ; 判断节点数量
  372. PAGE:0063F4CF 3D jz short loc_63F50E
  373. PAGE:0063F4D1 8B E0 mov eax, [ebp+EProcess]
  374. PAGE:0063F4D4 8B B0 mov esi, [eax+280h] ; esi == Process->VadRoot->RightChild
  375. PAGE:0063F4DA 8B 0C mov eax, [ebp+BaseAddress]
  376. PAGE:0063F4DD 8B C8 mov ecx, eax
  377. PAGE:0063F4DF C1 E9 0C shr ecx, 0Ch ; 右移12位,取得高20位,获得页帧编号
  378. PAGE:0063F4DF ; ecx == 查询地址的页帧编号
  379. PAGE:0063F4E2 EB 1E jmp short loc_63F502
  380. PAGE:0063F4E4 ; ---------------------------------------------------------------------------
  381. PAGE:0063F4E4
  382. PAGE:0063F4E4 loc_63F4E4: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2C2j
  383. PAGE:0063F4E4 8B 0C mov edx, [esi+0Ch] ; 遍历AVL
  384. PAGE:0063F4E7 3B CA cmp ecx, edx
  385. PAGE:0063F4E9 jb short loc_63F4F4
  386. PAGE:0063F4EB 3B 4E cmp ecx, [esi+10h]
  387. PAGE:0063F4EE jbe short loc_63F508 ; ???
  388. PAGE:0063F4F0 3B CA cmp ecx, edx
  389. PAGE:0063F4F2 jnb short loc_63F4F9
  390. PAGE:0063F4F4
  391. PAGE:0063F4F4 loc_63F4F4: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2A7j
  392. PAGE:0063F4F4 8B mov edx, [esi+]
  393. PAGE:0063F4F7 EB jmp short loc_63F4FC
  394. PAGE:0063F4F9 ; ---------------------------------------------------------------------------
  395. PAGE:0063F4F9
  396. PAGE:0063F4F9 loc_63F4F9: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2B0j
  397. PAGE:0063F4F9 8B mov edx, [esi+]
  398. PAGE:0063F4FC
  399. PAGE:0063F4FC loc_63F4FC: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2B5j
  400. PAGE:0063F4FC D2 test edx, edx
  401. PAGE:0063F4FE jz short loc_63F515
  402. PAGE:0063F500 8B F2 mov esi, edx
  403. PAGE:0063F502
  404. PAGE:0063F502 loc_63F502: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2A0j
  405. PAGE:0063F502 F6 test esi, esi ; 判断子节点是否有效
  406. PAGE:0063F504 DE jnz short loc_63F4E4 ; 如果有效就跳转,遍历AVL
  407. PAGE:0063F506 EB 0D jmp short loc_63F515 ; 退出循环
  408. PAGE:0063F508 ; ---------------------------------------------------------------------------
  409. PAGE:0063F508
  410. PAGE:0063F508 loc_63F508: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2ACj
  411. PAGE:0063F508 4D E4 or [ebp+var_1C??Attached], ; 如果之前有靠挂,Attached1,此时or 2 Attached==3
  412. PAGE:0063F508 ; 如果没有靠挂,此时Attached = 2
  413. PAGE:0063F50C EB jmp short loc_63F515
  414. PAGE:0063F50E ; ---------------------------------------------------------------------------
  415. PAGE:0063F50E
  416. PAGE:0063F50E loc_63F50E: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+28Dj
  417. PAGE:0063F50E F6 xor esi, esi
  418. PAGE:0063F510 C9 xor ecx, ecx
  419. PAGE:0063F512 8B 0C mov eax, [ebp+BaseAddress]
  420. PAGE:0063F515
  421. PAGE:0063F515 loc_63F515: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2BCj
  422. PAGE:0063F515 ; NtQueryVirtualMemory(x,x,x,x,x,x)+2C4j
  423. PAGE:0063F515 ; NtQueryVirtualMemory(x,x,x,x,x,x)+2CAj
  424. PAGE:0063F515 F6 E4 test byte ptr [ebp+var_1C??Attached], ; 一般情况此时Attached=3,跳转发生
  425. PAGE:0063F519 0F 0D jnz loc_63F62C
  426. PAGE:0063F51F F6 test esi, esi
  427. PAGE:0063F521 jnz short loc_63F52C
  428. PAGE:0063F523
  429. PAGE:0063F523 loc_63F523: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2FAj
  430. PAGE:0063F523 8B D8 mov esi, [ebp+var_28]
  431. PAGE:0063F526 2B sub esi, [ebp+MemoryInformation]
  432. PAGE:0063F529 inc esi
  433. PAGE:0063F52A EB jmp short loc_63F551
  434. PAGE:0063F52C ; ---------------------------------------------------------------------------
  435. PAGE:0063F52C
  436. PAGE:0063F52C loc_63F52C: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2DFj
  437. PAGE:0063F52C 8B 0C mov eax, [esi+0Ch]
  438. PAGE:0063F52F 3B C1 cmp eax, ecx
  439. PAGE:0063F531 jnb short loc_63F549
  440. PAGE:0063F533 8B CE mov ecx, esi
  441. PAGE:0063F535 E8 E2 8D E4 FF call @MiGetNextNode@4 ; MiGetNextNode(x)
  442. PAGE:0063F53A C0 test eax, eax
  443. PAGE:0063F53C E5 jz short loc_63F523
  444. PAGE:0063F53E 8B 0C mov esi, [eax+0Ch]
  445. PAGE:0063F541 C1 E6 0C shl esi, 0Ch
  446. PAGE:0063F544 2B sub esi, [ebp+MemoryInformation]
  447. PAGE:0063F547 EB jmp short loc_63F551
  448. PAGE:0063F549 ; ---------------------------------------------------------------------------
  449. PAGE:0063F549
  450. PAGE:0063F549 loc_63F549: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2EFj
  451. PAGE:0063F549 C1 E0 0C shl eax, 0Ch
  452. PAGE:0063F54C 2B sub eax, [ebp+MemoryInformation]
  453. PAGE:0063F54F 8B F0 mov esi, eax
  454. PAGE:0063F551
  455. PAGE:0063F551 loc_63F551: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2E8j
  456. PAGE:0063F551 ; NtQueryVirtualMemory(x,x,x,x,x,x)+305j
  457. PAGE:0063F551 C9 xor ecx, ecx
  458. PAGE:0063F553 8B E0 mov eax, [ebp+EProcess]
  459. PAGE:0063F556 add eax, 100h
  460. PAGE:0063F55B 8B D0 mov edx, eax
  461. PAGE:0063F55D 6A push 11h
  462. PAGE:0063F55F pop eax
  463. PAGE:0063F560 F0 0F B1 0A lock cmpxchg [edx], ecx
  464. PAGE:0063F564 F8 cmp eax, 11h
  465. PAGE:0063F567 0E jz short loc_63F577
  466. PAGE:0063F569 8B 4D E0 mov ecx, [ebp+EProcess]
  467. PAGE:0063F56C C1 add ecx, 100h
  468. PAGE:0063F572 E8 E4 FF call @ExfReleasePushLockShared@4 ; ExfReleasePushLockShared(x)
  469. PAGE:0063F577
  470. PAGE:0063F577 loc_63F577: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+325j
  471. PAGE:0063F577 A3 +and byte ptr [ebx+289h], 0FBh
  472. PAGE:0063F57E FF +inc word ptr [ebx+86h]
  473. PAGE:0063F585 0F B7 +movzx eax, word ptr [ebx+86h]
  474. PAGE:0063F58C C0 test ax, ax
  475. PAGE:0063F58F 0C jnz short loc_63F59D
  476. PAGE:0063F591 C3 add ebx, 40h
  477. PAGE:0063F594 1B cmp [ebx], ebx
  478. PAGE:0063F596 jz short loc_63F59D
  479. PAGE:0063F598 E8 DA DD DE FF call _KiCheckForKernelApcDelivery@0 ; KiCheckForKernelApcDelivery()
  480. PAGE:0063F59D
  481. PAGE:0063F59D loc_63F59D: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+34Dj
  482. PAGE:0063F59D ; NtQueryVirtualMemory(x,x,x,x,x,x)+354j
  483. PAGE:0063F59D F6 E4 test byte ptr [ebp+var_1C??Attached],
  484. PAGE:0063F5A1 jz short loc_63F5B4
  485. PAGE:0063F5A3 8D A0 lea eax, [ebp+ApcState]
  486. PAGE:0063F5A6 push eax
  487. PAGE:0063F5A7 E8 A6 E2 FF call _KeUnstackDetachProcess@4 ; KeUnstackDetachProcess(x)
  488. PAGE:0063F5AC 8B 4D E0 mov ecx, [ebp+EProcess] ; Object
  489. PAGE:0063F5AF E8 6E E1 FF call @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
  490. PAGE:0063F5B4
  491. PAGE:0063F5B4 loc_63F5B4: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+35Fj
  492. PAGE:0063F5B4 C9 xor ecx, ecx
  493. PAGE:0063F5B6 4D cmp [ebp+MemoryInformationClass], ecx
  494. PAGE:0063F5B9 jnz short loc_63F622
  495. PAGE:0063F5BB E4 FD and [ebp+var_1C??Attached], 0FFFFFFFDh
  496. PAGE:0063F5BF C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  497. PAGE:0063F5C6 4F mov [edi+], ecx
  498. PAGE:0063F5C9 4F mov [edi+], ecx
  499. PAGE:0063F5CC 8B mov eax, [ebp+MemoryInformation]
  500. PAGE:0063F5CF mov [edi], eax
  501. PAGE:0063F5D1 0C mov [edi+0Ch], esi
  502. PAGE:0063F5D4 C7 +mov dword ptr [edi+10h], 10000h
  503. PAGE:0063F5DB C7 +mov dword ptr [edi+14h],
  504. PAGE:0063F5E2 4F mov [edi+18h], ecx
  505. PAGE:0063F5E5 4D E4 or [ebp+var_1C??Attached],
  506. PAGE:0063F5E9 8B 1C mov eax, [ebp+ReturnLength]
  507. PAGE:0063F5EC 3B C1 cmp eax, ecx
  508. PAGE:0063F5EE
  509. PAGE:0063F5EE loc_63F5EE: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+5FDj
  510. PAGE:0063F5EE 0F C5 FD FF FF jz loc_63F3B9
  511. PAGE:0063F5F4 C7 1C mov dword ptr [eax], 1Ch
  512. PAGE:0063F5FA E9 BA FD FF FF jmp loc_63F3B9
  513. PAGE:0063F5FF ; ---------------------------------------------------------------------------
  514. PAGE:0063F5FF
  515. PAGE:0063F5FF loc_63F5FF: ; DATA XREF: .text:stru_450F18o
  516. PAGE:0063F5FF 8B EC mov eax, [ebp+ms_exc.exc_ptr] ; Exception filter 4 for function 63F242
  517. PAGE:0063F602 8B mov eax, [eax]
  518. PAGE:0063F604 8B mov eax, [eax]
  519. PAGE:0063F606 C8 mov [ebp+var_38], eax
  520. PAGE:0063F609 C0 xor eax, eax
  521. PAGE:0063F60B inc eax
  522. PAGE:0063F60C C3 retn
  523. PAGE:0063F60D ; ---------------------------------------------------------------------------
  524. PAGE:0063F60D
  525. PAGE:0063F60D loc_63F60D: ; DATA XREF: .text:stru_450F18o
  526. PAGE:0063F60D 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 4 for function 63F242
  527. PAGE:0063F610 F6 E4 test byte ptr [ebp+var_1C??Attached],
  528. PAGE:0063F614 0F 9F FD FF FF jnz loc_63F3B9
  529. PAGE:0063F61A 8B C8 mov eax, [ebp+var_38]
  530. PAGE:0063F61D E9 CB FC FF FF jmp loc_63F2ED
  531. PAGE:0063F622 ; ---------------------------------------------------------------------------
  532. PAGE:0063F622
  533. PAGE:0063F622 loc_63F622: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+377j
  534. PAGE:0063F622 ; NtQueryVirtualMemory(x,x,x,x,x,x)+629j
  535. PAGE:0063F622 B8 C0 mov eax, 0C0000141h
  536. PAGE:0063F627 E9 1D jmp loc_63F949
  537. PAGE:0063F62C ; ---------------------------------------------------------------------------
  538. PAGE:0063F62C
  539. PAGE:0063F62C loc_63F62C: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2D7j
  540. PAGE:0063F62C F0 FF FF and eax, 0FFFFF000h ; eax == BaseAddress,这里取BaseAddress的虚拟内存页的首地址
  541. PAGE:0063F631 0C mov [ebp+BaseAddress], eax
  542. PAGE:0063F634 mov [ebp+var_7C], eax
  543. PAGE:0063F637 8B 0C mov eax, [esi+0Ch] ; 取得此子节点的起始编号 MMVAD->StartingVpn
  544. PAGE:0063F63A C1 E0 0C shl eax, 0Ch ; 左移12位,取得虚拟内存页的页首地址
  545. PAGE:0063F63D mov [ebp+var_78], eax
  546. PAGE:0063F640 8B mov eax, [esi+14h] ; 取得MMVAD->u 其实是此节点的内存描述信息,
  547. PAGE:0063F640 ; u是一个联合体,表示一个Flags
  548. PAGE:0063F643 8B C8 mov ecx, eax ; ???对Flag进行某种运算
  549. PAGE:0063F645 C1 E9 shr ecx, 18h
  550. PAGE:0063F648 E1 1F and ecx, 1Fh
  551. PAGE:0063F64B 8B 0C 8D E8 1E +mov ecx, ds:_MmProtectToValue[ecx*] ; 很明显是取数组中的元素,
  552. PAGE:0063F64B ; 可以在Windbgkd> dd MmProtectToValue查看
  553. PAGE:0063F64B ; 其实MmProtectToValue就是一个数组,保存内存页的保护属性,
  554. PAGE:0063F64B ; 前面的Flags其实就是得到数组的下标,然后从中取出值
  555. PAGE:0063F652 4D 8C mov [ebp+var_74], ecx ; 保存查询地址的内存页属性
  556. PAGE:0063F655 C0 test eax, eax
  557. PAGE:0063F657 jns short loc_63F662
  558. PAGE:0063F659 C7 9C +mov [ebp+var_64], 20000h
  559. PAGE:0063F660 EB jmp short loc_63F6C3
  560. PAGE:0063F662 ; ---------------------------------------------------------------------------
  561. PAGE:0063F662
  562. PAGE:0063F662 loc_63F662: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+415j
  563. PAGE:0063F662 and eax, (offset loc_6FFFFD+) ; ????
  564. PAGE:0063F667 2D sub eax, 200000h
  565. PAGE:0063F66C F7 D8 neg eax ; ????指令不懂
  566. PAGE:0063F66E 1B C0 sbb eax, eax
  567. PAGE:0063F670 FF and eax, 0FF040000h
  568. PAGE:0063F675 add eax, 1000000h
  569. PAGE:0063F67A 9C mov [ebp+var_64], eax ; 之前就是对Flag进行某种运算,再保存
  570. PAGE:0063F67D 7D cmp [ebp+MemoryInformationClass], ; 我们就是2
  571. PAGE:0063F681 jnz short loc_63F6C3
  572. PAGE:0063F683 8B mov eax, [esi+24h] ; MMVAD->Subsection->ControlArea
  573. PAGE:0063F686 cmp dword ptr [eax], ; 判断CONTROL_AREA->Segment 是否有效
  574. PAGE:0063F689 2B jz short loc_63F6B6 ; 无效则跳转
  575. PAGE:0063F68B 8B mov eax, [eax]
  576. PAGE:0063F68D mov [ebp+ProcessHandle], eax ; 取出来,保存
  577. PAGE:0063F690 8B mov eax, [eax+24h] ; CONTROL_AREA->FilePointer 结构类型_EX_FAST_REF
  578. PAGE:0063F693 E0 F8 and eax, 0FFFFFFF8h ; 去除标志,只要是CONTROL_AREA下的文件指针,
  579. PAGE:0063F693 ; 全部都要这样去除标志,得到文件对象
  580. PAGE:0063F696 DC mov [ebp+var_24], eax ; 保存这块虚拟内存的文件对象FilePointer
  581. PAGE:0063F699 1B jz short loc_63F6B6
  582. PAGE:0063F69B 8B mov eax, [ebp+ProcessHandle]
  583. PAGE:0063F69E C0 add eax, 24h ; PEX_FAST_REF结构
  584. PAGE:0063F6A1 push eax
  585. PAGE:0063F6A2 E8 5F F5 E1 FF call @ObFastReferenceObject@4 ; 快速引用一个对象
  586. PAGE:0063F6A7 C0 test eax, eax ; 判断文件对象是否有效
  587. PAGE:0063F6A9 jnz short loc_63F6B3 ; 有效跳转
  588. PAGE:0063F6AB FF push [ebp+ProcessHandle]
  589. PAGE:0063F6AE E8 A3 E5 FF call _MiReferenceControlAreaFile@4 ; MiReferenceControlAreaFile(x)
  590. PAGE:0063F6B3
  591. PAGE:0063F6B3 loc_63F6B3: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+467j
  592. PAGE:0063F6B3 DC mov [ebp+var_24], eax ; 保存_File_Object
  593. PAGE:0063F6B6
  594. PAGE:0063F6B6 loc_63F6B6: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+447j
  595. PAGE:0063F6B6 ; NtQueryVirtualMemory(x,x,x,x,x,x)+457j
  596. PAGE:0063F6B6 7D DC cmp [ebp+var_24], ; 判断对象引用是否成功
  597. PAGE:0063F6BA jnz short loc_63F6C3 ; 引用成功则跳转
  598. PAGE:0063F6BC C7 DC +mov [ebp+var_24],
  599. PAGE:0063F6C3
  600. PAGE:0063F6C3 loc_63F6C3: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+41Ej
  601. PAGE:0063F6C3 ; NtQueryVirtualMemory(x,x,x,x,x,x)+43Fj
  602. PAGE:0063F6C3 ; NtQueryVirtualMemory(x,x,x,x,x,x)+478j
  603. PAGE:0063F6C3 7D cmp [ebp+MemoryInformationClass], ; 我们的方式是2
  604. PAGE:0063F6C7 0F D5 jnz loc_63F7A2 ; 不为 3 就跳转
  605. PAGE:0063F6CD 8B 4E mov ecx, [esi+10h]
  606. PAGE:0063F6D0 2B 4E 0C sub ecx, [esi+0Ch]
  607. PAGE:0063F6D3 inc ecx
  608. PAGE:0063F6D4 C1 E1 0C shl ecx, 0Ch
  609. PAGE:0063F6D7 4D mov [ebp+MemoryInformationClass], ecx
  610. PAGE:0063F6DA D2 xor edx, edx
  611. PAGE:0063F6DC 8B E0 mov eax, [ebp+EProcess]
  612. PAGE:0063F6DF add eax, 100h
  613. PAGE:0063F6E4 8B F0 mov esi, eax
  614. PAGE:0063F6E6 6A push 11h
  615. PAGE:0063F6E8 pop eax
  616. PAGE:0063F6E9 F0 0F B1 lock cmpxchg [esi], edx
  617. PAGE:0063F6ED F8 cmp eax, 11h
  618. PAGE:0063F6F0 jz short loc_63F703
  619. PAGE:0063F6F2 8B 4D E0 mov ecx, [ebp+EProcess]
  620. PAGE:0063F6F5 C1 add ecx, 100h
  621. PAGE:0063F6FB E8 FA E4 FF call @ExfReleasePushLockShared@4 ; ExfReleasePushLockShared(x)
  622. PAGE:0063F700 8B 4D mov ecx, [ebp+MemoryInformationClass]
  623. PAGE:0063F703
  624. PAGE:0063F703 loc_63F703: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+4AEj
  625. PAGE:0063F703 A3 +and byte ptr [ebx+289h], 0FBh
  626. PAGE:0063F70A FF +inc word ptr [ebx+86h]
  627. PAGE:0063F711 0F B7 +movzx eax, word ptr [ebx+86h]
  628. PAGE:0063F718 C0 test ax, ax
  629. PAGE:0063F71B 0F jnz short loc_63F72C
  630. PAGE:0063F71D C3 add ebx, 40h
  631. PAGE:0063F720 1B cmp [ebx], ebx
  632. PAGE:0063F722 jz short loc_63F72C
  633. PAGE:0063F724 E8 4E DC DE FF call _KiCheckForKernelApcDelivery@0 ; KiCheckForKernelApcDelivery()
  634. PAGE:0063F729 8B 4D mov ecx, [ebp+MemoryInformationClass]
  635. PAGE:0063F72C
  636. PAGE:0063F72C loc_63F72C: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+4D9j
  637. PAGE:0063F72C ; NtQueryVirtualMemory(x,x,x,x,x,x)+4E0j
  638. PAGE:0063F72C F6 E4 test byte ptr [ebp+var_1C??Attached],
  639. PAGE:0063F730 jz short loc_63F746
  640. PAGE:0063F732 8D A0 lea eax, [ebp+ApcState]
  641. PAGE:0063F735 push eax
  642. PAGE:0063F736 E8 E2 FF call _KeUnstackDetachProcess@4 ; KeUnstackDetachProcess(x)
  643. PAGE:0063F73B 8B 4D E0 mov ecx, [ebp+EProcess] ; Object
  644. PAGE:0063F73E E8 EA 6C E1 FF call @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
  645. PAGE:0063F743 8B 4D mov ecx, [ebp+MemoryInformationClass]
  646. PAGE:0063F746
  647. PAGE:0063F746 loc_63F746: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+4EEj
  648. PAGE:0063F746 E4 FD and [ebp+var_1C??Attached], 0FFFFFFFDh
  649. PAGE:0063F74A C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  650. PAGE:0063F751 8B mov eax, [ebp+var_78]
  651. PAGE:0063F754 mov [edi], eax
  652. PAGE:0063F756 8B 8C mov eax, [ebp+var_74]
  653. PAGE:0063F759 mov [edi+], eax
  654. PAGE:0063F75C 8B 9C mov eax, [ebp+var_64]
  655. PAGE:0063F75F mov [edi+], eax
  656. PAGE:0063F762 4F 0C mov [edi+0Ch], ecx
  657. PAGE:0063F765 4D E4 or [ebp+var_1C??Attached],
  658. PAGE:0063F769 8B 1C mov eax, [ebp+ReturnLength]
  659. PAGE:0063F76C C0 test eax, eax
  660. PAGE:0063F76E 0F FC FF FF jz loc_63F3B9
  661. PAGE:0063F774 C7 mov dword ptr [eax], 10h
  662. PAGE:0063F77A E9 3A FC FF FF jmp loc_63F3B9
  663. PAGE:0063F77F ; ---------------------------------------------------------------------------
  664. PAGE:0063F77F
  665. PAGE:0063F77F loc_63F77F: ; DATA XREF: .text:stru_450F18o
  666. PAGE:0063F77F 8B EC mov eax, [ebp+ms_exc.exc_ptr] ; Exception filter 5 for function 63F242
  667. PAGE:0063F782 8B mov eax, [eax]
  668. PAGE:0063F784 8B mov eax, [eax]
  669. PAGE:0063F786 C4 mov [ebp+var_3C], eax
  670. PAGE:0063F789 C0 xor eax, eax
  671. PAGE:0063F78B inc eax
  672. PAGE:0063F78C C3 retn
  673. PAGE:0063F78D ; ---------------------------------------------------------------------------
  674. PAGE:0063F78D
  675. PAGE:0063F78D loc_63F78D: ; DATA XREF: .text:stru_450F18o
  676. PAGE:0063F78D 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 5 for function 63F242
  677. PAGE:0063F790 F6 E4 test byte ptr [ebp+var_1C??Attached],
  678. PAGE:0063F794 0F 1F FC FF FF jnz loc_63F3B9
  679. PAGE:0063F79A 8B C4 mov eax, [ebp+var_3C]
  680. PAGE:0063F79D E9 4B FB FF FF jmp loc_63F2ED
  681. PAGE:0063F7A2 ; ---------------------------------------------------------------------------
  682. PAGE:0063F7A2
  683. PAGE:0063F7A2 loc_63F7A2: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+485j
  684. PAGE:0063F7A2 7D cmp [ebp+MemoryInformationClass], ; 我们是2,继续跳转
  685. PAGE:0063F7A6 jnz short loc_63F7BA
  686. PAGE:0063F7A8 push esi
  687. PAGE:0063F7A9 FF 0C push [ebp+BaseAddress]
  688. PAGE:0063F7AC 8D lea eax, [ebp+var_7C]
  689. PAGE:0063F7AF E8 7E B2 E4 FF call _MiQueryAddressSpan@12 ; MiQueryAddressSpan(x,x,x)
  690. PAGE:0063F7B4 2B sub eax, [ebp+var_7C]
  691. PAGE:0063F7B7 mov [ebp+var_70], eax
  692. PAGE:0063F7BA
  693. PAGE:0063F7BA loc_63F7BA: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+564j
  694. PAGE:0063F7BA C9 xor ecx, ecx
  695. PAGE:0063F7BC 8B E0 mov eax, [ebp+EProcess]
  696. PAGE:0063F7BF add eax, 100h ; +0x100 AddressCreationLock : _EX_PUSH_LOCK
  697. PAGE:0063F7BF ; 地址空间锁
  698. PAGE:0063F7C4 8B D0 mov edx, eax
  699. PAGE:0063F7C6 6A push 11h
  700. PAGE:0063F7C8 pop eax
  701. PAGE:0063F7C9 F0 0F B1 0A lock cmpxchg [edx], ecx
  702. PAGE:0063F7CD F8 cmp eax, 11h
  703. PAGE:0063F7D0 0E jz short loc_63F7E0
  704. PAGE:0063F7D2 8B 4D E0 mov ecx, [ebp+EProcess]
  705. PAGE:0063F7D5 C1 add ecx, 100h
  706. PAGE:0063F7DB E8 1A E4 FF call @ExfReleasePushLockShared@4 ; ExfReleasePushLockShared(x)
  707. PAGE:0063F7E0
  708. PAGE:0063F7E0 loc_63F7E0: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+58Ej
  709. PAGE:0063F7E0 A3 +and byte ptr [ebx+289h], 0FBh
  710. PAGE:0063F7E7 FF +inc word ptr [ebx+86h]
  711. PAGE:0063F7EE 0F B7 +movzx eax, word ptr [ebx+86h]
  712. PAGE:0063F7F5 C0 test ax, ax
  713. PAGE:0063F7F8 0C jnz short loc_63F806
  714. PAGE:0063F7FA C3 add ebx, 40h
  715. PAGE:0063F7FD 1B cmp [ebx], ebx
  716. PAGE:0063F7FF jz short loc_63F806
  717. PAGE:0063F801 E8 DB DE FF call _KiCheckForKernelApcDelivery@0 ; KiCheckForKernelApcDelivery()
  718. PAGE:0063F806
  719. PAGE:0063F806 loc_63F806: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+5B6j
  720. PAGE:0063F806 ; NtQueryVirtualMemory(x,x,x,x,x,x)+5BDj
  721. PAGE:0063F806 F6 E4 test byte ptr [ebp+var_1C??Attached], ; 判断进程是否靠挂
  722. PAGE:0063F80A jz short loc_63F81D
  723. PAGE:0063F80C 8D A0 lea eax, [ebp+ApcState]
  724. PAGE:0063F80F push eax
  725. PAGE:0063F810 E8 3D E2 FF call _KeUnstackDetachProcess@4 ; KeUnstackDetachProcess(x)
  726. PAGE:0063F815 8B 4D E0 mov ecx, [ebp+EProcess] ; Object
  727. PAGE:0063F818 E8 6C E1 FF call @ObfDereferenceObject@4 ; 解除对进程对象的引用
  728. PAGE:0063F81D
  729. PAGE:0063F81D loc_63F81D: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+5C8j
  730. PAGE:0063F81D 7D cmp [ebp+MemoryInformationClass],
  731. PAGE:0063F821 jnz short loc_63F867
  732. PAGE:0063F823 E4 FD and [ebp+var_1C??Attached], 0FFFFFFFDh
  733. PAGE:0063F827 C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  734. PAGE:0063F82E 6A push
  735. PAGE:0063F830 pop ecx
  736. PAGE:0063F831 8D lea esi, [ebp+var_7C]
  737. PAGE:0063F834 F3 A5 rep movsd
  738. PAGE:0063F836 4D E4 or [ebp+var_1C??Attached],
  739. PAGE:0063F83A 8B 1C mov eax, [ebp+ReturnLength]
  740. PAGE:0063F83D C0 test eax, eax
  741. PAGE:0063F83F E9 AA FD FF FF jmp loc_63F5EE
  742. PAGE:0063F844 ; ---------------------------------------------------------------------------
  743. PAGE:0063F844
  744. PAGE:0063F844 loc_63F844: ; DATA XREF: .text:stru_450F18o
  745. PAGE:0063F844 8B EC mov eax, [ebp+ms_exc.exc_ptr] ; Exception filter 6 for function 63F242
  746. PAGE:0063F847 8B mov eax, [eax]
  747. PAGE:0063F849 8B mov eax, [eax]
  748. PAGE:0063F84B C0 mov [ebp+var_40], eax
  749. PAGE:0063F84E C0 xor eax, eax
  750. PAGE:0063F850 inc eax
  751. PAGE:0063F851 C3 retn
  752. PAGE:0063F852 ; ---------------------------------------------------------------------------
  753. PAGE:0063F852
  754. PAGE:0063F852 loc_63F852: ; DATA XREF: .text:stru_450F18o
  755. PAGE:0063F852 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 6 for function 63F242
  756. PAGE:0063F855 F6 E4 test byte ptr [ebp+var_1C??Attached],
  757. PAGE:0063F859 0F 5A FB FF FF jnz loc_63F3B9
  758. PAGE:0063F85F 8B C0 mov eax, [ebp+var_40]
  759. PAGE:0063F862 E9 FA FF FF jmp loc_63F2ED
  760. PAGE:0063F867 ; ---------------------------------------------------------------------------
  761. PAGE:0063F867
  762. PAGE:0063F867 loc_63F867: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+5DFj
  763. PAGE:0063F867 7D DC cmp [ebp+var_24], ; 又是对文件对象的判断
  764. PAGE:0063F86B 0F B1 FD FF FF jz loc_63F622 ; NULL,跳转
  765. PAGE:0063F871 7D DC cmp [ebp+var_24],
  766. PAGE:0063F875 0A jnz short loc_63F881 ; 有效,则跳转
  767. PAGE:0063F877 B8 C0 mov eax, 0C0000098h ; STATUS_FILE_INVALID 错误码
  768. PAGE:0063F87C E9 C8 jmp loc_63F949
  769. PAGE:0063F881 ; ---------------------------------------------------------------------------
  770. PAGE:0063F881
  771. PAGE:0063F881 loc_63F881: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+633j
  772. PAGE:0063F881 8D BC lea eax, [ebp+var_44]
  773. PAGE:0063F884 push eax ; ReturnLength
  774. PAGE:0063F885 FF push [ebp+MemoryInformationLength] ; Length
  775. PAGE:0063F888 push edi ; ObjectNameInfo
  776. PAGE:0063F889 FF DC push [ebp+var_24] ; Object
  777. PAGE:0063F88C E8 0D FE FF call _ObQueryNameString@16 ; wrk中搜函数原型
  778. PAGE:0063F891 8B F0 mov esi, eax
  779. PAGE:0063F893 8B 4D DC mov ecx, [ebp+var_24] ; Object
  780. PAGE:0063F896 E8 6B E1 FF call @ObfDereferenceObject@4 ; 释放对文件对象的引用
  781. PAGE:0063F89B 8B 1C mov eax, [ebp+ReturnLength] ; 判断传入的返回值是否为NULL
  782. PAGE:0063F89E C0 test eax, eax
  783. PAGE:0063F8A0 jz short loc_63F8CB ; NULL,则跳转
  784. PAGE:0063F8A2 C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  785. PAGE:0063F8A9 8B 4D BC mov ecx, [ebp+var_44] ; 实际字符串的长度
  786. PAGE:0063F8AC mov [eax], ecx ; 返回实际字符串的长度
  787. PAGE:0063F8AE EB jmp short loc_63F8C4
  788. PAGE:0063F8B0 ; ---------------------------------------------------------------------------
  789. PAGE:0063F8B0
  790. PAGE:0063F8B0 loc_63F8B0: ; DATA XREF: .text:stru_450F18o
  791. PAGE:0063F8B0 8B EC mov eax, [ebp+ms_exc.exc_ptr] ; Exception filter 7 for function 63F242
  792. PAGE:0063F8B3 8B mov eax, [eax]
  793. PAGE:0063F8B5 8B mov eax, [eax]
  794. PAGE:0063F8B7 B8 mov [ebp+var_48], eax
  795. PAGE:0063F8BA C0 xor eax, eax
  796. PAGE:0063F8BC inc eax
  797. PAGE:0063F8BD C3 retn
  798. PAGE:0063F8BE ; ---------------------------------------------------------------------------
  799. PAGE:0063F8BE
  800. PAGE:0063F8BE loc_63F8BE: ; DATA XREF: .text:stru_450F18o
  801. PAGE:0063F8BE 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 7 for function 63F242
  802. PAGE:0063F8C1 8B B8 mov esi, [ebp+var_48]
  803. PAGE:0063F8C4
  804. PAGE:0063F8C4 loc_63F8C4: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+66Cj
  805. PAGE:0063F8C4 C7 FC FE FF FF+mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  806. PAGE:0063F8CB
  807. PAGE:0063F8CB loc_63F8CB: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+65Ej
  808. PAGE:0063F8CB 8B C6 mov eax, esi ; ObQueryNameString 返回的status
  809. PAGE:0063F8CD EB 7A jmp short loc_63F949
  810. PAGE:0063F8CF ; ---------------------------------------------------------------------------
  811. PAGE:0063F8CF
  812. PAGE:0063F8CF loc_63F8CF: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+E1j
  813. PAGE:0063F8CF ; NtQueryVirtualMemory(x,x,x,x,x,x)+F4j
  814. PAGE:0063F8CF BB C0 mov ebx, 0C0000141h
  815. PAGE:0063F8D4 7D cmp [ebp+MemoryInformationClass],
  816. PAGE:0063F8D8 6D jnz short loc_63F947
  817. PAGE:0063F8DA C7 FC +mov [ebp+ms_exc.registration.TryLevel],
  818. PAGE:0063F8E1 inc esi
  819. PAGE:0063F8E2 mov [edi+], esi
  820. PAGE:0063F8E5 6A push
  821. PAGE:0063F8E7 5B pop ebx
  822. PAGE:0063F8E8 5F mov [edi+], ebx
  823. PAGE:0063F8EB 8B F0 mov esi, eax
  824. PAGE:0063F8ED F2 and esi, edx
  825. PAGE:0063F8EF mov [edi], esi
  826. PAGE:0063F8F1 C2 and eax, edx
  827. PAGE:0063F8F3 2B C8 sub ecx, eax
  828. PAGE:0063F8F5 inc ecx
  829. PAGE:0063F8F6 4F 0C mov [edi+0Ch], ecx
  830. PAGE:0063F8F9 C7 +mov dword ptr [edi+10h], 2000h
  831. PAGE:0063F900 C7 +mov dword ptr [edi+14h],
  832. PAGE:0063F907 C7 +mov dword ptr [edi+18h], 20000h
  833. PAGE:0063F90E 8B 1C mov eax, [ebp+ReturnLength]
  834. PAGE:0063F911 C0 test eax, eax
  835. PAGE:0063F913 jz short loc_63F91B
  836. PAGE:0063F915 C7 1C mov dword ptr [eax], 1Ch
  837. PAGE:0063F91B
  838. PAGE:0063F91B loc_63F91B: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+6D1j
  839. PAGE:0063F91B B8 FE 7F mov eax, 7FFE0000h
  840. PAGE:0063F920 3B F0 cmp esi, eax
  841. PAGE:0063F922 1A jnz short loc_63F93E
  842. PAGE:0063F924 mov [edi+], eax
  843. PAGE:0063F927 5F mov [edi+14h], ebx
  844. PAGE:0063F92A B8 mov eax, 1000h
  845. PAGE:0063F92F 0C mov [edi+0Ch], eax
  846. PAGE:0063F932 mov [edi+10h], eax
  847. PAGE:0063F935 EB jmp short loc_63F93E
  848. PAGE:0063F937 ; ---------------------------------------------------------------------------
  849. PAGE:0063F937
  850. PAGE:0063F937 loc_63F937: ; DATA XREF: .text:stru_450F18o
  851. PAGE:0063F937 C0 xor eax, eax ; Exception filter 1 for function 63F242
  852. PAGE:0063F939 inc eax
  853. PAGE:0063F93A C3 retn
  854. PAGE:0063F93B ; ---------------------------------------------------------------------------
  855. PAGE:0063F93B
  856. PAGE:0063F93B loc_63F93B: ; DATA XREF: .text:stru_450F18o
  857. PAGE:0063F93B 8B E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 1 for function 63F242
  858. PAGE:0063F93E
  859. PAGE:0063F93E loc_63F93E: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+6E0j
  860. PAGE:0063F93E ; NtQueryVirtualMemory(x,x,x,x,x,x)+6F3j
  861. PAGE:0063F93E C7 FC FE FF FF+mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  862. PAGE:0063F945 DB xor ebx, ebx
  863. PAGE:0063F947
  864. PAGE:0063F947 loc_63F947: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+1A7j
  865. PAGE:0063F947 ; NtQueryVirtualMemory(x,x,x,x,x,x)+696j
  866. PAGE:0063F947 8B C3 mov eax, ebx
  867. PAGE:0063F949
  868. PAGE:0063F949 loc_63F949: ; CODE XREF: NtQueryVirtualMemory(x,x,x,x,x,x)+2Cj
  869. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+4Ej
  870. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+B2j
  871. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+CCj
  872. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+12Cj
  873. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+159j
  874. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+180j
  875. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+27Ej
  876. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+3E5j
  877. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+63Aj
  878. PAGE:0063F949 ; NtQueryVirtualMemory(x,x,x,x,x,x)+68Bj
  879. PAGE:0063F949 E8 E1 FF call __SEH_epilog4
  880. PAGE:0063F94E C2 retn 18h
  881. PAGE:0063F94E _NtQueryVirtualMemory@24 endp
  882. PAGE:0063F94E

下面是wrk中的源代码

NTSTATUS
NtQueryVirtualMemory(
__in HANDLE ProcessHandle,
__in PVOID BaseAddress,
__in MEMORY_INFORMATION_CLASS MemoryInformationClass,
__out_bcount(MemoryInformationLength) PVOID MemoryInformation,
__in SIZE_T MemoryInformationLength,
__out_opt PSIZE_T ReturnLength
) /*++ Routine Description: This function provides the capability to determine the state,
protection, and type of a region of pages within the virtual address
space of the subject process. The state of the first page within the region is determined and then
subsequent entries in the process address map are scanned from the
base address upward until either the entire range of pages has been
scanned or until a page with a nonmatching set of attributes is
encountered. The region attributes, the length of the region of pages
with matching attributes, and an appropriate status value are
returned. If the entire region of pages does not have a matching set of
attributes, then the returned length parameter value can be used to
calculate the address and length of the region of pages that was not
scanned. Arguments: ProcessHandle - An open handle to a process object. BaseAddress - The base address of the region of pages to be
queried. This value is rounded down to the next host-page-
address boundary. MemoryInformationClass - The memory information class about which
to retrieve information. MemoryInformation - A pointer to a buffer that receives the specified
information. The format and content of the buffer
depend on the specified information class. MemoryBasicInformation - Data type is PMEMORY_BASIC_INFORMATION. MEMORY_BASIC_INFORMATION Structure ULONG RegionSize - The size of the region in bytes beginning at
the base address in which all pages have
identical attributes. ULONG State - The state of the pages within the region. State Values MEM_COMMIT - The state of the pages within the region
is committed. MEM_FREE - The state of the pages within the region
is free. MEM_RESERVE - The state of the pages within the
region is reserved. ULONG Protect - The protection of the pages within the region. Protect Values PAGE_NOACCESS - No access to the region of pages is allowed.
An attempt to read, write, or execute within
the region results in an access violation. PAGE_EXECUTE - Execute access to the region of pages
is allowed. An attempt to read or write within
the region results in an access violation. PAGE_READONLY - Read-only and execute access to the region
of pages is allowed. An attempt to write within
the region results in an access violation. PAGE_READWRITE - Read, write, and execute access to the region
of pages is allowed. If write access to the
underlying section is allowed, then a single
copy of the pages are shared. Otherwise,
the pages are shared read-only/copy-on-write. PAGE_GUARD - Read, write, and execute access to the
region of pages is allowed; however, access to
the region causes a "guard region entered"
condition to be raised in the subject process. PAGE_NOCACHE - Disable the placement of committed
pages into the data cache. PAGE_WRITECOMBINE - Disable the placement of committed
pages into the data cache, combine the
writes as well. ULONG Type - The type of pages within the region. Type Values MEM_PRIVATE - The pages within the region are private. MEM_MAPPED - The pages within the region are mapped
into the view of a section. MEM_IMAGE - The pages within the region are mapped
into the view of an image section. MemoryInformationLength - Specifies the length in bytes of
the memory information buffer. ReturnLength - An optional pointer which, if specified, receives the
number of bytes placed in the process information buffer. Return Value: NTSTATUS. Environment: Kernel mode. --*/ {
ULONG LocalReturnLength;
KPROCESSOR_MODE PreviousMode;
PEPROCESS TargetProcess;
PETHREAD Thread;
NTSTATUS Status;
PMMVAD Vad;
PVOID Va;
PVOID NextVaToQuery;
LOGICAL Found;
SIZE_T TheRegionSize;
ULONG NewProtect;
ULONG NewState;
PVOID FilePointer;
ULONG_PTR BaseVpn;
MEMORY_BASIC_INFORMATION Info;
PMEMORY_BASIC_INFORMATION BasicInfo;
LOGICAL Attached;
LOGICAL Leaped;
ULONG MemoryInformationLengthUlong;
KAPC_STATE ApcState;
PETHREAD CurrentThread;
PVOID HighestVadAddress;
PVOID HighestUserAddress; Found = FALSE;
Leaped = TRUE;
FilePointer = NULL; //
// Make sure the user's buffer is large enough for the requested operation.
//
// Check argument validity.
// switch (MemoryInformationClass) {
case MemoryBasicInformation:
if (MemoryInformationLength < sizeof(MEMORY_BASIC_INFORMATION)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
break; case MemoryWorkingSetInformation:
if (MemoryInformationLength < sizeof(ULONG_PTR)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
break; case MemoryWorkingSetExInformation:
if (MemoryInformationLength < sizeof (MEMORY_WORKING_SET_EX_INFORMATION)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
break; case MemoryMappedFilenameInformation:
break; default:
return STATUS_INVALID_INFO_CLASS;
} CurrentThread = PsGetCurrentThread ();
PreviousMode = KeGetPreviousModeByThread(&CurrentThread->Tcb); if (PreviousMode != KernelMode) { //
// Check arguments.
// try { ProbeForWrite(MemoryInformation,
MemoryInformationLength,
sizeof(ULONG_PTR)); if (ARGUMENT_PRESENT(ReturnLength)) {
ProbeForWriteUlong_ptr(ReturnLength);
} } except (EXCEPTION_EXECUTE_HANDLER) { //
// If an exception occurs during the probe or capture
// of the initial values, then handle the exception and
// return the exception code as the status value.
// return GetExceptionCode();
}
} if (BaseAddress > MM_HIGHEST_USER_ADDRESS) {
return STATUS_INVALID_PARAMETER;
} HighestUserAddress = MM_HIGHEST_USER_ADDRESS;
HighestVadAddress = (PCHAR) MM_HIGHEST_VAD_ADDRESS; #if defined(_WIN64) if (ProcessHandle == NtCurrentProcess()) {
TargetProcess = PsGetCurrentProcessByThread(CurrentThread);
}
else {
Status = ObReferenceObjectByHandle (ProcessHandle,
PROCESS_QUERY_INFORMATION,
PsProcessType,
PreviousMode,
(PVOID *)&TargetProcess,
NULL); if (!NT_SUCCESS(Status)) {
return Status;
}
} //
// If this is a wow64 process, then return the appropriate highest
// user address depending on whether the process has been started with
// a 2GB or a 4GB address space.
// if (TargetProcess->Wow64Process != NULL) { if (TargetProcess->Flags & PS_PROCESS_FLAGS_WOW64_4GB_VA_SPACE) {
HighestUserAddress = (PVOID) ((ULONG_PTR)_4gb - X64K - );
}
else {
HighestUserAddress = (PVOID) ((ULONG_PTR)_2gb - X64K - );
} HighestVadAddress = (PCHAR)HighestUserAddress - X64K; if (BaseAddress > HighestUserAddress) { if (ProcessHandle != NtCurrentProcess()) {
ObDereferenceObject (TargetProcess);
}
return STATUS_INVALID_PARAMETER;
}
} #endif if ((BaseAddress > HighestVadAddress) ||
(PAGE_ALIGN(BaseAddress) == (PVOID)MM_SHARED_USER_DATA_VA)) { //
// Indicate a reserved area from this point on.
// Status = STATUS_INVALID_ADDRESS; if (MemoryInformationClass == MemoryBasicInformation) { try {
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->AllocationBase =
(PCHAR) HighestVadAddress + ;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->AllocationProtect =
PAGE_READONLY;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->BaseAddress =
PAGE_ALIGN(BaseAddress);
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->RegionSize =
((PCHAR)HighestUserAddress + ) -
(PCHAR)PAGE_ALIGN(BaseAddress);
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->State = MEM_RESERVE;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->Protect = PAGE_NOACCESS;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->Type = MEM_PRIVATE; if (ARGUMENT_PRESENT(ReturnLength)) {
*ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
} if (PAGE_ALIGN(BaseAddress) == (PVOID)MM_SHARED_USER_DATA_VA) { //
// This is the page that is double mapped between
// user mode and kernel mode.
// ((PMEMORY_BASIC_INFORMATION)MemoryInformation)->AllocationBase =
(PVOID)MM_SHARED_USER_DATA_VA;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->Protect =
PAGE_READONLY;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->RegionSize =
PAGE_SIZE;
((PMEMORY_BASIC_INFORMATION)MemoryInformation)->State =
MEM_COMMIT;
} } except (EXCEPTION_EXECUTE_HANDLER) { //
// Just return success.
// NOTHING;
} Status = STATUS_SUCCESS;
} #if defined(_WIN64)
if (ProcessHandle != NtCurrentProcess()) {
ObDereferenceObject (TargetProcess);
}
#endif return Status;
} #if !defined(_WIN64) if (ProcessHandle == NtCurrentProcess()) {
TargetProcess = PsGetCurrentProcessByThread(CurrentThread);
}
else {
Status = ObReferenceObjectByHandle (ProcessHandle,
PROCESS_QUERY_INFORMATION,
PsProcessType,
PreviousMode,
(PVOID *)&TargetProcess,
NULL); if (!NT_SUCCESS(Status)) {
return Status;
}
} #endif if (MemoryInformationClass == MemoryWorkingSetExInformation) { Status = MiGetWorkingSetInfoList (
(PMEMORY_WORKING_SET_EX_INFORMATION) MemoryInformation,
MemoryInformationLength,
TargetProcess); if (ProcessHandle != NtCurrentProcess()) {
ObDereferenceObject (TargetProcess);
} //
// If MiGetWorkingSetInfoList failed then inform the caller.
// if (!NT_SUCCESS(Status)) {
return Status;
} try { if (ARGUMENT_PRESENT (ReturnLength)) {
*ReturnLength = MemoryInformationLength;
} } except (EXCEPTION_EXECUTE_HANDLER) {
NOTHING;
} return STATUS_SUCCESS;
} if (MemoryInformationClass == MemoryWorkingSetInformation) { Status = MiGetWorkingSetInfo (
(PMEMORY_WORKING_SET_INFORMATION) MemoryInformation,
MemoryInformationLength,
TargetProcess); if (ProcessHandle != NtCurrentProcess()) {
ObDereferenceObject (TargetProcess);
} //
// If MiGetWorkingSetInfo failed then inform the caller.
// if (!NT_SUCCESS(Status)) {
return Status;
} try { if (ARGUMENT_PRESENT(ReturnLength)) {
*ReturnLength = ((((PMEMORY_WORKING_SET_INFORMATION)
MemoryInformation)->NumberOfEntries - ) *
sizeof(ULONG_PTR)) +
sizeof(MEMORY_WORKING_SET_INFORMATION);
} } except (EXCEPTION_EXECUTE_HANDLER) {
} return STATUS_SUCCESS;
} //
// If the specified process is not the current process, attach
// to the specified process.
// if (ProcessHandle != NtCurrentProcess()) {
KeStackAttachProcess (&TargetProcess->Pcb, &ApcState);
Attached = TRUE;
}
else {
Attached = FALSE;
} //
// Get working set mutex and block APCs.
// LOCK_ADDRESS_SPACE (TargetProcess); //
// Make sure the address space was not deleted, if so, return an error.
// if (TargetProcess->Flags & PS_PROCESS_FLAGS_VM_DELETED) {
UNLOCK_ADDRESS_SPACE (TargetProcess);
if (Attached == TRUE) {
KeUnstackDetachProcess (&ApcState);
ObDereferenceObject (TargetProcess);
}
return STATUS_PROCESS_IS_TERMINATING;
} //
// Locate the VAD that contains the base address or the VAD
// which follows the base address.
// if (TargetProcess->VadRoot.NumberGenericTableElements != ) { Vad = (PMMVAD) TargetProcess->VadRoot.BalancedRoot.RightChild;
BaseVpn = MI_VA_TO_VPN (BaseAddress); while (TRUE) { if (Vad == NULL) {
break;
} if ((BaseVpn >= Vad->StartingVpn) &&
(BaseVpn <= Vad->EndingVpn)) {
Found = TRUE;
break;
} if (BaseVpn < Vad->StartingVpn) {
if (Vad->LeftChild == NULL) {
break;
}
Vad = Vad->LeftChild;
}
else {
ASSERT (BaseVpn > Vad->EndingVpn); if (Vad->RightChild == NULL) {
break;
} Vad = Vad->RightChild;
}
}
}
else {
Vad = NULL;
BaseVpn = ;
} if (!Found) { //
// There is no virtual address allocated at the base
// address. Return the size of the hole starting at
// the base address.
// if (Vad == NULL) {
TheRegionSize = (((PCHAR)HighestVadAddress + ) -
(PCHAR)PAGE_ALIGN(BaseAddress));
}
else {
if (Vad->StartingVpn < BaseVpn) { //
// We are looking at the Vad which occupies the range
// just before the desired range. Get the next Vad.
// Vad = MiGetNextVad (Vad);
if (Vad == NULL) {
TheRegionSize = (((PCHAR)HighestVadAddress + ) -
(PCHAR)PAGE_ALIGN(BaseAddress));
}
else {
TheRegionSize = (PCHAR)MI_VPN_TO_VA (Vad->StartingVpn) -
(PCHAR)PAGE_ALIGN(BaseAddress);
}
}
else {
TheRegionSize = (PCHAR)MI_VPN_TO_VA (Vad->StartingVpn) -
(PCHAR)PAGE_ALIGN(BaseAddress);
}
} UNLOCK_ADDRESS_SPACE (TargetProcess); if (Attached == TRUE) {
KeUnstackDetachProcess (&ApcState);
ObDereferenceObject (TargetProcess);
} //
// Establish an exception handler and write the information and
// returned length.
// if (MemoryInformationClass == MemoryBasicInformation) {
BasicInfo = (PMEMORY_BASIC_INFORMATION) MemoryInformation;
Found = FALSE;
try { BasicInfo->AllocationBase = NULL;
BasicInfo->AllocationProtect = ;
BasicInfo->BaseAddress = PAGE_ALIGN(BaseAddress);
BasicInfo->RegionSize = TheRegionSize;
BasicInfo->State = MEM_FREE;
BasicInfo->Protect = PAGE_NOACCESS;
BasicInfo->Type = ; Found = TRUE;
if (ARGUMENT_PRESENT(ReturnLength)) {
*ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
} } except (EXCEPTION_EXECUTE_HANDLER) { //
// Just return success if the BasicInfo was successfully
// filled in.
// if (Found == FALSE) {
return GetExceptionCode ();
}
} return STATUS_SUCCESS;
}
return STATUS_INVALID_ADDRESS;
} //
// Found a VAD.
// Va = PAGE_ALIGN(BaseAddress);
Info.BaseAddress = Va;
Info.AllocationBase = MI_VPN_TO_VA (Vad->StartingVpn);
Info.AllocationProtect = MI_CONVERT_FROM_PTE_PROTECTION (
Vad->u.VadFlags.Protection); //
// There is a page mapped at the base address.
// if ((Vad->u.VadFlags.PrivateMemory) ||
(Vad->u.VadFlags.VadType == VadRotatePhysical)) { Info.Type = MEM_PRIVATE;
}
else {
if (Vad->u.VadFlags.VadType == VadImageMap) {
Info.Type = MEM_IMAGE;
}
else {
Info.Type = MEM_MAPPED;
} if (MemoryInformationClass == MemoryMappedFilenameInformation) { if (Vad->ControlArea != NULL) {
FilePointer = Vad->ControlArea->FilePointer;
}
if (FilePointer == NULL) {
FilePointer = (PVOID);
}
else {
ObReferenceObject (FilePointer);
}
}
} Thread = PsGetCurrentThread (); LOCK_WS_SHARED (Thread, TargetProcess); Info.State = MiQueryAddressState (Va,
Vad,
TargetProcess,
&Info.Protect,
&NextVaToQuery); Va = NextVaToQuery; while (MI_VA_TO_VPN (Va) <= Vad->EndingVpn) { NewState = MiQueryAddressState (Va,
Vad,
TargetProcess,
&NewProtect,
&NextVaToQuery); if ((NewState != Info.State) || (NewProtect != Info.Protect)) { //
// The state for this address does not match, calculate
// size and return.
// Leaped = FALSE;
break;
}
Va = NextVaToQuery;
} UNLOCK_WS_SHARED (Thread, TargetProcess); //
// We may have aggressively leaped past the end of the VAD. Shorten the
// Va here if we did.
// if (Leaped == TRUE) {
Va = MI_VPN_TO_VA (Vad->EndingVpn + );
} Info.RegionSize = ((PCHAR)Va - (PCHAR)Info.BaseAddress); //
// A range has been found, release the mutexes, detach from the
// target process and return the information.
// UNLOCK_ADDRESS_SPACE (TargetProcess); if (Attached == TRUE) {
KeUnstackDetachProcess (&ApcState);
ObDereferenceObject (TargetProcess);
} if (MemoryInformationClass == MemoryBasicInformation) {
Found = FALSE;
try { *(PMEMORY_BASIC_INFORMATION)MemoryInformation = Info; Found = TRUE;
if (ARGUMENT_PRESENT(ReturnLength)) {
*ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
} } except (EXCEPTION_EXECUTE_HANDLER) { //
// Just return success if the BasicInfo was successfully
// filled in.
// if (Found == FALSE) {
return GetExceptionCode ();
}
}
return STATUS_SUCCESS;
} //
// Try to return the name of the file that is mapped.
// if (FilePointer == NULL) {
return STATUS_INVALID_ADDRESS;
} if (FilePointer == (PVOID)) {
return STATUS_FILE_INVALID;
} MemoryInformationLengthUlong = (ULONG)MemoryInformationLength; if ((SIZE_T)MemoryInformationLengthUlong < MemoryInformationLength) {
return STATUS_INVALID_PARAMETER_5;
} //
// We have a referenced pointer to the file. Call ObQueryNameString
// and get the file name.
// Status = ObQueryNameString (FilePointer,
(POBJECT_NAME_INFORMATION) MemoryInformation,
MemoryInformationLengthUlong,
&LocalReturnLength); ObDereferenceObject (FilePointer); if (ARGUMENT_PRESENT (ReturnLength)) {
try {
*ReturnLength = LocalReturnLength;
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode ();
}
} return Status;
}

Wrk NtQueryVirtualMemory

所以,我们也可以自己来遍历二叉树来获得进程的所有模块,而不用NtQueryVirtualMemory函数,就是一个AVL树的遍历,主要代码如下

typedef struct _MMADDRESS_NODE              // 0x14
{
union u1{ULONG u1;}; // +0x0(0x4)
struct _MMADDRESS_NODE* LeftChild; // +0x4(0x4)
struct _MMADDRESS_NODE* RightChild; // +0x8(0x4)
ULONG StartingVpn; // +0xc(0x4)
ULONG EndingVpn; // +0x10(0x4)
}MMADDRESS_NODE,*PMMADDRESS_NODE; #pragma pack(push,1) typedef struct _EX_FAST_REF
{
union
{
PVOID Object;
ULONG_PTR RefCnt:;
ULONG_PTR Value;
};
} EX_FAST_REF, *PEX_FAST_REF;
#pragma pack(pop) struct _SEGMENT // 0x38
{
struct _CONTROL_AREA* ControlArea; // +0x0(0x4)
ULONG TotalNumberOfPtes; // +0x4(0x4)
ULONG SegmentFlags; // +0x8(0x4)
ULONG NumberOfCommittedPages; // +0xc(0x4)
ULONGLONG SizeOfSegment; // +0x10(0x8)
union
{
struct _MMEXTEND_INFO* ExtendInfo; // +0x18(0x4)
void* BasedAddress; // +0x18(0x4)
};
EX_PUSH_LOCK SegmentLock; // +0x1c(0x4)
ULONG u1; // +0x20(0x4)
ULONG u2; // +0x24(0x4)
struct _MMPTE* PrototypePte; // +0x28(0x4)
//ULONGLONG ThePtes[0x1]; // +0x30(0x8)
};
struct _CONTROL_AREA // 0x50
{
struct _SEGMENT* Segment; // +0x0(0x4)
struct _LIST_ENTRY DereferenceList; // +0x4(0x8)
ULONG NumberOfSectionReferences; // +0xc(0x4)
ULONG NumberOfPfnReferences; // +0x10(0x4)
ULONG NumberOfMappedViews; // +0x14(0x4)
ULONG NumberOfUserReferences; // +0x18(0x4)
ULONG u; // +0x1c(0x4)
ULONG FlushInProgressCount; // +0x20(0x4)
struct _EX_FAST_REF FilePointer; // +0x24(0x4)
};
struct _SUBSECTION // 0x20
{
struct _CONTROL_AREA* ControlArea; // +0x0(0x4)
struct _MMPTE* SubsectionBase; // +0x4(0x4)
struct _SUBSECTION* NextSubsection; // +0x8(0x4)
ULONG PtesInSubsection; // +0xc(0x4)
ULONG UnusedPtes; // +0x10(0x4)
struct _MM_AVL_TABLE* GlobalPerSessionHead; // +0x10(0x4)
union u{ULONG u;}; // +0x14(0x4)
ULONG StartingSector; // +0x18(0x4)
ULONG NumberOfFullSectors; // +0x1c(0x4)
};
typedef struct _MMVAD // 0x3c
{
ULONG u1; // +0x0(0x4)
struct _MMVAD* LeftChild; // +0x4(0x4)
struct _MMVAD* RightChild; // +0x8(0x4)
ULONG StartingVpn; // +0xc(0x4)
ULONG EndingVpn; // +0x10(0x4)
ULONG u; // +0x14(0x4)
EX_PUSH_LOCK PushLock; // +0x18(0x4)
ULONG u5; // +0x1c(0x4)
ULONG u2; // +0x20(0x4)
struct _SUBSECTION* Subsection; // +0x24(0x4)
struct _MSUBSECTION* MappedSubsection; // +0x24(0x4)
struct _MMPTE* FirstPrototypePte; // +0x28(0x4)
struct _MMPTE* LastContiguousPte; // +0x2c(0x4)
struct _LIST_ENTRY ViewLinks; // +0x30(0x8)
struct _EPROCESS* VadsProcess; // +0x38(0x4)
}MMVAD; typedef struct _MM_AVL_TABLE // 0x20
{
struct _MMADDRESS_NODE BalancedRoot; // +0x0(0x14)
ULONG DepthOfTree; // +0x14(0x4)
ULONG Unused; // +0x14(0x4)
ULONG NumberGenericTableElements; // +0x14(0x4)
void* NodeHint; // +0x18(0x4)
void* NodeFreeHint; // +0x1c(0x4)
}MM_AVL_TABLE,*PMMAVL_TABLE; #define GetVadRoot(eprocess) ((PVOID)((char*)eprocess+0x278)) VOID PrintTree(MMVAD* Root)
{
POBJECT_NAME_INFORMATION Str=(POBJECT_NAME_INFORMATION )ExAllocatePool(PagedPool,);
ULONG RetLen=;
if(!Str||!Root)
return ;
RtlZeroMemory(Str,);//递归要节省堆栈资源,不要大量使用局部变量
__try
{
if(MmIsAddressValid(Root->Subsection)&&MmIsAddressValid(Root->Subsection->ControlArea))
{
if(MmIsAddressValid((PVOID)Root->Subsection->ControlArea->FilePointer.Value))
{
//最后三位清零
PFILE_OBJECT pFileObj=(PFILE_OBJECT)((Root->Subsection->ControlArea->FilePointer.Value>>)<<);
if(MmIsAddressValid(pFileObj))
{
NTSTATUS Status=ObQueryNameString(pFileObj,Str,,&RetLen);
if(NT_SUCCESS(Status))
{
DbgPrint("Base:%08X Size:%dKb Name:%wZ\r\n",Root->Subsection->ControlArea->Segment->BasedAddress,\
(Root->Subsection->ControlArea->Segment->SizeOfSegment)/0x1000, \
(PUNICODE_STRING)(&(Str->Name))); }
else
{
DbgPrint("不能获取到对象!%08X\n",Status);
} }
}
}
}
__except()
{
DbgPrint("Invalid Address!\n");
}
ExFreePool(Str);
__try
{
if(MmIsAddressValid(Root->LeftChild))
PrintTree(Root->LeftChild);
if(MmIsAddressValid(Root->RightChild))
PrintTree(Root->RightChild);
}
__except()
{
DbgPrint("Exception!");
return;
} } VOID ShowProcessModule(ULONG Pid)
{
#ifdef _DBG
_asm int
#endif
PMMAVL_TABLE Table;
PEPROCESS Epr=;
if(NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)Pid,&Epr)))
{
KeAttachProcess(Epr);
Table=(PMMAVL_TABLE)GetVadRoot(Epr);
if(Table->BalancedRoot.LeftChild)
PrintTree((MMVAD*)Table->BalancedRoot.LeftChild);
if(Table->BalancedRoot.RightChild)
PrintTree((MMVAD*)Table->BalancedRoot.RightChild);
KeDetachProcess();
}
}

由枚举模块到ring0内存结构 (分析NtQueryVirtualMemory)的更多相关文章

  1. Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析

    原文地址:http://www.javatang.com 一个典型的thread dump文件主要由一下几个部分组成: 上图将JVM上的线程堆栈信息和线程信息做了详细的拆解. 第一部分:Full th ...

  2. JVM内存结构、参数调优和内存泄露分析

    1. JVM内存区域和参数配置 1.1 JVM内存结构 Java堆(Heap) Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都 ...

  3. Swift 枚举-从汇编角度看枚举内存结构

    一.基本使用 先看枚举的几种使用(暂不要问,看看是否都能看懂,待会会逐一讲解) 1.操作一 简单使用 //第一种方式 enum Direction { case east case west case ...

  4. Linux内存技术分析(上)

    Linux内存技术分析(上) 一.Linux存储器 限于存储介质的存取速率和成本,现代计算机的存储结构呈现为金字塔型.越往塔顶,存取效率越高.但成本也越高,所以容量也就越小.得益于程序访问的局部性原理 ...

  5. Java 内存结构备忘录

    本文详细描述了 Java 堆内存模型,垃圾回收算法以及处理内存泄露的最佳方案,并辅之以图表,希望能对理解 Java 内存结构有所帮助.原文作者 Sumith Puri,本文系 OneAPM 工程师编译 ...

  6. 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控

    如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...

  7. java的线程安全、单例模式、JVM内存结构等知识学习和整理

    知其然,不知其所以然 !在技术的海洋里,前路漫漫,我一直在迷失着自我. 欢迎访问我的csdn博客,我们一同成长! "不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!" 博 ...

  8. Oracle内存全面分析

    Oracle内存全面分析 Oracle的内存配置与oracle性能息息相关.而且关于内存的错误(如4030.4031错误)都是十分令人头疼的问题.可以说,关于内存的配置,是最影响Oracle性能的配置 ...

  9. insmod模块加载过程代码分析1【转】

    转自:http://blog.chinaunix.net/uid-27717694-id-3966290.html 一.概述模块是作为ELF对象文件存放在文件系统中的,并通过执行insmod程序链接到 ...

随机推荐

  1. Android 设计模式

    简介 项目开发中发现问题.解决问题这个过程中会出现很多问题,比如重复出现.某个问题的遗留,这些问题的本质就是设计模式.今天记录设计模式的知识点. 内容 在java以及其他的面向对象设计模式中,类与类之 ...

  2. ASP.NET MVC中使用事务写法

    一些项目中,会涉及到事务的写法,比如订单相关,订单成功,会涉及到产品的库存和账户金额的一些信息变动,当然,如果整个流程成功,那是没什么问题,关键是如果中间某一步骤出现bug了,那之前已执行的一些变动就 ...

  3. [转]ubuntu 下minicom超级终端的使用方法

    [转]ubuntu 下minicom超级终端的使用方法 http://blog.chinaunix.net/uid-25909619-id-3184639.html 系统环境: Ubuntu 11.0 ...

  4. 元音字母A的发音规则

    摘抄自百度文库 A/a的发音比较复杂,归纳起来有10种情况: 一.在重读开音节中读[ei]. 例如: plane [plein]  radio [ˈreidiəu] wake [weik]  pape ...

  5. 28335 AD 转换

    #include "DSP2833x_Device.h"#include "DSP2833x_Examples.h" void Ad_init(void){ I ...

  6. 新手学Android

    Eclipse平台下的新手Android学习记录. 1.打开一个本地的项目 在Project Explorer右键->Import->Existing Projects into Work ...

  7. Kinect帮助文档翻译之三 多场景

    在多个Sense中使用KinectManager 为了在多个场景下都能使用KinectManager这个组件,它必须被附在一个只生成一次.不会被销毁且在所有场景中都能访问的游戏物体上,显然把它附在Ma ...

  8. .net 常用正则表达式

    Net中正则表达式的简单使用方法及常见验证判断 判断字符串是只是数字我们可以这样写:return new System.Text.RegularExpressions.Regex(@"^([ ...

  9. 【长期兼职】每天3小时写作=每月4000元外快(IT兼职写手)

    只要你有经验,每周平均有20来个小时的兼职时间. 只要你愿意静静地写一些心得总结. 那么就可以联系我QQ164349714,敲门:写作. 地址不限.特长不限.学历不限.年龄不限. 主要写作方向:1.投 ...

  10. hdu 3879 Base Station 最大权闭合图

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3879 A famous mobile communication company is plannin ...