模板头的格式:
template "title"
[description "description"]
[applies_to (file/disk/RAM)]
[fixed_start offset]
[sector-aligned]
[requires offset "hex values"]
[big-endian]
[hexadecimal/octal]
[read-only]
[multiple [fixed overall size]]
// Put any general comments to the template here.
begin
variable declarations
end
在方括号里的标签表示为可选项。标签的顺序没有硬性的规定,用户可以随意的更改他们的顺序。表达式中如果有空格则必须用双引号括起来。模板文件中的注释以为双斜杠开头。
关键字“applies_to”后必须跟着“file,disk,或RAM”中的一个。模板应用于不同的介质的时候,winhex将发出错误警告。
默认的情况下,模板将从窗口中光标的位置处执行,使用“fixed_start”选项将让模板从磁盘或文件的偏移量的绝对开头处运行。
应用于磁盘的模板,关键字“sector-aligned”将让模板从当前扇区的开头处运行,而忽略光标的当前位置。
关键字“requires”同“applies_to”的功能类似,都是为了避免模板定义的数据和应用程序的数据不匹配而引发的错误。可以利用“requires”事先指定好特征码。比如,一个有效的主引导扇区偏移量0x1FE位置必须为“55 AA”(也就是扇区的最后两个字节),而一个有效的可执行文件在偏移量0x0位置必须为“4D 5A”(“MZ”)。模板头中可以定义多行“ applies_to”。
关键字“big-endian”使模板中读到的字节以big-endian顺序排列(高位字节开头,intel平台中一般都是little-endian,苹果机中通常为big-endian,在windows下分析mac文件可能会用到此关键字)
关键字“hexadecimal”使模板中独到的数据都以16进制方式显示。
关键字“read-only”使模板执行后显示的模板面板为只读模式,不可通过模板面修改数据。
关键字“multiple”可以让模板直接读取临近的数据的数据结构(只适用于数据大小固定的情况下)。(可以参考winhex下的“FAT Directory Entry”模板)
2 主干:变量申明
模板文件的主干部分同其他编程语言一样,主要由变量申明组成。申明的基础形式如下:
type "title"
类型可以是以下类型的任意一种:
int8, uint8 = byte, int16, uint16, int24, uint24, int32, uint32, int64,
uint_flex
binary,
float = single, real, double, longdouble = extended,
char, char16, string, string16, zstring, zstring16,
boole8 = boolean, boole16, boole32
hex,
DOSDateTime, FileTime, OLEDateTime, SQLDateTime, UNIXDateTime = time_t, JavaDateTime
如果“title”包括空格就必须使用双引号括起来(“title”不能全都是数字,并且“title”部分大小写不敏感)。最多可以包含41个字符。
“type”部分至少可以使用下列的一个关键字来修饰:
big-endian little-endian
hexadecimal decimal octal
read-only read-write
这些关键字会直接作用于其后的变量。如果他们在头部已经定义过了,那么在主干部分再重复定义就显的多余了。(在头部定义后作用于全局)
在“type”之后的数字表示变量的长度(数值则为字节,字符串则为字符,在模板中可编辑的长度最多为8192个字节)。在winhex中使用“char16”,“string16”以及“hex”可以支持使用unicode字符和字符串,但不支持unicode字符开头的256个ANSI字符。
“string”,“string16”以及“hex”类型
The types string, string16, and hex require an additional parameter that specifies the
number of elements. This parameter may be a constant or a previously declared variable. If it is a
constant, it may be specified in hexadecimal format, which is recognized if the number is
preceded by 0x.
用户可以申明一个将数组变量,并且将数组变量的大小放在后面的方括号里(如果指定为“unlimited”,则模板会执行直到文件结尾处)。以下两行代码申明了一个动态的ASCII字符串,其长度取决于之前的变量大小:
uint8 "len"
char[len] "A string"
以下两句功能相同
byte "len"
string len "A string"
字符“~”表示数组编号的占位符(请看下面)。这个字符对“char”数据类型的变量无效,因此会自动的解析成字符串类型。
string,string16和hex类型的变量大小,可以通过数学表达式来表示,数学表达式需要用括号括起来,并且表达式中不能包含空格。同样也可以将变量带入数学表达式中(同样变量名不能有空格)。支持的操作有,加法(+),减法(-),乘法(*),整除(/),模除(%),逻辑运算符AND(&),OR(|),以及XOR(^)。比如:(5*2+1),(len1/(len2+4))。注意:结果必须为正整数。
3 主干:高级命令
当我们用大括号将一个代码块设置循环运行时,我们可以用占位符“~”来确定循环的次数,下列代码中“numbering”定义了初始值为1(默认为0)。
numbering 1
{
byte "len"
string len "String No. ~"
}[10]
上面代码在模板中的运行结果将显示:“String No. 1”, “String No. 2”...“String No. 10”。用户可以使用“unlimited”代替方括号中的10,这样winhex就会循环执行直到文件结尾部分。或者使用“ExitLoop”强迫循环终止。
在比较两个值是否相等方面,winhex模板给出了一个非常有用的命令“IfEqual”。“IfEqual”操作的两个表达式可以是10进制常量,整数变量或数学表达式,或者字符串(文本或16进制值(winhex将逐字节的进行比较))。ASCII字符串必须用双引号括起来。而16进制数必须用“0x”开头。公式需要用括号括起来。
{
byte Value
IfEqual Value 1
ExitLoop
EndIf
} [10]
“IfEqual”命令以“EndIf”语句作为结尾。如果表达式的值是相同的则继续运行。还可以在语句中插入“Else”语句,这样当“IfEqual”的两个表达式不相同时,跳转到“Else”下继续执行。“IfEqual”语句不可以镶套使用。“IfGeater”语句和“IfEqual”的用法相似。只是“IfGeater”是用来比较第一个表达式的值是否大于第二个表达式的值。字符串和16进制值将按照字典顺序排列。
为了方便阅读和查看模板文件,你可以将某些变量捆绑为一组,单独的显示在模板面板上:
section "...Section Title..."
...
endsection
“move”和“goto”命令不用来申明变量,但是可以精确的改变当前位置,跳过无关的数据。使用move n语句可以从当前位置条国n个字节到下一个位置,n可以为负值(正即向前跳,负即向后跳)。而goto n语句中的n则表示了从模板开始解释的地方到n的绝对位置(此时的n必须为正数)
下面的例子演示了如何将一个变量作为整数和16进制数值查看的方法:
int32 "Disk serial number (decimal)"
move -4
hex 4 "Disk serial number (hex)"
4 主干:灵活的整数变量
winhex模板支持的一个特殊的变量类型是“uint_flex”。