⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 玩转windows -dev-mem.txt

📁 可以对黑客编程有一定的了解
💻 TXT
📖 第 1 页 / 共 5 页
字号:

   mov     ecx, offset _PspActiveProcessMutex
   call    ds:__imp_@ExAcquireFastMutex@4
   [...]
   mov     ecx, offset _PspActiveProcessMutex
   call    ds:__imp_@ExReleaseFastMutex@4

    ExAcquireFastMutex 和 ExReleaseFastMutex被定义为_fastcall,因此参数被反向顺序压栈
(exc,edx,……)。它们在HAL.dll输出。BTW,我没有在winkps.c中锁定。 :)

    首先我们安装一个callgate来执行ring0函数 (MmGetPhysicalAddress and 
ExAcquireFastMutex/ExReleaseFastMutex) ,然后我们枚举进程,最后移除callgate。

    请看winkps.c

    你在例程中所见,安装callgate是简单的一步。困难的部分是读LIST_ENTRY结构。这有点点奇怪,
因为读一个链表不应该象假定的那么困难,但是要清楚的是,我们在处理物理内存。

    首先要避免使用太多的callgate,要尽可能少用。记住,在ring3运行ring0代码不是“好事”。在
线程执行的分配级就会发生问题,第二,你的线程(我认为)会有比设备驱动更低的优先权,即使你使
用SetThreadPriority()。

    调度程序基于两件事情进行调度,进程的基本优先权和当前优先权,当你用win32 API SetThreadPriority()
修改线程的优先权,当前优先权被改变,但是它只是相对于基本优先权而言的。在ring3,没有办法去
改变进程的基本优先权。

    为了不去影射进程所有的section,我只在需要的时侯映射1mb的section。我认为这是最好的办法,
因为多数的EPROCESS结构被定位在0xfce***** 到 0xfcf*****范围内。

C:\coding\phrack\winkps\Release>winkps
 *** win2k process lister ***

Allocation granularity: 65536 bytes
MmGetPhysicalAddress   : 0x804374e0
virtual address of GDT : 0x80036000
physical address of GDT: 0x0000000000036000
Allocated segment      : 3fb
mapped 0xb000 bytes @ 0x00430000 (init Size: 0xa184 bytes)
mapped 0x100000 bytes @ 0x0043e000 (init Size: 0x100000 bytes)
 + 8     System
mapped 0x100000 bytes @ 0x0054e000 (init Size: 0x100000 bytes)
 + 136   smss.exe
 + 160   csrss.exe
 + 156   winlogon.exe
 + 208   services.exe
 + 220   lsass.exe
 + 420   regsvc.exe
 + 436   svchost.exe
 + 480   svchost.exe
 + 524   WinMgmt.exe
mapped 0x100000 bytes @ 0x0065e000 (init Size: 0x100000 bytes)
 + 656   Explorer.exe
 + 764   OSA.EXE
 + 660   mdm.exe
 + 752   cmd.exe
 + 532   msdev.exe
 + 604   ssh.exe
 + 704   Livekd.exe
 + 716   i386kd.exe
 + 448   uedit32.exe
 + 260   winkps.exe

    3 sections mapping + 1 来选择第一个进程队列看起来还不错。我会在winkps.c中仔细描述,但
最好还是花时间去读代码。

winkps.c的流程

  - GetSystemInfo()
    先分配系统的间隔 (用于计算地址转化的偏移)   

  - LoadLibrary()
    取得ntoskrnl.exe中的MmGetPhysicalAddress地址。这也可以通过分解PE头做到。

  - NtOpenSection
    r/w打开\Device\PhysicalMemory

  - InstallCallgate()
    映射section来安装和删除callgate,并且用第二个参数作为Callgate函数来安装。

  - DisplayProcess()
    主循环。通过异常处理捕获错误。我这样做是为了尝试清除Callgate即使发生类似越界访问的错
