起因:調試A程序有很多斷點、註釋之類的,後來A程序變動成B程序,體積也變化了,但是之前操作的地址沒有什麼變化,這個時候,UDD文件就不能用了,豈不是浪費xi gan?
提醒:以下結構是其中一部分,因爲用到了這些所以分析了這些,還有一些未標註的,大家可以自己對應。
PS:如上想重新使用A程序的UDD文件,只需要修改UDD文件的頭部幾個字段即可。 // 前提是 沒有ASLR類似操作
// 0x0A 可以作爲結束,也可以作爲Signature的一部分。 我分析的時候和別人不一樣。。。
DWORD dwSignature; // Mod
DWORD dwSize; // data長度
BYTE byData[0x17]; // 長度 = 0x15 + '0'; 後邊有一個0A
BYTE byVerSignature[0x3]; // "Ver"
DWORD dwVerLength; // Ver的長度
BYTE* pbyVerBuffer; // Ver的字符串(長度爲dwVerLength+1)
BYTE byFileSignature[0x3]; // "Fil"
DWORD dwFileLength; // 文件路徑長度
BYTE* pbyFileName; // 文件路徑字符串(長度爲dwFileLength+1)
BYTE bySizeSignature[0x3]; // "Siz"
DWORD dwSizeLength; // Siz長度
BYTE* pbySizeBuffer; // Siz內容(長度爲dwSizeLength+1)
BYTE byTstSignature[0x3]; // "Tst"
DWORD dwTstLength; // Tst長度
BYTE* pbyTstBuffer; // Tst內容(長度爲dwTstLength+1)
BYTE byCcrSignature[0x3]; // "Ccr"
DWORD dwCcrLength; // Ccr長度
BYTE* pbyCcrBuffer; // Ccr內容(長度爲dwCcrLength+1)
// 下面是若干個 "Us6" - 用戶自定義註釋
BYTE byUs6Signature[0x3]; // "Us6"
DWORD dwUs6Length; // Us6長度
DWORD dwUs6Offset; // 自定義註釋的偏移(需要加上基地址)
BYTE* pbyUs6Buffer; // Us6內容(長度爲dwUs6Length-4+1)
// 下面是若干個 "Us:" - OD識別添加的註釋
BYTE byUsSignature[0x3]; // "Us:"
DWORD dwUsLength; // Us長度
DWORD dwUsOffset; // 註釋的偏移(需要加上基地址)
BYTE* pbyUsBuffer; // Us內容(長度爲dwUsLength-4+1)
// 下面 Usv, 註釋, 但是貌似中間是序號,無法定位,暫不用
// 下面 UsB, 指令, 但是貌似中間是序號,無法定位,暫不用
// 下面是若干個 "Us9" - OD識別添加的參數信息,特殊標記,謹慎使用
BYTE byUs9Signature[0x3]; // "Us9"
DWORD dwUs9Length; // Us9長度
DWORD dwUs9Offset; // 參數信息的偏移(需要加上基地址)
BYTE* pbyUs9Buffer; // Us9內容(長度爲dwUs9Length-4+1)
// 下面是若干個 "Us>" - OD識別添加跳轉信息,沒有跳轉也有標記,謹慎使用
BYTE byUsJSignature[0x3]; // "Us>"
DWORD dwUsJLength; // UsJ長度
DWORD dwUsJOffset; // 跳轉地址的偏移(需要加上基地址)
BYTE* pbyUsJBuffer; // UsJ內容(長度爲dwUsJLength-4+1)
// 下面 Us?, 作用未知,暫不用
// 下面是若干個 "Prc" - OD識別添加CALL信息
BYTE byPrcSignature[0x3]; // "Prc"
DWORD dwPrcLength; // Prc長度
DWORD dwPrcOffset; // CALL地址的偏移(需要加上基地址)
BYTE* pbyPrcBuffer; // Prc內容(長度爲dwPrcLength-4+1)
// 下面是若干個 "Swi" - OD識別添加Switch信息
BYTE bySwiSignature[0x3]; // "Swi"
DWORD dwSwiLength; // Swi長度
DWORD dwSwiOffset; // Switch地址的偏移(需要加上基地址)
BYTE* pbySwiBuffer; // Swi內容(長度爲dwSwiLength-4+1)
// 下面是若干個 "Cfm" - OD識別添加,有名稱的函數調用
BYTE byCfmSignature[0x3]; // "Cfm"
DWORD dwCfmLength; // Cfm長度
DWORD dwCfmOffset; // 地址的偏移(需要加上基地址)
BYTE* pbyCfmBuffer; // Cfm內容(長度爲dwCfmLength-4+1)
// Cfm的內容前四個字節是RVA,後邊是Module的名稱
// 下面是若干個 "Cfa" - OD識別添加,寄存器函數調用
BYTE byCfaSignature[0x3]; // "Cfa"
DWORD dwCfaLength; // Cfa長度
DWORD dwCfaOffset; // 地址的偏移(需要加上基地址)
BYTE* pbyCfaBuffer; // Cfa內容(長度爲dwCfaLength-4+1)
// 下面是若干個 "Cfi" - CALL 立即數
BYTE byCfiSignature[0x3]; // "Cfi"
DWORD dwCfiLength; // Cfi長度
DWORD dwCfiOffset; // 地址的偏移(需要加上基地址)
BYTE* pbyCfiBuffer; // Cfi內容(長度爲dwCfiLength-4+1)
// Cfi的內容一般函數的RVA
// 下面是若干個 "Bpc" - 斷點
BYTE byBpcSignature[0x3]; // "Bpc"
DWORD dwBpcLength; // Bpc長度
DWORD dwBpcOffset; // 地址的偏移(需要加上基地址)
BYTE* pbyBpcBuffer; // Bpc內容(長度爲dwBpcLength-4+1)
// Bpc的buffer中有 斷點類型 + 斷點的原字節碼
// 下面是若干個 "Jdt" - 大結構,作用未知
BYTE byJdtSignature[0x3]; // "Jdt"
DWORD dwJdtLength; // Jdt長度
BYTE* pbyJdtBuffer; // Jdt內容(長度爲dwJdtLength+1)
// 下面是若干個 "Anc" - 大結構,作用未知
BYTE byAncSignature[0x3]; // "Anc"
DWORD dwAncLength; // Anc長度
BYTE* pbyAncBuffer; // Anc內容(長度爲dwAncLength+1)
// 下面是若干個 "Sva" - 作用未知
BYTE bySvaSignature[0x3]; // "Sva"
DWORD dwSvaLength; // Sva長度
BYTE* pbySvaBuffer; // Sva內容(長度爲dwSvaLength+1)
// 下面是若干個 "Pat" - 作用未知
BYTE byPatSignature[0x3]; // "Pat"
DWORD dwPatLength; // Pat長度
BYTE* pbyPatBuffer; // Pat內容(長度爲dwPatLength+1)
DWORD dwEndSignature; // 0x646E450A
DWORD dwZero; // 0x0
------------------ 華麗的分割線 -------------------------------------
// 下面是我在分析的時候找到的資料,忘了出處了,非常抱歉哈
.UDD (User-Defined Data) file consists of unaligned variable-length records.
Each record has the following format:
#define MI_SIGNATURE 0x00646F4DL // Module info signature
#define MI_FILENAME 0x6C69460AL // Record with full path of executable
#define MI_FILESIZE 0x7A69530AL // Record with file size
#define MI_TIMESTAMP 0x7473540AL // Record with timestamp file data
#define MI_USER 0x0073550AL // User data record (ORed with NM_xxx)
#define MI_INT3BREAK 0x7470420AL // Record with breakpoint data
#define MI_INT3BRKC 0x6370420AL // Record with checked breakpoint data
#define MI_ANALYSIS 0x616E410AL // Record with analysis data
#define MI_ANALPACK 0x636E410AL // Record with compressed analysis data
#define MI_CODECRC 0x7263430AL // Record with CRC of code for analysis
#define MI_SAVEAREA 0x6176530AL // Record with general-purpose save area
#define MI_END 0x646E450AL // End of module info data
struct t_record {
long tag; // Unique tag (MI_xxx) identifying record type
long size; // Size of data, bytes (may be 0)
char data[size]; // Data itself
};
(Try to read tags as ASCII text). File must begin with MI_SIGNATURE record
containing 22-byte string "Module info file v1.1\0". All other records are
optional. If OllyDbg doesn't know the meaning of the record, it simply ignores
it. This assures backward compatibility: breakpoints set by v1.02, for example,
will appear in OllyDbg v1.00.
MI_FILENAME contains full path to the file.
MI_FILESIZE contains 32-bit file size. (I haven't heard yet about .exe or .dll
that is longer than 4G bytes).
MI_TIMESTAMP is formed as follows:
FILETIME tlastwrite;
// Get timestamp (time of last update) and size of executable file.
hf=CreateFile(pmod->path,0,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hf==INVALID_HANDLE_VALUE)
return; // Unable to query executable file
GetFileTime(hf,NULL,NULL,&tlastwrite);
filesize=GetFileSize(hf,NULL); // Here you has file size for MI_FILESIZE
CloseHandle(hf);
Saverecord(f,MI_TIMESTAMP,sizeof(tlastwrite),&tlastwrite);
For you, the most important record is MI_USER. I use it to save all types of
user data that are text. Size of data in MI_USER+xx records never exceeds 260
bytes (including terminal '\0'). I don't use MI_USER directly; instead, it is
ORed with type of user data (NM_XXX) shifted 24 bits to the left (so NM_XXX
comes into the most significant byte of the tag).
#define NM_LABEL 0x31 // User-defined label
#define NM_EXPORT 0x32 // Exported (global) name
#define NM_IMPORT 0x33 // Imported name
#define NM_LIBRARY 0x34 // Name from library or object file
#define NM_CONST 0x35 // User-defined constant
#define NM_COMMENT 0x36 // User-defined comment
#define NM_LIBCOMM 0x37 // Comment from library or object file
#define NM_BREAK 0x38 // Condition related with breakpoint
#define NM_ARG 0x39 // Arguments decoded by analyser
#define NM_ANALYSE 0x3A // Comment added by analyser
#define NM_BREAKEXPR 0x3B // Expression related with breakpoint
#define NM_BREAKEXPL 0x3C // Explanation related with breakpoint
#define NM_INSPECT 0x40 // Several last inspect expressions
#define NM_WATCH 0x41 // Watch expressions
#define NM_ASM 0x42 // Several last assembled strings
#define NM_FINDASM 0x43 // Several last find assembler strings
#define NM_LASTWATCH 0x48 // Several last watch expressions
#define NM_SOURCE 0x49 // Several last source search strings
#define NMHISTORY 0x40 // Converts NM_xxx to type of init list
struct t_midata {
long offset; // Offset of symbol from the beginning of the module
char sztext[size-4]; // Zero-terminated symbolic name, 256 bytes max
};
Following user data types are associated with some module and can appear in any
.udd file:
NM_LABEL, // User-defined label
NM_LIBRARY, // Name extracted by object scanner
NM_COMMENT, // User-defined comment
NM_LIBCOMM, // Comment generated by object scanner
NM_BREAK, // Condition related with breakpoint
NM_BREAKEXPR, // Expression related with breakpoint
NM_BREAKEXPL, // Explanation related with breakpoint
NM_ANALYSE, // Comment added by analyser
NM_ARG // Decoding of known function
.udd file of main module (.exe) also keeps watch expressions and history lists
(they appear if you open pull-down window of the combobox). For this data,
offset field is simply a 1-based ordinal:
NM_LABEL | NMHISTORY, // List of last entered labels
NM_COMMENT | NMHISTORY, // List of last entered comments
NM_BREAK | NMHISTORY, // List of last entered break conditions
NM_BREAKEXPR | NMHISTORY, // List of last break expressions
NM_BREAKEXPL | NMHISTORY, // List of last break explanations
NM_INSPECT, // Inspect expressions
NM_WATCH, // Watch expressions
NM_ASM, // Several last assembled strings
NM_FINDASM, // Several last find assembler strings
NM_LASTWATCH, // Several last watch expressions
NM_SOURCE // Several last source search strings
When OllyDbg encounters MI_END, it stops file processing.
------------------------------------------------------------------------------------------------------------------------------------
V1.0 from od plugin.h
// Record tags in .udd files.
#define MI_SIGNATURE 0x00646F4DL // Module info signature
#define MI_VERSION 0x7265560AL // OllyDbg version
#define MI_FILENAME 0x6C69460AL // Record with full name of executable
#define MI_FILESIZE 0x7A69530AL // Record with file size
#define MI_TIMESTAMP 0x7473540AL // Record with timestamp file data
#define MI_SFXENTRY 0x6566530AL // Real entry of SFX-able module
#define MI_PATCH 0x7461500AL // Record with patch data
#define MI_USER 0x0073550AL // Record with user-defined label/comment
#define MI_PROCDATA 0x6372500AL // Record with procedure data
#define MI_SWDATA 0x6977530AL // Record with switch data
#define MI_CALLFINT 0x6966430AL // Record with internal call (前四個字節Caller,後四個字節Call)
#define MI_CALLFMOD 0x6D66430AL // Record with intermodular call
#define MI_CALLFABS 0x6166430AL // Record with absolute call
#define MI_INT3BREAK 0x7470420AL // Record with breakpoint data
#define MI_INT3BRKC 0x6370420AL // Record with checked breakpoint data
#define MI_HDWRBREAK 0x7262480AL // Record with hardware breakpoint data
#define MI_JDDATA 0x74644A0AL // Record with all module jump data
#define MI_ANALYSIS 0x616E410AL // Record with analysis data
#define MI_ANALPACK 0x636E410AL // Record with compressed analysis data
#define MI_AHINT 0x7468410AL // Record with analysis hint data
#define MI_TRACE 0x6172540AL // Record with trace data
#define MI_TRACEPACK 0x6372540AL // Record with compressed trace data
#define MI_CODECRC 0x7263430AL // Record with CRC of code for analysis
#define MI_SAVEAREA 0x6176530AL // Record with general-purpose save area
#define MI_END 0x646E450AL // End of module info data
// Tags reserved for 3rd-party plugins.
#define MI_WINJUG 0x67754A0AL // WindowJuggler by EsseEmme
#define MI_WINJU1 0x31754A0AL
#define MI_WINJU2 0x32754A0AL
#define MI_WINJU3 0x33754A0AL
#define MI_APPST 0x73614F0AL // OllyAppStarter by Homunculus
// Types of names used in name functions. Note that higher-priority types have
// smaller identifiers!
#define NM_NONAME 0x00 // Undefined name
#define NM_ANYNAME 0xFF // Name of any type
// Names saved in the data file of module they appear.
#define NM_PLUGCMD 0x30 // Plugin commands to execute at break
#define NM_LABEL 0x31 // User-defined label
#define NM_EXPORT 0x32 // Exported (global) name
#define NM_IMPORT 0x33 // Imported name
#define NM_LIBRARY 0x34 // Name from library or object file
#define NM_CONST 0x35 // User-defined constant
#define NM_COMMENT 0x36 // User-defined comment
#define NM_LIBCOMM 0x37 // Comment from library or object file
#define NM_BREAK 0x38 // Condition related with breakpoint
#define NM_ARG 0x39 // Arguments decoded by analyzer
#define NM_ANALYSE 0x3A // Comment added by analyzer
#define NM_BREAKEXPR 0x3B // Expression related with breakpoint
#define NM_BREAKEXPL 0x3C // Explanation related with breakpoint
#define NM_ASSUME 0x3D // Assume function with known arguments
#define NM_STRUCT 0x3E // Code structure decoded by analyzer
#define NM_CASE 0x3F // Case description decoded by analyzer
// Names saved in the data file of main module.
#define NM_INSPECT 0x40 // Several last inspect expressions
#define NM_WATCH 0x41 // Watch expressions
#define NM_ASM 0x42 // Several last assembled strings
#define NM_FINDASM 0x43 // Several last find assembler strings
#define NM_LASTWATCH 0x48 // Several last watch expressions
#define NM_SOURCE 0x49 // Several last source search strings
#define NM_REFTXT 0x4A // Several last ref text search strings
#define NM_GOTO 0x4B // Several last expressions to follow
#define NM_GOTODUMP 0x4C // Several expressions to follow in Dump
#define NM_TRPAUSE 0x4D // Several expressions to pause trace
// Pseudonames.
#define NM_IMCALL 0xFE // Intermodular call
#define NMHISTORY 0x40 // Converts NM_xxx to type of init list
結束!
如果有什麼問題,歡迎留言討論。