任何一个成熟的软件都会具有可扩展性,可扩展性是现代软件的一个重要特征,因为它使软件更易于维护和适应变化的需求,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) 函数的原型和解释:

  1. 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) 函数的原型和解释:

  1. 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适用于初始化插件的,例如增加插件菜单栏,设置插件功能等,我们以如下代码为例做一个简单的解释;

  1. PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
  2. {
  3. initStruct->pluginVersion = PLUGIN_VERSION;
  4. initStruct->sdkVersion = PLUG_SDKVERSION;
  5. strncpy_s(initStruct->pluginName, PLUGIN_NAME, _TRUNCATE);
  6. pluginHandle = initStruct->pluginHandle;
  7. // 插件初始化
  8. initStruct->sdkVersion = PLUG_SDKVERSION;
  9. initStruct->pluginVersion = 1;
  10. const char *name = "CheckME -->";
  11. memset(initStruct->pluginName, 0, 128);
  12. memcpy(initStruct->pluginName, name, strlen(name));
  13. return pluginInit(initStruct);
  14. }

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

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

  1. PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
  2. {
  3. hwndDlg = setupStruct->hwndDlg;
  4. hMenu = setupStruct->hMenu;
  5. hMenuDisasm = setupStruct->hMenuDisasm;
  6. hMenuDump = setupStruct->hMenuDump;
  7. hMenuStack = setupStruct->hMenuStack;
  8. // 增加二级菜单
  9. char sub_menu[] = { "PowerBy LyShark" };
  10. _plugin_menuaddentry(setupStruct->hMenu, 2, sub_menu);
  11. pluginSetup();
  12. }

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

