內核獲取未導出函數

第一步:IDA查看這個函數的交叉引用,看到PspAlloCateThread 調用了該函數算法

 

 

 

 

 

 

 

 

 二. 繼續查看有誰調用了PspAllocateThread 這個函數函數

 

 

 

看到了一個導出函數 NtCreateUserProcess ,思路就是   NtCreateUserProcess --> PspAllocateThread --> PspUserThreadStartup  這樣子就能找到 PspUserThreadStartup  函數的地址spa

記錄一下特徵碼 這裏我在  NtCreateUserProcess 調用  PspAllocateThread 的call 附加尋找特徵碼 ,我尋找的特徵碼是  94 24 18 01   其實這種特徵碼不靠譜 但這個函數很小並且從函數頭到調用的位置只出現一次code

這裏順便記錄一下  94這個字節  距離真正調用call 相差 9 個字節blog

 

 

 

接下來尋找 PspAllocateThread 調用 PspUserThreadStartup   附加的特徵碼,8B 86 10 06   這裏距離 lea r8,PspUserThreadStartup   相差16個字節class

 

 

 接下來編寫一個函數暴力枚舉出來引用

PVOID GetPspUserThreadStartup2(ULONG64 函數地址, 暴力掃描* 信息, UCHAR 特徵碼[])
{
    if (!MmIsAddressValid(&函數地址))
    {
        return 0;
    }
    INT code1 = NULL;
    ULONG64 addr = NULL;
    ULONG64 返回地址 = NULL;
    for (size_t i = 0; i < 0x1BF8CA; i++)
    {
        if (memcmp((PVOID)(函數地址 + i), 特徵碼, 信息->特徵碼長度) == 0) 
        {
            addr = 函數地址 + i + 信息->特徵碼距離函數地址偏移;
            信息->偏移 = __insn_len_x86((PVOID)addr, __b64);   //信息->偏移  能夠理解爲地址的彙編長度  好比 0x123456   E8 01  這個0x123456地址長度就是 2
            for (int i = 信息->偏移; i >= 4; i--)
            {
                if (i == 4)
                {
                    信息->偏移 = 信息->偏移 - i;    //這裏算法能夠計算出函數調用位置的後四字節
                    break;
                }
            }
            memcpy(&code1, (PVOID)(addr + 信息->偏移), 4);  //這裏拷貝 調用的位置後四個字節  好比上面看到的 call PspAllocateThread  E8 0D 4E 0C 00    這裏須要拿到後四個字節計算函數真正地址  計算公式  函數真正地址=當前地址+後四字節地址+地址長度
            函數地址 = (addr + code1 + __insn_len_x86((PVOID)addr, __b64));
            返回地址 = 函數地址;
            break;
        }
    }

    return (PVOID)返回地址;
}

使用方法,能夠定義一個結構體方法

 

 

 

 

 上面GetFUnaddr  是 NtcreateUserProcess 在SSDT中的編號  獲取它在SSDT中的地址獲取im

結果:call

相關文章
相關標籤/搜索