guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
阅读:4398回复:15

如何实现NtUserGetWindowLong?

楼主#
更多 发布于:2007-12-05 17:13
shadow ssdt中并没有NtUserGetWindowLong对应的索引号,为了实现GetWindowLong的功能,我尝试通过两次调用NtUserSetWindowLong,实现NtUserGetWindowLong,因为NtUserSetWindowLong在为一个窗口设置一个索引值的时候,会返回原来的值,借助于这一点的确可以通过两次调用NtUserSetWindowLong实现NtUserGetWindowLong。不过结果很不理想。如何在内核中实现NtUserGetWindowLong函数的调用。比如说WIndows 2000/xp/2003
killvxk
论坛版主
论坛版主
  • 注册日期2005-10-03
  • 最后登录2014-04-14
  • 粉丝3
  • 关注1
  • 积分1082分
  • 威望2003点
  • 贡献值0点
  • 好评度1693点
  • 原创分2分
  • 专家分0分
沙发#
发布于:2007-12-05 18:29
你可以看看user32.dll->ntdll.dll中是不是调用ntuserXXX系列函数干的~~
没有战争就没有进步 X3工作组 为您提供最好的军火
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-12-06 09:06
killvxk ,用你的法轮大法拦截一下
NtUserCallNextHookEx(
    HHOOK Hook,
    int Code,
    WPARAM wParam,
    LPARAM lParam)
试试,为什么替换的函数获得控制权后,对应的几个参数驴头不对马嘴啊?为了获得这些参数我还要费劲千辛万苦,从ebp跟踪Win32  API CallNextHookEx的调用堆栈,把这些入口参数找出来。什么原因造成我的
NewNtUserCallNextHookEx,入口参数紊乱啊?
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-12-06 09:10
我看了一下User32!GetWindowLong的汇编代码(Windows xp sp2),没有找到user32.dll->ntdll.dll,调用ntuser*系列函数的痕迹。
WQXNETQIQI
驱动大牛
驱动大牛
  • 注册日期2006-06-12
  • 最后登录2010-10-26
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望1076点
  • 贡献值0点
  • 好评度895点
  • 原创分1分
  • 专家分0分
地下室#
发布于:2007-12-06 10:58
Win32下GetWindowLong是如下实现的:
ULONG_PTR _GetWindowLongPtr(
    PWND pwnd,
    int index,
    BOOL bAnsi)
{
    ULONG_PTR           dwProc;
    DWORD              dwCPDType = 0;
    ULONG_PTR UNALIGNED *pudw;

    /*
     * If it's a dialog window, only a few indices are permitted.
     */
    if (GETFNID(pwnd) != 0) {
        if (TestWF(pwnd, WFDIALOGWINDOW)) {
            switch (index) {
            case DWLP_DLGPROC:    // See similar case GWLP_WNDGPROC

                /*
                 * Hide the window proc from other processes
                 */
                if (!TestWindowProcess(pwnd)) {
                    RIPERR1(ERROR_ACCESS_DENIED,
                            RIP_WARNING,
                            "Access denied to \"pwnd\" (%#p) in _GetWindowLong",
                            pwnd);

                    return 0;
                }

                dwProc = (ULONG_PTR)PDLG(pwnd)->lpfnDlg;

                /*
                 * If a proc exists check it to see if we need a translation
                 */
                if (dwProc) {

                    /*
                     * May need to return a CallProc handle if there is an
                     * Ansi/Unicode transition
                     */
                    if (bAnsi != ((PDLG(pwnd)->flags & DLGF_ANSI) ? TRUE : FALSE)) {
                        dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
                    }

                    if (dwCPDType) {
                        ULONG_PTR cpd;

                        cpd = GetCPD(pwnd, dwCPDType | CPD_DIALOG, dwProc);

                        if (cpd) {
                            dwProc = cpd;
                        } else {
                            RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n");
                        }
                    }
                }

                /*
                 * return proc (or CPD handle)
                 */
                return dwProc;

            case DWLP_MSGRESULT:
                 return (ULONG_PTR)((PDIALOG)pwnd)->resultWP;

            case DWLP_USER:
                 return (ULONG_PTR)((PDIALOG)pwnd)->unused;

            default:
                if (index >= 0 && index < DLGWINDOWEXTRA) {
                    RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, "");
                    return 0;
                }
            }
        } else {
            if (index >= 0 &&
                    (index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
                switch (GETFNID(pwnd)) {
                case FNID_MDICLIENT:
                    /*
                     * Allow the 0 index (which is reserved) to be set/get.
                     * Quattro Pro 1.0 uses this index!
                     */
                    if (index != 0)
                        break;

                    goto GetData;
                    break;

                case FNID_EDIT:

                    if (index != 0)
                        break;

                    /*
                     * If we get to this point we need to return the first
                     * entry in the lookaside.  This will provide backward
                     * compatibilty for 3.51 that allowed edit-controls to
                     * do this.  PeachTree is one app which required this.
                     */
                    pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pwnd + 1));

                    /*
                     * Do not dereference the pointer if we are not in
                     *  the proper address space. Apps like Spyxx like to
                     *  do this on other process' windows
                     */
                    return (TestWindowProcess(pwnd) ? *(ULONG_PTR UNALIGNED *)*pudw : (ULONG_PTR)pudw);

                }

                RIPERR3(ERROR_INVALID_INDEX,
                        RIP_WARNING,
                        "GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)",
                        pwnd, index, (DWORD)pwnd->fnid);
                return 0;
            }
        }
    }

    if (index < 0) {
        return GetWindowData(pwnd, index, bAnsi);
    } else {
        if ((UINT)index + sizeof(ULONG_PTR) > (UINT)pwnd->cbwndExtra) {
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
            return 0;
        } else {

GetData:
            pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pwnd + 1) + index);
            return *pudw;
        }
    }
}


