1.5 为x64dbg编写插件

news2024/11/25 9:34:59

任何一个成熟的软件都会具有可扩展性,可扩展性是现代软件的一个重要特征,因为它使软件更易于维护和适应变化的需求,x64dbg也不例外其可通过开发插件的方式扩展其自身功能,x64dbg提供了多种插件接口,包括脚本插件、DLL插件、Python插件和.NET插件等。此外,x64dbg还支持用户自定义命令和快捷键。这使得用户可以自由地扩展和自定义软件的功能,从而更好地适应开发需求。

我们以C/C++语言为开发模板,x64dbg插件表现出来的其实也是一个DLL文件,他里面导出了x64dbg所需要的几个函数,从而可以在x64dbg启动时被加载,除去所必须的导出函数外,其他功能的实现与DLL基本一致。

(1)开发前的准备工作

在开发x64dbg插件时,首先需要配置插件的开发工具包,请读者将x64dbg插件包中的pluginsdk解压到任意路径下,该包内就是开发所必须要用到的SDK库。

并打开Visual Studio 2013并新建一个DLL空项目,此时请读者打开"调试"->"属性页"并在配置属性页,VC++目录中引入pluginsdk库,读者只需要配置包含目录库目录即可,具体配置参数如下图所示;

当读者正确引入后,那么下一步则是新建配置文件,x64dbg官方针对配置方法给予了一个模板文件,读者可以自行去下载该模板使用。

  • 项目地址:https://github.com/x64dbg/PluginTemplate

在开发插件时,至少需要导出两个函数,函数plugsetup以及pluginit这两个函数是插件的标识,x64dbg将会通过这两个函数来判断是否可被加载,所以在开发时这两个插件是必须要存在的。

以下是 void plugsetup(PLUG_SETUPSTRUCT* setupStruct) 函数的原型和解释:

void plugsetup(PLUG_SETUPSTRUCT* setupStruct);

plugsetup 函数是一个可选的插件函数,用于初始化插件和设置其参数。该函数在插件加载时由主程序调用。

该函数的参数是一个指向 PLUG_SETUPSTRUCT 结构的指针,该结构包含了一些与插件有关的信息和设置。通过读取和设置 PLUG_SETUPSTRUCT 结构中的字段,插件可以初始化其自身并与主程序进行通信。具体来说,PLUG_SETUPSTRUCT 结构包含以下字段:

  • StructSize: 结构体大小,用于指示传递给插件的结构的大小。插件应该使用 sizeof 运算符来设置此字段的值。
  • PluginHandle: 插件的句柄,由主程序分配并传递给插件,用于标识该插件。
  • hwndDlg: 插件界面的句柄,如果插件具有界面,则应该将该字段设置为其窗口句柄。
  • hMenu: 插件的菜单句柄,如果插件具有菜单,则应该将该字段设置为其菜单句柄。
  • hMenuDisasm: 反汇编窗口的菜单句柄,如果插件需要访问反汇编窗口的菜单,则应该将该字段设置为反汇编窗口的菜单句柄。
  • hMenuDump: 转储窗口的菜单句柄,如果插件需要访问转储窗口的菜单,则应该将该字段设置为转储窗口的菜单句柄。

插件应该使用 plugsetup 函数来完成其自身的初始化和参数设置,以便在主程序中正确地运行。

以下是 bool pluginit(PLUG_INITSTRUCT* initStruct) 函数的原型和解释:

bool pluginit(PLUG_INITSTRUCT* initStruct);

pluginit 函数是一个必需的插件函数,用于初始化插件和注册插件的命令。该函数在插件加载时由主程序调用。

该函数的参数是一个指向 PLUG_INITSTRUCT 结构的指针,该结构包含了一些与插件有关的信息和设置。通过读取和设置 PLUG_INITSTRUCT 结构中的字段,插件可以初始化其自身并注册其命令。具体来说,PLUG_INITSTRUCT 结构包含以下字段:

  • StructSize: 结构体大小,用于指示传递给插件的结构的大小。插件应该使用 sizeof 运算符来设置此字段的值。
  • PluginHandle: 插件的句柄,由主程序分配并传递给插件,用于标识该插件。
  • sdkVersion: 主程序的 SDK 版本号,由主程序传递给插件。
  • pluginVersion: 插件的版本号,由插件设置并传递给主程序。
  • PluginName: 插件的名称,由插件设置并传递给主程序。
  • PluginAuthor: 插件的作者,由插件设置并传递给主程序。
  • PluginDescription: 插件的描述,由插件设置并传递给主程序。