(2)开发插件实战

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

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

  1. #pragma once
  2. // Plugin information
  3. #define PLUGIN_NAME "LySharkBlog"
  4. #define PLUGIN_VERSION 1
  5. #include "./bridgemain.h"
  6. #include "./_plugins.h"
  7. #include "./_scriptapi_argument.h"
  8. #include "./_scriptapi_assembler.h"
  9. #include "./_scriptapi_bookmark.h"
  10. #include "./_scriptapi_comment.h"
  11. #include "./_scriptapi_debug.h"
  12. #include "./_scriptapi_flag.h"
  13. #include "./_scriptapi_function.h"
  14. #include "./_scriptapi_gui.h"
  15. #include "./_scriptapi_label.h"
  16. #include "./_scriptapi_memory.h"
  17. #include "./_scriptapi_misc.h"
  18. #include "./_scriptapi_module.h"
  19. #include "./_scriptapi_pattern.h"
  20. #include "./_scriptapi_register.h"
  21. #include "./_scriptapi_stack.h"
  22. #include "./_scriptapi_symbol.h"
  23. #include "./DeviceNameResolver/DeviceNameResolver.h"
  24. #include "./jansson/jansson.h"
  25. #include "./lz4/lz4file.h"
  26. #include "./TitanEngine/TitanEngine.h"
  27. #include "./XEDParse/XEDParse.h"
  28. #ifdef _WIN64
  29. #pragma comment(lib, "./x64dbg.lib")
  30. #pragma comment(lib, "./x64bridge.lib")
  31. #pragma comment(lib, "./DeviceNameResolver/DeviceNameResolver_x64.lib")
  32. #pragma comment(lib, "./jansson/jansson_x64.lib")
  33. #pragma comment(lib, "./lz4/lz4_x64.lib")
  34. #pragma comment(lib, "./TitanEngine/TitanEngine_x64.lib")
  35. #pragma comment(lib, "./XEDParse/XEDParse_x64.lib")
  36. #else
  37. #pragma comment(lib, "./x32dbg.lib")
  38. #pragma comment(lib, "./x32bridge.lib")
  39. #pragma comment(lib, "./DeviceNameResolver/DeviceNameResolver_x86.lib")
  40. #pragma comment(lib, "./jansson/jansson_x86.lib")
  41. #pragma comment(lib, "./lz4/lz4_x86.lib")
  42. #pragma comment(lib, "./TitanEngine/TitanEngine_x86.lib")
  43. #pragma comment(lib, "./XEDParse/XEDParse_x86.lib")
  44. #endif //_WIN64
  45. #define Cmd(x) DbgCmdExecDirect(x)
  46. #define Eval(x) DbgValFromString(x)
  47. #define dprintf(x, ...) _plugin_logprintf("[" PLUGIN_NAME "] " x, __VA_ARGS__)
  48. #define dputs(x) _plugin_logprintf("[" PLUGIN_NAME "] %s\n", x)
  49. #define PLUG_EXPORT extern "C" __declspec(dllexport)
  50. //superglobal variables
  51. extern int pluginHandle;
  52. extern HWND hwndDlg;
  53. extern int hMenu;
  54. extern int hMenuDisasm;
  55. extern int hMenuDump;
  56. extern int hMenuStack;
  57. //functions
  58. bool pluginInit(PLUG_INITSTRUCT* initStruct);
  59. void pluginStop();
  60. void pluginSetup();

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

  1. #include "pluginmain.h"
  2. #include <Windows.h>
  3. #include <process.h>
  4. int pluginHandle;
  5. HWND hwndDlg;
  6. int hMenu;
  7. int hMenuDisasm;
  8. int hMenuDump;
  9. int hMenuStack;
  10. // 导出函数
  11. extern "C" __declspec(dllexport) void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info);
  12. extern "C" __declspec(dllexport) void plugsetup(PLUG_SETUPSTRUCT* setupStruct);
  13. extern "C" __declspec(dllexport) bool pluginit(PLUG_INITSTRUCT* initStruct);
  14. // 在这里初始化插件数据。
  15. bool pluginInit(PLUG_INITSTRUCT* initStruct)
  16. {
  17. // 返回false以取消加载插件。
  18. return true;
  19. }
  20. // 在此处取消初始化插件数据。
  21. void pluginStop()
  22. {
  23. }
  24. // 在这里做GUI/菜单相关的事情。
  25. void pluginSetup()
  26. {
  27. }
  28. // 菜单被点击回调
  29. void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info)
  30. {
  31. // 此菜单用于实现功能,并测试
  32. MessageBox(0, L"hello lyshark", 0, 0);
  33. }
  34. PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
  35. {
  36. initStruct->pluginVersion = PLUGIN_VERSION;
  37. initStruct->sdkVersion = PLUG_SDKVERSION;
  38. strncpy_s(initStruct->pluginName, PLUGIN_NAME, _TRUNCATE);
  39. pluginHandle = initStruct->pluginHandle;
  40. // 插件初始化
  41. initStruct->sdkVersion = PLUG_SDKVERSION;
  42. initStruct->pluginVersion = 1;
  43. const char *name = "CheckME -->";
  44. memset(initStruct->pluginName, 0, 128);
  45. memcpy(initStruct->pluginName, name, strlen(name));
  46. return pluginInit(initStruct);
  47. }
  48. PLUG_EXPORT bool plugstop()
  49. {
  50. pluginStop();
  51. return true;
  52. }
  53. PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
  54. {
  55. hwndDlg = setupStruct->hwndDlg;
  56. hMenu = setupStruct->hMenu;
  57. hMenuDisasm = setupStruct->hMenuDisasm;
  58. hMenuDump = setupStruct->hMenuDump;
  59. hMenuStack = setupStruct->hMenuStack;
  60. // 增加二级菜单
  61. char sub_menu[] = { "PowerBy LyShark" };
  62. _plugin_menuaddentry(setupStruct->hMenu, 2, sub_menu);
  63. pluginSetup();
  64. }

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

