// tools-MFCDlg.cpp: 实现文件 // #include "stdafx.h" #include "tools-MFC.h" #include "tools-MFCDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include // /I"../../../../third/Blackbone/src" #ifdef _DEBUG #pragma comment(lib, "../../../../third/Blackbone/build/Win32/Debug(XP)/BlackBone.lib") #else #pragma comment(lib, "../../../../third/Blackbone/build/Win32/Release(XP)/BlackBone.lib") #endif ////////////////////////////////////////////////////////////////////////// // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_ABOUTBOX }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 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() // CtoolsMFCDlg 对话框 CtoolsMFCDlg::CtoolsMFCDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_TOOLSMFC_DIALOG, pParent) , m_mem_data(_T("")) , m_mem_length(0) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CtoolsMFCDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_MEM_DATA, m_mem_data); DDX_Text(pDX, IDC_EDIT_LENGTH, m_mem_length); DDX_Control(pDX, IDC_EDIT_ADDRESS, m_mem_address); DDX_Control(pDX, IDC_COMBO_PROCESS, m_combo_process); DDX_Control(pDX, IDC_COMBO_READ_TYPE, m_combo_read_type); } BEGIN_MESSAGE_MAP(CtoolsMFCDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_READ, &CtoolsMFCDlg::OnBnClickedButtonRead) ON_CBN_DROPDOWN(IDC_COMBO_PROCESS, &CtoolsMFCDlg::OnCbnDropdownComboProcess) ON_CBN_SELCHANGE(IDC_COMBO_PROCESS, &CtoolsMFCDlg::OnCbnSelchangeComboProcess) END_MESSAGE_MAP() // CtoolsMFCDlg 消息处理程序 BOOL CtoolsMFCDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 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); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 OnCbnDropdownComboProcess(); m_combo_process.SetCurSel(0); m_mem_address.SetWindowText(_T("400000")); m_mem_length = 0x20; UpdateData(FALSE); m_combo_read_type.AddString(_T("ReadProcessMemory")); m_combo_read_type.AddString(_T("BlackBone_R3")); m_combo_read_type.AddString(_T("BlackBone_R0")); m_combo_read_type.SetCurSel(0); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CtoolsMFCDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CtoolsMFCDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 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; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CtoolsMFCDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } std::string ToHex(PBYTE bytes, DWORD length) { if (bytes == NULL || length <= 0) { return ""; } std::string result; for (DWORD i = 0; i < length; ++i) { char hex_byte[4] = { 0 }; sprintf_s(hex_byte, 4, "%02X ", bytes[i]); result += hex_byte; } return result; } std::string ToHexLines(PBYTE bytes, DWORD length) { if (bytes == NULL || length <= 0) { return ""; } DWORD line = length / 0x10; DWORD left = length % 0x10; std::string result; for (DWORD i = 0; i < line; ++i) { result += ToHex(bytes + 0x10 * i, 0x10); result += "\r\n"; } result += ToHex(bytes + 0x10 * line, left); return result; } void CtoolsMFCDlg::OnBnClickedButtonRead() { // 更新控件数据,清空16进制显示控件内容 UpdateData(); m_mem_data.SetString(_T("")); // 获取目标进程内存地址:ll_address CString str_address; m_mem_address.GetWindowText(str_address); str_address = _T("0x") + str_address; LONGLONG ll_address = _tcstoull_l(str_address.GetBuffer(), NULL, 16, 0); // 获取目标进程ID:pid int nIndex = m_combo_process.GetCurSel(); DWORD pid = m_combo_process.GetItemData(nIndex); // 获取读取方式:str_read_type CString str_read_type; m_combo_read_type.GetWindowText(str_read_type); // 打开目标进程 blackbone::Process process; process.Attach(pid); if (!process.valid()) { AfxMessageBox(_T("打开进程失败。")); return; } PBYTE bytes = new BYTE[m_mem_length]; if (NULL == bytes) { return; } // ReadProcessMemory方式 if (str_read_type == _T("ReadProcessMemory")) { SIZE_T byte_read; BOOL result = ReadProcessMemory(process.core().handle(), (LPCVOID)ll_address, (LPVOID)bytes, (SIZE_T)m_mem_length, &byte_read); if (result == FALSE) { AfxMessageBox(_T("读取进程内存失败,请检查内存地址和大小。")); return; } } // blackbone方式: NtWow64ReadVirtualMemory64 else if (str_read_type == _T("BlackBone_R3")) { NTSTATUS status = process.memory().Read(ll_address, m_mem_length, (PVOID)bytes); if (!NT_SUCCESS(status)) { AfxMessageBox(_T("读取进程内存失败,请检查内存地址和大小。")); return; } } // 驱动方式 else if (str_read_type == _T("BlackBone_R0")) { // 加载驱动 NTSTATUS status = blackbone::Driver().EnsureLoaded(); if (!NT_SUCCESS(status)) { AfxMessageBox(_T("加载驱动失败。")); return; } // 驱动内存读取 status = blackbone::Driver().ReadMem(pid, ll_address, m_mem_length, (PVOID)bytes); if (!NT_SUCCESS(status)) { AfxMessageBox(_T("读取进程内存失败,请检查内存地址和大小。")); return; } } // m_mem_data.Format(_T("%02X %02X %02X %02X %02X %02X %02X %02X "), bytes[0], bytes[1], bytes[2], bytes[3] // , bytes[4], bytes[5], bytes[6], bytes[7]); std::string str_mem_data = ToHexLines(bytes, m_mem_length); m_mem_data = CStringA(str_mem_data.data()); if (bytes) { delete(bytes); bytes = NULL; } UpdateData(FALSE); } void CtoolsMFCDlg::OnCbnDropdownComboProcess() { // TODO: 在此添加控件通知处理程序代码 m_combo_process.ResetContent(); blackbone::Process process; std::vector vct_pids = blackbone::Process::EnumByName(L""); for (auto pid : vct_pids) { NTSTATUS status = process.Attach(pid); CString msg; if (NT_SUCCESS(status)) { if (process.modules().GetMainModule()) { CString str_64 = process.core().isWow64() ? _T("x86") : _T("x64"); msg.Format(_T("[%05d][%s] %s"), process.pid(), str_64.GetBuffer(), process.modules().GetMainModule()->fullPath.data()); } else { msg.Format(_T("[%d] %s"), process.pid(), _T("failed_get_path")); } } else { msg.Format(_T("[%d] %s"), pid, _T("failed_Attach")); } m_combo_process.AddString(msg); int nIndex = m_combo_process.GetCount() - 1; m_combo_process.SetItemData(nIndex, pid); } } void CtoolsMFCDlg::OnCbnSelchangeComboProcess() { // TODO: 在此添加控件通知处理程序代码 int nIndex = m_combo_process.GetCurSel(); DWORD pid = m_combo_process.GetItemData(nIndex); blackbone::Process process; process.Attach(pid); if (!process.valid()) { return; } if (process.modules().GetMainModule() == nullptr) { return; } CString str_address; str_address.Format(_T("%llX"), process.modules().GetMainModule()->baseAddress); m_mem_address.SetWindowText(str_address); }