Nattevak 发表于 2021-12-8 21:53

分析OD插件原理并制作反反调试插件

1.OllyDbg,文中均简称为OD。OD版本为论坛专用虚拟机工具包中的OD2.0版本。
OD的插件本质上就是一个到处有指定函数的DLL文件,这些按照指定名称、指定格式导出的函数会在OD执行到某一阶段或触发某个事件时主动调用。
OD启动时会遍历指定目录下的所有DLL文件并加载,然后根据插件返回的API版本信息决定是否继续加载,如果API版本不符合则会卸载此插件。
// OD 2.0 版本的插件接口
#define PLUGIN_VERSION 0x02010001      // Version 2.01.0001 of plugin interface
    // 1. 检查OD的兼容版本
    if (ollydbgversion < 201)
      return 0;
    // 2. 设置OD插件的名称与版本
    StringCchCopy(pluginname, SHORTNAME, PLUGINNAME);
    StringCchCopy(pluginversion, SHORTNAME, MY_VERSION);
    // 3. 返回需要的API版本
   return PLUGIN_VERSION;
2.编写插件需要包含“plugin.h”,“ollydbg.lib”两个文件
#include "Plugin/od_plugin.h"
#pragma comment(lib,".\\Plugin\\ollydbg.lib")
3.此外,还需要在C/C++命令行选项中添加“/J”,以说明工程中的char均为unsigned类型


4.定义全局变量与宏定义
#include <Windows.h>
#include <winternl.h>
#include "Plugin/od_plugin.h"
#pragma comment(lib,"ntdll.lib")
#pragma comment(lib,".\\Plugin\\ollydbg.lib")

#define PLUGINNAME L"ODPlugin"// 插件名称
#define MY_VERSION L"0.00.01"       // 插件版本
t_table   g_stcPlugin = { 0 };

/**********************************************************/
/* 函数名:插件信息查询函数【回调函数】
/* 说明:    此函数是必须存在的函数,也是OllyDBG第1个调用的函数。此函数负责检查当前的OllyDBG版本是否可以运行此插件,如果不能运行则需要返回0 。
/**********************************************************/
extc int __cdecl ODBG2_Pluginquery(int ollydbgversion, ulong* features, wchar_t pluginname, wchar_t pluginversion)
{
    // 1. 检查OD的兼容版本
    if (ollydbgversion < 201)
      return 0;
    // 2. 设置OD插件的名称与版本
    StringCchCopy(pluginname, SHORTNAME, PLUGINNAME);
    StringCchCopy(pluginversion, SHORTNAME, MY_VERSION);
    // 3. 返回需要的API版本
   return PLUGIN_VERSION;
}
// 函数名:插件初始化函数【回调函数】
// 说   明:此函数是可选函数,也是OllyDBG第2个调用的函数。负责初始化插件的初始资源。
// 返回值:
//   int : 成功返回0,失败返回-1
extc int __cdecl ODBG2_Plugininit(void) {
    MessageBox(0, L"插件加载成功,此时正在初始化",L"提示", 0);
    return 0;
};
// 函数名:插件重置函数【回调函数】
// 说   明:    此函数是可选函数,当O重新加载程序或打开新的程序时,这个函数将会被调用。
extc void __cdecl ODBG2_Pluginreset(void) {
Deletesorteddatarange(&(g_stcPlugin.sorted), 0, 0xFFFFFFFF);
};
// 函数名:插件关闭函数【回调函数】
extc int __cdecl ODBG2_Pluginclose(void) {
    Writetoini(NULL, (WCHAR*)PLUGINNAME, (WCHAR*)L"Restore", (WCHAR*)L"%i", g_stcPlugin.hw != NULL);
return 0;
};
// 函数名:插件销毁函数【回调函数】。
extc void __cdecl ODBG2_Plugindestroy(void) {
    Destroysorteddata(&(g_stcPlugin.sorted));
};
5.插件菜单部分
①菜单响应函数是OD已经预定义好的函数类型,响应函数根据被调用的时机做出处理
static int MenuFun(t_table* pt, wchar_t* name, ulong index, int mode)
{
    if (mode == MENU_VERIFY)    // 第一次调用(一般执行初始化操作)
      return MENU_NORMAL;
    if (mode == MENU_EXECUTE)   // 第二次调用(一般执行菜单逻辑操作)
    {
      MessageBox(0, L"我被点击了", L"提示",0);
      return MENU_NOREDRAW;
    }

    return MENU_ABSENT;
};
②菜单结构体数组
// 设置主菜单数组
static t_menu g_stcMainMenu[] = {
    { (WCHAR*)L"反反调试",
    (WCHAR*)L"提示:主菜单。",
    K_NONE, MenuAntiAntiDebug, NULL, 0 },
    { NULL, NULL, K_NONE, NULL, NULL, 0 }
};
// 设置右键单数组
static t_menu g_stcDISASMMenu[] = {
    {(WCHAR*)L"右键菜单",
    (WCHAR*)L"提示:右键菜单。",
    KK_DIRECT | KK_CTRL | 'A', MenuFun, NULL, 0 },
    { NULL, NULL, K_NONE, NULL, NULL, 0 }
};
③实现反反调试
检查PEB中的BeingDebugged标志以确定进程是否正在被用户模式的调试器调试。
static int MenuAntiAntiDebug(t_table* pt, wchar_t* name, ulong index, int mode)
{
    if (mode == MENU_VERIFY)    // 第一次调用(一般执行初始化操作)
      return MENU_NORMAL;
    if (mode == MENU_EXECUTE)   // 第二次调用(一般执行菜单逻辑操作)
    {
      MessageBox(0, L"开始反反调试", L"提示", 0);

      //1. 打开目标进程
       HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, g_nId);
       //2. 获取对方PEB的地址
       _PROCESS_BASIC_INFORMATION pbi = {0};
       DWORD dwSize = 0;
       NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi),&dwSize);
       //3. 修改BeingDebugged
       char cCh = 0;
       WriteProcessMemory(hProcess, (LPVOID)((DWORD)pbi.PebBaseAddress + 0x02), &cCh, 1, &dwSize);
      return MENU_NOREDRAW;
    }
    return MENU_ABSENT;
};

