首页
社区
课程
招聘
[求助][讨论]GetCursorPos在驱动层的实现原理
发表于: 2014-3-25 01:40 9671

[求助][讨论]GetCursorPos在驱动层的实现原理

2014-3-25 01:40
9671
为了了解GetCursorPos在驱动层是怎么实现的,本人通过对NtUserCallOneParam 和 NtUserCallTwoParam下勾,再在用户层调用GetCursorPos

第一次测试为XP虚拟机,HOOK到的函数是NtUserCallOneParam,第一个参数为返回值的指针,第二个擦拭为0x26

第二次测试为USB鼠标和键盘的WIN7 32位主机,HOOK到的函数是NtUserCallTwoParam,第一个参数为返回值的指针,第二个参数为0x1

两个不同的系统,内部实现的原理居然不一样,不知道是不是主机用了USB鼠标键盘的原因,希望有经验的大大给指点下,本人想在DDK中实现GetCursorPos这个函数

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
参考ReactOS(仅供参考)
WIN7下实现已经改了好多了 这两个函数
BOOL
WINAPI
GetCursorPos(LPPOINT lpPoint)
{
    BOOL res;
    /* Windows doesn't check if lpPoint == NULL, we do */
    if(!lpPoint)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    res = NtUserxGetCursorPos(lpPoint);

    return res;
}


EXTINLINE BOOL NtUserxGetCursorPos(POINT* lpPoint)
{
    return (BOOL)NtUserCallOneParam((DWORD_PTR)lpPoint, ONEPARAM_ROUTINE_GETCURSORPOS);
}


      case ONEPARAM_ROUTINE_GETCURSORPOS:
      {
          BOOL Ret = TRUE;
          PPOINTL pptl;
          PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
          if (pti->rpdesk != IntGetActiveDesktop()) RETURN(FALSE);
          _SEH2_TRY
          {
              ProbeForWrite((POINT*)Param,sizeof(POINT),1);
             pptl = (PPOINTL)Param;
             *pptl = gpsi->ptCursor;
          }
          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          {
             Ret = FALSE;
          }
          _SEH2_END;
          RETURN(Ret);
      }
2014-3-25 02:09
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
其实就是获取一个全局结构体变量 这个结构体挺庞大的
直接暴力搜索

附上结构
typedef struct tagSERVERINFO
{
    DWORD           dwSRVIFlags;
    ULONG_PTR       cHandleEntries;
    PFN_FNID        mpFnidPfn[FNID_NUM];
    WNDPROC         aStoCidPfn[FNID_NUMSERVERPROC];
    USHORT          mpFnid_serverCBWndProc[FNID_NUM];
    PFNCLIENT       apfnClientA;
    PFNCLIENT       apfnClientW;
    PFNCLIENTWORKER apfnClientWorker;
    ULONG           cbHandleTable;
    ATOM            atomSysClass[ICLS_NOTUSED+1];
    DWORD           dwDefaultHeapBase;
    DWORD           dwDefaultHeapSize;
    UINT            uiShellMsg;
    MBSTRING        MBStrings[MAX_MB_STRINGS];
    ATOM            atomIconSmProp;
    ATOM            atomIconProp;
    ATOM            atomContextHelpIdProp;
    ATOM            atomFrostedWindowProp;
    CHAR            acOemToAnsi[256];
    CHAR            acAnsiToOem[256];
    DWORD           dwInstalledEventHooks;
    PERUSERSERVERINFO;
} SERVERINFO, *PSERVERINFO;