1.5 为x64dbg编写插件的更多相关文章

  1. jquery编写插件的方法

     版权声明:作者原创,转载请注明出处! 编写插件的两种方式: 1.类级别开发插件(1%) 2.对象级别开发(99%) 类级别的静态开发就是给jquery添加静态方法,三种方式 1.添加新的全局函数 2 ...

  2. 再谈:jquery编写插件的方法

    版权声明:作者原创,转载请注明出处! 编写插件的两种方式: 1.类级别开发插件(1%) 2.对象级别开发(99%) 类级别的静态开发就是给jquery添加静态方法,三种方式 1.添加新的全局函数 2. ...

  3. jQuery自己编写插件()

    引言: 在项目中不同页面经常要用到已经写好的交互,比如弹窗,比如下拉菜单,比如选项卡,比如删除... 此时如果每次都把代码copy一份无疑是一件比较麻烦并且无趣的事情,而且个人认为有些low了,我们可 ...

  4. 【原】jQuery编写插件

    分享一下编写设置和获取颜色的插件,首先我将插件的名字命名为jquery.color.js.该插件用来实现以下两个功能1.设置元素的颜色.2.获取元素的颜色. 先在搭建好如下编写插件的框架: ;(fun ...

  5. jquery编写插件

    jquery编写插件的方法    版权声明:作者原创,转载请注明出处! 编写插件的两种方式: 1.类级别开发插件(1%) 2.对象级别开发(99%) 类级别的静态开发就是给jquery添加静态方法,三 ...

  6. Qt中如何 编写插件 加载插件 卸载插件

    Qt中如何 编写插件 加载插件 卸载插件是本文要介绍的内容.Qt提供了一个类QPluginLoader来加载静态库和动态库,在Qt中,Qt把动态库和静态库都看成是一个插件,使用QPluginLoade ...

  7. vscode编写插件

    vscode编写插件详细过程 前言 之前编写了一个vscode插件用vscode写博客和发布,然后有园友要求写一篇来介绍如何开发一个vscode扩展插件,或者说介绍开发这个插件的过程.然而文章还没有写 ...

  8. saltstack主机管理项目:编写插件基类-获取主机列表-提取yaml配置文件(四)

    一.编写插件基类 1.目录结构 1.我是如何获知我有多少种系统? 当客户端第一连接过来的时候,我就已经把这些文件存下来了 ,存在到哪里了?存到数据库了 每次对主机发送命令的动作时,我从库里把数据取出来 ...

  9. javascript&&jquery编写插件模板

    javascrpt插件编写模板 这里不分享如何编写插件,只留一个框架模板,使用面向对象的形式进行编写,方便管理 ;(function(window,document){ function FnName ...

  10. 13 Maven 编写插件

    Maven 编写插件 Maven 的任何行为都是由插件完成的,包括项目的清理.绵编译.测试以及打包等操作都有其对应的 Maven 插件.每个插件拥有一个或者多个目标,用户可以直接从命令行运行这些插件目 ...

随机推荐

  1. 认证,权限,频率源码分析 自定义频率类 SimpleRateThrottle缓存频率类 基于APIView编写分页

    目录 昨日回顾 三种位置的token获取 三种权限校验方式 原生django的cookie+session认证底层原理 断点调试使用 认证,权限,频率源码分析(了解) 权限源码分析 认证源码分析 频率 ...

  2. GitHub CEO发文:严格限制俄罗斯获取侵略性军事能力所需要的技术

    前几天,在微信群里就有小伙伴发了一些关于GitHub将限制俄罗斯开发人员使用开源软件的消息,引起程序员圈子的热烈讨论. 就在不久前,GitHub CEO在GitHub官方博客发文阐述了对乌克兰战争的回 ...

  3. AcWing 每日一题 - Summer

    本篇解题记录题源来自 AcWing 的 Summer 每日一题 补题链接:Here 2021/07/01 done Week 1 星期一 AcWing 3485. 最大异或和 (Hard 思路 先求出 ...

  4. debian更新openssh 9.6

    先更新一下,然后安装libssl-dev zlib1g-dev依赖文件 apt update apt install build-essential apt-get install -y libssl ...

  5. 8 Englishi 词根

    测一测 physical obesity skinny sliny stout skeleton external appearance recede unprecededented feinge e ...

  6. html5离线存储manifest

    https://www.bilibili.com/video/BV1Up4y1t7pV?p=5

  7. SV 数据类型-2

    动态数组 数组定义的时候不用给定数组元素个数 动态数组实例 例1 队列

  8. Verilog Review

    Agenda 目的 Verilog概述 Verilog建模 模块 模块组成 书写建议 时延 Verilog基本语法 标识符 可读性 注释 空格 数据类型 操作数 运算符 条件语句 循环语句 函数 Ve ...

  9. SD协议-时序

    1.SD Timing 时序主要体现在CMD和Response的时序 S - 起始位,一直为0 T - Transmitter,1表示CMD(发起端是Host),0表示Response(发起端是Car ...

  10. 使用华为路由连接WiFi,被限制网速?

    1.问题 使用华为路由连接WiFi,但是网速非常慢,经常半天才能加载一个界面? 2.解决方法 登陆http://192.168.3.1/网址,发现限速一栏被框选,取消即可