找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2901|回复: 1

OllyDbg插件深入分析二

[复制链接]

307

主题

228

回帖

7337

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5587 个
贡献
253 次
宅之契约
0 份
在线时间
948 小时
注册时间
2014-1-25
发表于 2015-1-2 23:47:16 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
OllyDbg插件深入分析一        http://www.0xaa55.com/forum.php? ... tid=1133&extra=


第二章 OllyDbg1输出函数按功能分类

学习Windows编程需要熟悉WindowsAPI,同样地,熟悉OllyDbg插件编程也要熟悉OllyDbg API,下面是我的学习路线。

插件函数

intRegisterpluginclass(char *classname,char *iconname,HINSTANCE dllinst,WNDPROCclassproc);
voidUnregisterpluginclass(char *classname);
intPluginwriteinttoini(HINSTANCE dllinst,char *key,int value);
intPluginwritestringtoini(HINSTANCE dllinst,char *key,char *s);
intPluginreadintfromini(HINSTANCE dllinst,char *key,int def);
intPluginreadstringfromini(HINSTANCE dllinst,char *key,char *s,char *def);
intPluginsaverecord(ulong tag,ulong size,void *data);
intPlugingetvalue(int type);
t_statusGetstatus(void);
Registerpluginclass

原型:intRegisterpluginclass(char *classname,char *iconname,HINSTANCE dllinst,

WNDPROCclassproc)

功能:生成唯一的类名并注册为插件窗口。如果iconname为NULL则使用标准插件图标(字母P)
返回:成功时返回0并填充classname,失败时返回1
参数:
      classname 指向大小大于32字符的缓冲区用于接收类名
      iconname 插件DLL中图标资源名
      dllinst 插件实例句柄
      classproc 新类的窗口过程地址
注意:注册后窗口类有8个整数(32字节)的额外空间,插件可以自由使用第2到7个整数空间(偏移8到28用于GetWindowLong和SetWindowLong)。ODBG_Plugininit是执行该函数的最佳位置
Unregisterpluginclass

原型:voidUnregisterpluginclass(char *classname)

功能:注销之前通过Registerpluginclass注册的窗口类
参数:
      classname 函数Registerpluginclass返回的类名
注意:在ODBG_Plugindestroy中对所有注册的窗口类调用该函数
Pluginwriteinttoini

原型:intPluginwriteinttoini(HINSTANCE dllinst,char *key,int value)

功能:将整数值绑定的键值对存储在ollydbg.ini的插件自定义区段中
返回:成功时返回1,失败时返回0
参数:
      dllinst 插件实例句柄
      key 整数相关的键名
      value 要存储在ollydbg.ini的整数
Pluginwritestringtoini

原型:intPluginwritestringtoini(HINSTANCE dllinst,char *key,char *s)

功能:将ASCII字符串绑定的键值对存储在ollydbg.ini的插件自定义区段中
返回:成功时返回1,失败时返回0
参数:
      dllinst 插件实例句柄
      key 字符串相关的键名
      s 要存储在ollydbg.ini的字符串
Pluginreadintfromini

原型:intPluginreadintfromini(HINSTANCE dllinst,char *key,int def)

功能:将整数值绑定的键值对从ollydbg.ini的插件自定义区段中读取出来
返回:成功时返回目标整数,失败时返回默认值
参数:
      dllinst 插件实例句柄
      key 整数相关的键名
      def 默认值
Pluginreadstringfromini

原型:intPluginreadstringfromini(HINSTANCE dllinst,char *key,char *s,char *def)

功能:将字符串绑定的键值对从ollydbg.ini的插件自定义区段中读取出来
返回:成功时返回目标字符串,失败时返回默认值
参数:
      dllinst 插件实例句柄
      key 字符串相关的键名
      s 用于接收目标字符串
      def 默认字符串,以零终止符结尾
Pluginsaverecord

原型:intPluginsaverecord(ulong tag,ulong size,void *data)

功能:将一个记录写入.udd文件
返回:成功时返回1,失败时返回0
参数:
      tag 插件唯一的标签
      size 写入.udd文件的数据大小,最大USERLEN
      data 写入.udd文件的数据缓冲区
注意:只能从ODBG_Pluginsaveudd中调用,否则会崩溃
Plugingetvalue

原型:intPlugingetvalue(int type)

