因为最近的项目有在内核中查找全局变量的需求,有2种方法可以实现此功能。
本项目涉及2个主要程序,因为需要展示SSDT表,所以就使用MFC应用
来做展示。然后DIA2DUMP
和dbghelp.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);
/
/
不用提前注册,需要加上
hr
=
NoRegCoCreate(L
"msdia140.dll"
,
/
/
直接使用dll名
__uuidof(DiaSource),
__uuidof(IDiaDataSource),
(void
*
*
)ppSource);
/
/
hr
=
CoCreateInstance(__uuidof(DiaSource),
/
/
NULL,
/
/
CLSCTX_INPROC_SERVER,
/
/
__uuidof(IDiaDataSource),
/
/
(void
*
*
)ppSource);
/
/
不用提前注册,需要加上
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;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2022-6-8 23:15
被jack.Chen编辑
,原因: 图片太大