Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
fixed CFG function list stride bug
Browse files Browse the repository at this point in the history
  • Loading branch information
zodiacon committed May 28, 2022
1 parent 59310d7 commit ea341eb
Show file tree
Hide file tree
Showing 13 changed files with 419 additions and 50 deletions.
20 changes: 20 additions & 0 deletions TotalPE/DebugView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ CString CDebugView::GetColumnText(HWND, int row, int col) const {
case 3: return std::format(L"0x{:X}", item.get_address_of_raw_data()).c_str();
case 4: return PEStrings::ToMemorySize(item.get_size_of_data()).c_str();
case 5: return std::format(L"0x{:X}", item.get_pointer_to_raw_data()).c_str();
case 6: return GetDetails(row).c_str();
}
return CString();
}
Expand Down Expand Up @@ -49,6 +50,24 @@ void CDebugView::OnStateChanged(HWND h, int from, int to, DWORD oldState, DWORD
}
}

std::wstring CDebugView::GetDetails(int row) const {
struct CodeView {
char format[4];
GUID guid;
ULONG count;
char pdb[64];
};
auto& item = m_Items[row];
switch (item.get_type()) {
case IMAGE_DEBUG_TYPE_CODEVIEW:
auto data = (CodeView*)item.get_item_data().data();
return std::format(L"Format: {}{}{}{} GUID: {} Pdb: {}",
data->format[0], data->format[1], data->format[2], data->format[3],
PEStrings::GuidToString(data->guid), (PCWSTR)CString(data->pdb));
}
return std::wstring();
}

LRESULT CDebugView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
m_hWndClient = m_Splitter.Create(m_hWnd, rcDefault, nullptr, WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
m_List.Create(m_hWndClient, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
Expand All @@ -63,6 +82,7 @@ LRESULT CDebugView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
cm->AddColumn(L"Address", LVCFMT_RIGHT, 110);
cm->AddColumn(L"Size", LVCFMT_RIGHT, 130);
cm->AddColumn(L"Pointer to Raw Data", LVCFMT_RIGHT, 130);
cm->AddColumn(L"Details", LVCFMT_LEFT, 300);
cm->UpdateColumns();

m_List.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
Expand Down
1 change: 1 addition & 0 deletions TotalPE/DebugView.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class CDebugView :
CString GetColumnText(HWND, int row, int col) const;
void DoSort(SortInfo const* si);
void OnStateChanged(HWND h, int from, int to, DWORD oldState, DWORD newState);
std::wstring GetDetails(int row) const;

BEGIN_MSG_MAP(CDebugView)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
Expand Down
50 changes: 40 additions & 10 deletions TotalPE/LoadConfigView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "LoadConfigView.h"
#include "PEStrings.h"
#include "SortHelper.h"
#include "resource.h"

CString CLoadConfigView::GetColumnText(HWND h, int row, int col) const {
if (h == m_List) {
Expand Down Expand Up @@ -45,20 +46,27 @@ void CLoadConfigView::DoSort(SortInfo const* si) {
}

bool CLoadConfigView::IsSortable(HWND h, int col) const {
if(h == m_List)
if (h == m_List)
return col == 0; // sort on Name column only
return true;
}

int CLoadConfigView::GetRowImage(HWND hList, int row, int col) const {
if (hList == m_List)
return -1;

return m_CfgFunctions[row].Export ? 1 : 0;
}

LRESULT CLoadConfigView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
m_hWndClient = m_Splitter.Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS);
m_List.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
LVS_REPORT | LVS_OWNERDATA, WS_EX_CLIENTEDGE);
m_List.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
auto cm = GetColumnManager(m_List);
cm->AddColumn(L"Name", LVCFMT_LEFT, 150);
cm->AddColumn(L"Name", LVCFMT_LEFT, 180);
cm->AddColumn(L"Value", LVCFMT_LEFT, 200);
cm->AddColumn(L"Details", LVCFMT_LEFT, 450);
cm->AddColumn(L"Details", LVCFMT_LEFT, 550);
cm->UpdateColumns();

m_CfgList.Create(m_Splitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
Expand All @@ -68,6 +76,11 @@ LRESULT CLoadConfigView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
cm->AddColumn(L"Function Name", LVCFMT_LEFT, 220);
cm->AddColumn(L"Address", LVCFMT_RIGHT, 100);
cm->UpdateColumns();
CImageList images;
images.Create(16, 16, ILC_COLOR32 | ILC_MASK, 2, 2);
images.AddIcon(AtlLoadIconImage(IDI_FUNCTION));
images.AddIcon(AtlLoadIconImage(IDI_FUNC_IMPORT));
m_CfgList.SetImageList(images, LVSIL_SMALL);

BuildItems();
m_Splitter.SetSplitterPanes(m_List, m_CfgList);
Expand All @@ -80,32 +93,49 @@ LRESULT CLoadConfigView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
}

void CLoadConfigView::BuildItems() {
auto baseAddress = m_symbols.LoadSymbolsForModule(CStringA(Frame()->GetPEPath()));
auto& lc = PE().get_load_config();
auto cfg = lc.get_code_integrity();

m_Items = std::vector<DataItem>{
{ L"Time Stamp", std::format(L"0x{:X}", lc.get_timestamp()) },
{ L"Size", std::format(L"0x{:X}", lc.get_size()) },
{ L"Version", std::format(L"{}.{}", lc.get_major_version(), lc.get_minor_version()) },
{ L"Affinity Mask", std::format(L"0x{:X}", lc.get_process_affinity_mask()) },
{ L"CFG Flags", std::format(L"0x{:X}", lc.get_guard_flags()), PEStrings::CFGFlagsToString(lc.get_guard_flags()) },
{ L"Process Affinity Mask", std::format(L"0x{:X}", lc.get_process_affinity_mask()) },
{ L"Guard Flags", std::format(L"0x{:X}", lc.get_guard_flags()), PEStrings::CFGFlagsToString(lc.get_guard_flags()) },
{ L"Heap Flags", std::format(L"0x{:X}", lc.get_process_heap_flags()) },
{ L"Virtual Memory Threshold", std::format(L"0x{:X}", lc.get_virtual_memory_threshold()) },
{ L"Global Flags Set", std::format(L"0x{:X}", lc.get_global_flagsset()) },
{ L"Global Flags Clear", std::format(L"0x{:X}", lc.get_global_flagsclear()) },
{ L"Lock Prefix Table", std::format(L"0x{:X}", lc.get_lock_prefix_table()) },
{ L"Default CS Timeout", std::format(L"0x{:X}", lc.get_criticalsection_default_timeout()) },
{ L"Dependent Load Flags", std::format(L"0x{:X}", lc.get_dependent_load_flags()) },
{ L"Security Cookie", std::format(L"0x{:X}", lc.get_security_cookie()) },
{ L"CSD Version", std::format(L"0x{:X}", lc.get_csd_version()) },
{ L"CFG Functions", std::format(L"{}", lc.get_guard_cf_function_count()) },
};

m_CfgFunctions.reserve(lc.get_guard_cf_function_count());
auto& exports = PE().get_exports().get_functions();
for (auto& f : lc.get_guard_cf_functions()) {
auto const& exports = PE().get_exports().get_functions();
for (auto const& f : lc.get_guard_cf_functions()) {
CfgFunction func;
func.Rva = f;
if(auto it = std::ranges::find_if(exports, [&](auto& exp) {
return exp.get_rva() == f;
}); it != exports.end())
auto rva = PE().get_image().va_to_rva(f);
if (auto it = std::ranges::find_if(exports, [&](auto& exp) {
return exp.get_rva() == f;
}); it != exports.end()) {
func.Name = it->get_func_name();
func.Export = true;
}
else {
func.Export = false;
if (baseAddress) {
DWORD64 offset = 0;
auto sym = m_symbols.GetSymbolFromAddress(f + baseAddress, &offset);
if (sym && offset == 0)
func.Name = sym->GetSymbolInfo()->Name;
}
}
m_CfgFunctions.emplace_back(std::move(func));
}
m_List.SetItemCount((int)m_Items.size());
Expand Down
4 changes: 4 additions & 0 deletions TotalPE/LoadConfigView.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "View.h"
#include <VirtualListView.h>
#include <SortedFilteredVector.h>
#include "SymbolsHandler.h"

class CLoadConfigView :
public CView<CLoadConfigView>,
Expand All @@ -13,6 +14,7 @@ class CLoadConfigView :
CString GetColumnText(HWND, int row, int col) const;
void DoSort(SortInfo const* si);
bool IsSortable(HWND, int col) const;
int GetRowImage(HWND hList, int row, int col) const;

BEGIN_MSG_MAP(CLoadConfigView)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
Expand All @@ -31,11 +33,13 @@ class CLoadConfigView :
struct CfgFunction {
std::string Name;
uint32_t Rva;
bool Export;
};
CListViewCtrl m_List;
CSplitterWindow m_Splitter;
CListViewCtrl m_CfgList;
std::vector<DataItem> m_Items;
std::vector<CfgFunction> m_CfgFunctions;
SymbolsHandler m_symbols;
};

7 changes: 7 additions & 0 deletions TotalPE/PEStrings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,13 @@ std::wstring PEStrings::CFGFlagsToString(uint32_t flags) {
return result;
}

std::wstring PEStrings::GuidToString(GUID const& guid) {
WCHAR sguid[64];
if(::StringFromGUID2(guid, sguid, _countof(sguid)))
return sguid;
return std::wstring();
}

std::wstring PEStrings::FileFlagsToString(uint32_t flags) {
static const struct {
uint32_t value;
Expand Down
1 change: 1 addition & 0 deletions TotalPE/PEStrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ struct PEStrings abstract final {
static PCWSTR CertificateTypeToString(uint32_t type);
static PCWSTR x64RelocationTypeToString(BYTE type);
static std::wstring CFGFlagsToString(uint32_t flags);
static std::wstring GuidToString(GUID const& guid);
};

58 changes: 58 additions & 0 deletions TotalPE/SymbolManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "pch.h"
#include "SymbolManager.h"

SymbolManager& SymbolManager::Get() {
static SymbolManager mgr;
return mgr;
}

SymbolManager::~SymbolManager() {
Term();
}

void SymbolManager::Term() {
_procSymbols.clear();
}

SymbolsHandler* SymbolManager::GetCommon() {
return &_commonSymbols;
}

SymbolsHandler* SymbolManager::GetForProcess(DWORD pid) {
auto it = _procSymbols.find(pid);
if (it == _procSymbols.end()) {
// attempt to get one

auto symbols = SymbolsHandler::CreateForProcess(pid);
if (symbols == nullptr)
return nullptr;
auto sym = symbols.get();
_procSymbols.insert({ pid, std::move(symbols) });
return sym;
}
if (::WaitForSingleObject(it->second->GetHandle(), 0) == WAIT_OBJECT_0) {
// process dead, remove and try again
_procSymbols.erase(pid);
return GetForProcess(pid);
}
return it->second.get();
}

std::unique_ptr<SymbolInfo> SymbolManager::GetSymbolFromAddress(DWORD pid, DWORD64 address, PDWORD64 offset) {
if ((int64_t)address < 0) {
// kernel address
_commonSymbols.LoadKernelModule(address);
return _commonSymbols.GetSymbolFromAddress(address, offset);
}

auto handler = GetForProcess(pid);
if (handler) {
auto symbol = handler->GetSymbolFromAddress(address, offset);
if (symbol)
return symbol;
}
return nullptr;
}

SymbolManager::SymbolManager() {
}
22 changes: 22 additions & 0 deletions TotalPE/SymbolManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "SymbolsHandler.h"

class SymbolManager {
public:
static SymbolManager& Get();
~SymbolManager();
void Term();

SymbolsHandler* GetCommon();
SymbolsHandler* GetForProcess(DWORD pid);

std::unique_ptr<SymbolInfo> GetSymbolFromAddress(DWORD pid, DWORD64 address, PDWORD64 offset = nullptr);

private:
SymbolManager();

SymbolsHandler _commonSymbols;
std::unordered_map<DWORD, std::unique_ptr<SymbolsHandler>> _procSymbols;
};

Loading

0 comments on commit ea341eb

Please sign in to comment.