最近在科锐上课学了如何生成sig文件,研究了一下PAT文件格式,下面是得到的信息,欢迎大家指正。

一、特征码区(前32个字节):
存放的是OBJ文件代码段的前16个机器码,存放机器码的方法如下:
1.  将值的16进制数转换成对应的ASCII码(如:E8 09 --> 45 38 30 39)。
2.  CALL或者Jxx后面跟随的绝对地址、相对地址都不做为特征码,用 2E 即 "." 替代。
3.  如果OBJ文件的机器码少于16字节,用 2E 补齐。
4.  如果OBJ文件的机器码多于16字节,将多余的特征码放入第六部分附加特征码空间中。

二、被忽略的特征码数量(4个字节):
    前后两个字节为空格,用于分隔,中间两个字节表示后面附加特征码空间机器码与前面特征码区中间省略的特征码的长度。最大值为FF。

三、校验码(4个字节):
    对忽略的特征码进行CRC-16校验算法(校验公式为 0x8408 = 216 + 212 + 25 + 1),并将值的16进制数转换成ASCII码填入这4个字节中,下面有校验算法的源码

四、代码段长度(6个字节):
    前后两个字节为空格,用于分隔,中间4个字节表示代码段的长度,以16进制显示。

五、标识符信息(长度不定):
该信息是一个结构体数组,结构体如下:
{
unsigned char[]       标识处偏移行数,以空格结束
unsigned char[]    标识名,以空格结束
}

标识处偏移行数有三种表示方式:
1.  第一个变量以 : 开头,后面接偏移,最后空格结束(如 : 0000 )
2.  如果是标识符则以 : 开头,偏移后面接 @ ,最后空格结束(如 : 004C@ )
3.  如果是函数名、标识符则以 ^ 开头,后面接偏移,最后空格结束(如 ^005B )

六、附加特征码空间(长度不定、可选):
    如果特征码超过32字节,剩余部分减去被忽略的字节数量(即第二部分的值),其他放入这个区域中

七、结束标识(最后7个字节):
0D 0A 2D 2D 2D 0D 0A   ----->   ..---..
标志PAT文件结束


上面是综合性的归纳,下面给两个小例子说明一下(一个是有第六部分的、一个是没有第六部分的):

1、没有第六部分的例子:
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
第一部分: 特征码区,这里只有16字节的机器码
00000000   42 38 30 33 30 30 30 30  30 30 43 33 39 30 39 30   B803000000C39090
00000010   39 30 39 30 39 30 39 30  39 30 39 30 39 30 39 30   9090909090909090
00000020   2E 2E 2E 2E 2E 2E 2E 2E  2E 2E 2E 2E 2E 2E 2E 2E   ................
00000030   2E 2E 2E 2E 2E 2E 2E 2E  2E 2E 2E 2E 2E 2E 2E 2E   ................
第二部分: 被忽略特征码区数量区,这里是0
00000040   20 30 30 20                                         00 
第三部分: 校验码,这里是0
00000040               30 30 30 30                                0000
第四部分: 代码段长度,这里是10H,即是16个字节
00000040                            20 30 30 31 30 20                  0010 
第五部分: 标识符信息,这里只有一个函数名
00000040                                              3A 30                 :0
00000050   30 30 30 20 3F 74 32 40  40 59 41 48 58 5A 20      000 ?t2@@YAHXZ 
第六部分: 这里特征码只有16字节,不用另外的空间存放
第七部分: 结束标识
00000050                                                 0D                  .
00000060   0A 2D 2D 2D 0D 0A                                  .---..

