从需求出发:
定位一个句柄占用导致的文件无法删除的问题:
#include
#include
#include
#include
std::wstring getlineFromConsole()
{
std::wstring strRet;
std::getline(std::wcin, strRet);
return strRet;
}
void ErrorWork(const std::wstring strPath)
{
auto hFile = CreateFile(strPath.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,// 不共享删除
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
std::wcout << L"open [" << strPath << L"] error with gle[" << GetLastError() << L"]" << std::endl;
}
}
int main()
{
auto filePath = getlineFromConsole();
while(!std::filesystem::exists(filePath)) {
std::wcout << L"[" << filePath << L"] not exis" << std::endl;
filePath = getlineFromConsole();
}
ErrorWork(filePath);
std::error_code ecode;
if (!std::filesystem::remove(filePath, ecode)) {
std::wcout << "del [" << filePath << L"] error with[" << ecode << L"]" << std::endl;
}
else {
std::wcout << "del [" << filePath << L"] success" << std::endl;
}
return 0;
}
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-htrace
0:004> !htrace -diff
Handle tracing information snapshot successfully taken.
0x28 new stack traces since the previous snapshot.
Ignoring handles that were already closed...
Outstanding handles opened since the previous snapshot:
--------------------------------------
Handle = 0x00000130 - OPEN
Thread ID = 0x00005030, Process ID = 0x00001b90
0x7c864f50: +0x7c864f50
0x7c864688: +0x7c864688
0x7c3d3c18: +0x7c3d3c18
0x9911c724: +0x9911c724
0x98d7513a: +0x98d7513a
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e20ac: ntdll!NtOpenFile+0x0000000c
0x776f632d: ntdll!RtlProcessFlsData+0x000000cd
--------------------------------------
Handle = 0x000000e8 - OPEN
Thread ID = 0x00005030, Process ID = 0x00001b90
0x7c8be19c: +0x7c8be19c
0x7c8be01d: +0x7c8be01d
0x7c8c003f: +0x7c8c003f
0x7c3d3c18: +0x7c3d3c18
0x9911e414: +0x9911e414
0x98d76532: +0x98d76532
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1e7c: ntdll!ZwOpenKey+0x0000000c
--------------------------------------
Handle = 0x000000e4 - OPEN
Thread ID = 0x00005030, Process ID = 0x00001b90
0x7c864f50: +0x7c864f50
0x7c864719: +0x7c864719
0x7c3d3c18: +0x7c3d3c18
0x9911cb64: +0x9911cb64
0x98d74dc5: +0x98d74dc5
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e22cc: ntdll!NtCreateFile+0x0000000c
0x770a217d: KERNELBASE!CreateFileW+0x0000034d
--------------------------------------
Handle = 0x000000b4 - OPEN
Thread ID = 0x00005030, Process ID = 0x00001b90
0x7c8be19c: +0x7c8be19c
0x7c8be01d: +0x7c8be01d
0x7c8c003f: +0x7c8c003f
0x7c3d3c18: +0x7c3d3c18
0x9911e414: +0x9911e414
0x98d76532: +0x98d76532
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1e7c: ntdll!ZwOpenKey+0x0000000c
--------------------------------------
大多数时候,当我们发现了问题,已经知道了当前有问题的句柄是什么,就直接只看目标的句柄的堆栈即可:
0:004> !htrace 0xe4
--------------------------------------
Handle = 0x000000e4 - OPEN
Thread ID = 0x00005030, Process ID = 0x00001b90
0x7c864f50: +0x7c864f50
0x7c864719: +0x7c864719
0x7c3d3c18: +0x7c3d3c18
0x9911cb64: +0x9911cb64
0x98d74dc5: +0x98d74dc5
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e22cc: ntdll!NtCreateFile+0x0000000c
0x770a217d: KERNELBASE!CreateFileW+0x0000034d
--------------------------------------
可以看到,这里的堆栈显然是残缺的,导致我们只能看到很少的信息,需要想办法将信息拿更全一些:
想到的办法是:通过python 脚本,抽取出来最底层的调用点,并下断点:
#/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import sys
print(sys.argv)
import time
def get_break_from_line(line):
first_find = line.find(': ')
second_find = line.find('+')
if second_find != -1:
return 'bu ' + line[first_find + 2:second_find] + ' "kp;g;";'
else:
return ''
def get_lines_from_file(file_path):
with open(file_path,'rt',encoding='utf-8') as f:
try:
data = f.readlines()
except Exception as e:
with open(file_path,'rt',encoding='gbk') as f:
data = f.readlines()
return data
def get_map_dat(file_path):
out_put = {}
data = get_lines_from_file(file_path)
if len(data) != 0:
modeopen = 0
modeclose = 1;
currentmode = 3
preline = ''
for line in data:
if line == '\r' or line == '\n' or line == '\r\n':
continue
if line.find('- OPEN') != -1:
#print(line)
currentmode = modeopen;
elif line.find('- CLOSE') != -1:
#print(line)
currentmode = modeclose
elif line.find('Thread ID =') != -1:
#print(line)
if currentmode == modeopen:
if not line in out_put:
out_put[line] = 0
out_put[line] = out_put[line] + 1
elif currentmode == modeclose:
if not line in out_put:
out_put[line] = 0
out_put[line] = out_put[line] - 1
else:
error
elif line.find('--------------------------------------') != -1:
#print('pre line',preline)
if currentmode == modeopen:
if not preline in out_put:
out_put[preline] = 0
out_put[preline] = out_put[preline] + 1
elif currentmode == modeclose:
if not preline in out_put:
out_put[preline] = 0
out_put[preline] = out_put[preline] - 1
preline = line
print('final result')
for item in out_put:
if out_put[item] > 0:
print(item,out_put[item])
for item in out_put:
if out_put[item] < 0:
print(item,out_put[item])
dbg_line = ''
for item in out_put:
if out_put[item] > 0:
dbg_line = dbg_line + get_break_from_line(item)
print('dbg_line')
print(dbg_line)
get_map_dat(sys.argv[1])
输出为:
E:\wds_learn>python windbg_log_an.py runlog.txt
['windbg_log_an.py', 'runlog.txt']
final result
Thread ID = 0x00005030, Process ID = 0x00001b90
1
0x770a217d: KERNELBASE!CreateFileW+0x0000034d
1
dbg_line
bu KERNELBASE!CreateFileW "kp;g;";
上面的做法,就是为了缩小范围,在复杂的多线程执行环境下,常常一堆线程在做open 和 close 操作,我们把那些打开了却不释放的线程列出来,另外,我们这里假定windbg获取的调用栈是比较全的,由此调用栈顶部的未知的open 和 close 也应该配对,否则,我们也统计出来。
为了解决最上面的,!htrace 0xec 获取的堆栈不太全的问题,我们需要获取一个windbg 断点的列表,并在函数执行的时候就输出其调用栈,然后,继续执行,效果如下:
0:000> !htrace -enable
Handle tracing enabled.
Handle tracing information snapshot successfully taken.
0:000> bu KERNELBASE!CreateFileW "kp;g;";
0:000> g
*** WARNING: Unable to verify checksum for cppLeakHandle.exe
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 012ff6c4 0011d6b1 KERNELBASE!CreateFileW
01 012ff7dc 001268a3 cppLeakHandle!ErrorWork(class std::basic_string,std::allocator > strPath = "e:\wds_learn\temp.txt")+0x71 [E:\wds_learn\cppLeakHandle\cppLeakHandle\main.cpp @ 13]
02 012ff9e4 0012a2c3 cppLeakHandle!main(void)+0x163 [E:\wds_learn\cppLeakHandle\cppLeakHandle\main.cpp @ 31]
03 012ffa04 0012a117 cppLeakHandle!invoke_main(void)+0x33 [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78]
04 012ffa60 00129fad cppLeakHandle!__scrt_common_main_seh(void)+0x157 [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
05 012ffa68 0012a348 cppLeakHandle!__scrt_common_main(void)+0xd [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331]
06 012ffa70 771c6359 cppLeakHandle!mainCRTStartup(void)+0x8 [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17]
07 012ffa80 776d7b74 KERNEL32!BaseThreadInitThunk+0x19
08 012ffadc 776d7b44 ntdll!RtlGetAppContainerNamedObjectPath+0xe4
09 012ffaec 00000000 ntdll!RtlGetAppContainerNamedObjectPath+0xb4
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 012ff5c8 0012922d KERNELBASE!CreateFileW
01 012ff600 0012720c cppLeakHandle!__std_fs_open_handle(__std_fs_file_handle * _Handle = 0x012ff6c0, wchar_t * _File_name = 0x014657c8 "e:\wds_learn\temp.txt", __std_access_rights _Desired_access = _Delete (0n65536), __std_fs_file_flags _Flags = 0n35651584 (No matching enumerant))+0x3d [d:\agent\_work\6\s\src\vctools\crt\github\stl\src\filesystem.cpp @ 291]
02 012ff61c 00129466 cppLeakHandle!std::_Fs_file::_Fs_file(wchar_t * _File_name = 0x014657c8 "e:\wds_learn\temp.txt", __std_access_rights _Desired_access = _Delete (0n65536), __std_fs_file_flags _Flags = 0n35651584 (No matching enumerant), __std_win_error * _Err = 0x012ff6c8)+0x1c [d:\agent\_work\6\s\src\vctools\crt\github\stl\inc\xfilesystem_abi.h @ 326]
03 012ff6d8 001237c5 cppLeakHandle!__std_fs_remove(wchar_t * _Target = 0x014657c8 "e:\wds_learn\temp.txt")+0xf6 [d:\agent\_work\6\s\src\vctools\crt\github\stl\src\filesystem.cpp @ 651]
04 012ff7f0 0012691b cppLeakHandle!std::error_code::category()+0x35 [D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\filesystem @ 3572]
05 012ff9e4 0012a2c3 cppLeakHandle!main(void)+0x1db [E:\wds_learn\cppLeakHandle\cppLeakHandle\main.cpp @ 35]
06 012ffa04 0012a117 cppLeakHandle!invoke_main(void)+0x33 [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78]
07 012ffa60 00129fad cppLeakHandle!__scrt_common_main_seh(void)+0x157 [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
08 012ffa68 0012a348 cppLeakHandle!__scrt_common_main(void)+0xd [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331]
09 012ffa70 771c6359 cppLeakHandle!mainCRTStartup(void)+0x8 [d:\agent\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17]
0a 012ffa80 776d7b74 KERNEL32!BaseThreadInitThunk+0x19
0b 012ffadc 776d7b44 ntdll!RtlGetAppContainerNamedObjectPath+0xe4
0c 012ffaec 00000000 ntdll!RtlGetAppContainerNamedObjectPath+0xb4
当然,实际情况,比这个更加复杂,可能从导致问题的点,到该隐藏的问题开始影响程序正常执行,已经过了很久很久。这个时候,文件操作将有特别特别多。我们不能在所有情况下都输出调用栈。
比如,我们通过ui 程序来重写我们的测试程序:
mfc 工程如下:
// MfcHandleLeakDlg.cpp : implementation file
//
#include "pch.h"
#include "framework.h"
#include "MfcHandleLeak.h"
#include "MfcHandleLeakDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CMfcHandleLeakDlg dialog
CMfcHandleLeakDlg::CMfcHandleLeakDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MFCHANDLELEAK_DIALOG, pParent)
, m_targetFilePath(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMfcHandleLeakDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_FILE_PATH, m_targetFilePath);
}
BEGIN_MESSAGE_MAP(CMfcHandleLeakDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON3, &CMfcHandleLeakDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON1, &CMfcHandleLeakDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CMfcHandleLeakDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON_NORMAL_OP, &CMfcHandleLeakDlg::OnBnClickedButtonNormalOp)
END_MESSAGE_MAP()
// CMfcHandleLeakDlg message handlers
BOOL CMfcHandleLeakDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_targetFilePath = LR"(E:\wds_learn\temp.txt)";
return TRUE; // return TRUE unless you set the focus to a control
}
void CMfcHandleLeakDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMfcHandleLeakDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMfcHandleLeakDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CMfcHandleLeakDlg::OnBnClickedButton3()
{
BOOL isOpen = TRUE; //是否打开(否则为保存)
CString defaultDir = LR"(E:\wds_learn)"; //默认打开的文件路径
CString fileName = L""; //默认打开的文件名
CFileDialog openFileDlg(isOpen, defaultDir, fileName, OFN_HIDEREADONLY | OFN_READONLY, nullptr, NULL);
INT_PTR result = openFileDlg.DoModal();
if (result == IDOK) {
m_targetFilePath = openFileDlg.GetPathName();
UpdateData(FALSE);
}
}
#include
#include
void ErrorWork(CString strPath)
{
auto hFile = CreateFile(strPath.GetBuffer(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,// 不共享删除
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
std::wcout << L"open [" << strPath << L"] error with gle[" << GetLastError() << L"]" << std::endl;
}
}
void CMfcHandleLeakDlg::OnBnClickedButton1()
{
UpdateData(TRUE);
std::thread t1(ErrorWork, m_targetFilePath);
t1.join();
}
#include
void delOP(CString strPath)
{
std::error_code ecode;
if (!std::filesystem::remove(strPath.GetString(), ecode)) {
std::wcout << "del [" << strPath.GetString() << L"] error with[";
std::cout << ecode.message();
std::wcout << L"]" << std::endl;
}
}
void CMfcHandleLeakDlg::OnBnClickedButton2()
{
UpdateData(TRUE);
std::thread t1(delOP, m_targetFilePath);
t1.join();
}
#include
void NormalOp(CString strPath)
{
std::wifstream fileObj{ std::wstring(strPath.GetString()) };
if (!fileObj.bad()) {
std::wcout << fileObj.rdbuf();
fileObj.close();
}
}
void CMfcHandleLeakDlg::OnBnClickedButtonNormalOp()
{
UpdateData(TRUE);
std::thread t1(NormalOp, m_targetFilePath);
t1.join();
}
重复上面的操作如下:
0:025> !htrace 0x268
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c8a2c3a: +0x7c8a2c3a
0x7c8a2940: +0x7c8a2940
0x7c3d3c18: +0x7c3d3c18
0x9911ca04: +0x9911ca04
0x98d7555b: +0x98d7555b
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e221c: ntdll!NtCreateSection+0x0000000c
0x770a0779: KERNELBASE!CreateFileMappingNumaW+0x000000b9
--------------------------------------
Handle = 0x00000268 - CLOSE
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c3d3c18: +0x7c3d3c18
0x77661cbc: +0x77661cbc
0x77661c7b: +0x77661c7b
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d8856d: +0x98d8856d
0x97192709: +0x97192709
0x9911fe34: +0x9911fe34
0x7c88eab5: +0x7c88eab5
0x98e1a4f8: +0x98e1a4f8
0x98f25be6: +0x98f25be6
0x98f2566f: +0x98f2566f
0x98f211dc: +0x98f211dc
0x98f0929d: +0x98f0929d
0x98e74880: +0x98e74880
0x7c3d3c18: +0x7c3d3c18
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c864f50: +0x7c864f50
0x7c864719: +0x7c864719
0x7c3d3c18: +0x7c3d3c18
0x9911cb64: +0x9911cb64
0x98d74dc5: +0x98d74dc5
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d8856d: +0x98d8856d
0x97192709: +0x97192709
0x9911fe34: +0x9911fe34
0x7c88eab5: +0x7c88eab5
0x98e1a4f8: +0x98e1a4f8
0x98f25be6: +0x98f25be6
0x98f2566f: +0x98f2566f
--------------------------------------
Handle = 0x00000268 - CLOSE
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c3d3c18: +0x7c3d3c18
0x77661cbc: +0x77661cbc
0x77661c7b: +0x77661c7b
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d8856d: +0x98d8856d
0x97192709: +0x97192709
0x9911fe34: +0x9911fe34
0x7c88eab5: +0x7c88eab5
0x98e1a4f8: +0x98e1a4f8
0x98f25be6: +0x98f25be6
0x98f2566f: +0x98f2566f
0x98f211dc: +0x98f211dc
0x98f0929d: +0x98f0929d
0x98e74880: +0x98e74880
0x7c3d3c18: +0x7c3d3c18
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c8be19c: +0x7c8be19c
0x7c8be01d: +0x7c8be01d
0x7c8c003f: +0x7c8c003f
0x7c3d3c18: +0x7c3d3c18
0x9911e414: +0x9911e414
0x98d77c9c: +0x98d77c9c
0x98d7714f: +0x98d7714f
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d8856d: +0x98d8856d
0x97192709: +0x97192709
0x9911fe34: +0x9911fe34
0x7c88eab5: +0x7c88eab5
0x98e1a4f8: +0x98e1a4f8
0x98f25be6: +0x98f25be6
--------------------------------------
Handle = 0x00000268 - CLOSE
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c3d3c18: +0x7c3d3c18
0x77661cbc: +0x77661cbc
0x77661c7b: +0x77661c7b
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d8856d: +0x98d8856d
0x97192709: +0x97192709
0x9911fe34: +0x9911fe34
0x7c88eab5: +0x7c88eab5
0x98e1a4f8: +0x98e1a4f8
0x98f25be6: +0x98f25be6
0x98f2566f: +0x98f2566f
0x98f211dc: +0x98f211dc
0x98f0929d: +0x98f0929d
0x98e74880: +0x98e74880
0x7c3d3c18: +0x7c3d3c18
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c8be19c: +0x7c8be19c
0x7c8be01d: +0x7c8be01d
0x7c8c003f: +0x7c8c003f
0x7c3d3c18: +0x7c3d3c18
0x9911e414: +0x9911e414
0x98d77c9c: +0x98d77c9c
0x98d7714f: +0x98d7714f
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d8856d: +0x98d8856d
0x97192709: +0x97192709
0x9911fe34: +0x9911fe34
0x7c88eab5: +0x7c88eab5
0x98e1a4f8: +0x98e1a4f8
0x98f25be6: +0x98f25be6
--------------------------------------
Handle = 0x00000268 - CLOSE
Thread ID = 0x00004744, Process ID = 0x00004b08
0x7c3d3c18: +0x7c3d3c18
0x77661cbc: +0x77661cbc
0x77661c7b: +0x77661c7b
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x990f196b: +0x990f196b
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1e4c: ntdll!NtClose+0x0000000c
0x776c97dd: ntdll!RtlSetThreadWorkOnBehalfTicket+0x0000059d
0x776baed4: ntdll!RtlOpenCurrentUser+0x000002b4
0x776a4dc6: ntdll!RtlRbInsertNodeEx+0x00000686
0x776c7f59: ntdll!TpCallbackIndependent+0x000029d9
0x776c6adc: ntdll!TpCallbackIndependent+0x0000155c
0x771c6359: KERNEL32!BaseThreadInitThunk+0x00000019
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00004744, Process ID = 0x00004b08
0x7c8a2c3a: +0x7c8a2c3a
0x7c8a2940: +0x7c8a2940
0x7c3d3c18: +0x7c3d3c18
0x9911ca04: +0x9911ca04
0x98d7555b: +0x98d7555b
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x990f196b: +0x990f196b
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e221c: ntdll!NtCreateSection+0x0000000c
0x776c9789: ntdll!RtlSetThreadWorkOnBehalfTicket+0x00000549
0x776baed4: ntdll!RtlOpenCurrentUser+0x000002b4
--------------------------------------
Handle = 0x00000268 - CLOSE
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c3d3c18: +0x7c3d3c18
0x77661cbc: +0x77661cbc
0x77661c7b: +0x77661c7b
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1e4c: ntdll!NtClose+0x0000000c
0x770a24ba: KERNELBASE!CloseHandle+0x0000004a
0x69db2b31: thumbcache!CreateMutexWithUserSecurity+0x00000151
0x69db2989: thumbcache!CThumbnailCacheIndex::GetDataFileSize+0x000000f9
0x69db2173: thumbcache!CThumbnailCache::_GetCurrentCacheSize+0x00000503
0x69db09a9: thumbcache!CThumbnailCache::_CheckIfResizingOfCacheFilesNeeded+0x0000004c
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c8a9e35: +0x7c8a9e35
0x7c8a9803: +0x7c8a9803
0x7c3d3c18: +0x7c3d3c18
0x9911c584: +0x9911c584
0x98d7ba94: +0x98d7ba94
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1fdc: ntdll!NtOpenProcess+0x0000000c
0x770a0e28: KERNELBASE!OpenProcess+0x00000048
--------------------------------------
Handle = 0x00000268 - CLOSE
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c3d3c18: +0x7c3d3c18
0x77661cbc: +0x77661cbc
0x77661c7b: +0x77661c7b
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1e4c: ntdll!NtClose+0x0000000c
0x771d95ed: KERNEL32!CreateToolhelp32Snapshot+0x00003cdd
0x771c351d: KERNEL32!CreateActCtxWWorker+0x0000166d
0x771c32a6: KERNEL32!CreateActCtxWWorker+0x000013f6
0x771c2263: KERNEL32!CreateActCtxWWorker+0x000003b3
0x6adc70f1: COMCTL32!GetWindowSubclass+0x00000321
--------------------------------------
Handle = 0x00000268 - OPEN
Thread ID = 0x00002fbc, Process ID = 0x00004b08
0x7c8be19c: +0x7c8be19c
0x7c8be01d: +0x7c8be01d
0x7c8c003f: +0x7c8c003f
0x7c3d3c18: +0x7c3d3c18
0x9911e414: +0x9911e414
0x98d76532: +0x98d76532
0x98d77123: +0x98d77123
0x77661783: +0x77661783
0x77661199: +0x77661199
0x98d7c77a: +0x98d7c77a
0x98d7c637: +0x98d7c637
0x99153ff3: +0x99153ff3
0x99141df5: +0x99141df5
0x990f1853: +0x990f1853
0x990f17fe: +0x990f17fe
0x776e1e7c: ntdll!ZwOpenKey+0x0000000c
--------------------------------------
Parsed 0x6111 stack traces.
Dumped 0xD stack traces.
分析日志结果为:
E:\wds_learn>python windbg_log_an.py runlog.txt
['windbg_log_an.py', 'runlog.txt']
final result
Thread ID = 0x00002fbc, Process ID = 0x00004b08
1
0x770a0779: KERNELBASE!CreateFileMappingNumaW+0x000000b9
1
0x98f2566f: +0x98f2566f
1
0x98f25be6: +0x98f25be6
2
0x776baed4: ntdll!RtlOpenCurrentUser+0x000002b4
1
0x770a0e28: KERNELBASE!OpenProcess+0x00000048
1
0x776e1e7c: ntdll!ZwOpenKey+0x0000000c
1
0x7c3d3c18: +0x7c3d3c18
-3
0x771c6359: KERNEL32!BaseThreadInitThunk+0x00000019
-1
0x69db09a9: thumbcache!CThumbnailCache::_CheckIfResizingOfCacheFilesNeeded+0x0000004c
-1
0x6adc70f1: COMCTL32!GetWindowSubclass+0x00000321
-1
dbg_line
bu KERNELBASE!CreateFileMappingNumaW "kp;g;";bu "kp;g;";bu "kp;g;";bu ntdll!RtlOpenCurrentUser "kp;g;";bu KERNELBASE!OpenProcess "kp;g;";bu ntdll!ZwOpenKey "kp;g;";
只有一个线程id 异常,且泄露了一次,基本就比较靠谱了,实际工作中,我们可以结合这个线程的角色,做进一步的分析,另外,我们看到,这里面有很多不是文件相关的,我们可以直接去除就好,另外还有直接是纯地址,一点符号都没有的,这种情况,我估计是符号不全。有符号了,就会好一点。尝试设置符号路径:
-------------未完待续,,,不完整,待补充