1. 程式人生 > >核心特徵碼搜尋 獲取未匯出函式

核心特徵碼搜尋 獲取未匯出函式

無聊寫了下

有Bug 注意下就好啦~

#include "GetUndocumentFunctionAdress.h"
#pragma warning(disable : 4047)

PVOID GetCallPoint(PVOID pCallPoint)
{
    ULONG dwOffset = 0;
    ULONG_PTR returnAddress = 0;
    LARGE_INTEGER returnAddressTemp = { 0 };
    PUCHAR pFunAddress = NULL;

    if (pCallPoint == NULL || !MmIsAddressValid(pCallPoint))
        return NULL;

    pFunAddress = pCallPoint;
    // 函式偏移
    RtlCopyMemory(&dwOffset, (PVOID)(pFunAddress + 1), sizeof(ULONG));

    // JMP向上跳轉
    if ((dwOffset & 0x10000000) == 0x10000000)
    {
        dwOffset = dwOffset + 5 + pFunAddress;
        returnAddressTemp.QuadPart = (ULONG_PTR)pFunAddress & 0xFFFFFFFF00000000;
        returnAddressTemp.LowPart = dwOffset;
        returnAddress = returnAddressTemp.QuadPart;
        return (PVOID)returnAddress;
     }

     returnAddress = (ULONG_PTR)dwOffset + 5 + pFunAddress;
     return (PVOID)returnAddress;

}

PVOID GetUndocumentFunctionAddress(IN PUNICODE_STRING pFunName, IN PUCHAR pStartAddress, IN UCHAR* pFeatureCode, IN ULONG FeatureCodeNum, ULONG SerSize ,UCHAR SegCode, ULONG AddNum, BOOLEAN ByName)
{
    ULONG dwIndex = 0;
    PUCHAR pFunAddress = NULL;
    ULONG dwCodeNum = 0;

    if (pFeatureCode == NULL)
        return NULL;

    if (FeatureCodeNum >= 15)
        return NULL;

    if (SerSize > 0x1024)
        return NULL;

    if (ByName)
    {
        if (pFunName == NULL || !MmIsAddressValid(pFunName->Buffer))
            return NULL;

        pFunAddress = (PUCHAR)MmGetSystemRoutineAddress(pFunName);
        if (pFunAddress == NULL)
            return NULL;
    }
    else
    {
        if (pStartAddress == NULL || !MmIsAddressValid(pStartAddress))
            return NULL;

        pFunAddress = pStartAddress;
    }

    for (dwIndex = 0; dwIndex < SerSize; dwIndex++)
    {
        __try
        {
            if (pFunAddress[dwIndex] == pFeatureCode[dwCodeNum] || pFeatureCode[dwCodeNum] == SegCode)
            {
                dwCodeNum++;

                if (dwCodeNum == FeatureCodeNum)
                    return pFunAddress + dwIndex - dwCodeNum + 1 + AddNum;

                continue;
            }

            dwCodeNum = 0;
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            return 0;
        } 
    }

    return 0;
}

#ifndef _GetUndocumentFunctionAdress_h_
#define _GetUndocumentFunctionAdress_h_ 1

#include <ntddk.h>

/*
獲取Call的地址
考慮了向上跳的問題
引數:e8 開始的地址
*/
PVOID GetCallPoint(PVOID pCallPoint);

/*
獲取未匯出函式所在地址(沒有計算call 和跳轉) 得到的地址需要計算偏移
支援模糊搜尋 可用分隔符代替未知
存在問題:記憶體重疊時出現問題(見例子)
實際此函式為特徵碼搜尋函式
引數:
PUNICODE_STRING pFunName : 函式名稱(需要是匯出函式)
PUCHAR pStartAddress: 開始搜尋的地址
UCHAR* pFeatureCode: 特徵碼 不能超過15個
ULONG FeatureCodeNum: 特徵碼個數
ULONG SerSize: 搜尋範圍大小 不能超過0x1024
UCHAR SegCode: 分割符 用於支援模糊搜尋
ULONG AddNum: 預設返回特徵碼開始的地址 可利用這個數值進行調整
BOOLEAN ByName: 是否是通過函式名搜尋

返回: 失敗返回NULL 成功返回搜尋到的地址
*/

PVOID GetUndocumentFunctionAddress(IN PUNICODE_STRING pFunName, IN PUCHAR pStartAddress, IN UCHAR* pFeatureCode, IN ULONG FeatureCodeNum, ULONG SerSize, UCHAR SegCode, ULONG AddNum, BOOLEAN ByName);

#endif // _GetUndocumentFunctionAdress_h_


/*
使用例子:
例子:

nt!NtOpenProcess:
fffff800`041b62ec 4883ec38        sub     rsp,38h
fffff800`041b62f0 65488b042588010000 mov   rax,qword ptr gs:[188h]
fffff800`041b62f9 448a90f6010000  mov     r10b,byte ptr [rax+1F6h]
fffff800`041b6300 4488542428      mov     byte ptr [rsp+28h],r10b 
fffff800`041b6305 4488542420      mov     byte ptr [rsp+20h],r10b <--如果使用44 ?? ?? ?? ?? e8 做特徵碼 會失敗 原因是前面出現了44 並且特徵碼長度大於了此段程式碼 類似於記憶體重疊
fffff800`041b630a e851fcffff      call    nt!PsOpenProcess (fffff800`041b5f60) <-- 使用e8開頭做特徵碼就不會存在此問題
fffff800`041b630f 4883c438        add     rsp,38h
fffff800`041b6313 c3              ret


UCHAR shellcode[11] =
"\xe8\x60\x60\x60\x60"
"\x48\x60\x60\x60"
"\xc3";

PVOID p = GetUndocumentFunctionAddress(NULL, (PUCHAR)0xfffff800041b62ec, shellcode, 10, 0x300, 0x60, 0, FALSE);
if (p != NULL)
{
    DbgPrint("CallFrom:0x%p -- CallPoint:0x%p\n", p, GetCallPoint(p));
}
*/

使用例子:

#include <ntddk.h>
#include "GetUndocumentFunctionAdress.h"

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
    
    UNICODE_STRING usFunc = { 0 };
    
    UCHAR shellcode2[13] =
        "\x4c\x60\x60\x60\x60"
        "\xe8\x60\x60\x60\x60"
        "\x41\xbd";

    /*
    nt!NtOpenProcess:
    fffff800`041b62ec 4883ec38        sub     rsp,38h
    fffff800`041b62f0 65488b042588010000 mov   rax,qword ptr gs:[188h]
    fffff800`041b62f9 448a90f6010000  mov     r10b,byte ptr [rax+1F6h]
    fffff800`041b6300 4488542428      mov     byte ptr [rsp+28h],r10b
    fffff800`041b6305 4488542420      mov     byte ptr [rsp+20h],r10b
    fffff800`041b630a e851fcffff      call    nt!PsOpenProcess (fffff800`041b5f60)
    fffff800`041b630f 4883c438        add     rsp,38h
    fffff800`041b6313 c3              ret
    */

    UCHAR shellcode[11] =
        "\xe8\x60\x60\x60\x60"
        "\x48\x60\x60\x60"
        "\xc3";

    PVOID p = GetUndocumentFunctionAddress(NULL, (PUCHAR)0xfffff800041b62ec, shellcode, 10, 0x300, 0x60, 0, FALSE);
    if (p != NULL)
    {
        DbgPrint("CallFrom:0x%p -- CallPoint:0x%p\n", p, GetCallPoint(p));
    }
    else
        DbgBreakPoint();

    pDriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}