首页 > 其他分享 >1.5 为x64dbg编写插件

1.5 为x64dbg编写插件

时间:2023-10-14 09:22:20浏览次数:41  
标签:PLUG 1.5 插件 setupStruct lib initStruct x64dbg include

任何一个成熟的软件都会具有可扩展性,可扩展性是现代软件的一个重要特征,因为它使软件更易于维护和适应变化的需求,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官方针对配置方法给予了一个模板文件,读者可以自行去下载该模板使用。

在开发插件时,至少需要导出两个函数,函数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
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

标签:PLUG,1.5,插件,setupStruct,lib,initStruct,x64dbg,include
From: https://www.cnblogs.com/LyShark/p/17763688.html

相关文章

  • 1.1 熟悉x64dbg调试器
    x64dbg是一款开源、免费、功能强大的动态反汇编调试器,它能够在Windows平台上进行应用程序的反汇编、调试和分析工作。与传统的调试器如Ollydbg相比,x64dbg调试器的出现填补了Ollydbg等传统调试器的不足,为反汇编调试工作提供了更高效、更可靠的解决方案。正是因为有了这些优点,才能......
  • MybatisPlus的动态表名插件
          ......
  • Sonar Qube社区版多分支插件集成
    社区版本不支持对多分枝的区分,要实现其功能,可以通过一个开源的插件来完成,插件的地址:https://github.com/mc1arke/sonarqube-community-branch-plugin第一步:下载匹配的插件首先我们根据所安装的Sonar版本来下载相应版本的sonarqube-community-branch-plugin插件SonarQubeVersionPlu......
  • Solidworks流体仿真插件安装及案例分析
    Solidworks流体仿真插件安装及案例分析1流体仿真插件的安装如图1所示,安装时勾选SolidworksFlowSimuation模块,一路“下一步”安装完毕。完成安装后打开软件,图2所示,点击Solidworks插件按钮,找到SolidworksFlowSimuation按钮,双击可打开说明插件安装成2案例分析2.1案例背景......
  • pycharm使用Headers插件完成快捷操作
    在pycharm的Preferences-Plugins-Marketplace下搜索Headersinstall安装、apply应用,ok确定接下来只要复制相关headers就可以了XXX={直接在此处,右键,点击Headers-Headers,瞬间完成字典转换}如图:......
  • java项目使用Mybatis-Plus插件,QueryWrapper日期开始-结束范围查询
    1、参数开始日期startTime、结束日期endTime挺好用,开始日期、结束日期当天都包含进去了,如果使用qw.between("create_time",startTime,endTime)方法是不含endTime结束日期当天的qw.apply(bCulresCardMvVO.getStartTime()!=null,"date_format(create_time,......
  • folder-alias vscode左侧目录树 起别名 插件
    folder-aliasvscode左侧目录树起别名插件插件效果不足文件路径或目录路径中包含中文会挂不上别名,纯英文路径没问题个人意见我的项目都是纯英文,所以到不用考虑中文问题,还有个小惊喜就是打开的tab会带上别名非常不错......
  • 好用的IDEA插件之Mybatis Log Free
    今天看到一个公众号说的插件,可以记录MyBatis执行的SQL语句,不用去拼接sql语句,可以直接看到sql语句。没用插件之前: 可以看到那个分页查询需要去拼接sql语句,把2拼接上。使用了插件后; 不用自己拼接,可以直接看见sql语句。非常方便,也可以帮助排查sql语句错误。最后那个插件样......
  • 【OpenJudge】NOI / 1.5编程基础之循环控制
    25:求特殊自然数总时间限制: 1000ms 内存限制: 65536kB描述一个十进制自然数,它的七进制与九进制表示都是三位数,且七进制与九进制的三位数码表示顺序正好相反。编程求此自然数,并输出显示。输入无。输出三行:第一行是此自然数的十进制表示;第二行是此自然数的七进制表示;第三......
  • BootStrapt iCheck表单美化插件使用方法
    一、特色:1、在不同浏览器(包括ie6+)和设备上都有相同的表现—包括桌面和移动设备2、支持触摸设备—iOS、Android、BlackBerry、WindowsPhone等系统4、方便定制—用HTML和CSS即可为其设置样式(多套皮肤)5、体积小巧—gzip压缩后只有1kb6、25种参数用来......