插件应该使用 pluginit 函数来完成其自身的初始化和命令注册。该函数应该返回 true 表示初始化成功,或 false 表示初始化失败。如果返回 false,主程序将卸载该插件并显示错误信息。

如上函数解释,我们可知pluginit适用于初始化插件的,例如增加插件菜单栏,设置插件功能等,我们以如下代码为例做一个简单的解释;

PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
{
    initStruct->pluginVersion = PLUGIN_VERSION;
    initStruct->sdkVersion = PLUG_SDKVERSION;
    strncpy_s(initStruct->pluginName, PLUGIN_NAME, _TRUNCATE);
    pluginHandle = initStruct->pluginHandle;

    // 插件初始化
    initStruct->sdkVersion = PLUG_SDKVERSION;
    initStruct->pluginVersion = 1;
    const char *name = "CheckME -->";
    memset(initStruct->pluginName, 0, 128);
    memcpy(initStruct->pluginName, name, strlen(name));

    return pluginInit(initStruct);
}

代码中通过initStruct->pluginVersion设置了插件版本,通过initStruct->sdkVersion设置了SDK版本,并在initStruct->pluginName中设置了插件名称,最后调用了pluginInit(initStruct)初始化了插件,至此该插件即创建完毕了;

plugsetup函数则是用于在初始化时在setupStruct->hMenu也就是菜单顶部增加一个菜单栏,标题为PowerBy LyShark的列表。

PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
{
    hwndDlg = setupStruct->hwndDlg;
    hMenu = setupStruct->hMenu;
    hMenuDisasm = setupStruct->hMenuDisasm;
    hMenuDump = setupStruct->hMenuDump;
    hMenuStack = setupStruct->hMenuStack;

    // 增加二级菜单
    char sub_menu[] = { "PowerBy LyShark" };
    _plugin_menuaddentry(setupStruct->hMenu, 2, sub_menu);

    pluginSetup();
}

当菜单被点击是则会触发CBMENUENTRY函数,执行该函数内的流程,如上就是插件的加载流程。

(2)开发插件实战

在本节,笔者将带领大家实现一个简单的x64dbg插件,该插件的功能很简单,当用户点击菜单栏中的选项是,我们让其弹出一个消息框,此处为了开发方便,我做了精简化,你可以直接使用我的方法来新建文件,建出来的文件只有两个非常简洁。

首先在头文件部分新建一个pluginmain.h并增加PLUGIN_NAME替换成自己项目的名字。

#pragma once

// Plugin information
#define PLUGIN_NAME "LySharkBlog"
#define PLUGIN_VERSION 1

#include "./bridgemain.h"
#include "./_plugins.h"

#include "./_scriptapi_argument.h"
#include "./_scriptapi_assembler.h"
#include "./_scriptapi_bookmark.h"
#include "./_scriptapi_comment.h"
#include "./_scriptapi_debug.h"
#include "./_scriptapi_flag.h"
#include "./_scriptapi_function.h"
#include "./_scriptapi_gui.h"
#include "./_scriptapi_label.h"
#include "./_scriptapi_memory.h"
#include "./_scriptapi_misc.h"
#include "./_scriptapi_module.h"
#include "./_scriptapi_pattern.h"
#include "./_scriptapi_register.h"
#include "./_scriptapi_stack.h"
#include "./_scriptapi_symbol.h"

#include "./DeviceNameResolver/DeviceNameResolver.h"
#include "./jansson/jansson.h"
#include "./lz4/lz4file.h"
#include "./TitanEngine/TitanEngine.h"
#include "./XEDParse/XEDParse.h"