typedef struct _PERUSERSERVERINFO
{
    INT           aiSysMet[SM_CMETRICS];
    ULONG         argbSystemUnmatched[NUM_SYSCOLORS];
    COLORREF      argbSystem[NUM_SYSCOLORS];
    HBRUSH        ahbrSystem[NUM_SYSCOLORS];
    HBRUSH        hbrGray;
    POINT         ptCursor; //在这里
    POINT         ptCursorReal;
    DWORD         dwLastRITEventTickCount;
    INT           nEvents;
    UINT          dtScroll;
    UINT          dtLBSearch;
    UINT          dtCaretBlink;
    UINT          ucWheelScrollLines;
    UINT          ucWheelScrollChars;
    INT           wMaxLeftOverlapChars;
    INT           wMaxRightOverlapChars;
    INT           cxSysFontChar;
    INT           cySysFontChar;
    TEXTMETRICW   tmSysFont;
    DPISERVERINFO dpiSystem;
    HICON         hIconSmWindows;
    HICON         hIcoWindows;
    DWORD         dwKeyCache;
    DWORD         dwAsyncKeyCache;
    ULONG         cCaptures;
    OEMBITMAPINFO oembmi[93];
    RECT          rcScreenReal;
    USHORT        BitCount;
    USHORT        dmLogPixels;
    BYTE          Planes;
    BYTE          BitsPixel;
    ULONG         PUSIFlags;
    UINT          uCaretWidth;
    USHORT        UILangID;
    DWORD         dwLastSystemRITEventTickCountUpdate;
    ULONG         adwDBGTAGFlags[35];
    DWORD         dwTagCount;
    DWORD         dwRIPFlags;
} PERUSERSERVERINFO, *PPERUSERSERVERINFO;
2014-3-25 02:33
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
无聊帮你看看WIN7的
1: kd> u user32!GetCursorPos l 99
USER32!GetCursorPos:
7676a4b3 8bff            mov     edi,edi
7676a4b5 55              push    ebp
7676a4b6 8bec            mov     ebp,esp
7676a4b8 6a69            push    69h //Routine
7676a4ba 6a01            push    1    //Param2
7676a4bc ff7508          push    dword ptr [ebp+8] //Param1 GetCursorPos 的参数
7676a4bf e808370000      call    USER32!NtUserCallTwoParam (7676dbcc)
7676a4c4 5d              pop     ebp
7676a4c5 c20400          ret     4
7676a4c8 90              nop
7676a4c9 90              nop
7676a4ca 90              nop
7676a4cb 90              nop
7676a4cc 90              nop


1: kd> u win32k!NtUserCallTwoParam l 400
win32k!NtUserCallTwoParam:
838189d7 8bff            mov     edi,edi
838189d9 55              push    ebp
838189da 8bec            mov     ebp,esp
838189dc 56              push    esi
838189dd e8578e0200      call    win32k!UserEnterUserCritSec (83841839)
838189e2 8b4510          mov     eax,dword ptr [ebp+10h]
838189e5 8d4898          lea     ecx,[eax-68h]
838189e8 83f90f          cmp     ecx,0Fh
838189eb 7711            ja      win32k!NtUserCallTwoParam+0x27 (838189fe)
838189ed ff750c          push    dword ptr [ebp+0Ch]
838189f0 ff7508          push    dword ptr [ebp+8]
838189f3 ff1485082d9783  call    dword ptr win32k!apfnSimpleCall (83972d08)[eax*4] //我记得这个是叫做 简单调用函数 是一个很大的数组 保存很多例程的地址
838189fa 8bf0            mov     esi,eax
838189fc eb02            jmp     win32k!NtUserCallTwoParam+0x29 (83818a00)
838189fe 33f6            xor     esi,esi
83818a00 e8528e0200      call    win32k!UserSessionSwitchLeaveCrit (83841857)
83818a05 8bc6            mov     eax,esi
83818a07 5e              pop     esi
83818a08 5d              pop     ebp
83818a09 c20c00          ret     0Ch
83818a0c 90              nop
83818a0d 90              nop
83818a0e 90              nop
83818a0f 90              nop
83818a10 90              nop


apfnSimpleCall (83972d08)[eax*4]  = 83972d08 + Routine * 4(83972d08 + 0x69 *4)

//windbg poi(83972d08 + 0x69 *4)
1: kd> dd 83972d08 + 0x69 *4
83972eac  837cf4d2 8382151d 8379b608 837edd5c


837cf4d2 便是Routine 0x69的函数地址
其实就是  win32k!xxxGetCursorPos

1: kd> u win32k!xxxGetCursorPos l 70
win32k!xxxGetCursorPos:
837cf4d2 6a08            push    8
837cf4d4 68d0029883      push    offset win32k!__safe_se_handler_table+0x2380 (839802d0)
837cf4d9 e802270700      call    win32k!_SEH_prolog4 (83841be0)
837cf4de 8b1d58eb9983    mov     ebx,dword ptr [win32k!gptiCurrent (8399eb58)]
837cf4e4 6a02            push    2
837cf4e6 e8ce270300      call    win32k!CheckWinstaAttributeAccess (83801cb9)
837cf4eb 85c0            test    eax,eax
837cf4ed 0f84fb000000    je      win32k!xxxGetCursorPos+0x11c (837cf5ee)
837cf4f3 8b83c8000000    mov     eax,dword ptr [ebx+0C8h]
837cf4f9 85c0            test    eax,eax
837cf4fb 7414            je      win32k!xxxGetCursorPos+0x3f (837cf511)
837cf4fd 3b0514f59983    cmp     eax,dword ptr [win32k!grpdeskRitInput (8399f514)]
837cf503 740c            je      win32k!xxxGetCursorPos+0x3f (837cf511)
837cf505 6a05            push    5
837cf507 e84e640400      call    win32k!UserSetLastError (8381595a)
837cf50c e9dd000000      jmp     win32k!xxxGetCursorPos+0x11c (837cf5ee)
837cf511 8b450c          mov     eax,dword ptr [ebp+0Ch]
837cf514 48              dec     eax
837cf515 741a            je      win32k!xxxGetCursorPos+0x5f (837cf531)
837cf517 48              dec     eax
837cf518 0f85d0000000    jne     win32k!xxxGetCursorPos+0x11c (837cf5ee)
837cf51e a1fcd29983      mov     eax,dword ptr [win32k!gpsi (8399d2fc)]//就是这个全局变量了
837cf523 8bb0580a0000    mov     esi,dword ptr [eax+0A58h]
837cf529 8bb85c0a0000    mov     edi,dword ptr [eax+0A5Ch]
837cf52f eb64            jmp     win32k!xxxGetCursorPos+0xc3 (837cf595)
837cf531 a1fcd29983      mov     eax,dword ptr [win32k!gpsi (8399d2fc)]
837cf536 8bb0500a0000    mov     esi,dword ptr [eax+0A50h]
837cf53c 8bb8540a0000    mov     edi,dword ptr [eax+0A54h]
837cf542 53              push    ebx
837cf543 e825b10300      call    win32k!IsThreadDesktopComposed (8380a66d)
837cf548 85c0            test    eax,eax
837cf54a 7449            je      win32k!xxxGetCursorPos+0xc3 (837cf595)
837cf54c 8b83b8000000    mov     eax,dword ptr [ebx+0B8h]
837cf552 f7400800000020  test    dword ptr [eax+8],20000000h
837cf559 753a            jne     win32k!xxxGetCursorPos+0xc3 (837cf595)
837cf55b a1fcd29983      mov     eax,dword ptr [win32k!gpsi (8399d2fc)]
837cf560 8b88580a0000    mov     ecx,dword ptr [eax+0A58h]
837cf566 8bb85c0a0000    mov     edi,dword ptr [eax+0A5Ch]
837cf56c 0fb780fe100000  movzx   eax,word ptr [eax+10FEh]
837cf573 50              push    eax
837cf574 6a60            push    60h
837cf576 51              push    ecx
837cf577 e813290600      call    win32k!EngMulDiv (83831e8f)
837cf57c 8bf0            mov     esi,eax
837cf57e a1fcd29983      mov     eax,dword ptr [win32k!gpsi (8399d2fc)]
837cf583 0fb780fe100000  movzx   eax,word ptr [eax+10FEh]
837cf58a 50              push    eax
837cf58b 6a60            push    60h
837cf58d 57              push    edi
837cf58e e8fc280600      call    win32k!EngMulDiv (83831e8f)
837cf593 8bf8            mov     edi,eax
837cf595 8365fc00        and     dword ptr [ebp-4],0
837cf599 8b4d08          mov     ecx,dword ptr [ebp+8]
837cf59c a1b0fc9983      mov     eax,dword ptr [win32k!W32UserProbeAddress (8399fcb0)]
837cf5a1 3bc8            cmp     ecx,eax
837cf5a3 7203            jb      win32k!xxxGetCursorPos+0xd6 (837cf5a8)
837cf5a5 c60000          mov     byte ptr [eax],0
837cf5a8 8a01            mov     al,byte ptr [ecx]
837cf5aa 8801            mov     byte ptr [ecx],al
837cf5ac 8a4107          mov     al,byte ptr [ecx+7]
837cf5af 884107          mov     byte ptr [ecx+7],al
837cf5b2 6afe            push    0FFFFFFFEh
837cf5b4 5a              pop     edx
837cf5b5 8955fc          mov     dword ptr [ebp-4],edx
837cf5b8 33c0            xor     eax,eax
837cf5ba 40              inc     eax
837cf5bb 8945fc          mov     dword ptr [ebp-4],eax
837cf5be 8931            mov     dword ptr [ecx],esi
837cf5c0 897904          mov     dword ptr [ecx+4],edi
837cf5c3 8955fc          mov     dword ptr [ebp-4],edx
837cf5c6 eb28            jmp     win32k!xxxGetCursorPos+0x11e (837cf5f0)
837cf5c8 8b45ec          mov     eax,dword ptr [ebp-14h]
837cf5cb 8b00            mov     eax,dword ptr [eax]
837cf5cd ff30            push    dword ptr [eax]
837cf5cf e83aa11900      call    win32k!_W32ExceptionHandler (8396970e)
837cf5d4 c3              ret
837cf5d5 eb0d            jmp     win32k!xxxGetCursorPos+0x112 (837cf5e4)
837cf5d7 8b45ec          mov     eax,dword ptr [ebp-14h]
837cf5da 8b00            mov     eax,dword ptr [eax]
837cf5dc ff30            push    dword ptr [eax]
837cf5de e82ba11900      call    win32k!_W32ExceptionHandler (8396970e)
837cf5e3 c3              ret
837cf5e4 8b65e8          mov     esp,dword ptr [ebp-18h]
837cf5e7 c745fcfeffffff  mov     dword ptr [ebp-4],0FFFFFFFEh
837cf5ee 33c0            xor     eax,eax
837cf5f0 e830260700      call    win32k!_SEH_epilog4 (83841c25)
837cf5f5 c20800          ret     8
2014-3-25 03:09
0
雪    币: 136
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好感动,给我回复了这么多。 我基础不好,看了几遍都没全部理解。
大概是NtUserCallOneParam 和 NtUserCallTwoParam 是获取系统内核的两个结构体,XP鼠标的位置放在第一个结构体里,所以用NtUserCallOneParam获取,而WIN7,微软把鼠标位置放在第二个结构体了,所以要用NtUserCallTwoParam获取
NTSTATUS NtUserCallOneParam(
        IN ULONG Param,
        IN ULONG Routine);
这个函数的参数是这样,NtUserCallTwoParam这个的参数还是一样的吗,好像不止两个了
2014-3-25 15:55
0
雪    币: 136
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
DWORD
NTAPI
NtUserCallTwoParam(
  DWORD Param1,
  DWORD Param2,
  DWORD Routine)
Parameter
DWORD Param1
Parameter depending on the routine
DWORD Param2
Parameter depending on the routine
DWORD Routine
The routine to be executed, see apfnSimpleCall
找到了,嘻嘻
2014-3-25 15:59
0
雪    币: 136
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
WIN7下通过调用NtUserCallTwoParam(返回值指针,0x1,0x69); 可以成功获取到鼠标的位置,谢谢大大的帮助了,给我贴了这么多代码
2014-3-25 16:36
0
雪    币: 478
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
收藏一下,我会用的到
2014-3-26 05:09
0
雪    币: 15
活跃值: (135)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
收藏一下
2014-11-10 15:02
0
游客
登录 | 注册 方可回帖
返回
//