首页
社区
课程
招聘
[原创]通过pdb解析SSDT表地址
发表于: 2022-6-8 23:08 24937

[原创]通过pdb解析SSDT表地址

2022-6-8 23:08
24937

因为最近的项目有在内核中查找全局变量的需求,有2种方法可以实现此功能。

本项目涉及2个主要程序,因为需要展示SSDT表,所以就使用MFC应用来做展示。然后DIA2DUMPdbghelp.dll用于提供解析PDB服务。

使用PDB解析函数,需要用到vs中自带的DIA2DUMP项目,目录在C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK\Samples\DIA2Dump,因为需要使用里面的函数,所以将其构建为静态库,供外部调用。 图片描述

在DIA2DUMP的原代码是通过CoCreateInstance函数来获取组件对象,这个函数需要提前把dll通过regsvr32注册到系统才可以使用。过于麻烦,因此替换成NoRegCoCreate,该函数不需要提前注册.代码如下

将需要用到的功能封装成了导出函数,因为目前只用到RVA来查符号名,所以封装了一个GetSymbolNameByRVA函数,使用该函数需要在LoadPdb之后,当不使用则可以调用UnloadPdb去卸载。

到此DIA2Dump这块就处理完了,构建后将导出的静态库放入我们的实际项目中。
图片描述

并将msdia140.dlll放到可执行文件目录下
图片描述