功能:返回OllyDbg多个设置和变量信息
参数:
      type 要返回的设置或变量信息
  
type
  
  
实际类型
  
  
含义
  
  
VAL_HINST
  
  
HINST
  
  
当前OllDbg实例句柄
  
  
VAL_HWMAIN
  
  
HWND
  
  
OllyDbg主窗口句柄
  
  
VAL_HWCLIENT
  
  
HWND
  
  
MDI用户窗口句柄
  
  
VAL_NCOLORS
  
  
  
  
常见颜色数
  
  
VAL_COLORS
  
  
COLORREF*
  
  
常见颜色RGB值数组
  
  
VAL_BRUSHES
  
  
HBRUSH*
  
  
常见颜色画刷句柄数组
  
  
VAL_PENS
  
  
HPEN*
  
  
常见颜色画笔句柄数组
  
  
VAL_NFONTS
  
  
  
  
常见字体数
  
  
VAL_FONTS
  
  
HFONT*
  
  
常见字体句柄数组
  
  
VAL_FONTNAMES
  
  
Char**
  
  
内部字体名称
  
  
VAL_FONTWIDTHS
  
  
int*
  
  
常见字体平均宽度
  
  
VAL_FONTHEIGHTS
  
  
int*
  
  
常见字体平均高度
  
  
VAL_NFIXFONTS
  
  
  
  
固定字宽字体数
  
  
VAL_DEFFONT
  
  
  
  
默认字体序号
  
  
VAL_NSCHEMES
  
  
  
  
配色方案数
  
  
VAL_SCHEMES
  
  
t_scheme*
  
  
配色方案数组
  
  
VAL_DEFSCHEME
  
  
  
  
默认配色方案数组
  
  
VAL_DEFHSCROLL
  
  
  
  
默认水平滚动
  
  
VAL_RESTOREWINDOWPOS
  
  
  
  
.ini文件恢复窗口位置
  
  
VAL_HPROCESS
  
  
HANDLE
  
  
被调试进程句柄
  
  
VAL_PROCESSID
  
  
  
  
被调试进程标志ID
  
  
VAL_HMAINTHREAD
  
  
HANDLE
  
  
被调试进程主线程句柄
  
  
VAL_MAINTHREADID
  
  
  
  
被调试进程主线程标志ID
  
  
VAL_MAINBASE
  
  
  
  
被调试进程主模块基址
  
  
VAL_PROCESSNAME
  
  
char*
  
  
被调试进程名
  
  
VAL_EXEFILENAME
  
  
char*
  
  
被调试程序文件名
  
  
VAL_CURRENTDIR
  
  
char*
  
  
被调试进程当前目录
  
  
VAL_SYSTEDIR
  
  
char*
  
  
系统目录
  
  
VAL_DECODEANYIP
  
  
  
  
不依赖EIP解码寄存器
  
  
VAL_PASCALSTRINGS
  
  
  
  
解码Pascal格式字符串
  
  
VAL_ONLYASCII
  
  
  
  
只解码可打印ASCII字符
  
  
VAL_DIACRITICALS
  
  
  
  
允许字符串有变音符号
  
  
VAL_GLOBALSEARCH
  
  
  
  
从块的开始处搜索
  
  
VAL_ALIGNEDSEARCH
  
  
  
  
逐项搜索
  
  
VAL_SEARCHMARGIN
  
  
  
  
浮点搜索允许误差
  
  
VAL_KEEPSELSIZE
  
  
  
  
保存16进制编辑中选择项数
  
  
VAL_MMXDISPLAY
  
  
  
  
对话框MMX显示模式(0:16进制 1:有符号 2:无符号)
  
  
VAL_WINDOWFONT
  
  
  
  
对话框中使用窗口字体
  
  
VAL_TABSTOPS
  
  
  
  
制表符大小
  
  
VAL_MODULES
  
  
t_table*
  
  
模块表(包括.EXE.DLL)
  
  
VAL_MEMORY
  
  
t_table*
  
  
分配内存块表
  
  
VAL_THREADS
  
  
t_table*
  
  
活动线程表
  
  
VAL_BREAKPOINTS
  
  
t_table*
  
  
激活断点表
  
  
VAL_REFERENCES
  
  
t_table*
  
  
查找到的参考信息表
  
  
VAL_SOURCELIST
  
  
t_table*
  
  
源文件表
  
  
VAL_WATCHES
  
  
t_table*
  
  
监视情况表
  
  
VAL_CPUFEATURES
  
  
  
  
CPUID返回的CPU特征位
  
  
VAL_TRACEFILE
  
  
FILE*
  
  
运行跟踪记录文件句柄
  
  
VAL_ALIGNDIALOGS
  
  
  
  
对齐对话框
  
  
VAL_CPUDASM
  
  
t_dump*
  
  
获取CPU反汇编窗口描述符
  
  
VAL_CPUDDUMP
  
  
t_dump*
  
  
获取CPU内存窗口描述符
  
  
VAL_CPUDSTACK
  
  
t_dump*
  
  
获取CPU栈窗口描述符
  
  
VAL_APIHELP
  
  
char*
  
  
选择的API帮助文件名
  
  
VAL_HARDBP
  
  
  
  
硬件断点是否激活
  
  
VAL_PATCHES
  
  
t_table*
  
  
补丁表
  
  
VAL_HINTS
  
  
t_sorted*
  
  
带分析提示的排序数据
  

