您的位置:首页 > 产品设计 > UI/UE

使用NtUserBuildHwndList遍历窗口_win7x64

2016-06-08 22:15 1811 查看
在我的上一篇文章中讲到
http://blog.csdn.net/zhuhuibeishadiao/article/details/51604788
枚举窗口 使用EnumWinodws是调用内核中NtUserBuildHwndList 这个函数最后2个参数必须是R3的地址

不然会返回0xC0000008错误,并且如果使用控制台窗口测试,这时ETHREAD下的win32Thread是NULL 也会返回0xC0000008错误 

去实现的时候,返回成功了,但只传回线程的窗口HWND

然后去看了看win32k.sys的这个函数

下面是我修改了好的IDA F5这个函数

// typedef NTSTATUS (__fastcall *PFN_NTUSERBULIDHWNDLIST)(
// __int64 hDesktop,
// __int64 hWndParent,
// BOOLEAN bChildren,
// unsigned int dwThreadId,
// unsigned int lParam,
// OUT PVOID pWnd,
// OUT PVOID pBufSize);

/*参考链接: http://read.pudn.com/downloads3/sourcecode/windows/248345/win2k/private/ntos/w32/ntuser/kernel/enumwin.c__.htm (win2k\private\ntos\w32\ntuser\kernel\enumwin.c) http://svn.netlabs.org/repos/odin32/trunk/include/win/win.h https://www.reactos.org/wiki/Techwiki:Win32k/WND https://www.reactos.org/wiki/Techwiki:Win32k/THREADINFO http://bbs.pediy.com/showthread.php?t=100983 http://www.mengwuji.net/thread-99-1-1.html http://bbs.pediy.com/showthread.php?t=131950
*/
__int64 __fastcall NtUserBuildHwndList(__int64 hDesktop, __int64 hWndParent, BOOL bChildren, unsigned int dwThreadId, unsigned int MaxNum_user, PVOID pWnd_User, unsigned __int64 pBuffSize_User)
{
int m_ThreadId; // ebx@1
BOOL m_bChildren; // er14@1
__int64 m_hWndParent; // rdi@1
__int64 m_hDesktop; // rsi@1
__int64 m_m_pBwl; // r12@1
UINT flags; // er13@1
__int64 v13; // rax@1
__int64 v14; // rdx@1
tagWND *m_tagWnd; // rax@4
NTSTATUS status; // ebx@5
tagTHREADINFO *m_pti; // rax@8
tagTHREADINFO *m_m_pti; // rdi@8
tagDESKTOP *m_rpdesk; // rax@9
tagDESKTOP *m_p_desk_top; // rsi@16
tagTHREADINFO *v21; // rax@16
tagWND *m_top_wnd; // rax@22
__int64 m_pBwl; // rax@27
unsigned int m_max_hwnd; // edi@29
__int64 m_max_num_user; // rbx@29
unsigned __int64 m_p_buff_size_user; // r13@31
unsigned __int64 m_m_p_buff_size_user; // rdx@31
int v29; // [sp+48h] [bp-40h]@16
tagTHREADINFO *v30; // [sp+50h] [bp-38h]@16
tagDESKTOP *v31; // [sp+58h] [bp-30h]@16
int v32; // [sp+60h] [bp-28h]@16
int v33; // [sp+64h] [bp-24h]@16
PVOID Object; // [sp+98h] [bp+10h]@14

m_ThreadId = dwThreadId;
m_bChildren = bChildren;
m_hWndParent = hWndParent;
m_hDesktop = hDesktop;
m_m_pBwl = 0i64;
flags = 2;
LODWORD(v13) = ExEnterPriorityRegionAndAcquireResourceExclusive(gpresUser);
gptiCurrent = v13;
gbValidateHandleForIL = 0;
if ( *(_BYTE *)gpsi & 4 )
flags = 10;
if ( m_hWndParent )
{
LODWORD(m_tagWnd) = ValidateHwnd(m_hWndParent);
if ( !m_tagWnd )
{
status = 0xC0000008;
goto LABEL_41;
}
}
else
{
m_tagWnd = 0i64;
}
if ( m_ThreadId )
{
m_pti = (tagTHREADINFO *)PtiFromThreadId(m_ThreadId);
m_m_pti = m_pti;
if ( !m_pti || (m_rpdesk = m_pti->rpdesk) == 0i64 )
{
status = 0xC0000008;
UserSetLastError(0x57);
goto LABEL_41;
}
m_tagWnd = m_rpdesk->pDeskInfo->spwnd->spwndChild;
}
else
{
m_m_pti = 0i64;
}
if ( !m_hDesktop )
{
m_p_desk_top = 0i64;
Object = 0i64;
goto LABEL_20;
}
LOBYTE(v14) = 1;
if ( (int)ValidateHdesk((void *)m_hDesktop, v14, 1i64, &Object) < 0 )
{
status = 0xC0000008;
goto LABEL_41;
}
v32 = 0;
v33 = 0;
m_p_desk_top = (tagDESKTOP *)Object;
v31 = (tagDESKTOP *)Object;
v29 = 1;
LODWORD(v21) = PsGetCurrentProcess();
v30 = v21;
status = MapDesktop(&v29);
if ( status >= 0 )
{
m_tagWnd = m_p_desk_top->pDeskInfo->spwnd->spwndChild;
LABEL_20:
if ( m_tagWnd )
{
if ( m_bChildren )
{
flags |= 1u;
m_tagWnd = m_tagWnd->spwndChild;
}
}
else if ( !m_p_desk_top )
{
m_top_wnd = (tagWND *)GetThreadDesktopWindow((__int64)m_m_pti);// /*0x060*/ struct _tagWND* spwndChild;
if ( !m_top_wnd )
{
status = 0xC0000008;
UserSetLastError(0x57);
goto LABEL_41;
}
m_tagWnd = m_top_wnd->spwndChild; // /*0x060*/ struct _tagWND* spwndChild;
}
m_pBwl = BuildHwndList(m_tagWnd, flags, m_m_pti);
m_m_pBwl = m_pBwl; // _BWL 这个结构符号里找不到
/*
ROS 中2k xp中定义如下:
typedef struct _BWL
{
struct _BWL *pbwlNext;
HWND *phwndNext;
HWND *phwndMax;
PTHREADINFO ptiOwner;
HWND rghwnd[1];
} BWL, *PBWL;
*/
if ( m_pBwl )
{
m_max_hwnd = (unsigned __int64)((*(_QWORD *)(m_pBwl + 8) - m_pBwl - 0x20) >> 3) + 1;
m_max_num_user = MaxNum_user;
if ( MaxNum_user > 0x1FFFFFFF )
ExRaiseAccessViolation();
ProbeForWrite(pWnd_User, 8 * m_max_num_user, 4u);
m_p_buff_size_user = pBuffSize_User;
m_m_p_buff_size_user = pBuffSize_User;
if ( pBuffSize_User >= (unsigned __int64)W32UserProbeAddress )
m_m_p_buff_size_user = (unsigned __int64)W32UserProbeAddress;
*(_DWORD *)m_m_p_buff_size_user = *(_DWORD *)m_m_p_buff_size_user;
if ( m_max_hwnd > (unsigned int)m_max_num_user )
{
status = 0xC0000023;
}
else
{
memmove(pWnd_User, (const void *)(m_m_pBwl + 0x20), 8i64 * m_max_hwnd);
status = 0;
}
*(_DWORD *)m_p_buff_size_user = m_max_hwnd;
}
else
{
status = 0xC0000008;
UserSetLastError(8);
}
goto LABEL_37;
}
UserSetLastError(6);
LABEL_37:
if ( m_m_pBwl )
FreeHwndList(m_m_pBwl);
if ( m_p_desk_top )
ObfDereferenceObject(m_p_desk_top);
LABEL_41:
UserSessionSwitchLeaveCrit();
return (unsigned int)status;
}可以看到 最后两个参数必须是R3的地址