在初始化完成后下载PDB文件,比如去微软下载pdb文件,它中间的hash值是需要通过算法解析PE文件生成的
图片描述
解析PE生成HASH的算法是网上找的,直接贴(注:在PEHeaderReader函数中写明了下载符号的服务器地址,默认是微软符号服务器,这里我改成了国内镜像服务器,下载速度会快很多

下载PDB代码

下载PDB效果
图片描述

下载完PDB后,开始使用pdb解析SSDT表, dbghelp.dll中提供了通过符号名获取RVA的功能,而在DIA2DUMP中提供了RVA转符号名的功能。两者可以在具体场景下使用,因为只是demo,所以就简单的做了一下演示

完工!
图片描述

 
//hr = CoCreateInstance(__uuidof(DiaSource),
//    NULL,
//    CLSCTX_INPROC_SERVER,
//    __uuidof(IDiaDataSource),
//    (void**)ppSource);
// 不用提前注册,需要加上#include "diacreate.h"这个头文件
hr = NoRegCoCreate(L"msdia140.dll", // 直接使用dll名
    __uuidof(DiaSource),
    __uuidof(IDiaDataSource),
    (void**)ppSource);
//hr = CoCreateInstance(__uuidof(DiaSource),
//    NULL,
//    CLSCTX_INPROC_SERVER,
//    __uuidof(IDiaDataSource),
//    (void**)ppSource);
// 不用提前注册,需要加上#include "diacreate.h"这个头文件
hr = NoRegCoCreate(L"msdia140.dll", // 直接使用dll名
    __uuidof(DiaSource),
    __uuidof(IDiaDataSource),
    (void**)ppSource);
enum LOAD_PDB_STATUS{
    LOAD_PDB_SUCCESS,
    LOAD_PDB_ERROR,
    OPEN_PDB_ERROR
};
extern "C" {
    // 加载PDB
    int LoadPdb(wchar_t* pFileName) {
          FILE *pFile;
          if (_wfopen_s(&pFile, pFileName, L"r") || !pFile) {
            // 打开文件失败
            return OPEN_PDB_ERROR;
          }
 
          fclose(pFile);
          g_szFilename = pFileName;
          if (!LoadDataFromPdb(g_szFilename, &g_pDiaDataSource, &g_pDiaSession, &g_pGlobalSymbol)) {
              // 打开pdb失败
              return LOAD_PDB_ERROR;
          }
          // 成功
          return LOAD_PDB_SUCCESS;
    }
    // 获取符号名,通过RVA
    void GetSymbolNameByRVA(DWORD dwRVA, BSTR* pSymbolName) {
 
          IDiaSymbol* pSymbol = NULL;
          LONG lDisplacement;
          g_pDiaSession->findSymbolByRVAEx(dwRVA, SymTagNull, &pSymbol, &lDisplacement);
          pSymbol->get_name(pSymbolName);
    }
    // 卸载PDB
    void UnloadPdb() {
        Cleanup();
    }
}
enum LOAD_PDB_STATUS{
    LOAD_PDB_SUCCESS,
    LOAD_PDB_ERROR,
    OPEN_PDB_ERROR
};
extern "C" {
    // 加载PDB
    int LoadPdb(wchar_t* pFileName) {
          FILE *pFile;
          if (_wfopen_s(&pFile, pFileName, L"r") || !pFile) {
            // 打开文件失败
            return OPEN_PDB_ERROR;
          }
 
          fclose(pFile);
          g_szFilename = pFileName;
          if (!LoadDataFromPdb(g_szFilename, &g_pDiaDataSource, &g_pDiaSession, &g_pGlobalSymbol)) {
              // 打开pdb失败
              return LOAD_PDB_ERROR;
          }
          // 成功
          return LOAD_PDB_SUCCESS;
    }
    // 获取符号名,通过RVA
    void GetSymbolNameByRVA(DWORD dwRVA, BSTR* pSymbolName) {
 
          IDiaSymbol* pSymbol = NULL;
          LONG lDisplacement;
          g_pDiaSession->findSymbolByRVAEx(dwRVA, SymTagNull, &pSymbol, &lDisplacement);
          pSymbol->get_name(pSymbolName);
    }
    // 卸载PDB
    void UnloadPdb() {
        Cleanup();
    }
}
 
typedef struct _IMAGE_DEBUG_DIRECTORY_RAW {
    UCHAR format[4];
    UCHAR PdbSignature[16];
    ULONG PdbDbiAge;
    UCHAR ImageName[256];
} IMAGE_DEBUG_DIRECTORY_RAW, * PIMAGE_DEBUG_DIRECTORY_RAW;
 
void CMyDownloadPdbDlg::PEHeaderReader(char* PEFileName, char* url)
{
    FILE* File = fopen(PEFileName, "rb");
 
    IMAGE_DOS_HEADER DosHeader;
    fread(&DosHeader, sizeof(IMAGE_DOS_HEADER), 1, File);
    fseek(File, DosHeader.e_lfanew, SEEK_SET);
 
    // Add 4 bytes to the offset
    ULONG NtHeadersSignature;
    fread(&NtHeadersSignature, 4, 1, File);
 
    IMAGE_FILE_HEADER FileHeader;
    fread(&FileHeader, sizeof(IMAGE_FILE_HEADER), 1, File);
 
    ULONG is32BitHeader = FileHeader.Machine == IMAGE_FILE_MACHINE_I386;
 
    IMAGE_OPTIONAL_HEADER32 OptionalHeader32 = { 0 };
    IMAGE_OPTIONAL_HEADER64 OptionalHeader64 = { 0 };
 
    if (is32BitHeader)
        fread(&OptionalHeader32, sizeof(IMAGE_OPTIONAL_HEADER32), 1, File);
    else
        fread(&OptionalHeader64, sizeof(IMAGE_OPTIONAL_HEADER64), 1, File);
 
    ULONG offDebug = 0;
    ULONG cbFromHeader = 0;
 
    ULONG cbDebug = is32BitHeader ?
        OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size : OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
 
    for (int HeaderNo = 0; HeaderNo < FileHeader.NumberOfSections; ++HeaderNo) {
        IMAGE_SECTION_HEADER SectionHeader;
        fread(&SectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, File);
 
        if ((SectionHeader.PointerToRawData != 0) && (SectionHeader.SizeOfRawData != 0) &&
            (cbFromHeader < (SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData))) {
            cbFromHeader = SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData;
        }
 
        if (cbDebug != 0) {
            if (is32BitHeader) {
                if (SectionHeader.VirtualAddress <= OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress &&
                    ((SectionHeader.VirtualAddress + SectionHeader.SizeOfRawData) > OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)) {
                    offDebug = OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
                }
            }
 
            else {
                if (SectionHeader.VirtualAddress <= OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress &&
                    ((SectionHeader.VirtualAddress + SectionHeader.SizeOfRawData) > OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)) {
                    offDebug = OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
                }
            }
        }
    }
 
    fseek(File, offDebug, SEEK_SET);
 
    UCHAR loopexit = FALSE;
 
    IMAGE_DEBUG_DIRECTORY_RAW DebugRaw;
    while (cbDebug >= sizeof(IMAGE_DEBUG_DIRECTORY)) {
 
        if (loopexit == FALSE) {
 
            IMAGE_DEBUG_DIRECTORY DebugDirectory;
 
            fread(&DebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY), 1, File);
 
            ULONG seekPosition = ftell(File);
 
            if (DebugDirectory.Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
                fseek(File, DebugDirectory.PointerToRawData, SEEK_SET);
                fread(&DebugRaw, sizeof(IMAGE_DEBUG_DIRECTORY_RAW), 1, File);
                loopexit = TRUE;
 
                // Downloading logic for .NET native images
                if (strstr((char*)DebugRaw.ImageName, ".ni.") != 0) {
                    fseek(File, seekPosition, SEEK_SET);
                    loopexit = FALSE;
                }
            }
 
            if ((DebugDirectory.PointerToRawData != 0) && (DebugDirectory.SizeOfData != 0) &&
                (cbFromHeader < (DebugDirectory.PointerToRawData + DebugDirectory.SizeOfData))) {
                cbFromHeader = DebugDirectory.PointerToRawData + DebugDirectory.SizeOfData;
            }
        }
 
        cbDebug -= sizeof(IMAGE_DEBUG_DIRECTORY);
    }
 
    fclose(File);
 
    if (loopexit) {
 
        //const char MsServer[] = "http://msdl.microsoft.com/download/symbols";
        const char MsServer[] = "http://msdl.blackint3.com:88/download/symbols";
 
        sprintf(
            url, "%s/%s/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%d/%s",
            MsServer,
            DebugRaw.ImageName,
            DebugRaw.PdbSignature[3], DebugRaw.PdbSignature[2], DebugRaw.PdbSignature[1], DebugRaw.PdbSignature[0],
            DebugRaw.PdbSignature[5], DebugRaw.PdbSignature[4],
            DebugRaw.PdbSignature[7], DebugRaw.PdbSignature[6],
            DebugRaw.PdbSignature[8], DebugRaw.PdbSignature[9],
            DebugRaw.PdbSignature[10], DebugRaw.PdbSignature[11], DebugRaw.PdbSignature[12],
            DebugRaw.PdbSignature[13], DebugRaw.PdbSignature[14], DebugRaw.PdbSignature[15],
            DebugRaw.PdbDbiAge,
            DebugRaw.ImageName
        );
    }
    else {
        printf("PEHeaderReader Error: Invalid PE\n");
    }
}
typedef struct _IMAGE_DEBUG_DIRECTORY_RAW {
    UCHAR format[4];
    UCHAR PdbSignature[16];
    ULONG PdbDbiAge;
    UCHAR ImageName[256];
} IMAGE_DEBUG_DIRECTORY_RAW, * PIMAGE_DEBUG_DIRECTORY_RAW;
 