误(错误的映射就会发生)

  - UninstallCallgate()
    删除Callgate,取消映射

  - NtClose()
    简单地关闭句柄 :)

    现在,你最好读代码了,并且尝试重写winkdump.c,用支持callgate更好的地址转化。 :>


----[ 4.5 Bonus Track

    我能知道的是,现在唯一的产品来限制\Device\PhysicalMemory访问的是"Integrity Protection 
Driver (IPD)" Pedestal Software (see [6]).

---
from README:
    The IPD forbids any process from opening \Device\PhysicalMemory.
---

    呵呵,用ipd,我们也要去接触\Device\PhysicalMemory, :) 我不知道这个产品是否有名,但是无
论如何,我都要绕过它的保护。为了限制访问\Device\PhysicalMemory, IPD hook了ZwOpenSection(),
并且检查是否Section没有通过调用\Device\PhysicalMemory来被打开。

---
from h_mem.c
   if (restrictEnabled()) {
      if (ObjectAttributes && ObjectAttributes->ObjectName &&
          ObjectAttributes->ObjectName->Length>0) {
          if (_wcsicmp(ObjectAttributes->ObjectName->Buffer,
                       L"\\Device\\PhysicaMemory")==0) {
             WCHAR buf[200];
             swprintf(buf,
                      L"Blocking device/PhysicalMemory access,
                      procid=0x%x\n", PsGetCurrentProcessId());
             debugOutput(buf);
             return STATUS_ACCESS_DENIED;
          }
       }
    }
---

    _wcsicmp()提供了两个Unicode buffer的小写比较,因此,我们想办法用其他的名字打开对象。在
第一节中,我们已经看见有symbolic link对象类型,因此,如果我们可以用symbolic link对象连接到
\Device\PhysicalMemory,那不就很好了?

    通过查看ntdll.dll的导出表,你可以找到一个叫"NtCreateSymbolicLinkObject"的函数,跟其他很
多有意思的东西一样,它也没有被公开。它的原型类似:

NTSTATUS NtCreateSymbolicLinkObject(PHANDLE SymLinkHandle,
                                    ACCESS_MASK DesiredAccess,
                                    POBJECT_ATTRIBUTES ObAttributes,
                                    PUNICODE_STRING ObName);

    因此,我们只需要用"\Device\PhysicalMemory"作为ObName来调用这个函数,并在OBJECT_ATTRIBUTES
结构中设置新的名字。我们用"\??\"作为对象的根目录,那么名字就是:"\??\hack_da_ipd"。

    起初,我问自己当用"\??\hack_da_ipd"来调用NtOpenSection的时候,核心怎么来处理symbolic link。
如果NtOpenSection检查目标对象是一个symbolic link,那么就再次调用 NtOpenSection,并且用对象的
真实名字,我们的symbolic link没有用处,因为IPD能探测得到。因此我跟踪了一下:

---
[...]
3 NtCreateSymbolicLinkObject(0x1, {24, 0, 0x40, 0, 0,
     "\??\hack_da_ipd"}, 1245028, ... 48, ) == 0x0
4 NtAllocateVirtualMemory(-1, 1244448, 0, 1244480, 4096, 4, ... ) == 0x0
5 NtRequestWaitReplyPort(36, {124, 148, 0, 16711934, 4222620, 256, 0}, ...           
     {124, 148, 2, 868, 840, 7002, 0}, ) == 0x0
6 NtOpenSection (0x4, {24, 0, 0x40, 0, 0, "\??\hack_da_ipd"}, ... 44, )  
     == 0x0
7 NtRequestWaitReplyPort (36, {124, 148, 0, 868, 840, 7002, 0}, ... {124,
     148, 2, 868, 840, 7003, 0}, ) == 0x0
8 NtClose (44, ... ) == 0x0
9 NtClose (48, ... ) == 0x0
[...]
---

    (windows版的strace可以在BindView's RAZOR站点找到。 [7])

    正如你所见,NtOpenSection函数根本不会重调自己来处理真实的对象名字,这简直太好了!这样,
\Device\PhysicalMemory就完全的我们的了,而IPD简直糟透了。记住,你必须在SYSTEM用户下运行该程序。


--[ 5 示例代码

LICENSE:
Sample code provided with the article may be copied/duplicated and modified
in any form as long as this copyright is prepended unmodified.
Code are proof of concept and the author can and must not be made
responsible for any damage/data loss.
Use this code at your own risk.

                                            crazylord / CNS

----[ 5.1 kmem.h

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

#define OBJ_CASE_INSENSITIVE 0x00000040L
#define OBJ_KERNEL_HANDLE    0x00000200L

typedef LONG NTSTATUS;
#define STATUS_SUCCESS       (NTSTATUS) 0x00000000L
#define STATUS_ACCESS_DENIED (NTSTATUS) 0xC0000022L

#define MAKE_DWORD(_l, _h) (DWORD) (_l | (_h << 16))

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;
    PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

// useful macros
#define InitializeObjectAttributes( p, n, a, r, s ) { \
    (p)->Length = sizeof( OBJECT_ATTRIBUTES );        \
    (p)->RootDirectory = r;                           \
    (p)->Attributes = a;                              \
    (p)->ObjectName = n;                              \
    (p)->SecurityDescriptor = s;                      \
    (p)->SecurityQualityOfService = NULL;             \
    }

#define INIT_UNICODE(_var,_buffer)            \
        UNICODE_STRING _var = {               \
            sizeof (_buffer) - sizeof (WORD), \
            sizeof (_buffer),                 \
            _buffer }

// callgate info
typedef struct _KGDTENTRY {
   WORD LimitLow;
   WORD BaseLow;
   WORD BaseHigh;
} KGDTENTRY, *PKGDTENTRY;

typedef struct _CALLGATE_DESCRIPTOR {
   USHORT offset_0_15;
   USHORT selector;
   UCHAR  param_count :4;
   UCHAR  some_bits   :4;
   UCHAR  type        :4;
   UCHAR  app_system  :1;
   UCHAR  dpl         :2;
   UCHAR  present     :1;
   USHORT offset_16_31;
} CALLGATE_DESCRIPTOR, *PCALLGATE_DESCRIPTOR;

// section info
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
typedef enum _SECTION_INHERIT {
    ViewShare = 1,
    ViewUnmap = 2
} SECTION_INHERIT;

typedef struct _MAPPING {
/*000*/ PHYSICAL_ADDRESS pAddress;
/*008*/ PVOID            vAddress;
/*00C*/ DWORD            Offset;
/*010*/ } MAPPING, *PMAPPING;

// symlink info
#define SYMBOLIC_LINK_QUERY                              (0x0001)
#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)

// process info
// Flink to _EPROCESS
#define TO_EPROCESS(_a) ((DWORD) _a - 0xA0)
// Flink to UniqueProcessId
#define TO_PID(_a) (DWORD) ((DWORD) _a - 0x4)
// Flink to ImageFileName
#define TO_PNAME(_a) (PCHAR) ((DWORD) _a + 0x15C)

typedef struct _DISPATCHER_HEADER {
/*000*/ UCHAR Type;
/*001*/ UCHAR Absolute;
/*002*/ UCHAR Size;
/*003*/ UCHAR Inserted;
/*004*/ LONG SignalState;
/*008*/ LIST_ENTRY WaitListHead;
/*010*/ } DISPATCHER_HEADER;

typedef struct _KEVENT {
/*000*/ DISPATCHER_HEADER Header;
/*010*/ } KEVENT, *PKEVENT;

typedef struct _FAST_MUTEX {
/*000*/ LONG Count;
/*004*/ PVOID Owner;
/*008*/ ULONG Contention;
/*00C*/ KEVENT Event;
/*01C*/ ULONG OldIrql;
/*020*/ } FAST_MUTEX, *PFAST_MUTEX;

// the two following definition come from w2k_def.h by Sven B. Schreiber
typedef struct _MMSUPPORT {
/*000*/ LARGE_INTEGER LastTrimTime;
/*008*/ DWORD         LastTrimFaultCount;
/*00C*/ DWORD         PageFaultCount;
/*010*/ DWORD         PeakWorkingSetSize;
/*014*/ DWORD         WorkingSetSize;
/*018*/ DWORD         MinimumWorkingSetSize;
/*01C*/ DWORD         MaximumWorkingSetSize;
/*020*/ PVOID         VmWorkingSetList;
/*024*/ LIST_ENTRY    WorkingSetExpansionLinks;
/*02C*/ BOOLEAN       AllowWorkingSetAdjustment;
/*02D*/ BOOLEAN       AddressSpaceBeingDeleted;
/*02E*/ BYTE          ForegroundSwitchCount;
/*02F*/ BYTE          MemoryPriority;
/*030*/ } MMSUPPORT, *PMMSUPPORT;

typedef struct _IO_COUNTERS {
/*000*/ ULONGLONG  ReadOperationCount;
/*008*/ ULONGLONG  WriteOperationCount;
/*010*/ ULONGLONG  OtherOperationCount;
/*018*/ ULONGLONG ReadTransferCount;
/*020*/ ULONGLONG WriteTransferCount;
/*028*/ ULONGLONG OtherTransferCount;
/*030*/ } IO_COUNTERS, *PIO_COUNTERS;

// this is a very simplified version :) of the EPROCESS
// structure.

typedef struct _EPROCESS {
/*000*/ BYTE                   Pcb[0x6C];
/*06C*/ NTSTATUS               ExitStatus;
/*070*/ KEVENT                 LockEvent;
/*080*/ DWORD                  LockCount;
/*084*/ DWORD                  dw084;
/*088*/ LARGE_INTEGER          CreateTime;
/*090*/ LARGE_INTEGER          ExitTime;
/*098*/ PVOID                  LockOwner;
/*09C*/ DWORD                  UniqueProcessId;
/*0A0*/ LIST_ENTRY             ActiveProcessLinks; // see PsActiveListHead
/*0A8*/ DWORD                  QuotaPeakPoolUsage[2]; // NP, P
/*0B0*/ DWORD                  QuotaPoolUsage[2]; // NP, P
/*0B8*/ DWORD                  PagefileUsage;
/*0BC*/ DWORD                  CommitCharge;
/*0C0*/ DWORD                  PeakPagefileUsage;
/*0C4*/ DWORD                  PeakVirtualSize;
/*0C8*/ LARGE_INTEGER          VirtualSize;
/*0D0*/ MMSUPPORT              Vm;
/*100*/ LIST_ENTRY             SessionProcessLinks;
/*108*/ DWORD                  dw108[6];
/*120*/ PVOID                  DebugPort;
/*124*/ PVOID                  ExceptionPort;
/*128*/ PVOID                  ObjectTable;
/*12C*/ PVOID                  Token;
/*130*/ FAST_MUTEX             WorkingSetLock;
/*150*/ DWORD                  WorkingSetPage;
/*154*/ BOOLEAN                ProcessOutswapEnabled;
/*155*/ BOOLEAN                ProcessOutswapped;
/*156*/ BOOLEAN                AddressSpaceInitialized;
/*157*/ BOOLEAN                AddressSpaceDeleted;
/*158*/ FAST_MUTEX             AddressCreationLock;
/*178*/ KSPIN_LOCK             HyperSpaceLock;
/*17C*/ DWORD                  ForkInProgress;
/*180*/ WORD                   VmOperation;
/*182*/ BOOLEAN                ForkWasSuccessful;
/*183*/ BYTE                   MmAgressiveWsTrimMask;
/*184*/ DWORD                  VmOperationEvent;
/*188*/ PVOID                  PaeTop;
/*18C*/ DWORD                  LastFaultCount;
/*190*/ DWORD                  ModifiedPageCount;
/*194*/ PVOID                  VadRoot;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -