多维时空 发表于 2014-7-8 09:17:15

求帮望解决x64 SSDT NtUserBuildHwndList问题

求帮望解决下x64位SSDT hook 代码是引用别人的代码.
其他函数的HOOK没问题唯独NtUserBuildHwndList错误....
求帮望解决



00000015    13:07:25    NTUSERBUILDHWNDLISTHook: 0 0 0 fffffa8000000000 fffff96000000000 1fa002010000 0    //NtUserBuildHwndList参数
00000016    13:07:25    NTUSERBUILDHWNDLISTHook: c0000008 0      //NtUserBuildHwndList返回值
00000017    13:07:25    NTUSERBUILDHWNDLISTHook: 0 0 0 fffffa8000000000 fffff96000000000 1fa002010000 0    //NtUserBuildHwndList参数
00000018    13:07:25    NTUSERBUILDHWNDLISTHook: c0000008 0    //NtUserBuildHwndList返回值
00000019    13:07:26    NTUSERBUILDHWNDLISTHook: 0 0 0 fffffa8000000000 fffff96000000000 1fa002010000 0    //NtUserBuildHwndList参数
00000020    13:07:26    NTUSERBUILDHWNDLISTHook: c0000008 0    //NtUserBuildHwndList返回值

00000021    13:07:43    NTUSERBUILDHWNDLISTHook: 0 2028c 1 0 0 1f8002000000 8e2f8    //NtUserBuildHwndList参数00000022    13:07:43    NTUSERBUILDHWNDLISTHook: c0000023 0    //NtUserBuildHwndList返回值
x64错误代码0xc0000008和c0000023
//余下代码和解释
//替换函数

NTSTATUS   NTUSERBUILDHWNDLISTHook(
                                       HDESK hdesk,
                                       HWND hwndNext,
                                       ULONG fEnumChildren,
                                       DWORD idThread,
                                       UINT cHwndMax,
                                       HWND *phwndFirst,
                                       ULONG *pcHwndNeeded)
{
   NTSTATUS   status;


   //打印参数
   DbgPrint("NTUSERBUILDHWNDLISTHook: %llx %llx %llx %llx %llx %llx %llx",hdesk,hwndNext,fEnumChildren,idThread,cHwndMax,phwndFirst,pcHwndNeeded);

      //调用真正函数
   status = g_NtUserBuildHwndList(hdesk,
         hwndNext,
         fEnumChildren,
         idThread,
         cHwndMax,
         phwndFirst,
         pcHwndNeeded);
         //打印返回值
   DbgPrint("NTUSERBUILDHWNDLISTHook: %llx %llx",status,hdesk);


   return status;
}


//替换SSDT函数

VOID ModifySSSDT(ULONG64 Index, ULONG64 Address)
{

    ULONGLONG                W32pServiceTable=0, qwTemp=0;
    LONG                     dwTemp=0;
    PSYSTEM_SERVICE_TABLE    pWin32k;
    KIRQL                  irql;
    DbgPrint("ModifySSSDTAddress: %llx %llx",Address,Index);
    pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE));    //4*8
    W32pServiceTable=(ULONGLONG)(pWin32k->ServiceTableBase);
    qwTemp = W32pServiceTable + 4 * (Index);
    dwTemp = (LONG)(Address - W32pServiceTable);
    DbgPrint("ModifySSSDTAddress: %llx %llx",dwTemp,Address - W32pServiceTable);
    dwTemp = dwTemp << 4;    //DbgPrint("*(PLONG)qwTemp: %x, dwTemp: %x",*(PLONG)qwTemp,dwTemp);
    DbgPrint("ModifySSSDTAddress: %llx %llx",dwTemp,qwTemp);
    irql=WPOFFx64();
    *(PLONG)qwTemp = dwTemp;
    WPONx64(irql);
}

//写入替换函数
//为什么要写入机器码我解释下.......由于x64的读取SSDT是根据一个基址+偏于的 基址是64位的 偏于是32位的,所以我们无法直接替换函数地址进去....我做的解决是从ssdt的基址
//查找14个0x90机器码作为我的中转在jmp [到我的函数];这样就可以跳转64位地址了......
//还有很多种解决方案,或者重在SSDT基址这个有点复杂

VOID HOOK_ShadowSSDT(ULONG64 X_hookAddress,ULONG64 Index,ULONGLONG MyFun)
{

    KIRQL irql;
    ULONG64 myfun;
    UCHAR jmp_code[]="\xFF\x25\x00\x00\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90";    //需要14字节+4字节(jmp [我的函数])
    //代理函数地址
    myfun=MyFun;//取函数地址
    DbgPrint("HOOK_SSSDTmyfun: %llx",myfun);
    //填充shellcode
    memcpy(jmp_code+6,&myfun,8);
    irql=WPOFFx64();
    memcpy((PVOID)(X_hookAddress),jmp_code,14);//写入中转的机器码
    DbgPrint("HOOK_SSSDTmyfun: %s %llx",jmp_code,X_hookAddress);//输机器码和HOOK地址
    WPONx64(irql);
    ModifySSSDT(Index, X_hookAddress);//替换SSDT表
    DbgPrint("HOOK_SSSDT OK!");
}

//根据序号获取函数

ULONGLONG GetSSSDTFuncCurAddr64(ULONG64 Index)
{
    ULONGLONG                W32pServiceTable=0, qwTemp=0;
    LONG                     dwTemp=0;
    PSYSTEM_SERVICE_TABLE    pWin32k;
    pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE));
    W32pServiceTable=(ULONGLONG)(pWin32k->ServiceTableBase);
    ul64W32pServiceTable = W32pServiceTable;
    qwTemp = W32pServiceTable + 4 * (Index);    //这里是获得偏移地址的位置,要HOOK的话修改这里即可
    dwTemp = *(PLONG)qwTemp;
    dwTemp = dwTemp >> 4;
    qwTemp = W32pServiceTable + (LONG64)dwTemp;
    return qwTemp;
}

//获取x64 ShadowSSDT特征

ULONGLONG GetKeServiceDescriptorTableShadow64()
{   
    PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
    PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
    PUCHAR i = NULL;
    UCHAR b1=0,b2=0,b3=0;
    ULONG templong=0;
    ULONGLONG addr=0;
    //DbgPrint("templong地址 i=: %llx",i);
    for(i=StartSearchAddress;i<EndSearchAddress;i++)
    {   
      //DbgPrint("templong地址 i=: %llx",i);
      if( MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2) )
      {
            b1=*i;
            b2=*(i+1);
            b3=*(i+2);
            if( b1==0x4c && b2==0x8d && b3==0x1d ) //4c8d1d
            {
                memcpy(&templong,i+3,4);
            //    DbgPrint("templong地址: %llx",i);
            //    DbgPrint("templong地址: %llx",templong);
                addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
                HookNum = (int)(i+20);
                return addr;
            }
      }
    }
    return 0;
}
页: [1]
查看完整版本: 求帮望解决x64 SSDT NtUserBuildHwndList问题