2、有第六部分的例子:
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
第一部分: 特征码区,这里只有32字节的机器码,多余部分放在第六部分处
00000000   35 31 38 44 30 34 32 34  35 30 36 38 2E 2E 2E 2E   518D04245068....
00000010   2E 2E 2E 2E 46 46 31 35  2E 2E 2E 2E 2E 2E 2E 2E   ....FF15........
00000020   38 42 34 43 32 34 30 38  38 33 43 34 30 38 38 44   8B4C240883C4088D
00000030   34 31 46 46 38 33 46 38  30 33 37 37 34 46 46 46   41FF83F803774FFF
第二部分: 被忽略特征码数量区,这里是2
00000040   20 30 32 20                                         02 
第三部分: 校验码,这里是B198
00000040               42 31 39 38                                B198
第四部分: 代码段长度,这里是90H,即是144个字节
00000040                            20 30 30 39 30 20                  0090 
第五部分: 标识符信息,这里有函数名、标识符、跳转标志等
00000040                                              3A 30                 :0
00000050   30 30 30 20 5F 73 73 77  69 74 63 68 20 3A 30 30   000 _sswitch :00
00000060   38 30 40 20 6F 66 66 5F  34 30 31 30 37 43 20 3A   80@ off_40107C :
00000070   30 30 32 36 40 20 6C 6F  63 5F 34 30 31 30 32 36   0026@ loc_401026
00000080   20 3A 30 30 33 38 40 20  6C 6F 63 5F 34 30 31 30    :0038@ loc_4010
00000090   33 37 20 3A 30 30 34 41  40 20 6C 6F 63 5F 34 30   37 :004A@ loc_40
000000A0   31 30 34 38 20 3A 30 30  35 43 40 20 6C 6F 63 5F   1048 :005C@ loc_
000000B0   34 30 31 30 35 39 20 5E  30 30 30 36 20 73 7A 53   401059 ^0006 szS
000000C0   74 72 20 5E 30 30 30 43  20 73 63 61 6E 66 20 5E   tr ^000C scanf ^
000000D0   30 30 32 37 20 63 61 73  65 31 20 5E 30 30 32 44   0027 case1 ^002D
000000E0   20 70 72 69 6E 74 66 20  5E 30 30 33 39 20 63 61    printf ^0039 ca
000000F0   73 65 32 20 5E 30 30 34  42 20 63 61 73 65 33 20   se2 ^004B case3 
00000100   5E 30 30 35 44 20 63 61  73 65 34 20 5E 30 30 36   ^005D case4 ^006
00000110   46 20 64 65 66 61 75 6C  74 20                     F default 
第六部分: 剩余代码区
00000110                                  2E 2E 2E 2E 2E 2E             ......
00000120   2E 2E 36 38 2E 2E 2E 2E  2E 2E 2E 2E 46 46 31 35   ..68........FF15
00000130   2E 2E 2E 2E 2E 2E 2E 2E  38 33 43 34 30 34 33 33   ........83C40433
00000140   43 30 35 39 43 33 36 38  2E 2E 2E 2E 2E 2E 2E 2E   C059C368........
00000150   46 46 31 35 2E 2E 2E 2E  2E 2E 2E 2E 38 33 43 34   FF15........83C4
00000160   30 34 33 33 43 30 35 39  43 33 36 38 2E 2E 2E 2E   0433C059C368....
00000170   2E 2E 2E 2E 46 46 31 35  2E 2E 2E 2E 2E 2E 2E 2E   ....FF15........
00000180   38 33 43 34 30 34 33 33  43 30 35 39 43 33 36 38   83C40433C059C368
00000190   2E 2E 2E 2E 2E 2E 2E 2E  46 46 31 35 2E 2E 2E 2E   ........FF15....
000001A0   2E 2E 2E 2E 38 33 43 34  30 34 33 33 43 30 35 39   ....83C40433C059
000001B0   43 33 36 38 2E 2E 2E 2E  2E 2E 2E 2E 46 46 31 35   C368........FF15
000001C0   2E 2E 2E 2E 2E 2E 2E 2E  38 33 43 34 30 34 33 33   ........83C40433
000001D0   43 30 35 39 43 33 2E 2E  2E 2E 2E 2E 2E 2E 2E 2E   C059C3..........
000001E0   2E 2E 2E 2E 2E 2E 2E 2E  2E 2E 2E 2E 2E 2E 2E 2E   ................
000001F0   2E 2E 2E 2E 2E 2E                                  ......
第七部分: 结束标识
000001F0                     0D 0A  2D 2D 2D 0D 0A                  ..---..

这里两个例子的OBJ文件以及PAT文件我会在附件中给出,另外CRC校验码算法(pcf文件夹中已经提供)也一起给出。
呃……看来我权限不足哈,等我权限够了再上传......

这里还有一个问题没有跟出算法,不知谁有好的解决方法:
第二部分的被忽略的特征码是按照什么规律忽略的?