⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssdtdump.cpp

📁 在驱动下读取SSDT的例子
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////////
// SSDTDump by 李马
// http://www.titilima.cn
//////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <stdio.h>
#include "..\SYS\ioctl.h"
#include "SSDTDump.h"

#define MOV		0xb8

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

//
// MessageId: STATUS_INFO_LENGTH_MISMATCH
//
// MessageText:
//
//  The specified information record length does not match the length required for the specified information class.
//
#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemModuleInformation = 11
} SYSTEM_INFORMATION_CLASS;

typedef LONG NTSTATUS;

#pragma pack( push, 1 )
typedef struct _tagSSDTEntry {
    BYTE  byMov;   // 0xb8
    DWORD dwIndex;
} SSDTENTRY;
#pragma pack( pop )

typedef struct _SYSTEM_MODULE_INFORMATION { 
    ULONG Reserved[2]; 
    PVOID Base; 
    ULONG Size; 
    ULONG Flags; 
    USHORT Index; 
    USHORT Unknown; 
    USHORT LoadCount; 
    USHORT ModuleNameOffset; 
    CHAR ImageName[256]; 
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; 

typedef struct _tagSysModuleList {
    ULONG ulCount;
    SYSTEM_MODULE_INFORMATION smi[1];
} SYSMODULELIST, *PSYSMODULELIST;

// NtQuerySystemInformation
typedef DWORD ( WINAPI * QSIPTR )( SYSTEM_INFORMATION_CLASS, LPVOID, DWORD, PULONG );

//////////////////////////////////////////////////////////////////////////

BOOL GetSSDT( IN HANDLE hDriver, OUT PSSDT buf )
{
    if ( NULL == buf )
    {
        return FALSE;
    }
    DWORD dwReturned;
    BOOL bRet = DeviceIoControl( hDriver, IOCTL_GETSSDT, NULL, 0, buf,
        sizeof( SSDT ), &dwReturned, NULL );
    return bRet && ERROR_SUCCESS == GetLastError();
}

BOOL GetProc( IN HANDLE hDriver, IN ULONG ulIndex, OUT PULONG buf )
{
    if ( NULL == buf )
    {
        return FALSE;
    }
    DWORD dwReturned;
    BOOL bRet = DeviceIoControl( hDriver, IOCTL_GETPROC, &ulIndex,
        sizeof( ULONG ), buf, sizeof( ULONG ), &dwReturned, NULL );
    return bRet && ERROR_SUCCESS == GetLastError();
}

//////////////////////////////////////////////////////////////////////////

PSYSMODULELIST CreateModuleList( IN HMODULE hNtDll )
{
    QSIPTR NtQuerySystemInformation = (QSIPTR)GetProcAddress( hNtDll,
        "NtQuerySystemInformation" );

    NTSTATUS s;
    ULONG nRetSize;
    PSYSMODULELIST pRet = new SYSMODULELIST;

    s = NtQuerySystemInformation( SystemModuleInformation, pRet,
        sizeof( SYSMODULELIST ), &nRetSize );
    if ( STATUS_INFO_LENGTH_MISMATCH == s )
    {
        // 缓冲区太小,重新分配
        delete pRet;
        pRet = (PSYSMODULELIST)new BYTE[nRetSize];
        s = NtQuerySystemInformation( SystemModuleInformation, pRet,
            nRetSize, &nRetSize ); 
    } 
    if ( !NT_SUCCESS( s ) )
    {
        delete[] (LPBYTE)pRet;
        return NULL;
    }
    else
    {
        return pRet;
    }
}

void DestroyModuleList( IN PSYSMODULELIST pList )
{
    delete[] (LPBYTE)pList;
}

BOOL FindModuleByAddr( IN ULONG ulAddr, IN PSYSMODULELIST pList,
                      OUT LPSTR buf, IN DWORD dwSize )
{
    for ( ULONG i = 0; i < pList->ulCount; ++i )
    {
        ULONG ulBase = (ULONG)pList->smi[i].Base;
        ULONG ulMax  = ulBase + pList->smi[i].Size;
        if ( ulBase <= ulAddr && ulAddr < ulMax )
        {
            // 对于路径信息,截取之
            PCSTR pszModule = strrchr( pList->smi[i].ImageName, '\\' );
            if ( NULL != pszModule )
            {
                lstrcpynA( buf, pszModule + 1, dwSize );
            }
            else
            {
                lstrcpynA( buf, pList->smi[i].ImageName, dwSize );
            }
            return TRUE;
        }
    }
    return FALSE;
}

void EnumSSDT( IN HANDLE hDriver, IN HMODULE hNtDll )
{
    DWORD dwOffset                  = (DWORD)hNtDll;
    PIMAGE_EXPORT_DIRECTORY pExpDir = NULL;
    int nNameCnt                    = 0;
    LPDWORD pNameArray              = NULL;
    int i                           = 0;

    // 到PE头部
    dwOffset += ((PIMAGE_DOS_HEADER)hNtDll)->e_lfanew + sizeof( DWORD );
    // 到第一个数据目录
    dwOffset += sizeof( IMAGE_FILE_HEADER ) + sizeof( IMAGE_OPTIONAL_HEADER )
        - IMAGE_NUMBEROF_DIRECTORY_ENTRIES * sizeof( IMAGE_DATA_DIRECTORY );
    // 到导出表位置
    dwOffset = (DWORD)hNtDll
        + ((PIMAGE_DATA_DIRECTORY)dwOffset)->VirtualAddress;
    pExpDir = (PIMAGE_EXPORT_DIRECTORY)dwOffset;

    nNameCnt = pExpDir->NumberOfNames;
    // 到函数名RVA数组
    pNameArray = (LPDWORD)( (DWORD)hNtDll + pExpDir->AddressOfNames );

    // 初始化系统模块链表
    PSYSMODULELIST pList = CreateModuleList( hNtDll );

    // 循环查找函数名
    for ( i = 0; i < nNameCnt; ++i )
    {
        PCSTR pszName = (PCSTR)( pNameArray[i] + (DWORD)hNtDll );
        if ( 'N' == pszName[0] && 't' == pszName[1] )
        {
            // 找到了函数,则定位至查找表
            LPWORD pOrdNameArray = (LPWORD)( (DWORD)hNtDll + pExpDir->AddressOfNameOrdinals );
            // 定位至总表
            LPDWORD pFuncArray   = (LPDWORD)( (DWORD)hNtDll + pExpDir->AddressOfFunctions );
            LPCVOID pFunc        = (LPCVOID)( (DWORD)hNtDll + pFuncArray[pOrdNameArray[i]] );
            
            // 解析函数,获取服务名
            SSDTENTRY entry;
            CopyMemory( &entry, pFunc, sizeof( SSDTENTRY ) );
            if ( MOV == entry.byMov )
            {
                ULONG ulAddr = 0;
                GetProc( hDriver, entry.dwIndex, &ulAddr );

                CHAR strModule[MAX_PATH] = "[Unknown Module]";
                FindModuleByAddr( ulAddr, pList, strModule, MAX_PATH );
                printf( "0x%04X\t%s\t0x%08X\t%s\r\n", entry.dwIndex,
                    strModule, ulAddr, pszName );
            }
        }
    }

    DestroyModuleList( pList );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -