通过上一节的处理,我们拿到了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结构如下图所示:
class用于表示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。
python .\test_asn.py 301302010A80010AA10302010AC2010AE30302010A
30 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
asn.1 格式学习 ASN/1 TLV
这里先放上一节的流程图,在sub_77A950
中可以看到asn1码流的解析。 每个asn1类型被定义为一个结构体节点,一开始是无法准确地知道每个字段的含义。通过相关查找,确认这些节点都是在github上的开源代码asn1c-0.9.26 中定义。于是,我们对这些asn1节点有了较为清晰的了解。
通过观察asn1结构体节点,可以发现一般情况下,name字段和xml_tag字段指向同一个字符串,并且所有的节点都在data段内。我们可以在data段找两个即相邻又相同的指针,并且该指针指向的内容同样在data段内。节点之间通过elements字段关联,利用elements,我们可以为这些节点建立树状关系或层级关系,甚至可以恢复出整个asn1定义。下图LIF的asn1定义。
有了这些节点和节点关系,我们就可以用它来解析码流了。接下来我们就来看看LIF文件里面到底有什么东西。先说结论吧,LIF文件包含一段LIF-content、两个证书和一段签名值。其中LIF-content包含一些授权信息和一些限制条件。两份证书和签名值用于验证LIF文件是否被修改。 以下是我使用asn1tools解析的Terra2314.WibuCmLIF(这个LIF我都不记得是从哪里弄来的,见附件)
接下来将会详细讲解如何使用asn1tools解析文件后缀为WibuCmLIF
、WibuCmRaC
,WibuCmRaU
,并讲述其中几个关键密钥的生成和使用。
2 bit
1 bit
5 bit
class
p/s
tagv
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())
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())
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
-
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
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2022-12-15 20:51
被bluefish蓝鱼编辑
,原因: 新增asn1码流解析
上传的附件: