作者:@wordmeng

模块功能

添加当前模块大概功能的描述,希望不要把所有接口文档写在一个文件中,至少按模块分类。

  • 列表
  • 点击列表添加颜色
  • 右键某一列内容出现菜单



    代码实现

    ```cpp

    include “dialog_main.h”

    include

    include “dialog_pe.h”

    include “dialog_about.h”

    include “pe_tool.h”

// MAIN Dialog 消息处理函数 BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { BOOL result = TRUE; switch (uMsg) { case WM_INITDIALOG: // 对话框初始化消息 InitListViewProcess(hwndDlg); // 初始化Process ListCtrl InitListViewModules(hwndDlg); // 初始化Modules ListCtrl g_hwndMain = hwndDlg; break;

  1. case WM_CLOSE:
  2. // 处理窗口关闭消息
  3. EndDialog(hwndDlg, 0);
  4. break;
  5. case WM_DESTROY:
  6. PostQuitMessage(0);
  7. break;
  8. case WM_COMMAND:
  9. // 子控件消息处理
  10. switch (LOWORD(wParam))
  11. {
  12. case IDC_BUTTON_EXIT:
  13. EndDialog(hwndDlg, 0);
  14. break;
  15. case IDC_BUTTON_ABOUT:
  16. DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hwndDlg, DialogAboutProc);
  17. break;
  18. case IDC_BUTTON_PE:
  19. ShowPeDialog();
  20. // PE对话框
  21. break;
  22. default:
  23. result = FALSE;
  24. }
  25. case WM_NOTIFY:
  26. {
  27. NMHDR *pNmhdr = (NMHDR*)lParam;
  28. if (wParam == IDC_LIST_PROCESS && pNmhdr->code == NM_CLICK)
  29. {
  30. InitListContentModule();
  31. }
  32. else if (wParam == IDC_LIST_MODULES && pNmhdr->code == NM_DBLCLK)
  33. {
  34. CopyModulePath();
  35. }
  36. }
  37. default:
  38. result = FALSE;
  39. }
  40. return result;

}

void InitListViewProcess(HWND hwndDlg) { LV_COLUMN lv = { 0 }; HWND hwndList;

  1. // 获取句柄
  2. hwndList = GetDlgItem(hwndDlg, IDC_LIST_PROCESS);
  3. // 设置整行选中
  4. SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  5. lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  6. // 第一列
  7. lv.pszText = TEXT("进程名");
  8. lv.cx = 180;
  9. lv.iSubItem = 0;
  10. ListView_InsertColumn(hwndList, 0, &lv);
  11. // 第二列
  12. lv.pszText = TEXT("PID");
  13. lv.cx = 50;
  14. lv.iSubItem = 1;
  15. ListView_InsertColumn(hwndList, 1, &lv);
  16. // 第三列
  17. lv.pszText = TEXT("镜像地址");
  18. lv.cx = 80;
  19. lv.iSubItem = 2;
  20. ListView_InsertColumn(hwndList, 2, &lv);
  21. // 第四列
  22. lv.pszText = TEXT("镜像大小");
  23. lv.cx = 80;
  24. lv.iSubItem = 3;
  25. ListView_InsertColumn(hwndList, 3, &lv);
  26. // 遍历进程列表
  27. InitListContentProcess(hwndList);
  28. g_hwndListProcess = hwndList;

}

void InitListViewModules(HWND hwndDlg) {

  1. LV_COLUMN lv = { 0 };
  2. HWND hwndList;
  3. // 获取句柄
  4. hwndList = GetDlgItem(hwndDlg, IDC_LIST_MODULES);
  5. // 设置整行选中
  6. SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  7. lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  8. // 第一列
  9. lv.pszText = TEXT("模块名称");
  10. lv.cx = 100;
  11. lv.iSubItem = 0;
  12. ListView_InsertColumn(hwndList, 0, &lv);
  13. // 第二列
  14. lv.pszText = TEXT("模块位置");
  15. lv.cx = 300;
  16. lv.iSubItem = 1;
  17. ListView_InsertColumn(hwndList, 1, &lv);
  18. g_hwndListModules = hwndList;

}

void InitListContentProcess(hwndList) { // 1. 取得所有进程 // 2. 获取进程信息(进程名称, 主模块ImageBase, 主模块ImageSize, 主模块EOP) // 3. 填充列表数据

  1. //// 1. 获取所有进程ID
  2. //DWORD processIds[1024] = { 0 };
  3. //DWORD dwNumberOfIds = 0;
  4. //if (GetAllProcessId(processIds, sizeof(processIds), &dwNumberOfIds) == FALSE)
  5. //{
  6. // MessageBox(g_hwndMain, TEXT("获取进程列表!"), TEXT("WARRING"), MB_OK);
  7. // return;
  8. //}
  9. HANDLE lpSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  10. if (lpSnapshot == INVALID_HANDLE_VALUE)
  11. {
  12. MessageBox(g_hwndMain, TEXT("创建快照失败"), TEXT("ERROR"), MB_OK);
  13. return;
  14. }
  15. PROCESSENTRY32 p32;
  16. p32.dwSize = sizeof(p32);
  17. BOOL pr = Process32First(lpSnapshot, &p32);
  18. // 遍历所有进程
  19. for (int row = 0; pr; row++)
  20. {
  21. // 进程ID
  22. DWORD dwPid = p32.th32ProcessID;
  23. // 进程名
  24. LPTSTR name = p32.szExeFile;
  25. // 主模块信息
  26. MODULEINFO mi = { 0 };
  27. BOOL miResult = FALSE;
  28. miResult = GetMainModuleInfo(dwPid, &mi);
  29. LV_ITEM vitem = { 0 };
  30. vitem.mask = LVIF_TEXT;
  31. vitem.iItem = row;
  32. // 第一列(进程名)
  33. vitem.pszText = name;
  34. vitem.iSubItem = 0;
  35. ListView_InsertItem(hwndList, &vitem);
  36. // 第二列(PID)
  37. TCHAR buffer[16];
  38. wsprintf(buffer, TEXT("%d"), dwPid);
  39. vitem.pszText = buffer;
  40. vitem.iSubItem = 1;
  41. ListView_SetItem(hwndList, &vitem);
  42. if (miResult)
  43. {
  44. // 第三列(主模块基地址)
  45. wsprintf(buffer, TEXT("%p"), mi.lpBaseOfDll);
  46. vitem.pszText = buffer;
  47. vitem.iSubItem = 2;
  48. ListView_SetItem(hwndList, &vitem);
  49. // 第四列(镜像大小)
  50. wsprintf(buffer, TEXT("%p"), mi.SizeOfImage);
  51. vitem.pszText = buffer;
  52. vitem.iSubItem = 3;
  53. ListView_SetItem(hwndList, &vitem);
  54. }
  55. pr = Process32Next(lpSnapshot, &p32);
  56. }

}

void InitListContentModule() { // 1. 获取到进程的ID // 2. 遍历模块 // 3. 填充数据. 数据获取失败. 清空列表

  1. DWORD dwRowId;
  2. TCHAR szPid[0x20] = { 0 };
  3. dwRowId = SendMessage(g_hwndListProcess, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
  4. if (dwRowId == -1)
  5. {
  6. return;
  7. }
  8. // 清空所有数据行
  9. ListView_DeleteAllItems(g_hwndListModules);
  10. // 获取PID
  11. LV_ITEM lv = { 0 };
  12. lv.iSubItem = 1;
  13. lv.pszText = szPid;
  14. lv.cchTextMax = 0x20;
  15. SendMessage(g_hwndListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);
  16. DWORD dwPid = StrToInt(szPid);
  17. // 遍历模块
  18. DWORD dwNumOfModules = 0;
  19. BOOL bResult = FALSE;
  20. HMODULE hModules[1024];
  21. HANDLE hProcess;
  22. bResult = GetAllModules(dwPid, hModules, 1024, &dwNumOfModules);
  23. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
  24. if (bResult == FALSE || hProcess == NULL || dwNumOfModules == 0)
  25. {
  26. return;
  27. }
  28. // 填充所有行数据
  29. for (int row = 0; row < dwNumOfModules; row++)
  30. {
  31. // 获取模块数据: 模块名称,模块地址
  32. TCHAR strBaseName[1024] = { 0 };
  33. TCHAR strFileName[1024] = { 0 };
  34. GetModuleBaseName(hProcess, hModules[row], strBaseName, 1024);
  35. GetModuleFileNameEx(hProcess, hModules[row], strFileName, 1024);
  36. LV_ITEM vitem = { 0 };
  37. vitem.mask = LVIF_TEXT;
  38. vitem.iItem = row;
  39. // 第一列(模块名称)
  40. vitem.pszText = strBaseName;
  41. vitem.iSubItem = 0;
  42. ListView_InsertItem(g_hwndListModules, &vitem);
  43. // 第二列(模块位置)
  44. vitem.pszText = strFileName;
  45. vitem.iSubItem = 1;
  46. ListView_SetItem(g_hwndListModules, &vitem);
  47. MODULEINFO mi;
  48. if (GetModuleInformation(hProcess, hModules[row], &mi, sizeof(MODULEINFO)))
  49. {
  50. mi.lpBaseOfDll;
  51. vitem.pszText = strFileName;
  52. vitem.iSubItem = 1;
  53. ListView_SetItem(g_hwndListModules, &vitem);
  54. }
  55. }
  56. CloseHandle(hProcess);

}

void ShowPeDialog() { // 选择文件 // 加载PE

  1. // 弹出文件选择器
  2. TCHAR strFeFileExt[128] = TEXT("PE File(*.exe,*.dll,*.sys)\0*.exe;*.dll*;.sys\0") \
  3. TEXT("All File(*.*)\0*.*\0\0");
  4. TCHAR strFileName[256] = { 0 };
  5. OPENFILENAMEW st = { 0 };
  6. ZeroMemory(&st, sizeof(OPENFILENAME));
  7. st.lStructSize = sizeof(OPENFILENAME);
  8. st.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
  9. st.hwndOwner = g_hwndMain;
  10. st.lpstrFilter = strFeFileExt;
  11. st.lpstrFile = strFileName;
  12. st.nMaxFile = MAX_PATH;
  13. if (GetOpenFileName(&st) == FALSE)
  14. {
  15. SetStaticMessage(TEXT("未选择文件!"));
  16. return;
  17. }
  18. //PVOID g_pFileBuffer = NULL;
  19. //DWORD g_dwFileSize = 0;
  20. if (ReadPeFile(strFileName, &g_pFileBuffer, &g_dwFileSize) == FALSE)
  21. {
  22. SetStaticMessage(TEXT("加载PE文件失败!"));
  23. return;
  24. }
  25. TCHAR buf[1024];
  26. wsprintf(buf, TEXT("已打开文件 %s"), strFileName);
  27. SetStaticMessage(buf);
  28. DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_PE), g_hwndMain, DialogPeProc);

}

BOOL GetAllModules(DWORD dwPid, HMODULE pModuel, int nSize, DWORD dwNumOfModules) {

  1. HANDLE hProcess;
  2. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
  3. if (hProcess == NULL)
  4. {
  5. return FALSE;
  6. }
  7. DWORD cbNeeded;
  8. if (EnumProcessModules(hProcess, pModuel, nSize, &cbNeeded) == FALSE)
  9. {
  10. CloseHandle(hProcess);
  11. return FALSE;
  12. }
  13. *dwNumOfModules = cbNeeded / sizeof(DWORD);
  14. return TRUE;

}

BOOL GetAllProcessId(DWORD *pPids, DWORD cb, PDWORD lpNumberOfPids) { DWORD cbNeeded; if (!EnumProcesses(pPids, cb, &cbNeeded)) { return FALSE; }

  1. *lpNumberOfPids = cbNeeded / sizeof(DWORD);
  2. return TRUE;

}

BOOL GetMainModuleInfo(DWORD dwPid, MODULEINFO* mi) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (hProcess == NULL) { return FALSE; }

  1. HMODULE hModules[1];
  2. DWORD cbNeeded;
  3. if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded) == FALSE)
  4. {
  5. CloseHandle(hProcess);
  6. return FALSE;
  7. }
  8. MODULEINFO info;
  9. DWORD cb;
  10. if (GetModuleInformation(hProcess, hModules[0], &info, &cb) == FALSE)
  11. {
  12. CloseHandle(hProcess);
  13. return FALSE;
  14. }
  15. *mi = info;
  16. CloseHandle(hProcess);
  17. return TRUE;

}

void SetStaticMessage(LPCTSTR str) { HWND hwndStatic = GetDlgItem(g_hwndMain, IDC_STATIC1); SetWindowText(hwndStatic, str); }

void CopyModulePath() {

  1. DWORD dwRowId;
  2. TCHAR strPath[4096] = { 0 };
  3. dwRowId = SendMessage(g_hwndListModules, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
  4. if (dwRowId == -1)
  5. {
  6. return;
  7. }
  8. // 获取路径
  9. LV_ITEM lv = { 0 };
  10. lv.iSubItem = 1;
  11. lv.pszText = strPath;
  12. lv.cchTextMax = 4096;
  13. SendMessage(g_hwndListModules, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);
  14. TCHAR buf[1024];
  15. wsprintf(buf, TEXT("已复制 %s"), strPath);
  16. SetStaticMessage(buf);
  17. CopyTextToClipboard(strPath, sizeof(TCHAR));

}

BOOL CopyTextToClipboard(LPCTSTR strText) { // 打开剪贴板
if (!OpenClipboard(NULL) || !EmptyClipboard()) { SetStaticMessage(TEXT(“打开或清空剪切板出错”)); return; }

  1. HGLOBAL hMen;
  2. // 分配全局内存
  3. hMen = GlobalAlloc(GMEM_MOVEABLE, ((_tcslen(strText) + 1)*sizeof(TCHAR)));
  4. if (!hMen)
  5. {
  6. SetStaticMessage(TEXT("分配全局内存出错!"));
  7. // 关闭剪切板
  8. CloseClipboard();
  9. return;
  10. }
  11. // 把数据拷贝考全局内存中
  12. // 锁住内存区
  13. LPTSTR lpStr = (LPTSTR)GlobalLock(hMen);
  14. // 内存复制
  15. memcpy(lpStr, strText, ((_tcslen(strText))*sizeof(TCHAR)));
  16. // 字符结束符
  17. lpStr[_tcslen(strText)] = (TCHAR)0;
  18. // 释放锁
  19. GlobalUnlock(hMen);
  20. // 把内存中的数据放到剪切板上
  21. DWORD flag = sizeof(TCHAR) == 2 ? CF_UNICODETEXT : CF_TEXT;
  22. SetClipboardData(CF_UNICODETEXT, hMen);
  23. CloseClipboard();
  24. return;

}

```

结果展示