parent
7759bf39fd
commit
09fa1705ed
|
@ -338,5 +338,7 @@ int main(int argc,char *argv[] )
|
|||
CloseHandle(hExe);
|
||||
CloseHandle(hTransactedFile);
|
||||
CloseHandle(hTransaction);
|
||||
|
||||
getchar();
|
||||
return 0;
|
||||
}
|
|
@ -1,778 +0,0 @@
|
|||
# Process Herpaderping Technical Deep Dive
|
||||
|
||||
This section is a technical deep dive on the behavior behind the exploit.
|
||||
|
||||
## Repeated executions despite the bits on disk changing
|
||||
Let's try to understand why the process successfully executes multiple times
|
||||
despite the bits on disk not being `CMD.exe`. Below is some `WinDbg` output.
|
||||
I've executed the tool as in the demo above, the first herpaderped process was
|
||||
created, then I started another. Let's compare:
|
||||
|
||||
```
|
||||
PROCESS ffff998aab671080
|
||||
SessionId: 1 Cid: 0230 Peb: 3783820000 ParentCid: 28d4
|
||||
DirBase: 12a49a000 ObjectTable: ffff8201fd4cba40 HandleCount: 79.
|
||||
Image: lol.exe
|
||||
|
||||
0: kd> dt nt!_EPROCESS ffff998aab671080
|
||||
...
|
||||
+0x3c0 SectionObject : 0xffff8201`ff93db70 Void
|
||||
...
|
||||
+0x448 ImageFilePointer : (null)
|
||||
...
|
||||
|
||||
0: kd> !object 0xffff8201`ff93db70
|
||||
Object: ffff8201ff93db70 Type: (ffff998aa54d2e80) Section
|
||||
ObjectHeader: ffff8201ff93db40 (new version)
|
||||
HandleCount: 0 PointerCount: 1
|
||||
Directory Object: 00000000 Name: \Users\jxy\Desktop\lol.exe
|
||||
```
|
||||
```
|
||||
PROCESS ffff998aab971080
|
||||
SessionId: 1 Cid: 20a8 Peb: 4d492ca000 ParentCid: 12dc
|
||||
DirBase: 199f9e000 ObjectTable: ffff8201ffc3d200 HandleCount: 71.
|
||||
Image: lol.exe
|
||||
|
||||
0: kd> dt nt!_EPROCESS ffff998aab971080
|
||||
...
|
||||
+0x3c0 SectionObject : 0xffff8201`fc004a10 Void
|
||||
...
|
||||
+0x448 ImageFilePointer : 0xffff998a`adf2dde0 _FILE_OBJECT
|
||||
...
|
||||
|
||||
0: kd> !object 0xffff8201`ff93db70
|
||||
Object: ffff8201ff93db70 Type: (ffff998aa54d2e80) Section
|
||||
ObjectHeader: ffff8201ff93db40 (new version)
|
||||
HandleCount: 0 PointerCount: 1
|
||||
Directory Object: 00000000 Name: \Users\jxy\Desktop\lol.exe
|
||||
|
||||
0: kd> !object 0xffff998a`adf2dde0
|
||||
Object: ffff998aadf2dde0 Type: (ffff998aa54d3820) File
|
||||
ObjectHeader: ffff998aadf2ddb0 (new version)
|
||||
HandleCount: 0 PointerCount: 1
|
||||
Directory Object: 00000000 Name: \Users\jxy\Desktop\lol.exe {HarddiskVolume3}
|
||||
```
|
||||
|
||||
Note the two processes. I've dumped the relevant parts of the `EPROCESS` for
|
||||
each. They have different section objects, as expected, as they need their own
|
||||
sections since they are independent processes. The first process'
|
||||
`ImageFilePointer` is null, since the tool calls `NtCreateProcessEx` and
|
||||
explicitly hands the OS a section to use. We'll circle back around to this
|
||||
later. For now, let's take a closer look at the [FILE_OBJECT][msdn.FILE_OBJECT]:
|
||||
|
||||
```
|
||||
0: kd> dt nt!_FILE_OBJECT 0xffff998a`adf2dde0
|
||||
+0x000 Type : 0n5
|
||||
+0x002 Size : 0n216
|
||||
+0x008 DeviceObject : 0xffff998a`a73c8930 _DEVICE_OBJECT
|
||||
+0x010 Vpb : 0xffff998a`a75ec2a0 _VPB
|
||||
+0x018 FsContext : 0xffff8201`fa92a170 Void
|
||||
+0x020 FsContext2 : 0xffff8202`0514a2e0 Void
|
||||
+0x028 SectionObjectPointer : 0xffff998a`ae08aae8 _SECTION_OBJECT_POINTERS
|
||||
+0x030 PrivateCacheMap : (null)
|
||||
+0x038 FinalStatus : 0n0
|
||||
+0x040 RelatedFileObject : (null)
|
||||
+0x048 LockOperation : 0 ''
|
||||
+0x049 DeletePending : 0 ''
|
||||
+0x04a ReadAccess : 0x1 ''
|
||||
+0x04b WriteAccess : 0 ''
|
||||
+0x04c DeleteAccess : 0 ''
|
||||
+0x04d SharedRead : 0x1 ''
|
||||
+0x04e SharedWrite : 0 ''
|
||||
+0x04f SharedDelete : 0x1 ''
|
||||
+0x050 Flags : 0x44042
|
||||
+0x058 FileName : _UNICODE_STRING "\Users\jxy\Desktop\lol.exe"
|
||||
+0x068 CurrentByteOffset : _LARGE_INTEGER 0x0
|
||||
+0x070 Waiters : 0
|
||||
+0x074 Busy : 0
|
||||
+0x078 LastLock : (null)
|
||||
+0x080 Lock : _KEVENT
|
||||
+0x098 Event : _KEVENT
|
||||
+0x0b0 CompletionContext : (null)
|
||||
+0x0b8 IrpListLock : 0
|
||||
+0x0c0 IrpList : _LIST_ENTRY [ 0xffff998a`adf2dea0 - 0xffff998a`adf2dea0 ]
|
||||
+0x0d0 FileObjectExtension : (null)
|
||||
```
|
||||
|
||||
First, that file object looks different than what we had originally opened with.
|
||||
This is expected since executing the process normally (as the user would, by
|
||||
double clicking it) will cause `explorer.exe` to invoke `NtCreateUserProcess`.
|
||||
That somewhat explains the behavior we see. But if it was using the file,
|
||||
why did it execute `CMD.exe`? We've overwritten it. Its behavior seems like the
|
||||
section is being reused. Let's verify this assumption. The file object stores
|
||||
[SECTION_OBJECT_POINTERS][msdn.SECTION_OBJECT_POINTERS] at
|
||||
`SectionObjectPointer`. Let's look there.
|
||||
|
||||
```
|
||||
0: kd> dx -id 0,0,ffff998aa547b2c0 -r1 ((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffff998aae08aae8)
|
||||
((ntkrnlmp!_SECTION_OBJECT_POINTERS *)0xffff998aae08aae8) : 0xffff998aae08aae8 [Type: _SECTION_OBJECT_POINTERS *]
|
||||
[+0x000] DataSectionObject : 0xffff998aae04c6d0 [Type: void *]
|
||||
[+0x008] SharedCacheMap : 0x0 [Type: void *]
|
||||
[+0x010] ImageSectionObject : 0xffff998aa7c2d660 [Type: void *]
|
||||
```
|
||||
|
||||
According to the documentation the
|
||||
`DataSectionObject` and `ImageSectionObject` are `CONTROL_AREA` structures. And
|
||||
`SharedCacheMap` is `SHARED_CACHE_MAP`. Let's set a breakpoint and see where
|
||||
`ImageSectionObject` is accessed. I'll run another instance of `lol.exe`.
|
||||
|
||||
```
|
||||
ba r8 0xffff998aae08aae8+0x108
|
||||
|
||||
Breakpoint 0 hit
|
||||
nt!MiReferenceControlArea+0x59:
|
||||
fffff802`2f4955e1 408af8 mov dil,al
|
||||
2: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffffd89`f2772640 fffff802`2f9f8111 nt!MiReferenceControlArea+0x59
|
||||
01 fffffd89`f27726d0 fffff802`2f9f8574 nt!MiCreateImageOrDataSection+0x171
|
||||
02 fffffd89`f27727c0 fffff802`2f9f7bcf nt!MiCreateSection+0xf4
|
||||
03 fffffd89`f2772940 fffff802`2f9f7960 nt!MiCreateSectionCommon+0x1ff
|
||||
04 fffffd89`f2772a20 fffff802`2f5d3c15 nt!NtCreateSection+0x60
|
||||
05 fffffd89`f2772a90 00007ffb`de0fc9b4 nt!KiSystemServiceCopyEnd+0x25
|
||||
06 00000000`0496d848 00007ffb`db8a1a47 ntdll!NtCreateSection+0x14
|
||||
07 00000000`0496d850 00007ffb`db8a55a0 KERNELBASE!BasepLoadLibraryAsDataFileInternal+0x2e7
|
||||
08 00000000`0496da80 00007ffb`db88c41d KERNELBASE!LoadLibraryExW+0xe0
|
||||
09 00000000`0496daf0 00007ffb`dd39c9c1 KERNELBASE!GetFileVersionInfoSizeExW+0x3d
|
||||
0a 00000000`0496db50 00007ffb`dd39c94c SHELL32!_LoadVersionInfo+0x39
|
||||
0b 00000000`0496dbc0 00007ffb`db1c43c1 SHELL32!CVersionPropertyStore::Initialize+0x2c5
|
||||
...
|
||||
2d 00000000`0496f3c0 00007ffb`dd376a4a SHELL32!CRegistryVerbsContextMenu::_Execute+0xcb
|
||||
2e 00000000`0496f430 00007ffb`dd362df3 SHELL32!CRegistryVerbsContextMenu::InvokeCommand+0xaa
|
||||
2f 00000000`0496f730 00007ffb`dd391069 SHELL32!HDXA_LetHandlerProcessCommandEx+0x117
|
||||
30 00000000`0496f840 00007ffb`dd54857d SHELL32!CDefFolderMenu::InvokeCommand+0x139
|
||||
31 00000000`0496fba0 00007ffb`dd7faf49 SHELL32!SHInvokeCommandOnContextMenu2+0x1f5
|
||||
32 00000000`0496fde0 00007ffb`dc13dd25 SHELL32!s_DoInvokeVerb+0xc9
|
||||
33 00000000`0496fe50 00007ffb`dc5c7bd4 shcore!_WrapperThreadProc+0xf5
|
||||
34 00000000`0496ff30 00007ffb`de0cce51 KERNEL32!BaseThreadInitThunk+0x14
|
||||
35 00000000`0496ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21
|
||||
|
||||
3: kd> g
|
||||
Breakpoint 0 hit
|
||||
nt!MiReferenceControlArea+0x59:
|
||||
fffff802`2f4955e1 408af8 mov dil,al
|
||||
3: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffffd89`f2771f30 fffff802`2f9f8111 nt!MiReferenceControlArea+0x59
|
||||
01 fffffd89`f2771fc0 fffff802`2f9f8574 nt!MiCreateImageOrDataSection+0x171
|
||||
02 fffffd89`f27720b0 fffff802`2fa52b83 nt!MiCreateSection+0xf4
|
||||
03 fffffd89`f2772230 fffff802`2fa500ee nt!MmCreateSpecialImageSection+0xbb
|
||||
04 fffffd89`f27722e0 fffff802`2f5d3c15 nt!NtCreateUserProcess+0x54e
|
||||
05 fffffd89`f2772a90 00007ffb`de0fd8e4 nt!KiSystemServiceCopyEnd+0x25
|
||||
06 00000000`0496d858 00007ffb`db8df36a ntdll!NtCreateUserProcess+0x14
|
||||
07 00000000`0496d860 00007ffb`db8dbd06 KERNELBASE!CreateProcessInternalW+0x1f7a
|
||||
08 00000000`0496e9b0 00007ffb`dc5cbe93 KERNELBASE!CreateProcessW+0x66
|
||||
09 00000000`0496ea20 00007ffb`db17cf36 KERNEL32!CreateProcessWStub+0x53
|
||||
...
|
||||
14 00000000`0496f3c0 00007ffb`dd376a4a SHELL32!CRegistryVerbsContextMenu::_Execute+0xcb
|
||||
15 00000000`0496f430 00007ffb`dd362df3 SHELL32!CRegistryVerbsContextMenu::InvokeCommand+0xaa
|
||||
16 00000000`0496f730 00007ffb`dd391069 SHELL32!HDXA_LetHandlerProcessCommandEx+0x117
|
||||
17 00000000`0496f840 00007ffb`dd54857d SHELL32!CDefFolderMenu::InvokeCommand+0x139
|
||||
18 00000000`0496fba0 00007ffb`dd7faf49 SHELL32!SHInvokeCommandOnContextMenu2+0x1f5
|
||||
19 00000000`0496fde0 00007ffb`dc13dd25 SHELL32!s_DoInvokeVerb+0xc9
|
||||
1a 00000000`0496fe50 00007ffb`dc5c7bd4 shcore!_WrapperThreadProc+0xf5
|
||||
1b 00000000`0496ff30 00007ffb`de0cce51 KERNEL32!BaseThreadInitThunk+0x14
|
||||
1c 00000000`0496ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21
|
||||
|
||||
3: kd> g
|
||||
Breakpoint 0 hit
|
||||
nt!MiReferenceControlArea+0x59:
|
||||
fffff802`2f4955e1 408af8 mov dil,al
|
||||
0: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffffd89`f28b5640 fffff802`2f9f8111 nt!MiReferenceControlArea+0x59
|
||||
01 fffffd89`f28b56d0 fffff802`2f9f8574 nt!MiCreateImageOrDataSection+0x171
|
||||
02 fffffd89`f28b57c0 fffff802`2f9f7bcf nt!MiCreateSection+0xf4
|
||||
03 fffffd89`f28b5940 fffff802`2f9f7960 nt!MiCreateSectionCommon+0x1ff
|
||||
04 fffffd89`f28b5a20 fffff802`2f5d3c15 nt!NtCreateSection+0x60
|
||||
05 fffffd89`f28b5a90 00007ffb`de0fc9b4 nt!KiSystemServiceCopyEnd+0x25
|
||||
06 000000a1`98f7dd78 00007ffb`db8a1a47 ntdll!NtCreateSection+0x14
|
||||
07 000000a1`98f7dd80 00007ffb`db8a55a0 KERNELBASE!BasepLoadLibraryAsDataFileInternal+0x2e7
|
||||
08 000000a1`98f7dfb0 00007ffb`dcfab65b KERNELBASE!LoadLibraryExW+0xe0
|
||||
09 000000a1`98f7e020 00007ffb`dd34bcfc USER32!PrivateExtractIconsW+0x15b
|
||||
0a 000000a1`98f7e530 00007ffb`dd34ba78 SHELL32!SHPrivateExtractIcons+0x1ec
|
||||
0b 000000a1`98f7ea30 00007ff7`70a856ee SHELL32!ExtractIconExW+0xe8
|
||||
```
|
||||
|
||||
As we see, after I double click to start `lol.exe` again, the
|
||||
`ImageSectionObject` is accessed from
|
||||
[SECTION_OBJECT_POINTERS][msdn.SECTION_OBJECT_POINTERS] of the
|
||||
[FILE_OBJECT][msdn.FILE_OBJECT] a number of times. The section data appears to
|
||||
be reused. This would ignore the data on disk and helps explain the behavior
|
||||
we're seeing with multiple executions. This is a smart optimization, if you've
|
||||
already done the work to parse and map the image, why duplicate that work?
|
||||
|
||||
With a bit of reverse engineering of `MiReferenceControlArea` we notice:
|
||||
|
||||
```cpp
|
||||
struct CREATE_SECTION_PACKET
|
||||
{
|
||||
ULONG Flags;
|
||||
DWORD Unknown04;
|
||||
POBJECT_ATTRIBUTES InputObjectAttributes;
|
||||
ULONG AllocateAttributes;
|
||||
ULONG InputAllocationAttributes;
|
||||
UCHAR InputSectionSignatureLevel;
|
||||
BYTE Unknown19;
|
||||
WORD Unknown1A;
|
||||
ULONG InputSectionPageProtection;
|
||||
ULONG PageProtectionMask;
|
||||
DWORD Unknown24;
|
||||
HANDLE InputFileHandle;
|
||||
PFILE_OBJECT InputFileObject;
|
||||
PFILE_OBJECT FileObject;
|
||||
CONTROL_AREA* SectionControlArea;
|
||||
KPROCESSOR_MODE InputPreviousMode;
|
||||
BYTE Unknown49[67];
|
||||
DWORD Unknown8C;
|
||||
SECTION* SectionObject;
|
||||
PLARGE_INTEGER MaximumSize;
|
||||
PACCESS_TOKEN InputToken;
|
||||
DWORD InputSessionId;
|
||||
DWORD UnknownAC;
|
||||
MI_PARTITION* Partition;
|
||||
PIRP TopLevelIrp;
|
||||
BYTE UnknownC0;
|
||||
BYTE UnknownC1[3];
|
||||
DWORD UnknownC4;
|
||||
};
|
||||
|
||||
NTSTATUS __fastcall MiReferenceControlArea(
|
||||
CREATE_SECTION_PACKET* CreateSectionPacket,
|
||||
CONTROL_AREA* ControlArea,
|
||||
CONTROL_AREA** ControlAreaOut)
|
||||
{
|
||||
CONTROL_AREA* controlArea;
|
||||
//...
|
||||
fileObject = CreateSectionPacket->FileObject;
|
||||
//
|
||||
// Retrieve section object pointers. If SEC_IMAGE use ImageSectionObject
|
||||
// otherwise use DataSectionObject
|
||||
//
|
||||
controlArea = fileObject->SectionObjectPointer->DataSectionObject;
|
||||
if ((CreateSectionPacket->AllocateAttributes & SEC_IMAGE) != 0)
|
||||
{
|
||||
controlArea = fileObject->SectionObjectPointer->ImageSectionObject;
|
||||
}
|
||||
//...
|
||||
//
|
||||
// Some exceptionally ugly lock loops and validation.
|
||||
//
|
||||
//...
|
||||
*ControlAreaOut = controlArea;
|
||||
return STATUS_SUCCESS;
|
||||
//...
|
||||
}
|
||||
|
||||
NTSTATUS __fastcall MiCreateImageOrDataSection(
|
||||
CREATE_SECTION_PACKET* CreateSectionPacket)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PFILE_OBJECT fileObject;
|
||||
CONTROL_AREA controlArea;
|
||||
CONTROL_AREA* newControlArea;
|
||||
//...
|
||||
fileObject = CreateSectionPacket->InputFileObject;
|
||||
if (fileObject)
|
||||
{
|
||||
//
|
||||
// A file object was provided already, use it.
|
||||
//
|
||||
goto HaveFileObject;
|
||||
}
|
||||
if ((allocationAttributes & SEC_LARGE_PAGES) == 0)
|
||||
{
|
||||
//
|
||||
// Get the file object form the input file handle.
|
||||
//
|
||||
status = ObReferenceObjectByHandle(
|
||||
CreateSectionPacket->InputFileHandle,
|
||||
MmMakeFileAccess[CreateSectionPacket->PageProtectionMask & 7],
|
||||
IoFileObjectType,
|
||||
CreateSectionPacket->InputPreviousMode,
|
||||
&fileObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (!fileObject->SectionObjectPointer)
|
||||
{
|
||||
//
|
||||
// If the file handle was used and there was not section crated for
|
||||
// it already, this is a failure condition.
|
||||
//
|
||||
status = STATUS_INVALID_FILE_FOR_SECTION;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
:HaveFileObject
|
||||
//...
|
||||
//
|
||||
// Store some information in the packet and the local CONTROL_AREA to
|
||||
// maintain state for further calls.
|
||||
//
|
||||
ObfReferenceObject(fileObject);
|
||||
CreateSectionPacket->FileObject = fileObject;
|
||||
controlArea.u.LongFlags = 2;
|
||||
controlArea.FilePointer.Value = fileObject;
|
||||
newControlArea = NULL;
|
||||
//...
|
||||
while (1)
|
||||
{
|
||||
//...
|
||||
//
|
||||
// Go reference the correct control area.
|
||||
//
|
||||
status = MiReferenceControlArea(CreateSectionPacket,
|
||||
&controlArea,
|
||||
§ionControlArea);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ((status == 0xC000060B) || (status == 0xC0000476))
|
||||
{
|
||||
//
|
||||
// The control area is not charged or is invalid.
|
||||
//
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
CreateSectionPacket->SectionControlArea = sectionControlArea;
|
||||
if ((sectionControlArea->u.LongFlags & 2) != 0)
|
||||
{
|
||||
//
|
||||
// We have the section control area which will have the reference
|
||||
// section. Now, go create the new one.
|
||||
//
|
||||
status = MiCreateNewSection(CreateSectionPacket,
|
||||
&newControlArea);
|
||||
if (NT_SUCCESS(status)))
|
||||
{
|
||||
//...
|
||||
CreateSectionPacket->SectionControlArea = newControlArea;
|
||||
goto Exit;
|
||||
//...
|
||||
Exit:
|
||||
//...
|
||||
return status;
|
||||
}
|
||||
```
|
||||
|
||||
The above code shows that this path will reference the input file object and
|
||||
attempt to reuse the section from the control area to create a new section
|
||||
based on it. In our example, this returns to `MiCreateSection` which does some
|
||||
finalization. Let's go back to the debugger now and identify that file object.
|
||||
From my reverse engineering, I know that `CREATE_SECTION_PACKET` is stored on
|
||||
the stack from a higher call. I'll go identify that.
|
||||
|
||||
This is the structure `CREATE_SECTION_PACKET` in the stack starting at
|
||||
`InputFileHandle` and ending at `FileObject`. Between these fields there exists
|
||||
`InputFileObject`:
|
||||
```
|
||||
0: kd> dq fffffd89`f016b868 L3
|
||||
fffffd89`f016b868 00000000`0000255c 00000000`00000000
|
||||
fffffd89`f016b878 ffff998a`ae91ea20
|
||||
```
|
||||
|
||||
The input file object is null, which is expected in this path. And the
|
||||
`InputFileHandle` is a handle to an almost identical
|
||||
[FILE_OBJECT][msdn.FILE_OBJECT] from the `EPROCESS` of the previous process.
|
||||
But it isn't the same. However, the `SectionObjectPointer` is the same for both
|
||||
objects.
|
||||
|
||||
```
|
||||
0: kd> !handle 00000000`0000255c
|
||||
|
||||
PROCESS ffff998aab1b2480
|
||||
SessionId: 1 Cid: 12dc Peb: 0099d000 ParentCid: 12b8
|
||||
DirBase: 1ab742000 ObjectTable: ffff8201fa4fa6c0 HandleCount: 2041.
|
||||
Image: explorer.exe
|
||||
|
||||
Handle table at ffff8201fa4fa6c0 with 2041 entries in use
|
||||
|
||||
255c: Object: ffff998aae91ea20 GrantedAccess: 00120089 (Protected) (Inherit) (Audit) Entry: ffff8201fbdf9570
|
||||
Object: ffff998aae91ea20 Type: (ffff998aa54d3820) File
|
||||
ObjectHeader: ffff998aae91e9f0 (new version)
|
||||
HandleCount: 1 PointerCount: 32770
|
||||
Directory Object: 00000000 Name: \Users\jxy\Desktop\lol.exe {HarddiskVolume3}
|
||||
|
||||
0: kd> !object ffff998a`ae91ea20
|
||||
Object: ffff998aae91ea20 Type: (ffff998aa54d3820) File
|
||||
ObjectHeader: ffff998aae91e9f0 (new version)
|
||||
HandleCount: 1 PointerCount: 32770
|
||||
Directory Object: 00000000 Name: \Users\jxy\Desktop\lol.exe {HarddiskVolume3}
|
||||
0: kd> dt nt!_FILE_OBJECT ffff998a`ae91ea20
|
||||
+0x000 Type : 0n5
|
||||
+0x002 Size : 0n216
|
||||
+0x008 DeviceObject : 0xffff998a`a73c8930 _DEVICE_OBJECT
|
||||
+0x010 Vpb : 0xffff998a`a75ec2a0 _VPB
|
||||
+0x018 FsContext : 0xffff8201`fa92a170 Void
|
||||
+0x020 FsContext2 : 0xffff8201`ff956940 Void
|
||||
+0x028 SectionObjectPointer : 0xffff998a`ae08aae8 _SECTION_OBJECT_POINTERS
|
||||
+0x030 PrivateCacheMap : (null)
|
||||
+0x038 FinalStatus : 0n0
|
||||
+0x040 RelatedFileObject : (null)
|
||||
+0x048 LockOperation : 0 ''
|
||||
+0x049 DeletePending : 0 ''
|
||||
+0x04a ReadAccess : 0x1 ''
|
||||
+0x04b WriteAccess : 0 ''
|
||||
+0x04c DeleteAccess : 0 ''
|
||||
+0x04d SharedRead : 0x1 ''
|
||||
+0x04e SharedWrite : 0 ''
|
||||
+0x04f SharedDelete : 0x1 ''
|
||||
+0x050 Flags : 0xc0042
|
||||
+0x058 FileName : _UNICODE_STRING "\Users\jxy\Desktop\lol.exe"
|
||||
+0x068 CurrentByteOffset : _LARGE_INTEGER 0x0
|
||||
+0x070 Waiters : 0
|
||||
+0x074 Busy : 0
|
||||
+0x078 LastLock : (null)
|
||||
+0x080 Lock : _KEVENT
|
||||
+0x098 Event : _KEVENT
|
||||
+0x0b0 CompletionContext : (null)
|
||||
+0x0b8 IrpListLock : 0
|
||||
+0x0c0 IrpList : _LIST_ENTRY [ 0xffff998a`ae91eae0 - 0xffff998a`ae91eae0 ]
|
||||
+0x0d0 FileObjectExtension : (null)
|
||||
```
|
||||
|
||||
We now see how the [SECTION_OBJECT_POINTERS][msdn.SECTION_OBJECT_POINTERS] are
|
||||
shared between each [FILE_OBJECT][msdn.FILE_OBJECT]. The new bits from the file
|
||||
don't ever become mapped for a new process until all the
|
||||
[FILE_OBJECT][msdn.FILE_OBJECT] are reclaimed with the shared
|
||||
`SectionObjectPointer` and `ImageSectionObject`.
|
||||
|
||||
```
|
||||
Breakpoint 0 hit
|
||||
nt!MiClearFilePointer+0x5d:
|
||||
fffff802`2f4f9385 ebe2 jmp nt!MiClearFilePointer+0x41 (fffff802`2f4f9369)
|
||||
3: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffffd89`f254f690 fffff802`2f56f501 nt!MiClearFilePointer+0x5d
|
||||
01 fffffd89`f254f6c0 fffff802`2f56f4a9 nt!MiDestroySection+0x29
|
||||
02 fffffd89`f254f6f0 fffff802`2f5eaca0 nt!MiCleanSection+0x6d
|
||||
03 fffffd89`f254f790 fffff802`2f42324e nt!MiCheckControlArea+0x1c7a40
|
||||
04 fffffd89`f254f800 fffff802`2f9da4c3 nt!MiDereferenceControlAreaBySection+0x2a
|
||||
05 fffffd89`f254f830 fffff802`2fa189e0 nt!MiSectionDelete+0x83
|
||||
06 fffffd89`f254f860 fffff802`2f4a1004 nt!ObpRemoveObjectRoutine+0x80
|
||||
07 fffffd89`f254f8c0 fffff802`2fa6d64c nt!ObfDereferenceObject+0xa4
|
||||
08 fffffd89`f254f900 fffff802`2fa26743 nt!PspRundownSingleProcess+0x16c
|
||||
09 fffffd89`f254f980 fffff802`2fa5c4fb nt!PspExitThread+0x60b
|
||||
0a fffffd89`f254fa90 fffff802`2f5d3c15 nt!NtTerminateProcess+0xeb
|
||||
0b fffffd89`f254fb00 00007ffb`de0fc5f4 nt!KiSystemServiceCopyEnd+0x25
|
||||
0c 00000025`020ff718 00000000`00000000 ntdll!NtTerminateProcess+0x14
|
||||
```
|
||||
|
||||
## When is the image section cached?
|
||||
Given the information in the previous section, we know the image section object
|
||||
is cached in the [FILE_OBJECT][msdn.FILE_OBJECT], this image section is then
|
||||
used as a "reference" image section when a new process is created, finally we
|
||||
know that this cached "reference" image section is shared between each
|
||||
[FILE_OBJECT][msdn.FILE_OBJECT].
|
||||
|
||||
But when is that initial section created and cached? This is strait forward to
|
||||
identify with some breakpoints:
|
||||
|
||||
```
|
||||
2: kd> bp nt!NtCreateSection
|
||||
2: kd> g
|
||||
Breakpoint 1 hit
|
||||
nt!NtCreateSection:
|
||||
fffff804`3ebd9fe0 4053 push rbx
|
||||
3: kd> bp /w @$curprocess.Name.Contains("Herpaderp")
|
||||
breakpoint 1 redefined
|
||||
3: kd> g;k
|
||||
0: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffff58c`00d83a08 fffff804`3e7d2e15 nt!NtCreateSection
|
||||
01 fffff58c`00d83a10 00007fff`c0ebca04 nt!KiSystemServiceCopyEnd+0x25
|
||||
02 00000012`076fe9e8 00007fff`c0e6b365 ntdll!NtCreateSection+0x14
|
||||
03 00000012`076fe9f0 00007fff`c0e6b662 ntdll!CsrpConnectToServer+0x1b1
|
||||
04 00000012`076febe0 00007fff`be7fadf2 ntdll!CsrClientConnectToServer+0xe2
|
||||
05 00000012`076fec40 00007fff`be7faa5d KERNELBASE!_KernelBaseBaseDllInitialize+0x212
|
||||
06 00000012`076feec0 00007fff`c0e450a1 KERNELBASE!KernelBaseDllInitialize+0xd
|
||||
07 00000012`076feef0 00007fff`c0e89405 ntdll!LdrpCallInitRoutine+0x65
|
||||
08 00000012`076fef60 00007fff`c0e891f8 ntdll!LdrpInitializeNode+0x1b1
|
||||
09 00000012`076ff0a0 00007fff`c0e89222 ntdll!LdrpInitializeGraphRecurse+0x80
|
||||
0a 00000012`076ff0e0 00007fff`c0e4aa97 ntdll!LdrpInitializeGraphRecurse+0xaa
|
||||
0b 00000012`076ff120 00007fff`c0e42591 ntdll!LdrpPrepareModuleForExecution+0xbf
|
||||
0c 00000012`076ff160 00007fff`c0e422a8 ntdll!LdrpLoadDllInternal+0x199
|
||||
0d 00000012`076ff1e0 00007fff`c0e41764 ntdll!LdrpLoadDll+0xa8
|
||||
0e 00000012`076ff390 00007fff`c0ef4193 ntdll!LdrLoadDll+0xe4
|
||||
0f 00000012`076ff480 00007fff`c0ee1df5 ntdll!LdrpInitializeProcess+0x1a0b
|
||||
10 00000012`076ff8c0 00007fff`c0e91853 ntdll!_LdrpInitialize+0x50589
|
||||
11 00000012`076ff960 00007fff`c0e917fe ntdll!LdrpInitialize+0x3b
|
||||
12 00000012`076ff990 00000000`00000000 ntdll!LdrInitializeThunk+0xe
|
||||
0: kd> g;k
|
||||
Breakpoint 1 hit
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffff58c`00d83a08 fffff804`3e7d2e15 nt!NtCreateSection
|
||||
01 fffff58c`00d83a10 00007fff`c0ebca04 nt!KiSystemServiceCopyEnd+0x25
|
||||
02 00000012`076fdee8 00007ff7`511b6bcb ntdll!NtCreateSection+0x14
|
||||
03 00000012`076fdef0 00000012`076fe048 ProcessHerpaderping!Herpaderp::ExecuteProcess+0x4bb
|
||||
1: kd> !handle 0xac
|
||||
|
||||
PROCESS ffffa78260243440
|
||||
SessionId: 2 Cid: 043c Peb: 12075a2000 ParentCid: 2200
|
||||
DirBase: 36641002 ObjectTable: ffffd08243acfe00 HandleCount: 41.
|
||||
Image: ProcessHerpaderping.exe
|
||||
|
||||
Handle table at ffffd08243acfe00 with 41 entries in use
|
||||
|
||||
00ac: Object: ffffa782611330b0 GrantedAccess: 0012019f Entry: ffffd08246cef2b0
|
||||
Object: ffffa782611330b0 Type: (ffffa782594fb2a0) File
|
||||
ObjectHeader: ffffa78261133080 (new version)
|
||||
HandleCount: 1 PointerCount: 32754
|
||||
Directory Object: 00000000 Name: \Users\Jxy\Desktop\lol.exe {HarddiskVolume4}
|
||||
|
||||
1: kd> dx ((nt!_FILE_OBJECT*)0xffffa782611330b0)->SectionObjectPointer
|
||||
((nt!_FILE_OBJECT*)0xffffa782611330b0)->SectionObjectPointer : 0xffffa78260d1e708 [Type: _SECTION_OBJECT_POINTERS *]
|
||||
[+0x000] DataSectionObject : 0xffffa7825ce5fb30 [Type: void *]
|
||||
[+0x008] SharedCacheMap : 0xffffa78260e24da0 [Type: void *]
|
||||
[+0x010] ImageSectionObject : 0x0 [Type: void *]
|
||||
1: kd> ba w8 0xffffa78260d1e708+0x10
|
||||
1: kd> g
|
||||
Breakpoint 2 hit
|
||||
nt!MiReferenceControlArea+0x129:
|
||||
fffff804`3e62d7f1 33d2 xor edx,edx
|
||||
1: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffff58c`00d835c0 fffff804`3ebda7f1 nt!MiReferenceControlArea+0x129
|
||||
01 fffff58c`00d83650 fffff804`3ebdac54 nt!MiCreateImageOrDataSection+0x171
|
||||
02 fffff58c`00d83740 fffff804`3ebda2af nt!MiCreateSection+0xf4
|
||||
03 fffff58c`00d838c0 fffff804`3ebda040 nt!MiCreateSectionCommon+0x1ff
|
||||
04 fffff58c`00d839a0 fffff804`3e7d2e15 nt!NtCreateSection+0x60
|
||||
05 fffff58c`00d83a10 00007fff`c0ebca04 nt!KiSystemServiceCopyEnd+0x25
|
||||
06 00000012`076fdee8 00007ff7`511b6bcb ntdll!NtCreateSection+0x14
|
||||
07 00000012`076fdef0 00000012`076fe048 ProcessHerpaderping!Herpaderp::ExecuteProcess+0x4bb
|
||||
1: kd> dx ((nt!_FILE_OBJECT*)0xffffa782611330b0)->SectionObjectPointer
|
||||
((nt!_FILE_OBJECT*)0xffffa782611330b0)->SectionObjectPointer : 0xffffa78260d1e708 [Type: _SECTION_OBJECT_POINTERS *]
|
||||
[+0x000] DataSectionObject : 0xffffa7825ce5fb30 [Type: void *]
|
||||
[+0x008] SharedCacheMap : 0xffffa78260e24da0 [Type: void *]
|
||||
[+0x010] ImageSectionObject : 0xfffff58c00d83680 [Type: void *]
|
||||
```
|
||||
|
||||
The above `WinDbg` output shows the image section object is cached within the
|
||||
first [FILE_OBJECT][msdn.FILE_OBJECT] at the call to
|
||||
[NtCreateSection][msdn.NtCreateSection]. We abuse this by forcing the OS to
|
||||
cache an image section object that will be used when process is executed.
|
||||
Before we begin execution of the process, we obscure the content on disk,
|
||||
the changes are not reflected in the cached image section.
|
||||
|
||||
There is an opportunity to inspect section creation from the kernel.
|
||||
[IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION][msdn.IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION]
|
||||
is invoked when the file and section control area locks are acquired. However,
|
||||
there is not a clear indicator in the callback data, in this case, the
|
||||
callback data does not contain the `AllocationAttributes` (`SEC_IMAGE`). For
|
||||
the exploit, in this path, the `PageProtection` will only show `PAGE_READONLY`.
|
||||
There are no `AllocationAttributes`, a future release on Windows 10 will extend
|
||||
this data to include the `AllocationAttributes`. So, `SEC_IMAGE` will be
|
||||
available, however inspection here is not ideal as software will map in this
|
||||
manner without the intention of executing a new process. Placing a hook sooner
|
||||
in this call stack might help, but we run into the same complications with
|
||||
respect to processes creating a section in this manner without the intention
|
||||
of using it to execute a process.
|
||||
|
||||
I'll note here that the section this section is then mapped into the process at
|
||||
the `NtCreateProcess` call:
|
||||
|
||||
```
|
||||
3: kd> k
|
||||
# Child-SP RetAddr Call Site
|
||||
00 fffff58c`00d836d8 fffff804`3ed81a63 nt!PspAllocateProcess
|
||||
01 fffff58c`00d836e0 fffff804`3eec5df5 nt!PspCreateProcess+0x233
|
||||
02 fffff58c`00d839b0 fffff804`3e7d2e15 nt!NtCreateProcessEx+0x85
|
||||
03 fffff58c`00d83a10 00007fff`c0ebca64 nt!KiSystemServiceCopyEnd+0x25
|
||||
04 00000012`076fdee8 00007ff7`511b6d71 ntdll!NtCreateProcessEx+0x14
|
||||
05 00000012`076fdef0 00000012`076fdf58 ProcessHerpaderping!Herpaderp::ExecuteProcess+0x661
|
||||
3: kd> gu
|
||||
nt!PspCreateProcess+0x233:
|
||||
fffff804`3ed81a63 8bf0 mov esi,eax
|
||||
0: kd> gu
|
||||
nt!NtCreateProcessEx+0x85:
|
||||
fffff804`3eec5df5 4883c458 add rsp,58h
|
||||
0: kd> !process 0 0 lol.exe
|
||||
PROCESS ffffa78260fb8080
|
||||
SessionId: 2 Cid: 02b4 Peb: e52ac5f000 ParentCid: 043c
|
||||
DirBase: 42546002 ObjectTable: ffffd0824a0f4a40 HandleCount: 3.
|
||||
Image: lol.exe
|
||||
|
||||
0: kd> .process /r /p ffffa78260fb8080
|
||||
Implicit process is now ffffa782`60fb8080
|
||||
.cache forcedecodeuser done
|
||||
Loading User Symbols
|
||||
PEB is paged out (Peb.Ldr = 000000e5`2ac5f018). Type ".hh dbgerr001" for details
|
||||
0: kd> !vad
|
||||
VAD Level Start End Commit
|
||||
ffffa782606ef080 3 7ffe0 7ffe0 1 Private READONLY
|
||||
ffffa782606ef120 2 7ffeb 7ffeb 1 Private READONLY
|
||||
ffffa782606f06b0 1 e52ac00 e52adff 1 Private READWRITE
|
||||
ffffa7825d3fea50 3 20ba8dc0 20ba8dda 0 Mapped READONLY Pagefile section, shared commit 0x1b
|
||||
ffffa7825d3ff630 2 7df5e58e0 7df5e58e0 0 Mapped READONLY Pagefile section, shared commit 0x1
|
||||
ffffa7825d3ff590 3 7df5e58f0 7df5e5912 0 Mapped READONLY Pagefile section, shared commit 0x23
|
||||
ffffa7825d3ff3b0 0 7df5e5920 7ff5e591f 2 Mapped NO_ACCESS Pagefile section, shared commit 0xdd6
|
||||
ffffa7825d3fd8d0 1 7ff7f4200 7ff7f4264 29 Mapped Exe EXECUTE_WRITECOPY \Users\Jxy\Desktop\lol.exe
|
||||
ffffa7825d3fe4b0 2 7fffc0e20 7fffc100f 16 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\ntdll.dll
|
||||
|
||||
Total VADs: 9, average level: 2, maximum depth: 3
|
||||
Total private commit: 0x32 pages (200 KB)
|
||||
Total shared commit: 0xe7a pages (14824 KB)
|
||||
```
|
||||
|
||||
## What this means for the process creation callback
|
||||
[PS_CREATE_NOTIFY_INFO][msdn.PS_CREATE_NOTIFY_INFO] contains a `FileObject`,
|
||||
which according to the documentation, is the file object of the process being
|
||||
created. How does [PS_CREATE_NOTIFY_INFO][msdn.PS_CREATE_NOTIFY_INFO] in the
|
||||
process creation callback get populated? Well `PspCallProcessNotifyRoutines`
|
||||
calls `PsReferenceProcessFilePointer` of course:
|
||||
|
||||
```cpp
|
||||
NTSTATUS __fastcall PsReferenceProcessFilePointer(
|
||||
PEPROCESS Process,
|
||||
PFILE_OBJECT* FileObject)
|
||||
{
|
||||
NTSTATUS status;
|
||||
CONTROL_AREA* controlArea;
|
||||
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (ExAcquireRundownProtection(&Process->RundownProtect))
|
||||
{
|
||||
if (Process->SectionObject)
|
||||
{
|
||||
controlArea = MiSectionControlArea(Process->SectionObject);
|
||||
*FileObject = MiReferenceControlAreaFile(controlArea);
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
```
|
||||
|
||||
We see here it gets the `FileObject` from the `SectionObject` field in the
|
||||
`EPROCESS`. What does this mean for the callback? I wrote a simple test driver
|
||||
that registers for the callback and prints some debug info.
|
||||
|
||||
```
|
||||
Process: FFFF998AAC8DF080
|
||||
ProcessId: 00000000000008C0
|
||||
CreateInfo: FFFFFD89F16F8E20
|
||||
Flags: 0x00000000
|
||||
ParentProcessId: 0000000000001B90
|
||||
FileObject: FFFF998AB534DAA0
|
||||
ImageFileName: "\Users\jxy\Desktop\lol.exe"
|
||||
CommandLine: ""
|
||||
```
|
||||
```
|
||||
0: kd> dt nt!_FILE_OBJECT FFFF998AB534DAA0
|
||||
+0x000 Type : 0n5
|
||||
+0x002 Size : 0n216
|
||||
+0x008 DeviceObject : 0xffff998a`a73c8930 _DEVICE_OBJECT
|
||||
+0x010 Vpb : 0xffff998a`a75ec2a0 _VPB
|
||||
+0x018 FsContext : 0xffff8202`23a8a170 Void
|
||||
+0x020 FsContext2 : 0xffff8202`23a8a3d0 Void
|
||||
+0x028 SectionObjectPointer : 0xffff998a`b5aa1118 _SECTION_OBJECT_POINTERS
|
||||
+0x030 PrivateCacheMap : (null)
|
||||
+0x038 FinalStatus : 0n0
|
||||
+0x040 RelatedFileObject : 0xffff998a`b239c560 _FILE_OBJECT
|
||||
+0x048 LockOperation : 0 ''
|
||||
+0x049 DeletePending : 0 ''
|
||||
+0x04a ReadAccess : 0x1 ''
|
||||
+0x04b WriteAccess : 0x1 ''
|
||||
+0x04c DeleteAccess : 0 ''
|
||||
+0x04d SharedRead : 0x1 ''
|
||||
+0x04e SharedWrite : 0x1 ''
|
||||
+0x04f SharedDelete : 0x1 ''
|
||||
+0x050 Flags : 0x44042
|
||||
+0x058 FileName : _UNICODE_STRING "\Users\jxy\Desktop\lol.exe"
|
||||
+0x068 CurrentByteOffset : _LARGE_INTEGER 0x44600
|
||||
+0x070 Waiters : 0
|
||||
+0x074 Busy : 0
|
||||
+0x078 LastLock : (null)
|
||||
+0x080 Lock : _KEVENT
|
||||
+0x098 Event : _KEVENT
|
||||
+0x0b0 CompletionContext : (null)
|
||||
+0x0b8 IrpListLock : 0
|
||||
+0x0c0 IrpList : _LIST_ENTRY [ 0xffff998a`b534db60 - 0xffff998a`b534db60 ]
|
||||
+0x0d0 FileObjectExtension : (null)
|
||||
```
|
||||
|
||||
That's the same access that I opened the file with to create the section. Let's
|
||||
try something. Let's run `ProcessHerpaderping` with the `--exclusive` option.
|
||||
This will hold the initial file handle open with exclusive rights.
|
||||
|
||||
```
|
||||
Process: FFFF998AB2BD5080
|
||||
ProcessId: 0000000000001C10
|
||||
CreateInfo: FFFFFD89F1B1DE20
|
||||
Flags: 0x00000000
|
||||
ParentProcessId: 000000000000255C
|
||||
FileObject: FFFF998AB21A6330
|
||||
ImageFileName: "\Users\jxy\Desktop\lol.exe"
|
||||
CommandLine: ""
|
||||
|
||||
0: kd> dt nt!_FILE_OBJECT FFFF998AB21A6330
|
||||
+0x000 Type : 0n5
|
||||
+0x002 Size : 0n216
|
||||
+0x008 DeviceObject : 0xffff998a`a73c8930 _DEVICE_OBJECT
|
||||
+0x010 Vpb : 0xffff998a`a75ec2a0 _VPB
|
||||
+0x018 FsContext : 0xffff8202`23a8a170 Void
|
||||
+0x020 FsContext2 : 0xffff8202`21292760 Void
|
||||
+0x028 SectionObjectPointer : 0xffff998a`b5aa1118 _SECTION_OBJECT_POINTERS
|
||||
+0x030 PrivateCacheMap : 0xffff998a`ab2d3a68 Void
|
||||
+0x038 FinalStatus : 0n0
|
||||
+0x040 RelatedFileObject : 0xffff998a`b239dcd0 _FILE_OBJECT
|
||||
+0x048 LockOperation : 0 ''
|
||||
+0x049 DeletePending : 0 ''
|
||||
+0x04a ReadAccess : 0x1 ''
|
||||
+0x04b WriteAccess : 0x1 ''
|
||||
+0x04c DeleteAccess : 0 ''
|
||||
+0x04d SharedRead : 0 ''
|
||||
+0x04e SharedWrite : 0 ''
|
||||
+0x04f SharedDelete : 0 ''
|
||||
+0x050 Flags : 0x40042
|
||||
+0x058 FileName : _UNICODE_STRING "\Users\jxy\Desktop\lol.exe"
|
||||
+0x068 CurrentByteOffset : _LARGE_INTEGER 0x44600
|
||||
+0x070 Waiters : 0
|
||||
+0x074 Busy : 0
|
||||
+0x078 LastLock : (null)
|
||||
+0x080 Lock : _KEVENT
|
||||
+0x098 Event : _KEVENT
|
||||
+0x0b0 CompletionContext : (null)
|
||||
+0x0b8 IrpListLock : 0
|
||||
+0x0c0 IrpList : _LIST_ENTRY [ 0xffff998a`b21a63f0 - 0xffff998a`b21a63f0 ]
|
||||
+0x0d0 FileObjectExtension : (null)
|
||||
```
|
||||
|
||||
I control this file access now. Meaning, I may hold this handle open and
|
||||
prevent others from accessing the file. While this isn't horrible for the
|
||||
kernel callback, it means any downstream logic that that makes the assumption
|
||||
they can open the file with read access will be broken. Well, such logic would have
|
||||
already been broken, given that I've overwritten the file content. And the kernel callback
|
||||
is boned too, since reading directly from the file using that
|
||||
[FILE_OBJECT][msdn.FILE_OBJECT] will just read the wrong data.
|
||||
|
||||
### But wait, there's more...
|
||||
This also means if I try to execute that process again, it does not work! I get
|
||||
a sharing violation. From user mode, without access to that original target
|
||||
file handle, no one may conventionally execute the process.
|
||||
|
||||
[//]: # (Hyperlink IDs)
|
||||
[github.wil]: https://github.com/microsoft/wil
|
||||
[github.phnt]: https://github.com/processhacker/phnt
|
||||
[msdn.PsSetCreateProcessNotifyRoutineEx]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex
|
||||
[msdn.PsSetCreateProcessNotifyRoutineEx2]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex2
|
||||
[msdn.PsSetCreateThreadNotifyRoutineEx]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreatethreadnotifyroutineex
|
||||
[msdn.PSCREATETHREADNOTIFYTYPE]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ne-ntddk-_pscreatethreadnotifytype
|
||||
[msdn.PSCREATEPROCESSNOTIFYTYPE]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ne-ntddk-_pscreateprocessnotifytype
|
||||
[msdn.IRP_MJ_CLEANUP]: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-cleanup
|
||||
[msdn.NtCreateSection]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwcreatesection
|
||||
[msdn.SEC_IMAGE]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga
|
||||
[msdn.IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/flt-parameters-for-irp-mj-acquire-for-section-synchronization
|
||||
[msdn.IRP_MJ_WRITE]: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-write
|
||||
[msdn.FILE_OBJECT]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_file_object
|
||||
[msdn.SECTION_OBJECT_POINTERS]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_section_object_pointers
|
||||
[msdn.PS_CREATE_NOTIFY_INFO]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_ps_create_notify_info
|
Binary file not shown.
Before Width: | Height: | Size: 266 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 11 MiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.4 MiB |
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 368 KiB |
Binary file not shown.
Loading…
Reference in New Issue