[C++] 纯文本查看 复制代码
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <mutex>
#include "binaryninjacore.h"
#include "binaryninjaapi.h"
using namespace BinaryNinja;
using namespace std;
struct ColorInfo
{
const char* name;
uint8_t r, g, b;
};
static const ColorInfo g_colors[] = {
{"标记为绿松石色", 64, 224, 208},
{"标记为橙色", 255, 165, 0},
{"标记为黄色", 255, 255, 0},
{"标记为紫色", 128, 0, 128},
{"标记为绿色", 0, 255, 0},
{"标记为灰色", 128, 128, 128},
{"标记为白色", 255, 255, 255},
{"标记为珊瑚色", 255, 127, 80},
{"标记为深绿色", 0, 100, 0},
{"标记为深橙色", 255, 140, 0},
{"标记为靛青色", 75, 0, 130},
{"标记为柠檬黄色", 255, 247, 0},
{"标记为黑色", 0, 0, 0},
{"标记为黄褐色", 210, 180, 140},
};
static const size_t g_colorCount = sizeof(g_colors) / sizeof(g_colors[0]);
struct HighlightEntry
{
string text;
uint64_t colorRgb;
uint8_t r, g, b;
};
static map<uint64_t, vector<HighlightEntry>> g_highlightMap;
static mutex g_hlMutex;
static uint64_t packRGB(uint8_t r, uint8_t g, uint8_t b)
{
return (static_cast<uint64_t>(r) << 16) | (static_cast<uint64_t>(g) << 8) | b;
}
static string getClipboardText()
{
if (!OpenClipboard(nullptr))
return {};
HANDLE hData = GetClipboardData(CF_TEXT);
if (!hData)
{
CloseClipboard();
return {};
}
char* pszText = static_cast<char*>(GlobalLock(hData));
if (!pszText)
{
CloseClipboard();
return {};
}
string result(pszText);
GlobalUnlock(hData);
CloseClipboard();
return result;
}
class HightLightRenderLayer : public RenderLayer
{
public:
HightLightRenderLayer() : RenderLayer("高亮标记") {}
virtual void ApplyToHighLevelILBody(
Ref<Function> function,
vector<LinearDisassemblyLine>& lines
) override
{
uint64_t funcStart = function->GetStart();
lock_guard<mutex> lock(g_hlMutex);
auto it = g_highlightMap.find(funcStart);
if (it == g_highlightMap.end() || it->second.empty())
return;
for (auto& line : lines)
{
for (auto& token : line.contents.tokens)
{
for (auto& hl : it->second)
{
size_t pos = token.text.find(hl.text);
if (pos != string::npos)
{
string before = token.text.substr(0, pos);
string match = token.text.substr(pos, hl.text.size());
string after = token.text.substr(pos + hl.text.size());
token.text = before + "\u300C" + match + "\u300D" + after;
break;
}
}
}
}
}
};
static void doHighlight(BinaryView* view, Function* func, const ColorInfo& color, size_t colorIdx)
{
string searchText = getClipboardText();
if (searchText.empty())
{
LogError("[高亮标记] 剪贴板为空!请先在伪代码中选中文本并按 Ctrl+C 复制");
return;
}
uint64_t funcStart = func->GetStart();
uint64_t rgb = packRGB(color.r, color.g, color.b);
// toggle check
{
lock_guard<mutex> lock(g_hlMutex);
auto& entries = g_highlightMap[funcStart];
auto it = find_if(entries.begin(), entries.end(), [&](const HighlightEntry& e) {
return e.text == searchText && e.colorRgb == rgb;
});
if (it != entries.end())
{
entries.erase(it);
if (entries.empty())
g_highlightMap.erase(funcStart);
func->MarkUpdatesRequired(UserFunctionUpdate);
LogInfo("[高亮标记] 已取消高亮: '%s' (%s)", searchText.c_str(), color.name);
return;
}
}
// search HLIL for matching addresses (for report)
Ref<HighLevelILFunction> hlil = func->GetHighLevelIL();
if (!hlil)
{
LogError("[高亮标记] 无法获取 HLIL (伪代码),请先分析该函数");
return;
}
size_t instrCount = hlil->GetInstructionCount();
if (instrCount == 0)
{
LogInfo("[高亮标记] 该函数没有 HLIL 指令");
return;
}
set<uint64_t> matchedAddrs;
for (size_t i = 0; i < instrCount; i++)
{
vector<DisassemblyTextLine> lines = hlil->GetInstructionText(i, nullptr);
for (const auto& line : lines)
{
if (!line.addr)
continue;
for (const auto& token : line.tokens)
{
if (token.text.find(searchText) != string::npos)
{
matchedAddrs.insert(line.addr);
break;
}
}
}
}
if (matchedAddrs.empty())
{
LogInfo("[高亮标记] 未找到匹配: '%s'", searchText.c_str());
ShowPlainTextReport("高亮标记结果",
"未找到匹配: '" + searchText + "'\n");
return;
}
// store highlight entry
{
lock_guard<mutex> lock(g_hlMutex);
g_highlightMap[funcStart].push_back({searchText, rgb, color.r, color.g, color.b});
}
// trigger re-render
func->MarkUpdatesRequired(UserFunctionUpdate);
// report
string report = "高亮标记结果\n\n";
report += " 文本: '" + searchText + "'\n";
report += " 颜色: " + string(color.name) + "\n";
report += " 数量: " + to_string(matchedAddrs.size()) + "\n\n";
for (uint64_t addr : matchedAddrs)
{
char buf[64];
snprintf(buf, sizeof(buf), "0x%llx\n", (unsigned long long)addr);
report += buf;
}
ShowPlainTextReport("高亮标记结果", report);
LogInfo("[高亮标记] 已高亮 %zu 处 '%s' (%s)", matchedAddrs.size(), searchText.c_str(), color.name);
}
extern "C"
{
BN_DECLARE_CORE_ABI_VERSION
BINARYNINJAPLUGIN bool CorePluginInit()
{
static HightLightRenderLayer* g_renderLayer = new HightLightRenderLayer();
RenderLayer::Register(g_renderLayer, AlwaysEnabledRenderLayerDefaultEnableState);
for (size_t i = 0; i < g_colorCount; i++)
{
PluginCommand::RegisterForFunction(
"高亮标记\\" + string(g_colors[i].name),
g_colors[i].name,
[i](BinaryView* view, Function* func) {
doHighlight(view, func, g_colors[i], i);
});
}
LogInfo("[高亮标记] 插件已加载 (%zu种颜色可用) — 用法: 复制文本后点菜单", g_colorCount);
return true;
}
}