否则返回0xC0000008错误,还有一点是如果这个线程的win32Thread是NULL的话也会返回0xC0000008错误(在控制台程序中出现)

修改后的代码,很明显可以知道如果dwThreadId是NULL的话就是枚举所有HWND

以下代码在win7 x64下测试通过

代码没有查询窗口的进程是谁

要查询的话只要调用

NtUserQueryWindow 即可得到

例如NtUserQueryWindow(hWnd,0);

R0:#include <ntddk.h>

#define DEVICE_NAME L"\\device\\DjWow"
#define LINK_NAME L"\\dosdevices\\DjWow" //\\??\\xxxx

#define IOCTRL_BASE 0x800

#define IOCTL_CODE(i) \
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE+i, METHOD_BUFFERED,FILE_ANY_ACCESS)

#define CTL_HELLO IOCTL_CODE(0)
#define CTL_ULONG IOCTL_CODE(1)
#define CTL_WCHAR IOCTL_CODE(2)
#define CTL_CALLLIST IOCTL_CODE(3)

VOID testGetWndList(unsigned int ThreadId,PVOID OutputBuffer,ULONG BufferSize,PVOID Outbuflenbuf);

typedef NTSTATUS (__fastcall *PFN_NTUSERBULIDHWNDLIST)(
__int64 hDesktop,
__int64 hWndParent,
BOOLEAN bChildren,
unsigned int dwThreadId,
unsigned int lParam,
OUT PVOID pWnd,
OUT PVOID pBufSize);
//硬编码了
PFN_NTUSERBULIDHWNDLIST g_NtUserBuildHwndList = (PFN_NTUSERBULIDHWNDLIST)0xfffff96000084630;

NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;

UNREFERENCED_PARAMETER(pDeviceObject);

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;

UNREFERENCED_PARAMETER(pDeviceObject);

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;

UNREFERENCED_PARAMETER(pDeviceObject);

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

NTSTATUS DispatchClear(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;

UNREFERENCED_PARAMETER(pDeviceObject);

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
PVOID pBuff = 0;
ULONG pBuffLen = 0;
ULONG pStackLen = 0;
PIO_STACK_LOCATION pStack = 0;
ULONG uMin = 0;

UNREFERENCED_PARAMETER(pDeviceObject);

pBuff = pIrp->AssociatedIrp.SystemBuffer;

pStack = IoGetCurrentIrpStackLocation(pIrp);

pStackLen = pStack->Parameters.Read.Length;

pBuffLen = (wcslen(L"hello world") + 1) * sizeof(WCHAR);

uMin = pBuffLen < pStackLen ? pBuffLen:pStackLen;

RtlCopyMemory(pBuff, L"hello wolrd", uMin);

pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uMin;

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

NTSTATUS DispatchWrite(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
PVOID pWriteBuff = 0;
PVOID pBuff = 0;
ULONG uWriteBuffLen = 0;
PIO_STACK_LOCATION pStack = 0;

UNREFERENCED_PARAMETER(pDeviceObject);

pWriteBuff = pIrp->AssociatedIrp.SystemBuffer;

pStack = IoGetCurrentIrpStackLocation(pIrp);

uWriteBuffLen = pStack->Parameters.Write.Length;

pBuff = ExAllocatePoolWithTag(PagedPool, uWriteBuffLen,'TSET');

if(pBuff == NULL)
{
pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
pIrp->IoStatus.Information = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}

RtlZeroMemory(pBuff, uWriteBuffLen);

RtlCopyMemory(pBuff,pWriteBuff, uWriteBuffLen);

ExFreePool(pBuff);
pBuff = 0;

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uWriteBuffLen;

return STATUS_SUCCESS;
}

NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
PIO_STACK_LOCATION pStack = 0;
PVOID pBuff = 0;
ULONG uOutLen = 0;
ULONG uInLen = 0;
ULONG uCtlCode = 0;
ULONG_PTR *Context;

PVOID64 outbuflenbuf;
PVOID64 OutBuf;
unsigned int ThreadId;

UNREFERENCED_PARAMETER(pDeviceObject);

pStack = IoGetCurrentIrpStackLocation(pIrp);

uOutLen = pStack->Parameters.DeviceIoControl.OutputBufferLength;
uInLen = pStack->Parameters.DeviceIoControl.InputBufferLength;

pBuff = pIrp->AssociatedIrp.SystemBuffer;

uCtlCode = pStack->Parameters.DeviceIoControl.IoControlCode;

switch (uCtlCode)
{
case CTL_HELLO:
DbgPrint("hello!\n");
break;
case CTL_ULONG:
{
DbgPrint("pid:%d\n",*(ULONG*)pBuff);
RtlCopyMemory(pBuff,L"ok",uOutLen);
break;
}
case CTL_WCHAR:
DbgPrint("%ws",pBuff);
break;
case CTL_CALLLIST:
{
Context = (ULONG_PTR*)pBuff;
ThreadId = (unsigned int)Context[0];
OutBuf = (PVOID)Context[1];
uOutLen = Context[2];
outbuflenbuf = (PVOID)Context[3];
DbgPrint("[Drv]Thread Id is %d OutpubBuffer=0x%08LLX BufLen=0x%X outbuflenbuf = 0x%08LLX\n",ThreadId,OutBuf,uOutLen,outbuflenbuf);
testGetWndList(ThreadId,OutBuf,uOutLen,outbuflenbuf);
break;
}
default:
DbgPrint("UNKNUW CTLCODE!\n");
break;
}

pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uOutLen;

IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

/*
参考: http://bbs.pediy.com/showthread.php?t=100983 http://www.mengwuji.net/thread-99-1-1.html http://bbs.pediy.com/showthread.php?t=131950 I:\IDA分析\win7 x64\win32k.sys / win32k.i64
*/
VOID testGetWndList(unsigned int ThreadId,PVOID64 OutputBuffer,ULONG BufferSize,PVOID64 Outbuflenbuf)
{
//ULONG_PTR *HwnBuf=NULL;
ULONG BufSize=0;
ULONG MaxNum = 0x1000;
NTSTATUS status;
int i = 0;
__int64 hwnd = 0;
__int64 *hwndtable = NULL;

BufSize = BufferSize;
MaxNum = BufferSize/sizeof(ULONG_PTR);
//HwnBuf = (ULONG_PTR*)OutputBuffer;
DbgPrint("MAXNUM:0x%x",MaxNum);
DbgPrint("准备调用NtUserBuildHwndList...\n");

status = g_NtUserBuildHwndList(0,
0,
FALSE,
NULL,//ThreadId,
MaxNum,//MaxNum
OutputBuffer,
Outbuflenbuf);

hwndtable = (__int64*)OutputBuffer;
DbgPrint("%d\n",*(ULONG_PTR*)Outbuflenbuf);

/*
0 d fffff960`00084862 e 1 0001 (0001) win32k!NtUserBuildHwndList+0x232
1 e fffff960`000847fb e 1 0001 (0001) win32k!NtUserBuildHwndList+0x1cb
3 e fffff960`00084804 e 1 0001 (0001) win32k!NtUserBuildHwndList+0x1d4
*/
for (i = 0; i < *(ULONG_PTR*)Outbuflenbuf; i++)
{
__try
{
hwnd = hwndtable[i];
DbgPrint("0x%llx\n",hwnd);
}
__except(1)
{
DbgPrint("except!\n");
}
}
DbgPrint("count:%d\n",i);
DbgPrint("NtUserBuildHwndList Returned status = 0x%08X \n",status);
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING strLinkName ={0};

RtlInitUnicodeString(&strLinkName,LINK_NAME);

IoDeleteSymbolicLink(&strLinkName);

if(pDriverObject->DeviceObject)
{
IoDeleteDevice(pDriverObject->DeviceObject);
}

DbgPrint("DriverUnload");

return;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
UNICODE_STRING strDeviceName = {0};
UNICODE_STRING strLinkName = {0};
NTSTATUS status = 0;
PDEVICE_OBJECT pDeviceObject = 0;
ULONG i = 0;

DbgPrint("[DJWOW]DriverEntry!\n");

UNREFERENCED_PARAMETER(pRegPath);

RtlInitUnicodeString(&strDeviceName, DEVICE_NAME);
RtlInitUnicodeString(&strLinkName, LINK_NAME);

status = IoCreateDevice(pDriverObject, 0, &strDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);

if(!NT_SUCCESS(status))
{
DbgPrint("CretaDevice Faild:0x%x\n",status);
return status;
}

pDeviceObject->Flags |= DO_BUFFERED_IO;

status = IoCreateSymbolicLink(&strLinkName,&strDeviceName);

if(!NT_SUCCESS(status))
{
IoDeleteDevice(pDeviceObject);
DbgPrint("IoCreateSymbolicdLink Faild:0x%x\n",status);
return status;
}

for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
{
pDriverObject->MajorFunction[i] = DispatchCommon;
}

pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctrl;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClear;

pDriverObject->DriverUnload = DriverUnload;

return STATUS_SUCCESS;

}

R3(也需要是x64):

int CMFC_EXEDlg::SendDeviceIoControl(void)
{
DWORD byteRetned=0;
DWORD retValue;
char buffer[300] = {0};
char wndbuffer[0x1000] = {0};
HWND* tmp = 0;

ULONG_PTR IoContext[4]={0};//ThreadId,Outputbuffer,outbuflen
DWORD dwThreadId = GetCurrentThreadId();
CString str;
/*sprintf(buffer,"[Client]Current TheadId = %d\n",dwThreadId);
OutputDebugStringA(buffer);*/
//printf("[Client]Current TheadId = %d\n",dwThreadId);
str.Format(L"%d",dwThreadId);
m_edit_string = str;
UpdateData(FALSE);
/*sprintf(buffer,"[Client]WndList Buffer = 0x%08X\n",wndbuffer);
OutputDebugStringA(buffer);*/
//printf("[Client]WndList Buffer = 0x%08X\n",wndbuffer);
str.Format(L"0x%08x\r\n",wndbuffer);
m_edit_string += str;

HANDLE hDevice = CreateFileA( "\\\\.\\DjWow",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( hDevice == ((HANDLE)0xFFFFFFFF) )
{
OutputDebugStringA("[Client]Open SymbolLink Failed!\n");
return 0;
}
//填充buffer
IoContext[0] = dwThreadId;
IoContext[1] = (ULONG_PTR)wndbuffer;
IoContext[2] = 0x1000;
IoContext[3] = (ULONG_PTR)&IoContext[2];

retValue=DeviceIoControl(hDevice,
CTL_CALLLIST,
IoContext,
sizeof(ULONG_PTR)*4,
wndbuffer,
0x1000,
&byteRetned,
NULL);
CloseHandle(hDevice);
/*sprintf(buffer,"[Client]return value=%d\n",retValue);
OutputDebugStringA(buffer);*/
//printf("[Client]return value=%d\n",retValue);
m_edit_string += "\r\nok!";
//str.Format(L"%s",wndbuffer);
//m_edit_string += L"\r\n" + str;
tmp = (HWND*)wndbuffer;
int i = 0;
while (i < 100)
{
GetWindowTextA(tmp[i],buffer,MAX_PATH-1);
str.Format(L"%s",buffer);
m_edit_string += L"\r\n" + str;
UpdateData(FALSE);
i++;
}
UpdateData(FALSE);
return 1;
}

为什么不用EnumWindows呢?

我就闲着无聊.....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息