#ifdef _WIN64
#pragma comment(lib, "./x64dbg.lib")
#pragma comment(lib, "./x64bridge.lib")
#pragma comment(lib, "./DeviceNameResolver/DeviceNameResolver_x64.lib")
#pragma comment(lib, "./jansson/jansson_x64.lib")
#pragma comment(lib, "./lz4/lz4_x64.lib")
#pragma comment(lib, "./TitanEngine/TitanEngine_x64.lib")
#pragma comment(lib, "./XEDParse/XEDParse_x64.lib")
#else
#pragma comment(lib, "./x32dbg.lib")
#pragma comment(lib, "./x32bridge.lib")
#pragma comment(lib, "./DeviceNameResolver/DeviceNameResolver_x86.lib")
#pragma comment(lib, "./jansson/jansson_x86.lib")
#pragma comment(lib, "./lz4/lz4_x86.lib")
#pragma comment(lib, "./TitanEngine/TitanEngine_x86.lib")
#pragma comment(lib, "./XEDParse/XEDParse_x86.lib")
#endif //_WIN64

#define Cmd(x) DbgCmdExecDirect(x)
#define Eval(x) DbgValFromString(x)
#define dprintf(x, ...) _plugin_logprintf("[" PLUGIN_NAME "] " x, __VA_ARGS__)
#define dputs(x) _plugin_logprintf("[" PLUGIN_NAME "] %s\n", x)
#define PLUG_EXPORT extern "C" __declspec(dllexport)

//superglobal variables
extern int pluginHandle;
extern HWND hwndDlg;
extern int hMenu;
extern int hMenuDisasm;
extern int hMenuDump;
extern int hMenuStack;

//functions
bool pluginInit(PLUG_INITSTRUCT* initStruct);
void pluginStop();
void pluginSetup();

其次新建一个实现文件pluginmain.cpp并写入以下代码,多数情况下我为了方便调试会使用这段代码,当我们点击菜单时会触发菜单功能,以此可以快速测试特定函数是否正常。

#include "pluginmain.h"
#include <Windows.h>
#include <process.h>

int pluginHandle;
HWND hwndDlg;
int hMenu;
int hMenuDisasm;
int hMenuDump;
int hMenuStack;

// 导出函数
extern "C" __declspec(dllexport) void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info);
extern "C" __declspec(dllexport) void plugsetup(PLUG_SETUPSTRUCT* setupStruct);
extern "C" __declspec(dllexport) bool pluginit(PLUG_INITSTRUCT* initStruct);

// 在这里初始化插件数据。
bool pluginInit(PLUG_INITSTRUCT* initStruct)
{
    // 返回false以取消加载插件。
    return true;
}

// 在此处取消初始化插件数据。
void pluginStop()
{
}

// 在这里做GUI/菜单相关的事情。
void pluginSetup()
{
}

// 菜单被点击回调
void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info)
{
    // 此菜单用于实现功能,并测试
    MessageBox(0, L"hello lyshark", 0, 0);
}

PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
{
    initStruct->pluginVersion = PLUGIN_VERSION;
    initStruct->sdkVersion = PLUG_SDKVERSION;
    strncpy_s(initStruct->pluginName, PLUGIN_NAME, _TRUNCATE);
    pluginHandle = initStruct->pluginHandle;

    // 插件初始化
    initStruct->sdkVersion = PLUG_SDKVERSION;
    initStruct->pluginVersion = 1;
    const char *name = "CheckME -->";
    memset(initStruct->pluginName, 0, 128);
    memcpy(initStruct->pluginName, name, strlen(name));

    return pluginInit(initStruct);
}

PLUG_EXPORT bool plugstop()
{
    pluginStop();
    return true;
}

PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
{
    hwndDlg = setupStruct->hwndDlg;
    hMenu = setupStruct->hMenu;
    hMenuDisasm = setupStruct->hMenuDisasm;
    hMenuDump = setupStruct->hMenuDump;
    hMenuStack = setupStruct->hMenuStack;

    // 增加二级菜单
    char sub_menu[] = { "PowerBy LyShark" };
    _plugin_menuaddentry(setupStruct->hMenu, 2, sub_menu);

    pluginSetup();
}