说明:带有VAL_N***的type变量表示获取数量,需要先获取该数量才能知道对应的VAL_***数据数组有多大。例如FONT系列,首先要调用Plugingetvalue(VAL_NFONTS)获取字体个数,之后再调用VAL_FONTNAMES等获取数据数组,数组元素个数就是前一步获取的个数。t_table和t_dump也类似,t_table内含的重要数据是t_sorteddata,而t_sorted结构体自身包含了元素个数,因此读者可根据例1写出输出更完整信息的程序了。返回t_dump类型的函数大部分是窗口数据,从这个意义上插件可以做的和OllyDbg一模一样!

Getstatus

原型:t_statusGetstatus(void)

功能:返回被调试进程的当前状态(STAT_XXX)
返回:
  STAT_NONE
  
  未调试进程
  
  STAT_STOPPED
  
  进程挂起
  
  STAT_EVENT
  
  处理调试事件,进程暂停
  
  STAT_RUNNING
  
  进程运行
  
  STAT_FINISHED
  
  进程结束
  
  STAT_CLOSING
  
  调用TerminateProcess()等待结果
  

例一

#include <windows.h>
#include <stdio.h>
#include "Plugin.h"
#pragma comment(lib,"OllyDbg.lib")
char classname[32];
HINSTANCE hinst=NULL;
class log//用于实现插件日志记录——单例模式
{
private:
        log()
        {
                 try
                 {
                         if(!AllocConsole())
                         {
                                  MessageBox(NULL,"无法创建命令行窗口","错误",MB_OK);
                                  throw "错误";
                         }
                 }
                 catch(...)
                 {
                         exit(0);
                 }
        };
        ~log()
        {
                 FreeConsole();
        }
public:
        static void v(char* tolog)
        {
                 static log obj;
                 HANDLEout=GetStdHandle(STD_OUTPUT_HANDLE);
                 DWORDWriteNum;
                 WriteConsole(out,tolog,strlen(tolog),&WriteNum,NULL);
        }
};
BOOL WINAPI DllMain(HINSTANCE hi,DWORD reason,LPVOID reserved)
{//DLL入口点
        if (reason==DLL_PROCESS_ATTACH)
        {
                 hinst=hi;//保存实例句柄供后面使用
        }
        return 1;
}
LRESULT CALLBACK WndProc(HWND hw,UINT msg,WPARAM wp,LPARAM lp)
{
        return DefWindowProc(hw,msg,wp,lp);//暂时不用这里,因此只写个空架子
}
extc int _export cdecl ODBG_Plugininit(int ollydbgversion,HWND hw,ulong *features)
{
        chartemp[256];
        sprintf(temp,"版本号:%d\n",ollydbgversion);
        log::v(temp);
        if(0 == Registerpluginclass(temp,NULL,hinst,WndProc))
        {
                 log::v("插件注册成功:");
                 log::v(temp);
                 log::v("\n");
        }
        else
        {
                 log::v("插件注册失败\n");
        }
        return 0;
}
extc int _export cdecl ODBG_Plugindata(char shortname[32])
{//用于插件菜单中显示插件名
        strcpy(shortname,"sample1");   
        return PLUGIN_VERSION;
}
extc int _export cdecl ODBG_Pluginshortcut(int origin,int ctrl,int alt,int shift,int key,void *item)
{//按下I键(代表Information)显示OLLYDBG和进程信息
                 if (key!='I')
                         return 0;
                 switch(Getstatus())
                 {
                         case STAT_NONE:
                                  log::v("——————————————未调试进程——————————————\n");
                                  break;
                         case STAT_STOPPED:
                                  log::v("——————————————进程挂起——————————————\n");
                                  break;
                         case STAT_EVENT:
                                  log::v("——————————————进程暂停,处理调试事件——————————————\n");
                                  break;
                         case STAT_RUNNING:
                                  log::v("——————————————进程运行——————————————\n");
                                  break;
                         case STAT_FINISHED:
                                  log::v("——————————————进程结束——————————————\n");
                                  break;
                         case STAT_CLOSING:
                                  log::v("——————————————进程等待关闭——————————————\n");
                                  break;
                 }
                 chartemp[256];
                 sprintf(temp,"OllyDbg实例句柄:0x%0x\n",Plugingetvalue(VAL_HINST));
                 log::v(temp);
                 sprintf(temp,"OllyDbg主窗口句柄:0x%0x\n",Plugingetvalue(VAL_HWMAIN));
                 log::v(temp);
                 sprintf(temp,"被调试进程句柄:0x%0x\n",Plugingetvalue(VAL_HPROCESS));
                 log::v(temp);
                 sprintf(temp,"被调试进程ID%d\n",Plugingetvalue(VAL_PROCESSID));
                 log::v(temp);
                 sprintf(temp,"被调试进程主线程句柄:0x%0x\n",Plugingetvalue(VAL_HMAINTHREAD));
                 log::v(temp);
                 sprintf(temp,"被调试进程主线程ID%d\n",Plugingetvalue(VAL_MAINTHREADID));
                 log::v(temp);
                 sprintf(temp,"被调试进程主模块基址:0x%0x\n",Plugingetvalue(VAL_MAINBASE));
                 log::v(temp);
                 sprintf(temp,"被调试进程名:%s\n",Plugingetvalue(VAL_PROCESSNAME));
                 log::v(temp);
                 sprintf(temp,"被调试进程文件名:%s\n",Plugingetvalue(VAL_EXEFILENAME));
                 log::v(temp);
                 sprintf(temp,"被调试进程当前目录:0x%0x\n",Plugingetvalue(VAL_CURRENTDIR));
                 log::v(temp);
                 sprintf(temp,"系统目录:%s\n",Plugingetvalue(VAL_SYSTEMDIR));
                 log::v(temp);
                 sprintf(temp,"被调试进程主模块基址:0x%0x\n",Plugingetvalue(VAL_MAINBASE));
                 log::v(temp);
};

