通过上一节的处理,我们拿到了asn1码流,这节我们将使用CodeMeterLin中asn1的定义进行更加有效的解析。
在wibu软授权系统中,大部分相关的数据都是使用asn1编码的,所以
ASN全称为Abstract Syntax Notation dotone,是定义抽象数据类型形式的标准,描绘了与任何表示数据的编码技术无关的通用数据结构,目前只定义一个版本(ASN.1)。ASN.1有四种类型:
除CHOICE和ANY外,每种ASN.1类型都有一个标签,该标签由一个类型号(class)和一个非负标签号(tag)组成。当且仅当它们的标签号相同时,ASN.1类型才抽象地相同。换句话说,ASN.1类型的名称不会影响其抽象含义,只有标签会影响它的抽象含义。
上述是asn1的描述,其中最关键的是每种asn1类型都有一个标签值这句话,这意味者我们通过标签值反过来找到asn1的定义。
ber编码是asn1中最基础一种的编码方式,它传输格式是TLV(Tag-Length-Value)三元组。
bits结构如下图所示:
2 bit | 1 bit | 5 bit |
---|---|---|
class | p/s | tagv |
class用于表示tagv所在的类属,分为以下四类
Universal
,asn1中最基础的类型都属于这个类属,如BOOLEAN
、INTEGER
,除该类属外,其他类属都是复合类型。Application
,特定于应用程序的类型都属于这个类属,目前已不推荐使用。Private
,特定于特定企业的类型都属于这个类属,本次分析的码流使用了该类属下的多个类型。Context-specific
,特定于特定结构化的类型都属于这个类属,用于标记特定的上下文,不同的上下文可能具有相同的tagv但其含义不同,在本次分析的码流也会出现这种情况。p/s用于表示TLV中的V是否为嵌套的TVL结构,当p/s为1时,表示存在嵌套。
tagv为具体的标签值,有效值为0-30,当tagv=31时,表示标签值使用长码表示,后面跟着的八元组为具体的标签值,直到八元组的最高bit不为0为止,此时八元组的最高位用于指示长码是否结束。
length表示TLV中的V的长度,不包含T和L的长度。
当length=0x80时,表示V为不定长数据,V最后要以两个00结尾。
当length=0x8?时,表示length使用长码,低7位表示长码的八元组数量。
当length为其他值时,表示length使用短码,该八元组就是具体长度。
value为TLV结构中的具体数据,该数据既可以是表示特定内容的数据,也可以嵌套的TLV结构。根据tag的不同,Value有着不同的表现形式。
默认情况下,大部分的asn1定义最终都是由Universal
类属中的基础类型定义。
当使用EXPLICIT
和IMPLICIT
关键字修饰时,表示使用中括号[]中指定的tag来描述该定义。
EXPLICIT
和IMPLICIT
关键字的区别在于,前者直接使用中括号[]中的tag的替换原数据的tag,后者在原数据前额外增加新的tag,而原来的tag保留不变。
EXPLICIT
和IMPLICIT
关键字默认使用Context-specific
作为cls,此外,可以通过PRIVATE
和APPLICATION
显示指定cls。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# !/usr/bin/env python3
# -*- coding:utf-8 -*-
import
asn1tools
asn_def
=
"TEST DEFINITIONS ::= BEGIN\n"
\
"Test ::= SEQUENCE\n"
\
"{\n"
\
"val1 INTEGER,\n"
\
"val2[0] IMPLICIT INTEGER,\n"
\
"val3[1] EXPLICIT INTEGER,\n"
\
"val4[PRIVATE 2] IMPLICIT INTEGER,\n"
\
"val5[PRIVATE 3] EXPLICIT INTEGER\n"
\
"}\n"
\
"END"
asn_def
=
asn1tools.compile_string(asn_def,
"der"
)
asn_res
=
asn_def.encode(
"Test"
, {
"val1"
:
10
,
"val2"
:
10
,
"val3"
:
10
,
"val4"
:
10
,
"val5"
:
10
})
print
(asn_res.
hex
().upper())
|
python .\test_asn.py
301302010A80010AA10302010AC2010AE30302010A30 13 #cls=0(Universal) tag=16(SEQUENCE) len=19
02 01 0A #正常情况:cls=0(Universal) tag=2(INTEGER) len=1 data=10
80 01 0A #加IMPLICIT修饰符并使用tag=0描述该定义:cls=2(Context-specific) tag=0 len=1 data=10
A1 03 #加EXPLICIT修饰符,在原来的数据前额外添加tag:cls=2(Context-specific) tag=1 len=3
02 01 0A #与正常情况的数据相同,cls=0(Universal) tag=2(INTEGER) len=1 data=10
C2 01 0A #同时指定cls和tag,cls=3(Private) tag=2 len=1 data=10
E3 03 #cls=3(Private) tag=3 len=3
02 01 0A #与正常情况的数据相同,cls=0(Universal) tag=2(INTEGER) len=1 data=10
这里先放上一节的流程图,在sub_77A950
中可以看到asn1码流的解析。
每个asn1类型被定义为一个结构体节点,一开始是无法准确地知道每个字段的含义。通过相关查找,确认这些节点都是在github上的开源代码中定义。于是,我们对这些asn1节点有了较为清晰的了解。
通过观察asn1结构体节点,可以发现一般情况下,name字段和xml_tag字段指向同一个字符串,并且所有的节点都在data段内。我们可以在data段找两个即相邻又相同的指针,并且该指针指向的内容同样在data段内。节点之间通过elements字段关联,利用elements,我们可以为这些节点建立树状关系或层级关系,甚至可以恢复出整个asn1定义。下图LIF的asn1定义。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
LIF
-
CONTENT DEFINITIONS ::
=
BEGIN
LIF
-
Content ::
=
[PRIVATE
228
] IMPLICIT SEQUENCE
{
sw
-
specs[PRIVATE
161
] IMPLICIT Software
-
Specs,
clocks[PRIVATE
100
] IMPLICIT Clocks,
license
-
description[PRIVATE
125
] IMPLICIT License
-
Description,
binding[PRIVATE
136
] IMPLICIT Binding
-
Scheme,
cmact
-
options[PRIVATE
133
] IMPLICIT CmAct
-
Options,
mask[PRIVATE
142
] IMPLICIT Mask OPTIONAL
}
Software
-
Specs ::
=
SEQUENCE
{
creator
-
name[PRIVATE
181
] IMPLICIT UTF8String,
creator
-
version[PRIVATE
165
] IMPLICIT
Format
-
Version,
required
-
version[PRIVATE
122
] IMPLICIT
Format
-
Version
}
Format
-
Version ::
=
SEQUENCE
{
sfl[PRIVATE
78
] IMPLICIT UInt8,
sfh[PRIVATE
84
] IMPLICIT UInt8,
feature
-
flags[PRIVATE
32
] IMPLICIT UInt32
}
UInt8 ::
=
[PRIVATE
31
] IMPLICIT INTEGER
UInt32 ::
=
[PRIVATE
34
] IMPLICIT INTEGER
Clocks ::
=
SEQUENCE
{
box
-
time[PRIVATE
178
] IMPLICIT Seconds
-
Since
-
2000
,
certified
-
time[PRIVATE
179
] IMPLICIT Seconds
-
Since
-
2000
}
Seconds
-
Since
-
2000
::
=
INTEGER
License
-
Description ::
=
SEQUENCE
{
license
-
description[PRIVATE
30
] IMPLICIT OCTET STRING,
-
-
BMPString, it does't work well
in
asn1tools, beacase asn1tools only support utf
-
8
, but here
is
utf
-
16
firm
-
code[PRIVATE
114
] IMPLICIT Firm
-
Code
}
Firm
-
Code ::
=
INTEGER
Binding
-
Scheme ::
=
SEQUENCE
{
cmact
-
id
[PRIVATE
148
] IMPLICIT CmAct
-
ID
,
telephone
-
id
[PRIVATE
127
] IMPLICIT Telephone
-
ID
,
binding
-
method[PRIVATE
128
] EXPLICIT Binding
-
Method
}
CmAct
-
ID
::
=
IA5String
Telephone
-
ID
::
=
INTEGER
Binding
-
Method ::
=
CHOICE
{
smartbind[PRIVATE
129
] IMPLICIT SmartBind
-
Parameters,
custom
-
binding[PRIVATE
131
] IMPLICIT CustomBinding
-
Parameters,
dcbn
-
classic[PRIVATE
132
] IMPLICIT DCBN
-
Parameters,
nonebind[PRIVATE
231
] IMPLICIT NULL,
cm
-
server
-
ip[PRIVATE
232
] IMPLICIT NULL,
serial
-
number[PRIVATE
233
] IMPLICIT NULL,
random[PRIVATE
234
] IMPLICIT NULL
}
SmartBind
-
Parameters ::
=
SEQUENCE
{
heuristic[PRIVATE
31
] IMPLICIT UInt8,
redundancy
-
level[PRIVATE
130
] IMPLICIT Redundancy
-
Level
}
Redundancy
-
Level ::
=
INTEGER
CustomBinding
-
Parameters ::
=
IA5String
DCBN
-
Parameters ::
=
SEQUENCE
{
disk[PRIVATE
1
] IMPLICIT BOOLEAN,
cpu
-
type
[PRIVATE
1
] IMPLICIT BOOLEAN,
board[PRIVATE
1
] IMPLICIT BOOLEAN,
network[PRIVATE
1
] IMPLICIT BOOLEAN,
tolerance[PRIVATE
2
] IMPLICIT UInt8 OPTIONAL
}
CmAct
-
Options ::
=
SEQUENCE
{
allow
-
vm[PRIVATE
219
] IMPLICIT BOOLEAN,
allow
-
reimport[PRIVATE
220
] IMPLICIT BOOLEAN
}
Mask ::
=
INTEGER
END
|
有了这些节点和节点关系,我们就可以用它来解析码流了。接下来我们就来看看LIF文件里面到底有什么东西。先说结论吧,LIF文件包含一段LIF-content、两个证书和一段签名值。其中LIF-content包含一些授权信息和一些限制条件。两份证书和签名值用于验证LIF文件是否被修改。
以下是我使用asn1tools解析的Terra2314.WibuCmLIF(这个LIF我都不记得是从哪里弄来的,见附件)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<signed>
<contentType>
1.2
.
840.113549
.
1.7
.
2
<
/
contentType>
<content>
<version>
1
<
/
version>
<digestAlgorithms>
<
0
>
<
0
>
2.16
.
840.1
.
101.3
.
4.2
.
1
<
/
0
>
<
/
0
>
<
/
digestAlgorithms>
<contentInfo>
<contentType>
1.3
.
6.1
.
4.1
.
44485.2
.
1
<
/
contentType>
<content> FF
81
64
81
C7 FF
81
21
37
DF
81
35
08
63
6D
62
6F
78
70
67
6D
FF
81
25
12
DF
4E
02
00
01
DF
54
02
00
01
DF
20
05
00
00
00
00
00
FF
7A
12
DF
4E
02
00
01
DF
54
02
00
01
DF
20
05
00
00
00
00
00
FF
64
12
DF
81
32
05
00
27
2A
DC
71
DF
81
33
05
00
27
04
8F
5F
FF
7D
3A
DE
30
54
00
65
00
72
00
72
00
61
00
20
00
43
00
6F
00
6E
00
74
00
61
00
69
00
6E
00
65
00
72
00
20
00
76
00
32
00
2E
00
33
00
2E
00
31
00
2E
00
34
00
DF
72
05
00
00
5B
91
26
FF
81
08
28
DF
81
14
04
32
30
30
31
DF
7F
05
00
00
00
00
00
FF
81
00
14
FF
81
04
10
C1
01
FF C1
01
FF C1
01
FF C1
01
00
C2
02
00
01
FF
81
05
0A
DF
81
5B
01
00
DF
81
5C
01
00
<
/
content>
<
/
contentInfo>
<certificates>
<
0
>
30
82
01
7B
30
82
01
28
A0
03
02
01
02
02
04
B2 D0
5E
01
30
0A
06
08
2A
86
48
CE
3D
04
03
02
30
26
31
15
30
13
06
03
55
04
0A
0C
0C
57
49
42
55
2D
53
59
53
54
45
4D
53
31
0D
30
0B
06
03
55
04
03
0C
04
52
6F
6F
74
30
1E
17
0D
31
35
30
31
30
31
30
30
30
30
30
30
5A
17
0D
33
35
31
32
33
31
32
33
35
39
35
39
5A
30
31
31
15
30
13
06
03
55
04
0A
0C
0C
57
49
42
55
2D
53
59
53
54
45
4D
53
31
18
30
16
06
03
55
04
03
0C
0F
57
69
62
75
2D
50
72
6F
64
75
63
74
69
6F
6E
30
4E
30
10
06
07
2A
86
48
CE
3D
02
01
06
05
2B
81
04
00
21
03
3A
00
04
32
37
DD
50
E5 A0 A5 A9
38
E2
88
47
36
13
12
39
26
B1 C2 FB
11
52
77
BE
21
88
45
BD A6 E0
14
EC F1 D1
99
05
8F
77
05
78
80
ED
3C
C5
83
F9 EF
09
B9 E4
80
D7
8E
30
F2
4A
81
15
00
78
A4
68
59
55
F6
77
32
49
E8
57
6C
2A
5D
48
FB BB EA C6 E2
82
15
00
C6
8C
60
C4 C5
15
26
82
20
5B
1F
40
55
A3 F8
2D
B9 A6
08
87
A3
16
30
14
30
12
06
03
55
1D
13
01
01
FF
04
08
30
06
01
01
FF
02
01
01
30
0A
06
08
2A
86
48
CE
3D
04
03
02
03
41
00
30
3E
02
1D
00
E1
5D
F5
35
01
59
75
89
1E
7F
1A
C8 F0 B1
7E
07
7C
C1
0E
67
45
27
46
67
5A
E0
52
26
02
1D
00
B6 E5 A1 AB CA
94
D5 B8 FE AB C7
94
94
10
07
83
92
61
F7
79
B4 DF F4 B3
4B
7B
C7
74
<
/
0
>
<
1
>
30
82
01
AF
30
82
01
5E
A0
03
02
01
02
02
04
B2 D0
64
B3
30
0A
06
08
2A
86
48
CE
3D
04
03
02
30
31
31
15
30
13
06
03
55
04
0A
0C
0C
57
49
42
55
2D
53
59
53
54
45
4D
53
31
18
30
16
06
03
55
04
03
0C
0F
57
69
62
75
2D
50
72
6F
64
75
63
74
69
6F
6E
30
1E
17
0D
31
35
30
31
30
31
30
30
30
30
30
30
5A
17
0D
33
35
31
32
33
31
32
33
35
39
35
39
5A
30
20
31
10
30
0E
06
03
55
04
0A
0C
07
36
30
30
30
39
33
34
31
0C
30
0A
06
03
55
04
03
0C
03
4C
50
4B
30
4E
30
10
06
07
2A
86
48
CE
3D
02
01
06
05
2B
81
04
00
21
03
3A
00
04
50
54
29
9D
03
A7
3F
13
EB
24
35
3D
BE
91
E9 A6
80
33
C3
01
57
52
81
3D
AA
0B
6B
50
EB
57
59
44
07
92
E9
7B
0A
39
A2
9A
73
38
D2 B7
83
95
7B
85
26
00
C4 DB
37
35
68
C9
81
15
00
C6
8C
60
C4 C5
15
26
82
20
5B
1F
40
55
A3 F8
2D
B9 A6
08
87
82
15
00
0B
EB FF D7
68
9A
1C
9B
08
7A
60
5E
46
32
DB A3
96
26
42
92
A3
52
30
50
30
0F
06
03
55
1D
13
01
01
FF
04
05
30
03
01
01
00
30
0F
06
03
55
1D
0F
01
01
FF
04
05
03
03
00
0F
00
30
2C
06
0A
2B
06
01
04
01
82
DB
45
03
01
01
01
FF
04
1B
FF
76
18
DF
72
03
5B
91
26
FF
78
0F
DF
81
5D
01
FF DF
81
5E
01
FF DF
81
5F
01
FF
30
0A
06
08
2A
86
48
CE
3D
04
03
02
03
3F
00
30
3C
02
1C
34
EA
5B
EB AD F0
70
17
22
A1
5B
D0 E1 D0 B0
7A
16
16
2B
CC CF E4
30
2F
F8 D7
14
2B
02
1C
09
11
EB F5
07
49
36
AA B9 D7
6B
62
6F
7B
49
35
9E
1E
EA
60
C0
2E
5B
A2 DF D7
87
AF <
/
1
>
<
/
certificates>
<signerInfos>
<
0
>
<version>
1
<
/
version>
<signerIdentifier>
<subjectKeyIdentifier>
0B
EB FF D7
68
9A
1C
9B
08
7A
60
5E
46
32
DB A3
96
26
42
92
<
/
subjectKeyIdentifier>
<
/
signerIdentifier>
<digestAlgorithm>
<
0
>
2.16
.
840.1
.
101.3
.
4.2
.
1
<
/
0
>
<
/
digestAlgorithm>
<digestEncryptionAlgorithm>
<
0
>
1.2
.
840.10045
.
4.3
.
2
<
/
0
>
<
/
digestEncryptionAlgorithm>
<encryptedDigest>
30
3D
02
1C
49
1D
06
76
D5 BE D1 E8
38
77
4B
E5
64
A7
7C
DF
9B
50
EB
1E
63
27
C5
3C
13
9A
86
73
02
1D
00
E4
3D
0E
F8 FC CD
80
FD D1
57
3C
18
70
95
D6
8C
9E
BF
85
6D
A0 D7 EC
0D
D9
9A
54
43
<
/
encryptedDigest>
<
/
0
>
<
/
signerInfos>
<
/
content>
<
/
signed>
|
接下来将会详细讲解如何使用asn1tools解析文件后缀为WibuCmLIF
、WibuCmRaC
,WibuCmRaU
,并讲述其中几个关键密钥的生成和使用。
更多【wibu证书 - asn1码流】相关视频教程:www.yxfzedu.com