OllyDbg完全教程 自定义函数描述[Custom function descriptions]
2006-06-10 09:03
549 查看
自定义函数描述[Custom function descriptions] 概论[Introduction] OllyDbg包含(做为内部资源)1900多种标准函数以及400多种标准C函数的名称和参数。分析器[Analyzer] 用这些描述使被调试程序更加易懂。比较下面一个例子,分析器的函数CreateFont: PUSH OT.00469F2A ; ASCII "Times New Roman" PUSH 12 PUSH 2 PUSH 0 PUSH 0 PUSH 0 PUSH 0 PUSH 0 MOV EAX,DWORD PTR [49FA70] PUSH EAX PUSH 190 PUSH 0 PUSH 0 PUSH 0 PUSH 10 CALL <JMP.&GDI32.CreateFontA> 这是分析后的: MOV EAX,DWORD PTR [49FA70] PUSH OT.00469F2A ; ?FaceName = "Times New Roman" PUSH 12 ; ?PitchAndFamily = VARIABLE_PITCH|FF_ROMAN PUSH 2 ; ?Quality = PROOF_QUALITY PUSH 0 ; ?ClipPrecision = CLIP_DEFAULT_PRECIS PUSH 0 ; ?OutputPrecision = OUT_DEFAULT_PRECIS PUSH 0 ; ?CharSet = ANSI_CHARSET PUSH 0 ; ?StrikeOut = FALSE PUSH 0 ; ?Underline = FALSE PUSH EAX ; ?Italic => TRUE PUSH 190 ; ?Weight = FW_NORMAL PUSH 0 ; ?Orientation = 0 PUSH 0 ; ?Escapement = 0 PUSH 0 ; ?Width = 0 PUSH 10 ; ?Height = 10 (16.) CALL <JMP.&GDI32.CreateFontA> ; ?CreateFontA 显然,后面的代码更容易理解。API函数CreateFont 有14个参数。分析器标记所有这些参数的名称并解码他们的值。如果寄存器跟踪开启,那么分析器同时会解码参数Italic 的值为地址49FA70处双字长的内容。解码使用参数的真实值,所以如果[49FA70]里的内容改变了,那么参数Italic的值也会随之改变。当EIP指向跳转或调用该函数的命令,或指向入口时,OllyDbg也会在栈中对已知函数的参数进行解码。 OllyDbg可以对像printf()这样参数个数可变的函数进行参数解码: PUSH EAX ; ?<%.*s> PUSH E8 ; ?<*> = E8 (232.) PUSH EBX ; ?<%08X> PUSH Mymodule.004801D2 ; ?format = "Size %08X (%.*s) bytes" PUSH ESI ; ?s CALL Mymodule.sprintf ; ?sprintf 您可以定义自己的函数。每次您打开某个应用程序时,OllyDbg都会重新设置函数参数表并用内嵌描述添充这个表。然后尝试打开文件“<OllyDbg目录>/common.arg”和“<OllyDbg目录>/<应用程序名>.arg”,这里<应用程序名>使用8.3格式(DOS)被调试程序文件名(不带路径和扩展名)。 下面看一个简单的.arg文件实例: INFO Simple .ARG file that decodes CreateHatchBrush TYPE HS_X IF 0 "HS_HORIZONTAL" IF 1 "HS_VERTICAL" IF 2 "HS_FDIAGONAL" IF 3 "HS_BDIAGONAL" IF 4 "HS_CROSS" IF 5 "HS_DIAGCROSS" ELSEINT END TYPE COLORREF IF 0 "<BLACK>" IF 00FFFFFF "<WHITE>" OTHERWISE TEXT "RGB(" FIELD 000000FF UINT TEXT "," FIELD 0000FF00 UINT TEXT "," FIELD 00FF0000 UINT TEXT ")" END STDFUNC CreateHatchBrush "style" HS_X "colorref" COLORREF END 标准Windos API函数CreateHatchBrush(int style,int colorref) 有两个参数。第一个必须是阴影风格[hatch style],第二个是常量由红色、绿色、蓝色组成,并用一个32 位整数的低三字节表示。为了解码这些参数,文件定义了两个新的参数类型:HS_X 和 COLORREF。 阴影风格是一个简单的枚举类型,如0表示HS_HORIZONTAL(水平风格)、1表示HS_VERTICAL(垂直风格)。IF关键字比较参数与第一个操作数(注意:其总是十六进制的),如果相同则显示第二个操作数里的文本。但万一匹配失败会如何?关键字ELSEINT 会然OllyDbg会将参数解释为一个整数。 COLORREF 更复杂一些。首先尝试解码两个广泛使用的颜色值:黑(全0组成)与白(全0xFF组成)。如果匹配失败,COLORREF尝试解码颜色为一个结构包含红、绿、蓝的亮度。FIELD会用第一个操作数与参数进行逻辑与操作。然后转换结果为整数,并同时按位右移第一个操作及该整数,直到第一个操作数的二进制个位数字为1,这时整数按位右移的结果以无符号10进制显示出来。这个例子做了三次这样的操作,以分离出每个颜色成份。TEXT关键字用于无条件显示文本。如果参数为00030201,那么 COLORREF将其解码为RGB(1.,2.,3.)。 大多断API函数都会从栈中移除参数并保护寄存器EBX, EBP, ESI 和 EDI。声明这样的函数为STDFUNC,以告诉分析器该函数做了这样的事情。否则请其描述为FUNCTION 。 万一某个参数由多个域及比特值组成,比如上面提到的fdwPitchAndFamily ,我们该怎么办?请看下面这个例子: TYPE FF_PITCH MASK 03 IF 00 "DEFAULT_PITCH" IF 01 "FIXED_PITCH" IF 02 "VARIABLE_PITCH" ELSEHEX TEXT "|" MASK 0C BIT 04 "4|" BIT 08 "8|" MASK FFFFFFF0 IF 00 "FF_DONTCARE" IF 10 "FF_ROMAN" IF 20 "FF_SWISS" IF 30 "FF_MODERN" IF 40 "FF_SCRIPT" IF 50 "FF_DECORATIVE" ELSEHEX END 前两个比特位(第0和等1位)表示倾斜度,必须一起解码。我们使用 MASK 03 来提取这两个比特并通过IF序列来解码。增加了连接符“|”,分别提取第2和第3个比特位,并分别单独解码。最后提取剩余部分并进行解码。 OllyDbg 会移除生成串尾部的连接符“|”、空格、冒号、逗号、分号和等号。 目前版本的分析仅能够解码32位参数。如您不能解码双精度浮点或长双精度浮点的函数参数。 格式描述 自定义解码信息由函数描述和类型描述两部分组成。函数描述部分非常的简单: FUNCTION|STDFUNC [模块名]函数名 <第一个参数的名称> <第一个参数的类型> …… <最后一个参数的名称> <最后一个参数的类型> END 如果函数从栈中移除参数并保护寄存器EBX, EBP, ESI 和 EDI,请使用关键字STDFUNC。大多少函数都遵循这样的规则。其他情况则声明为FUNCTION。模块(EXE 或 DLL)名是可选的。如果模块名被忽略,OllyDbg会对尝试匹配任何模块。模块名不区分大小写。 函数名称总是区分大小写的。有针对UNICODE的函数必须使用后缀 A 或 W 加以区分,比如SetWindowTextA.。 参数的顺序又C风格的参数使用惯例一致。而16位Windows和32位API函数也是按惯例使用。如果参数名由多个字组成,或者包含特殊字符,那么请将其用两个单引号引起来。与在C语言中一样,省略号(叄┦且桓鎏厥獾募锹加糜诒硎静问靠杀洹K匦朐诤枋龅淖詈蟆llyDbg不会尝试解码这样的参数。如果函数的参数为空,则按functionname(void)对待 OllyDbg 仅支持32位的参数。某些参数已经预定义好了: INT 以十六进制和带符号整数两种格式显示值 UINT 以十六进制和无符号整数两种格式显示值 HEX 以十六进制格式显示值 BOOL TRUE 或 FALSE CHAR ASCII 字符 WCHAR UNICODE 字符 FLOAT 32位浮点数 ERRCODE 系统错误代码(像由函数GetLastError()报告的) ADDR, PTR 地址(特殊情况:NULL) ASCII ASCII 串指针 UNICODE UNICODE 串指针 FORMAT 在类似函数printf()(不包括wscanfW()!)使用的 ASCII 格式串 WFORMAT 类似函数wsprintfW()(不包括scanf()!)使用的 UNICODE 格式串 RECT RECT(矩形)结构指针 MESSAGE MSG(ASCII 窗口消息)结构指针 WMESSAGE MSG(UNICODE 窗口消息)结构指针 HANDLE 句柄(特殊情况:NULL, ERROR_INVALID_HANDLE) HWND 窗口句柄 HMODULE 模块句柄 RSRC_STRING 带索引的资源串 NULL, DUMMY 有参数,但解码时跳过了 您不能重定义预定义类型。自定义类型允许您将参数分离成几个域并分别解码。类型描述有以下几种格式: TYPE 类型名 [TEXT "任何文本"] [<域选择器>] <域解码> <域解码> [TEXT "任何文本"] [PURGE] ... <域选择器> <域解码> <域解码> [TEXT "任何文本"] END 类型名的程度限制在16个字符以内。 OllyDbg会无条件将"任何文本"作为生成的解码。域选择器提取一部分参数用于解码。以下域选择器,可以用于提取域: MASK 十六进制掩码 - 域等于参数同十六进制掩码按位与(AND)的结果。 FIELD 十六进制掩码 - 参数同十六进制掩码按位与(AND)的数值,然后OllyDbg同时按位右移掩码和计算的数值直到掩码的二进制个位为1,这时数值按位右移的结果就是域的值。例如参数0xC250, FIELD F0,得到的结果是5。 SIGFIELD十六进制掩码 -参数同十六进制掩码按位与(AND)的数值,然后OllyDbg同时按位右移掩码和计算的数值直到掩码的二进制个位为1,这时数值按位右移的结果转成带符号32位数就是域的值。例如参数0xC250 ,SIGFIELD FF00,得到的结果是0xFFFFFFC2。 简单域的解码会一次显示整个域的内容: HEX - 以十六进制形式显示域内容; INT - 以带符号十进制形式显示域内容(带小数点); UINT -以无符号十进制形式显示域内容(带小数点); CHAR - 以 ASCII 字符形式显示域内容。 域若是一个枚举类型,则可以使用IF序列,如果必要的话还可以在IF序列后跟关键字 TRYxxx 与 ELSExxx: IF 十六进制值 "文本" - 如果域等于十六进制值,则将文本作为输出字符串; TRYASCII - 如果域是一个指向ASCII串的指针,则显示这个串; TRYUNICODE - 如果域是一个指向UNICODE串的指针,则显示这个串; TRYORDINAL - 如果域是一序号(有16位均为0),则会显示为序号(“#”后跟整数); OTHERWISE - 如果前面IF语句为真,则停止解码,否则继续解码; ELSEINT - 如果前面所有的 IF 和 TRYxxx 语句均失败,则以带符号十进制数形式(带小数点)显示这个域; ELSEHEX -如果前面所有的 IF 和 TRYxxx 语句均为失败,则以十六进制形式显示这个域; ELSECHAR -如果前面所有的 IF 和 TRYxxx 语句均为失败,则以 ASCII 字符形式显示这个域; ELSEWCHAR -如果前面所有的 IF 和 TRYxxx 语句均为失败,则以 UNICODE 字符形式显示这个域。 如果域是一个二进制位集,则可以使用BIT序列,如果必要的话可以后面跟关键字 BITZ 与 BITHEX : BIT 十六进制掩码 "文本" - 如果值与十六进制掩码按位与(AND)的结果不是0,则将文本做为输出串; BITZ十六进制掩码 "文本" - 如果值与十六进制掩码按位与(AND)的结果是0,则将文本做为输出串; BITHEX十六进制掩码 - 如果值与十六进制掩码按位与(AND)的结果不是0,则将结果以十六进制形式显示。 特殊关键字 PURGE 会从输出串尾部移除以下几种符号: 空格 ' ' 逗号 ',' 或 '|' 冒号 ':' 等于 '=' 这会让某些解码情况变的简单。关键字END是类型定义结尾标记并会自动运行PURGE命令。 预编译类型 OllyDbg在预编译资源时,已经包含150多种类型描述。以下列出了一部分。您可以在自定义文件中直接使用这些类型: LANG_X - 操作系统语言ID(0 - 未知、 9 - 语言、 C - 法语,等等) GENERIC_X - 访问类型(GENERIC_READ, GENERIC_WRITE...) FILE_SHARE_X - 共享类型(FILE_SHARE_READ, FILE_SHARE_WRITE) CREATEFILE_X - 文件创建模式(CREATE_NEW, OPEN_EXISTING...) FILE_ATTRIBUTE_X - 文件属性(READONLY, SYSTEM, DELETE_ON_CLOSE...) RT_AXX - 资源类型(RT_CURSOR, RT_GROUP_ICON, ASCII string...) RT_WXX - 资源类型(RT_CURSOR, RT_GROUP_ICON, UNICODE string...) COORD - 坐标结构 "(X=xxx,Y=yyy)" STD_IO_X - 标准句柄(STD_INPUT_HANDLE, STD_ERROR_HANDLE...) GMEM_X - 全局内存类型(GMEM_FIXED, GPTR...) LMEM_X - 局部内存类型(LMEM_FIXED, LPTR...) FSEEK_X - 文件查找类型(FILE_BEGIN, FILE_CURRENT...) OF_X - 文件模式(fOF_READ, OF_SHARE_COMPAT, OF_VERIFY...) O_X - 文件创建模式(O_RDONLY, O_BINARY, SH_COMPAT...) SEMAPHORE_X - 信号量类型(SEMAPHORE_ALL_ACCESS, SYNCHRONIZE...) SLEEP_TIMEOUT - 超时(INFINITE 或时间) ROP - 一些标准柵格运算标志代码(ROP)(SRCCOPY, MERGEPAINT...) COLORREF - RGB 颜色值("<WHITE>", "RGB(rr.,gg.,bb.)"...) WS_X - 窗口风格(WS_OVERLAPPED, WS_POPUP...) WS_EX_X - 扩展窗口风格(WS_EX_DLGMODALFRAME, WS_EX_TOPMOST...) MF_X - 菜单标志(MF_BYPOSITION, MF_ENABLED...) WM_X - ASCII窗口消息类型(WM_CREATE, WM_KILLFOCUS, CB_SETCURSEL...) WM_W - UNICODE窗口消息类型(WM_CREATE, WM_KILLFOCUS, CB_SETCURSEL...) VK_X - 虚拟键盘代码(VK_LBUTTON, VK_TAB, VK_F10...) MB_X - message box style (MB_OK, MB_ICONHAND...) HKEY_X - 预定义注册表句柄(HKEY_CLASSES_ROOT, HKEY_LOCAL_MACHINE...) 还有更多的预编译类型。如果常量在它文件被定义为ABC_ xxxxxxxx,那么一般就有ABC_X预编译类型。 |
相关文章推荐
- OllyDbg完全教程 自定义函数描述[Custom function descriptions]
- OllyDbg完全教程 自定义函数描述[Custom function descriptions]
- [转] ArcGIS自定义工具完全教程 1/2
- MySql DETERMINISTIC log_bin_trust_function_creators 自定义函数执行时报错
- SQL自定义函数function
- SQL中的自定义函数Function
- OllyDbg完全教程 反汇编器[Disassembler]
- DB2 FUNCTION【DB2中增加自定义函数】
- LinkButton OnCommand="function()" 找不到所自定义的函数的错误
- simulink调用自定义函数S-Function
- Python中自定义函数的教程
- OllyDbg完全教程
- Flash8中自定义函数function
- SQL Function 自定义函数
- python基础教程之自定义函数介绍
- PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
- simulink调用自定义函数S-Function
- 创建自定义的EL function(Creating a custom EL function)
- OllyDbg完全教程 分析器[Analysis]
- OllyDbg完全教程 单步执行与自动执行[Step-by-step execution and animation] Hit跟踪[Hit trace]