void CMyDownloadPdbDlg::PEHeaderReader(char* PEFileName, char* url)
{
    FILE* File = fopen(PEFileName, "rb");
 
    IMAGE_DOS_HEADER DosHeader;
    fread(&DosHeader, sizeof(IMAGE_DOS_HEADER), 1, File);
    fseek(File, DosHeader.e_lfanew, SEEK_SET);
 
    // Add 4 bytes to the offset
    ULONG NtHeadersSignature;
    fread(&NtHeadersSignature, 4, 1, File);
 
    IMAGE_FILE_HEADER FileHeader;
    fread(&FileHeader, sizeof(IMAGE_FILE_HEADER), 1, File);
 
    ULONG is32BitHeader = FileHeader.Machine == IMAGE_FILE_MACHINE_I386;
 
    IMAGE_OPTIONAL_HEADER32 OptionalHeader32 = { 0 };
    IMAGE_OPTIONAL_HEADER64 OptionalHeader64 = { 0 };
 
    if (is32BitHeader)
        fread(&OptionalHeader32, sizeof(IMAGE_OPTIONAL_HEADER32), 1, File);
    else
        fread(&OptionalHeader64, sizeof(IMAGE_OPTIONAL_HEADER64), 1, File);
 
    ULONG offDebug = 0;
    ULONG cbFromHeader = 0;
 
    ULONG cbDebug = is32BitHeader ?
        OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size : OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
 
    for (int HeaderNo = 0; HeaderNo < FileHeader.NumberOfSections; ++HeaderNo) {
        IMAGE_SECTION_HEADER SectionHeader;
        fread(&SectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, File);
 
        if ((SectionHeader.PointerToRawData != 0) && (SectionHeader.SizeOfRawData != 0) &&
            (cbFromHeader < (SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData))) {
            cbFromHeader = SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData;
        }
 
        if (cbDebug != 0) {
            if (is32BitHeader) {
                if (SectionHeader.VirtualAddress <= OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress &&
                    ((SectionHeader.VirtualAddress + SectionHeader.SizeOfRawData) > OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)) {
                    offDebug = OptionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
                }
            }
 
            else {
                if (SectionHeader.VirtualAddress <= OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress &&
                    ((SectionHeader.VirtualAddress + SectionHeader.SizeOfRawData) > OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)) {
                    offDebug = OptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
                }
            }
        }
    }
 
    fseek(File, offDebug, SEEK_SET);
 
    UCHAR loopexit = FALSE;
 
    IMAGE_DEBUG_DIRECTORY_RAW DebugRaw;
    while (cbDebug >= sizeof(IMAGE_DEBUG_DIRECTORY)) {
 
        if (loopexit == FALSE) {
 
            IMAGE_DEBUG_DIRECTORY DebugDirectory;
 
            fread(&DebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY), 1, File);
 
            ULONG seekPosition = ftell(File);
 
            if (DebugDirectory.Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
                fseek(File, DebugDirectory.PointerToRawData, SEEK_SET);
                fread(&DebugRaw, sizeof(IMAGE_DEBUG_DIRECTORY_RAW), 1, File);
                loopexit = TRUE;
 
                // Downloading logic for .NET native images
                if (strstr((char*)DebugRaw.ImageName, ".ni.") != 0) {
                    fseek(File, seekPosition, SEEK_SET);
                    loopexit = FALSE;
                }
            }
 
            if ((DebugDirectory.PointerToRawData != 0) && (DebugDirectory.SizeOfData != 0) &&
                (cbFromHeader < (DebugDirectory.PointerToRawData + DebugDirectory.SizeOfData))) {
                cbFromHeader = DebugDirectory.PointerToRawData + DebugDirectory.SizeOfData;
            }
        }
 
        cbDebug -= sizeof(IMAGE_DEBUG_DIRECTORY);
    }
 
    fclose(File);
 
    if (loopexit) {
 
        //const char MsServer[] = "http://msdl.microsoft.com/download/symbols";
        const char MsServer[] = "http://msdl.blackint3.com:88/download/symbols";
 
        sprintf(
            url, "%s/%s/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%d/%s",
            MsServer,
            DebugRaw.ImageName,
            DebugRaw.PdbSignature[3], DebugRaw.PdbSignature[2], DebugRaw.PdbSignature[1], DebugRaw.PdbSignature[0],
            DebugRaw.PdbSignature[5], DebugRaw.PdbSignature[4],
            DebugRaw.PdbSignature[7], DebugRaw.PdbSignature[6],
            DebugRaw.PdbSignature[8], DebugRaw.PdbSignature[9],
            DebugRaw.PdbSignature[10], DebugRaw.PdbSignature[11], DebugRaw.PdbSignature[12],
            DebugRaw.PdbSignature[13], DebugRaw.PdbSignature[14], DebugRaw.PdbSignature[15],
            DebugRaw.PdbDbiAge,
            DebugRaw.ImageName
        );
    }
    else {
        printf("PEHeaderReader Error: Invalid PE\n");
    }
}
// =====================CMfcTestPdbDlg.cpp============================
void CMfcTestPdbDlg::InitPdb()
{
    // 检测PDB是否已存在
    CString szNtPath = GetProgramPath();
    szNtPath += _T("ntkrnlmp.pdb");
    // 不存在则下载
     // 查找文件是否存在
    CFileFind tempFind;
    if (!tempFind.FindFile(szNtPath)) {
        // 不存在则先加载pdb
        CMyDownloadPdbDlg dlg;
        dlg.m_szPath = "C:\\Windows\\System32\\ntoskrnl.exe";
        dlg.m_szDstPath = _T("ntkrnlmp.pdb");
        dlg.DoModal();
    }
    tempFind.Close();
}
 
 
// ======================CMyDownloadPdbDlg.cpp==========================
UINT ThreadProc(LPVOID lParam)
{
    CMyDownloadPdbDlg* pDlg = (CMyDownloadPdbDlg*)lParam;
    char url[UCHAR_MAX] = { 0 };
    // 转url
    pDlg->PEHeaderReader(pDlg->m_szPath, url);
 
    //多字节转宽字节
    TCHAR szUrl[UCHAR_MAX] = { 0 };
    MultiByteToWideChar(CP_ACP, 0, url, -1, szUrl, UCHAR_MAX);
 
 
    CString  strProgramPath;
    GetModuleFileName(NULL, strProgramPath.GetBuffer(MAX_PATH), MAX_PATH);
    strProgramPath.ReleaseBuffer(MAX_PATH);
    int nPathPos = strProgramPath.ReverseFind('\\');
    strProgramPath = strProgramPath.Left(nPathPos + 1);
    strProgramPath += pDlg->m_szDstPath;
    INT  nStatus = pDlg->GetFile(szUrl, strProgramPath);
 
    // 下载完文件关闭自己
    pDlg->PostMessage(WM_CLOSE);
 
    return nStatus;
}
 