说明:如第一章所述,用到的OllyDbg-API有Registerpluginclass,Plugingetvalue,Getstatus都要在Plugin.h重新定义。该代码为Windows DLL项目主文件,插件启动后会出现控制台窗口,在加载了进程后,在OllyDbg窗口激活时按下“I”键,会输出类似下面的数据:
版本号:110
插件注册成功:OT_PLUGIN_0000
——————————————进程挂起——————————————
OllyDbg实例句柄:0x400000
OllyDbg主窗口句柄:0x3f1c14
被调试进程句柄:0x3c0
被调试进程ID:6932
被调试进程主线程句柄:0x758
被调试进程主线程ID:10444
被调试进程主模块基址:0x1000000
被调试进程名:RC
被调试进程文件名:D:\Program Files (x86)\Microsoft Visual Studio\Common\MSDev98\
Bin\RC.EXE
被调试进程当前目录:0x4d5c84
系统目录:C:\windows\system32\
被调试进程主模块基址:0x1000000
file:///C:/Users/lichao/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
本例中提供的log类极为有用,因此需要单独提取出来作为一个文件,后面例子只包含log.h即可,不再赘述
回复

使用道具 举报

0

主题

1

回帖

9

积分

用户组: 初·技术宅

UID
813
精华
0
威望
0 点
宅币
8 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2015-4-17
发表于 2015-4-17 11:17:52 | 显示全部楼层
写的很好,帮了很大忙,希望可以继续
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-20 15:07 , Processed in 0.038211 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表