通过使用Visual Studio 2013编译这段程序,其默认会生成一个*.dll的文件,根据不同版本需要将其更改为*.dp32或者*.dp64以此来代表这是一个插件,并将更改好的插件放入到x32/plugins目录下,重启x64dbg至此即可看到插件已经被加载成功。

原文地址

https://www.lyshark.com/post/531cd43f.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/722940.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于深度学习的高精度鸡蛋检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度鸡蛋检测识别系统可用于日常生活中或野外来检测与定位鸡蛋目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的鸡蛋目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型…

水星U3相机在Halcon里面不能使用GenICamTL库采集解决方案

在halcon里面使用采集助手&#xff0c;U3相机不能使用GenICamTL库实时采集。 &#xff08;首先确保已经安装好水星相机驱动&#xff0c;如果没有安装&#xff0c;GenICamTL库会找不到&#xff09; 查看电脑的系统环境变量&#xff0c;打开对应电脑位数的值。 只留下大恒水星相…

ESP32(MicroPython) TFT LCD多功能显示(RTC+DHT22)

本程序内容与之前的类似&#xff0c;传感器换成DHT22&#xff0c;测量温湿度更符合日常使用的需要。逻辑上的一项改动是测量的温度和湿度值统一保留一位小数。 代码如下 from ili934xnew import ILI9341, color565 from machine import Pin, SPI import m5stack import tt14 …

【Redis】五大数据类型

&#x1f3af;Redis 数据类型 &#x1f4ad;Redis支持五种数据类型&#xff1a;String(字符串)&#xff0c;Hash(哈希)&#xff0c;List(列表)&#xff0c;Set(集合)及zset(sorted set有序集合)。 &#x1f4dd;String(字符串) Redis的String类型是一种最基本的数据类型&…

基于OIDC的SSO单点登录

文章目录 什么是SSO&#xff08;Single Sign On&#xff09;单点登录OIDC&#xff08;Open ID Connect&#xff09;SSO服务授权流程&#xff08;OIDC&#xff09;授权模式授权码模式授权码模式授权流程请求授权码过程 授权模式对比总结 什么是SSO&#xff08;Single Sign On&am…

Navicat 备份和恢复MongoDB库的数据

1、前期准备 (1) 有数据的MongoDB数据库old_db、空数据库new_db (2) 准备好MongoDB Tools 前往页面&#xff1a;https://www.mongodb.com/try/download/database-tools 选择所需版本下载并解压到自己想要的目录中&#xff1a; 2、将数据库old_db中的数据备份导出 (1) 对old_db…

多国卫星遥感领域工作人员和专家莅临大势智慧考察交流

7月4日下午&#xff0c;商务部卫星主题研修班&#xff08;后简称“卫星研修班”&#xff09;20余名来自多个国家的卫星遥感相关领域的工作人员和专家莅临武汉大势智慧有限公司&#xff08;后简称“大势智慧”&#xff09;参观考察、交流学习。大势智慧黄先锋博士陪同考察并作交…

学生用的台灯有什么讲究吗?盘点暑假适合写作业的台灯

如今青少年近视的比例越来越大&#xff0c;而且年龄越来越提前了&#xff0c;前不久经过一个小学看到二三年级就已经有孩子开始近视佩戴眼镜。其实造成近视的原因不全是读写作业时的坐姿不标准、学习时间过长、缺少户外的运动等&#xff0c;也包括可能灯光光源的问题造成对于视…

使用QTreeView显示指定目录中的文件,并自定义Header

这次研究了QTreeView的用法&#xff0c;于是想使用QTreeView显示制定目录下的所有子目录和文件。过程中&#xff0c;遇到了几个问题&#xff0c;在此记录一下同时分享给大家&#xff0c;如有不妥之处&#xff0c;还请批评指正&#xff1a; 设置根目录后&#xff0c;仍然会展示…

thinkphp系列vulhub所有漏洞复现ThinkPHP 2.x 任意代码执行漏洞,ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞

ThinkPHP 2.x 任意代码执行漏洞 漏洞详情&#xff1a; hinkPHP 2.x版本中&#xff0c;使用preg_replace的/e模式匹配路由&#xff1a; $res preg_replace((\w).$depr.([^.$depr.\/])e, $var[\\\1\]"\\2";, implode($depr,$paths));导致用户的输入参数被插入双引号…