BOOL CMyDownloadPdbDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
 
    // 下载pdb
    AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL);
 
    return TRUE;  // return TRUE unless you set the focus to a control
                  // 异常: OCX 属性页应返回 FALSE
}
 
INT CMyDownloadPdbDlg::GetFile(const CString strUrl, const CString strSavePath)
{
    //检查传入的两个参数 
    if (strUrl.IsEmpty())
        return -5;
    if (strSavePath.IsEmpty())
        return -6;
 
    unsigned short nPort;       //用于保存目标HTTP服务端口 
    CString strServer, strObject;   //strServer用于保存服务器地址,strObject用于保存文件对象名称 
    DWORD dwServiceType, dwRet;      //dwServiceType用于保存服务类型,dwRet用于保存提交GET请求返回的状态号 
 
    //解析URL,获取信息 
    if (!AfxParseURL(strUrl, dwServiceType, strServer, strObject, nPort))
    {
        //解析失败,该Url不正确 
        return -1;
    }
    //创建网络连接对象,HTTP连接对象指针和用于该连接的HttpFile文件对象指针,注意delete 
    CInternetSession intsess;
    CHttpFile* pHtFile = NULL;
    //建立网络连接 
    CHttpConnection* pHtCon = intsess.GetHttpConnection(strServer, nPort);
    if (pHtCon == NULL)
    {
        //建立网络连接失败 
        intsess.Close();
        return -2;
    }
    //发起GET请求 
    pHtFile = pHtCon->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject);
    if (pHtFile == NULL)
    {
        //发起GET请求失败 
        intsess.Close();
        delete pHtCon; pHtCon = NULL;
        return -3;
    }
    //提交请求 
    pHtFile->SendRequest();
    //获取服务器返回的状态号 
    pHtFile->QueryInfoStatusCode(dwRet);
    if (dwRet != HTTP_STATUS_OK)
    {
        //服务器不接受请求 
        intsess.Close();
        delete pHtCon; pHtCon = NULL;
        delete pHtFile; pHtFile = NULL;
        return -4;
    }
    //获取文件大小 
    UINT nFileLen = (UINT)pHtFile->GetLength();
 
    DWORD dwRead = 1;       //用于标识读了多少,为1是为了进入循环 
    //创建缓冲区 
    CHAR* szBuffer = new CHAR[nFileLen + 1];
 
    TRY
    {
        // 进度条
        CProgressCtrl * m_prg = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS);//进度条ID
        m_prg->SetRange32(0, 100);
        int nPos = 0;
        //创建文件 
        CFile PicFile(strSavePath,CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive);
        while (dwRead > 0)
        {
            //清空缓冲区 
            memset(szBuffer,0,(size_t)(nFileLen + 1));
            //读取到缓冲区 
            dwRead = pHtFile->Read(szBuffer,nFileLen);
            //写入到文件 
            PicFile.Write(szBuffer,dwRead);
            nPos += 5;
            m_prg->SetPos(nPos);
        }
        m_prg->SetPos(100);
        //关闭文件 
        PicFile.Close();
        //释放内存 
        delete[]szBuffer;
        delete pHtFile;
        delete pHtCon;
        //关闭网络连接 
        intsess.Close();
    }
        CATCH(CFileException, e)
    {
        //释放内存 
        delete[]szBuffer;
        delete pHtFile;
        delete pHtCon;
        //关闭网络连接 
        intsess.Close();
        return -7;          //读写文件异常 
    }
    END_CATCH
        return 1;
}
// =====================CMfcTestPdbDlg.cpp============================
void CMfcTestPdbDlg::InitPdb()
{
    // 检测PDB是否已存在
    CString szNtPath = GetProgramPath();
    szNtPath += _T("ntkrnlmp.pdb");
    // 不存在则下载
     // 查找文件是否存在
    CFileFind tempFind;

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-6-8 23:15 被jack.Chen编辑 ,原因: 图片太大
上传的附件:
收藏
免费 12
支持
分享
最新回复 (18)
雪    币: 66
活跃值: (2735)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
以前好像在哪见过这种做法
2022-6-9 09:07
0
雪    币: 306
活跃值: (776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
实都 以前好像在哪见过这种做法
我也是整合了下
2022-6-9 09:34
0
雪    币: 4929
活跃值: (2355)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark
2022-6-10 15:28
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享。
2022-6-12 16:49
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
感谢分享!
2022-6-13 10:12
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
感谢分享。
2022-6-20 00:53
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
我看过agp的的源代码,就是用的pdb解析, 不过楼主的更好,谢谢分享
2022-6-20 09:49
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
@jack.Chen
为什么不本地化,直接把pdb放入当前目录,这样更快就不用下载了
2022-6-20 09:51
0
雪    币: 15
活跃值: (3546)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
改了个C语言版本的
上传的附件:
2022-6-20 10:38
0
雪    币: 306
活跃值: (776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
我skyddr @jack.Chen 为什么不本地化,直接把pdb放入当前目录,这样更快就不用下载了
因为系统会更新啊,我取的是SSDT表,如果本地的内核版本更新了,需要重新下载pdb的,我现在还没有给pdb建立hash文件夹,理论还要识别hash判断是否有更新
2022-6-20 11:38
0
雪    币: 306
活跃值: (776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
麻木的时间 改了个C语言版本的
2022-6-20 11:38
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
@
jack.Chen 
感谢大佬,学到了很多,
2022-6-20 17:14
0
雪    币: 182
活跃值: (2576)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
2022-6-25 20:28
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
为什么我不调用LoadPdb和UnloadPdb,也能将符号获取出来
2022-6-25 22:23
0
雪    币: 306
活跃值: (776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
sanqiu 为什么我不调用LoadPdb和UnloadPdb,也能将符号获取出来
肯定要加载才能解析的
2022-7-13 14:44
0
雪    币: 1475
活跃值: (14652)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
17
diaguids.lib 64位版本的您那有吗,我需要一个64位的lib
2022-8-19 10:14
0
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
感谢分享,mark
2022-8-19 10:38
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
jack.Chen 肯定要加载才能解析的
我最后没加载也解析出来了......
2022-11-5 23:02
0
游客
登录 | 注册 方可回帖
返回
//