1.OllyDbg,文中均简称为OD。OD版本为论坛专用虚拟机工具包中的OD2.0版本。
OD的插件本质上就是一个到处有指定函数的DLL文件,这些按照指定名称、指定格式导出的函数会在OD执行到某一阶段或触发某个事件时主动调用。
OD启动时会遍历指定目录下的所有DLL文件并加载,然后根据插件返回的API版本信息决定是否继续加载,如果API版本不符合则会卸载此插件。
[C] 纯文本查看 复制代码 // 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”两个文件
[C] 纯文本查看 复制代码 #include "Plugin/od_plugin.h"
#pragma comment(lib,".\\Plugin\\ollydbg.lib")
3.此外,还需要在C/C++命令行选项中添加“/J”,以说明工程中的char均为unsigned类型
3
4.定义全局变量与宏定义
[C] 纯文本查看 复制代码 #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[SHORTNAME], wchar_t pluginversion[SHORTNAME])
{
// 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已经预定义好的函数类型,响应函数根据被调用的时机做出处理
[C] 纯文本查看 复制代码 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;
};
②菜单结构体数组
[C] 纯文本查看 复制代码 // 设置主菜单数组
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标志以确定进程是否正在被用户模式的调试器调试。
[C] 纯文本查看 复制代码 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;
}
④菜单回调函数
[C] 纯文本查看 复制代码 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中
6.1
②修改路径,这里圈错了,UDD是第一个路径
6.2
7.调试检测
①未开启反调试
7.1
②加载插件
7.2.1
7.2.2
|