力扣 90. 子集 II

题目来源&#xff1a;https://leetcode.cn/problems/subsets-ii/description/ C题解1&#xff1a;由于解集不能包含重复的子集&#xff0c;所以我们先对nums进行排序&#xff0c; 以便后续去重。 采用递归回溯法&#xff0c;对每个子集都即使保存&#xff0c;在完成第一次子集…

一文晓得SaaS、IaaS和 PaaS 是什么,三者的区别是?

接下来我们直接直奔主题 首先&#xff0c;概念走起。 IaaS&#xff1a;基础设施服务&#xff0c; Infrastructure-as-a-service PaaS&#xff1a;平台服务&#xff0c;Platform-as-a-service SaaS&#xff1a;软件服务&#xff0c;Software-as-a-service IaaS 基础设施即服…

【C++】C++11的新特性

文章目录 1. C11简介2. 统一的列表初始化2.1 {}统一初始化2.2 std::initializer_list 3. 声明的新方式和范围for循环3.1 decltype3.2 auto&nullptr&范围for循环 4. STL的变化4.1 新容器4.2 新接口 1. C11简介 ​ 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1…

Java并发编程面试题

一、线程、进程、程序 进程&#xff1a; 我们把运行中的程序叫做进程,每个进程都会占用内存与CPU资源,进程与进程之间互相独立. 线程&#xff1a; 线程就是进程中的一个执行单元&#xff0c;负责当前进程中程序的执行。一个进程可以包含多个线程。多线程可以提高程序的并行运…

Stable Diffusion 常用主流checkpoint模型

AbyssOrangeMix2 https://civitai.com/models/4437/abyssorangemix2-sfwsoft-nsfw dosmix https://civitai.com/models/6250/dosmix Counterfeit-V3.0 https://civitai.com/models/4468/counterfeit-v30 万象熔炉 | Anything V5/Ink QteaMix 通用Q版模型 https://civitai.c…

Spring Boot 中的监控及使用

Spring Boot 中的监控及使用 Spring Boot 是一个非常流行的 Java 应用程序开发框架&#xff0c;它提供了一种快速构建应用程序的方法。除此之外&#xff0c;Spring Boot 还提供了一系列的监控功能&#xff0c;方便开发人员对应用程序进行监控和管理。本文将讨论 Spring Boot 中…

MachineLearningWu_第1+2章_SupervisedLearningUnsupervisedLearning

x.1 笔记 常见Supervised Learning的app&#xff0c;会有input和label 线性拟合做回归&#xff0c; 分类问题如下&#xff0c;当单个输入但是多个类别信息时可以简化为单轴向&#xff0c; 当分类问题是多输入时&#xff0c;可以简化为特征空间如下&#xff0c; *无监督算法的核…

SiLM27624系列 双通道30V, 5A/5A高速低边门极驱动器介绍

在开关电源系统中&#xff0c;需要利用门极驱动器来有效地驱动功率器件&#xff0c;实现功率器件的快速开关&#xff0c;以减少开关功率损耗、提高系统效率。在 GaN 等新兴的宽带隙功率器件技术中&#xff0c;需要快速的传输延时、精准的延迟匹配、极强的驱动能力以满足系统中高…

移动隔断地板无轨道,只需将轨道安装于天花板上

移动隔断地板无轨道设计可以提供更加灵活的空间划分和布局选择。相较于传统的固定轨道系统&#xff0c;只需将轨道安装在天花板上&#xff0c;就能实现移动隔断的收放和推动。这种设计可以避免地板上的轨道对于日常活动和清洁的干扰&#xff0c;并且减少了地板安装的复杂性。 在…

HDLBits刷题笔记9:Circuits.Sequential Logic.Counters + Shift Registers

Counters Four-bit binary counter module top_module (input clk,input reset, // Synchronous active-high resetoutput reg [3:0] q);always (posedge clk) beginif(reset)q < 0;elseq < q 1;end endmoduleDecade counter 建立一个计数器&#xff0c;从0计数…