没有完全对应的NtUser*函数(主要调用的有NtUserGetCPD)
驱动开发者 呵呵
WQXNETQIQI
驱动大牛
驱动大牛
  • 注册日期2006-06-12
  • 最后登录2010-10-26
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望1076点
  • 贡献值0点
  • 好评度895点
  • 原创分1分
  • 专家分0分
5楼#
发布于:2007-12-06 11:04
人Re:如何实现NtUserGetWindowLong?
引用第2楼guaiguaiguan于2007-12-06 09:06发表的  :
killvxk ,用你的法轮大法拦截一下
NtUserCallNextHookEx(
    HHOOK Hook,
    int Code,
    WPARAM wParam,
.......

人品问题
驱动开发者 呵呵
GNiDiA
驱动小牛
驱动小牛
  • 注册日期2006-10-11
  • 最后登录2017-10-09
  • 粉丝0
  • 关注0
  • 积分1002分
  • 威望145点
  • 贡献值0点
  • 好评度124点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2007-12-06 20:45
NtUserCallNextHookEx的原型不对,第一个参数是nCode。。。
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-12-07 10:49
谢谢楼上两位。看来在拦截NtUser*函数时,尝试得到窗口的各种属性值是非常麻烦的一件事。如果这样做

DWORD MyNtUserGetWindowLong(HWND hWnd, int nIndex)
{
     DWORD OldValue = NtUserSetWindowLong( hWnd,  nIndex,0);
     NtUserSetWindowLong( hWnd,  nIndex, OldValue);
    return OldValue;
}

结果使用dwStyle 调用上述函数后,某些程序开始紊乱,一些窗口打开后将被立即关闭。主要原因是某些窗口设置零的窗口风格。
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2007-12-07 10:55
NtUserCallNextHookEx函数汇编代码包含retn 10h,意味着这是一个四个参数的函数调用,联系到CallNextHookEx函数的四个参数,我们很容易把它们对应起来,事实上可能是个误区,我分别跟踪了这两个函数,发现CallNextHookEx->NtUserCallNextHookEx的过程中,第一个参数hHook钩子句柄不见了,剩余的三个参数逐个往前移了一个位置,变成了
NtUserCallNextHookEx(int code,WPARAM wParam,LPARAM lParam, DWORD dwKnown);
为了得到CallNextHookEx调用的hHook参数,不得已从系统调用NtUserCallNextHookEx的EBP寄存器中遍历调用堆栈,得到了CallNextHookEx入口的四个参数,方法十分烦琐。

GNiDiA能告诉咱,NtUserCallNextHookEx真正的原型是如何定义的,最后一个参数到底是什么含义。
slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2007-12-07 14:00
W32KAPI
LRESULT
NtUserCallNextHookEx(
    IN int nCode,
    IN WPARAM wParam,
    IN LPARAM lParam,
    IN BOOL bAnsi);

2K的source,难道过时了?
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-12-07 15:48
引用第9楼slwqw于2007-12-07 14:00发表的  :
W32KAPI
LRESULT
NtUserCallNextHookEx(
    IN int nCode,
    IN WPARAM wParam,
.......


多谢!
killvxk
论坛版主
论坛版主
  • 注册日期2005-10-03
  • 最后登录2014-04-14
  • 粉丝3
  • 关注1
  • 积分1082分
  • 威望2003点
  • 贡献值0点
  • 好评度1693点
  • 原创分2分
  • 专家分0分
11楼#
发布于:2007-12-09 02:24
可以用NtUserCallTwoParam来搞到WindowsLong~~
具体参数不能告知~~嘿嘿~~
没有战争就没有进步 X3工作组 为您提供最好的军火
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-12-10 09:29
引用第11楼killvxk于2007-12-09 02:24发表的  :
可以用NtUserCallTwoParam来搞到WindowsLong~~
具体参数不能告知~~嘿嘿~~

是在NtUserCallTwoParam函数实现中找NtUserGetWindowLong入口地址,还是通过调用NtUserCallTwoParam函数,实现NtUserGetWindowLong雷同的功能啊?好人做到底,送佛送西天


#define TWOPARAM_ROUTINE_ENABLEWINDOW       0x53
#define TWOPARAM_ROUTINE_UNKNOWN            0x54
#define TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS    0x55
#define TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW 0x56
#define TWOPARAM_ROUTINE_VALIDATERGN        0x57
#define TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID 0x58
#define TWOPARAM_ROUTINE_CURSORPOSITION     0x59
#define TWOPARAM_ROUTINE_SETCARETPOS        0x60
DWORD
STDCALL
NtUserCallTwoParam(
  DWORD Param1,
  DWORD Param2,
  DWORD Routine);

是否存在
#define TWOPARAM_ROUTINE_GETWINDOWLONG        xxxxxx
然后传入一个句柄,一个索引。返回值就是对应的属性值。
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2007-12-10 13:15
反汇编和跟踪GetWindowLongW的结果是没有发现调用NtUserCallTwoParam函数。
guaiguaiguan
驱动中牛
驱动中牛
  • 注册日期2003-10-11
  • 最后登录2011-01-12
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望556点
  • 贡献值0点
  • 好评度490点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2007-12-11 16:38
没有办法,只好根据不同的操作系统搜索NtUserMessageCall,
查找
:u0008:bf80efa5 L30
0008:bf80efa5  8bff                mov       edi,edi
0008:bf80efa7  55                  push      ebp
0008:bf80efa8  8bec                mov       ebp,esp
0008:bf80efaa  83ec0c              sub       esp,0c
0008:bf80efad  56                  push      esi
0008:bf80efae  57                  push      edi
0008:bf80efaf  e8361bffff          call     bf800aea
0008:bf80efb4  8b4d08              mov       ecx,[ebp+08]
0008:bf80efb7  e8e425ffff          call     bf8015a0
0008:bf80efbc  8b4d1c              mov       ecx,[ebp+1c]
0008:bf80efbf  8bf0                mov       esi,eax
0008:bf80efc1  85f6                test      esi,esi


得到bf8015a0地址后,使用fastcall调用,得到HWND对应的PWND结构,然后在这个结构中某某个成员(+20h)即为对应的dwStyle。谁给贴一份完整的PWND结构啊。



typedef struct tagWND {          // wnd
    THRDESKHEAD   head;

    WW;         // WOW-USER common fields. Defined in wowuserp.h
                //  The presence of "state" at the start of this structure is assumed
                //  by the STATEOFFSET macro.

    PWND                 spwndNext;    // Handle to the next window
    PWND                 spwndParent;  // Backpointer to the parent window.
    PWND                 spwndChild;   // Handle to child
    PWND                 spwndOwner;   // Popup window owner field

    RECT                 rcWindow;     // Window outer rectangle
    RECT                 rcClient;     // Client rectangle

    WNDPROC_PWND         lpfnWndProc;   // Can be WOW address or standard address

    PCLS                 pcls;         // Pointer to window class

    KHRGN                hrgnUpdate;   // Accumulated paint region

    PPROPLIST            ppropList;    // Pointer to property list
    PSBINFO              pSBInfo;   // Words used for scrolling

    PMENU                spmenuSys;  // Handle to system menu
    PMENU                spmenu;     // Menu handle or ID

    KHRGN                hrgnClip;     // Clipping region for this window

    LARGE_UNICODE_STRING strName;
    int                  cbwndExtra;   // Extra bytes in window
    PWND                 spwndLastActive; // Last active in owner/ownee list
    KHIMC                hImc;         // Associated input context handle
    KERNEL_ULONG_PTR     dwUserData;   // Reserved for random application data
} WND;
 上面的WW第二个成员是什么东东,

GETFNID(pwnd)

#define GETFNID(pwnd)       ((pwnd)->fnid & ~FNID_STATUS_BITS)
神秘的fnid偏移量是多少啊?
killvxk
论坛版主
论坛版主
  • 注册日期2005-10-03
  • 最后登录2014-04-14
  • 粉丝3
  • 关注1
  • 积分1082分
  • 威望2003点
  • 贡献值0点
  • 好评度1693点
  • 原创分2分
  • 专家分0分
15楼#
发布于:2007-12-12 00:18
真正的NtUserGetWindowLong不用CallTwo啊,某代码里用CallTwo实现雷同的~~可能是其他CallXXXParam,可以查找一下~~因为M$隐藏了很多CallXXXParam的功能~

NtUserXXX的搜索不是很难~~
没有战争就没有进步 X3工作组 为您提供最好的军火
游客

返回顶部