int g_nId = 0;
// 函数名:事件通知函数【回调函数】
// 说   明:当进程创建,线程创建,进程退出,线程退出会调用这个函数
// code 原因
// 当原因是进程创建的时候,parm1是进程PID
// 返回值:
void ODBG2_Pluginnotify(int code, void* data, ulong parm1, ulong parm2)
{
    //处理进程创建时消息
    if (code == PN_NEWPROC)
      g_nId = parm1;
    return;
}
④菜单回调函数
extc t_menu* __cdecl ODBG2_Pluginmenu(wchar_t* type)
{
    // 1. 判断是否为主菜单弹出请求,是则弹出主菜单
    if (!wcscmp(type, PWM_MAIN))
      return g_stcMainMenu;
    // 2. 判断是否为CPU窗口右键菜单弹出请求,是则弹出右键菜单
    if (!wcscmp(type, PWM_DISASM))
      return g_stcDISASMMenu;
    // 3. 返回空
    return NULL;
};
6.设置操作
①新建plugin 和 udd两个文件夹,将DLL放在plugin中

②修改路径,这里圈错了,UDD是第一个路径


7.调试检测
①未开启反调试


②加载插件

Nattevak 发表于 2021-12-10 11:12

matao5168 发表于 2021-12-10 11:05
这两个反反调试插件在哪儿可以下载呀,楼主???

论坛的OD1.0版本的自带有反反调试插件,这是自己随便写的一个OD2.0版本的插件,很简单就一两行代码的事儿

相约一生 发表于 2021-12-11 11:02

冥界3大法王 发表于 2021-12-8 22:41
这两文件相当于x64dbg的那个调试桥文件吧? 负责消息的传送?

你的签名很有个性,写的都是关于破解的。

Triple.J 发表于 2021-12-8 22:18

谢谢大佬分享,很有用

冥界3大法王 发表于 2021-12-8 22:41

“plugin.h”,“ollydbg.lib”两个文件
这两文件相当于x64dbg的那个调试桥文件吧? 负责消息的传送?

lingyun011 发表于 2021-12-8 22:51

{:301_993:}{:301_993:}{:301_993:}向楼主学习

Nattevak 发表于 2021-12-8 23:08

冥界3大法王 发表于 2021-12-8 22:41
这两文件相当于x64dbg的那个调试桥文件吧? 负责消息的传送?

调用od API

raycerlane 发表于 2021-12-8 23:50

一下子感觉自己又学到了不少{:1_893:}

Elaineliu 发表于 2021-12-9 00:04

我感觉我又行了

fyh505099 发表于 2021-12-9 00:29

感谢分享 支持一波

kennie611 发表于 2021-12-9 08:11


一下子感觉自己又学到了不少

southerlywindly 发表于 2021-12-9 08:19

学习一下
页: [1] 2 3 4
查看完整版本: 分析OD插件原理并制作反反调试插件