本节将描述wibu软授权中可能用到的一些文件,在初次接触wibu软授权的伙伴可以通过本文快速找准自己的方向。
部分描述均为个人猜测,仅作参考。
WibuCmLIF文件又称为LIF文件,其记录了待授权软件的信息、配置、环境要求等。一般地,WibuCmLIF文件会跟随软件一同发布,所以在软授权过程中,我们首先接触的就是WibuCmLIF文件。
以下是某份WibuCmLIF文件的内容:
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 | [WIBU - SYSTEMS Control File ]
Guid = { 00070001 - 0000 - 1100 - 8005 - 0000C06B5161 }
Description = CodeMeter License Transfer Generation Information
Version = 1.00
Encoding = UTF - 8
[Info]
CreationTime = 2020 - 10 - 27 21 : 26 : 09
TimeStamp = 1603805169
LicenseInformationSize = 1204
[LicenseInformation]
UZ2c7xT77 / 9BygbMO0cf8CM9VG1gdIywuAHhAjqn9rIxvyeP15rvdGjLGEzcaxYhANuJX1np0X25fTEyK8X3CU5r / f2NaEUPqq8g
gwLb0AKenTv2 / d6Q9njQExlKvhwHFDQXoPLg0Ak7fc / 8GhzZu8Pxq0biHmg82ToBYI4WTTdDENQNuFzzSwiqabadsq163iKfuVIb
7qg5DAIoihMb1NHNSRYypkIM6cmZbFoWh4mBFgN5Al0 / H5n3oDUqJhq1MY4t39JouPhJ0EXW3J6vEsneum6mnMROyJPNfcrFx9SR
tjeRZrB1crnOk2Bbcm7cQMiDOEIYKipYJw34YHRf5fCKRg5Ojhnoi2Q7bbis0ZAjBadl4a90ert / tGxUuKgvV2wn / / q4KYxq1Cpx
6xvENAdpQnSIJfliUHUgOfm3 / ML0mJSCXzY0psoI2E12nDXdDhNhFTVAcGRJO58xenxu2iHvpMH / DkbdG87SfCl / Rmz4pgJ68w1E
aN / 2XHDg3VG0OMI9JsFEWA / M + RQ6ohMj9yJ / NiZug3ChW4x26 / gQjLuyzVMEXJWuPPmFmmvcbc2Vg + 5CNSkpcU24F8HcLmeP + WFu
i8d77K99Dl3oCsNoUmQaXbNzHEpwhkThXewmo9a + lHsHCAoswUZs6Q5ukxmrMZbMzW4IVtwmITeQ / j + O + LC4HZf3OHGf6LJoYXS4
D0IDLa / KcffMAXPi6cIIqT6nV / eH1g6kYzPde7eir8eoNbr + 8QMXhKdBVRtzs / WgPbvmN4gWjlYgdYCI + MsEeJghBzxHX1V7fxOz
Bh + V1vunRbXQhOsX1dzHHMkKaiwHdzRWYKzr6BetVAkeJEyu7R1hG4aSlmFmCbZDTruY1rs / YckgqwQcYMgIMz3GK0M5vPUE2c5X
VPy / bIzrbpYGT + IbNoIv6GsOKYFL2xo253PxdOh8JX7 + 4uc8UhwCXcb1bMu8lLo9Fc1M0weNK2Gh + sGHgqCq4XJCOH / ImfVS + cDa
ml10fCyFc + an0GB7EwRaZTs7wW4Ic0fN9BwOq / sqCr7QBZCWRJ / kJGnzun1GbFqY9kRhqj0QmLZsFFSOLyjfQ35QAaFlVIIn5tkw
MLaqlZtrQISWsSa75pnWCpL2DvtPT3UKrYJ8e4ObLZB7W4Ho / AKAw4JDa4lykbXtaI19cm2OZMHU + fgG1x9AW0s2tKo + 8Ilc76Un
FdVPYoIBcOnSZ2s8KbqdnCQ0Qx + vyaJZKctQ1OEACXlnQsky6Mazlmp8mfmBNfVfAfd9DpiL / rwv7FERPmGpT9QEuUNIpUeFIW1o
NODjIAm5GosMJk + mfFtKm3qelVl9c5mEpPchK / 4bpWg2cVKj + GhXwdRkDSFOaS1PnM3Jncz4PXve + chit5uvXrtx1brD9E9S2F3c
Ysjd9GdsTezaSUcKQrXD3hb2uHovIDSVOVjiYHvPuzepnwXkYmLClG2o0EkuEjb5pcVmxLuKARYJzvkn3x07abrpTPqJLVnh / MT2
VrhdIwgnYJyZ6DvFHi0I / T + pe8Vv1WOc7cNrmfl + AXeQh3dWnq2fpAmPvB2Ypv0RQdIe3VcCK3Zri7oAbc52QqngonerSGz6 + 154
WAo5xw
|
我们可以看到,LIF文件的内容有点类似ini配置文件的结构,其中LicenseInformation节有逆向经验的伙伴很容易就能看出是BASE64编码的内容。
LIF文件的使用方式很简单,运行cmu -i -f xxx.WibuCmLIF
即可。运行后,将在wibu的软授权系统加载该LIF文件并且生成与本次加载相关的文件。值得注意的时,每次加载生成的相关文件都不相同,所以程序的说明文档(如果有)会提示不要重复运行该命令。以下是使用某份LIF文件运行该命令的输出,其中的Serial number每次运行该命令都会不同。
1 2 3 4 5 6 7 8 9 10 11 12 | cmu - CodeMeter Universal Support Tool.
Version 6.60 of 2017 - Dec - 18 (Build 2869 ) for Linux
Copyright (C) 2007 - 2017 by WIBU - SYSTEMS AG. All rights reserved.
The file contains 1 Update:
CmActLtLicense binding information: FirmCode 6000934
Execute Update ...
The file contains 1 Update:
CmActLtLicense update: Serial number 130 - 704886716 , FirmCode 6000934.
- - > successful
1 successful update done
|
WibuCmRaC文件又称RAC文件,它是我们接触到的第二个文件,它与当前机器的环境、状态等信息强关联。
该文件由命令cmu -c6000934 -s130-704886716 -f context.WibuCmRaC
生成,其中的-c和-s参数由导入LIF文件时确定。RAC文件的结构和LIF文件类似。以下为运行命令结果
1 2 3 4 5 | cmu - CodeMeter Universal Support Tool.
Version 6.60 of 2017 - Dec - 18 (Build 2869 ) for Linux
Copyright (C) 2007 - 2017 by WIBU - SYSTEMS AG. All rights reserved.
Write CmFAS for 130 - 704886716 for FirmItem 6000934
|
RAC文件需要提交到软件供应商处进行激活,软件供应商将返回一个RAU文件作为激活文件。
WibuCmRaU文件又称RAU文件,它是软件供应商提供的激活文件,只有LIF文件与RAC文件相匹配才能导入成功,之后就能正常使用程序。
RAU文件的导入方式和LIF文件类似,只要运行命令cmu -i -f xxx.WibuCmRaU
即可。
LIF文件、RAC文件和RAU文件的核心内容(base64编码那部分内容)均使用asn1编码,而asn1定义位于CodeMeterLin中。利用asn1定义可以使用如asn1c(c/c++平台)、asn1tools(python平台)进行解析,目前除RAU文件的部分内容外,其余文件本人都进行了解析并可以正确获取内容。
RAU文件的部分内容需要使用CmAct证书的私钥解密,而CmAct证书的私钥与机器绑定(或者说与导入LIF时的环境绑定),故需要能够接触真实运行的机器才能获取CmAct证书的私钥。只有RAU文件没有实际机器是无法解密该文件的,初次接触的小伙伴需要注意一下。
由于本人只有一份RAU文件,并且该RAU文件尚未过期,所以本人不会公开这个RAU文件。
wbc文件是LIF文件导入时生成的文件,主要包含了系统特征的哈希值,并且描述了RAC文件中CmAct证书私钥的生成参数,默认情况下位于/var/lib/CodeMeter/CmAct。
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | [WIBU - SYSTEMS Control File ]
Guid = { 000B0002 - 0000 - 1100 - 8005 - 0000C06B5161 }
Description = WIBU - SYSTEMS CmAct Inventory
Version = 1.00
Encoding = UTF - 8
[Inventory]
Nonce = 5B953B8DE30C80383851A1C4A0DCB4C08B5EA6DB5B57503C9F766B7EE75303B6
RedundancyData = 4B76D4A6ADA098349EE74931AD4686F251B512998CB181346527C4625B2BA8ADEA16AEA16335F3ACC84F1C4E532D5DCC8EEE91901D9C7BCBC71506F16FF71CFBE893EBDA3FE75A0AFE8F94FB05150C26A2611DFDD9A369B326B493C2EF03A49FFA83743C2100
Version0 = 6
Version1 = 60
Version2 = 2869
Version3 = 0
Heuristic = 2
Flags = 0
ItemCount = 13
[Item_0]
ID = 2B65AB32E1F52D647E2A6208CC3C5AD6F7E686FF6E71DE0030B2CF8F15C8AD06
Position = 0
Length = 67
Params = AB1A401EC3FBA4070FA7CA569EB44DE8
[Item_1]
ID = ABBB3C53DBAB3E9545CE8E030BC4936830983EFC0E68784272E70E2DECA7A64F
Position = 67
Length = 112
Params = 8B4FC28F523E3B201B0A21075DA160C1
[Item_2]
ID = 9B7AC9C0CCB23CE9B70E6962CBFC67A11A6399B2E3375DBAB367A6170F5359D9
Position = 179
Length = 42
Params = 2B0E51706F32DC52323AF862ABABFE3A
[Item_3]
ID = 3BF9F76D91B518204C05927CE7EE6E500016239F4AC1F42B7D9943DBAAC043B6
Position = 221
Length = 35
Params = 6B40611626E60FC67B30626610B878FD
[Item_4]
ID = CBA5E1C03BC3D91F2848E79A3039C2158CE3956493B8D8E6658FFBE4DBA90756
Position = 256
Length = 28
Params = 9BE631605A441A9B12E509782946EB78
[Item_5]
ID = BBBB1E63F5980CC754646CA9041C2A2060F32701932ABCD1869933AB33174C66
Position = 284
Length = 28
Params = 6B815996E45B0B54A80720D84B7F060E
[Item_6]
ID = FB0B8A33EF4007CF54B577927E3957826C4C88B57971565CD1CD183C5B046540
Position = 312
Length = 28
Params = 6B4B5DA0A249605BBE8FFA83ED843DA2
[Item_7]
ID = 8BA2DA67D3094E04F5810492B75FC5922A51865B38D66D33801FDA1FA08B8AE0
Position = 340
Length = 28
Params = 1B88A2D99C44F94561C03248732EB525
[Item_8]
ID = 6BFD47ABA498564E0A8633AA00E08F3BBF2B92008BD7E3EDADCAE57A23BD7D1F
Position = 368
Length = 21
Params = 6B10A5347FD4FCEE48C90BC1C4CA1E12
[Item_9]
ID = 5B8AF905FDBCD470CE3F87CDB02071C5D53B3A9DEA8784B77DC38AA2FEAD508A
Position = 389
Length = 21
Params = FB2238548392D8B0683ED68C372D80D2
[Item_10]
ID = 5BDC9C95A56535C52C34D0093DCAAFE19188748619136DF7F671FCC43E9C4CE0
Position = 410
Length = 45
Params = 0B71A077E2DC717B14EE02E0FE904B7F
[Item_11]
ID = 6B96BDE884536CDE60A3944FA37EE56BE6FECD499A8BFDE37F42B101139B3DD2
Position = 455
Length = 42
Params = 6B321A1A5B402142C827648B5447CEE6
[Item_12]
ID = 2B718715B76200DB0DB8B0FC2177A4B8BCC1ACF2999FF82F2E1B76499852427D
Position = 497
Length = 15
Params = DB7548975ACC0CD4FA7BC69F78B20164
|
wbc文件每一个Item节表示一个系统特征,当且仅当所有系统特征的哈希值与Item节的ID所对应时,该wbc文件才被认为是有效的。
每个Item节的Position和Length参数用于描述CmAct证书私钥的组成结构,所有Item节的Length参数加起来必须为512(比特)。Params字段具体作用未知。
wbc文件通常以<firmcode>_<CmActSerial-ID>.wbc
的形式命名,firmcode在导入LIF文件时我们就遇到过,CmActSerial-ID通常由40个字符(20个字节)构成,为了便于输入,CmActSerial-ID可以缩略为Serial number。
以6000934_820034d3a3fa6e51ce48f11c54f3e47b9c569e6d.wbc为例,firmcode为6000934,CmActSerial-ID为820034d3a3fa6e51ce48f11c54f3e47b9c569e6d,Serial number为130-2726490540。
1 2 3 4 5 6 7 | >>> import hashlib
>>>
>>> CmActSerial_ID = "820034d3a3fa6e51ce48f11c54f3e47b9c569e6d"
>>> part1 = int .from_bytes(bytes.fromhex(CmActSerial_ID)[ 0 : 2 ], "little" )
>>> part2 = int .from_bytes(hashlib.sha256(bytes.fromhex(CmActSerial_ID)).digest()[ 0 : 4 ], "little" )
>>> print ( "Serial number: %d-%d" % (part1, part2))
Serial number: 130 - 2726490540
|
wbc文件更细节的使用方式见后续章节。
WibuCmActDyn文件又称DYN文件,同样位于/var/lib/CodeMeter/CmAct,命名规则与wbc文件相同。
DYN文件一份被AES128-CBC加密的文件,IV固定为全0,而AES密钥需要使用CmAct证书的私钥解密。
DYN文件从asn1定义上看可以记录很多信息,如激活时间、过期时间、批量授权等。
此处我的DYN文件却没有这么多信息,原因未知。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <sw - specs>
<creator - name> CodeMeter Runtime < / creator - name>
<creator - version>
<sfl> 1 < / sfl>
<sfh> 1 < / sfh>
<feature - flags> 0 < / feature - flags>
< / creator - version>
<required - version>
<sfl> 1 < / sfl>
<sfh> 1 < / sfh>
<feature - flags> 0 < / feature - flags>
< / required - version>
< / sw - specs>
<cmact - serial - id > 82 00 34 D3 A3 FA 6E 51 CE 48 F1 1C 54 F3 E4 7B 9C 56 9E 6D < / cmact - serial - id >
<clocks>
<box - time> 579681158 < / box - time>
<certified - time> 552660672 < / certified - time>
< / clocks>
<tag> 2 < / tag>
<pi - dynamics>
< / pi - dynamics>
|
WibuCmActLic文件又称LIC文件,同样位于/var/lib/CodeMeter/CmAct,命名规则与wbc文件相同。
LIC文件与LIF文件大同小异,LIC文件多了一些与本次LIF导入相关的字段,如cmact-serial-id、CmAct证书等。
winsecurity文件位于/var/spool/ctmp下,文件名为随机构造。
winsecurity文件多为53字节和68字节,此处仅描述53字节结构,68字节未作分析。
winsecurity文件前32字节为对应wbc文件名的sha256,接下来的17字节为供wbc文件使用的数据(有效数据),最后4字节为数据类型。本人认为68字节的文件与53字节文件结构类似,只是有效数据的长度不同。
有效数据的用途还待挖掘。
CodeMeterLin是wibu软授权架构的核心程序,用于验证、生成软授权相关信息,采用C/S架构提供服务。
CodeMeterLin默认情况下位于/usr/sbin,服务端端口为22350。
CodeMeterLin默认情况下在后台运行(daemon模式),可以使用-f参数使其在前台运行。
解除反调试
在daemon模式下,原先的父进程会被终止,而fork出来的子进程将被init进程继承,如果动态跟踪的话,到daemon函数处就会终止,具体可查看daemon函数的手册,所以要调试CodeMeterLin最好添加-f参数。
运行起来的CodeMeterLin最终会在函数sub_4F8410的while中循环,该while语句仅在dword_B4FC50为0时终止。dword_B4FC50是检测CodeMeterLin运行环境的变量,一旦CodeMeterLin认为自身处于不安全的环境中,该值就会赋值为0,从而结束进程。
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 | __int64 __fastcall sub_4F8410(__int64 a1, __int64 a2)
{
__pid_t v2; / / eax
__int64 v3; / / rax
__int64 v4; / / rax
char v5; / / al
char v6; / / dl
sub_4F8270(a1);
v2 = getpid();
byte_B736E4 = 0 ;
dword_B73254 = v2;
byte_B73250 = 0 ;
sub_4C8F70(&dword_B73700, 0LL , 1LL );
dword_B4FC50 = 1 ;
signal( 10 , handler);
signal( 2 , handler);
signal( 15 , handler);
signal( 1 , handler);
signal( 12 , handler);
v3 = sub_43EA80();
v4 = sub_43E950(v3);
sub_526940(a2, v4);
msleep( 100 );
signal( 10 , handler);
signal( 12 , handler);
byte_B736E4 = 1 ;
msleep( 600 );
v5 = 0 ;
v6 = 0 ;
byte_B73250 = 0 ;
if ( dword_B4FC50 )
{
while ( 1 )
{
if ( v5 || !v6 )
{
usleep( 1500000u );
system( "/usr/bin/codemeter-info -SMmp > /dev/null" );
byte_B73250 = 0 ;
sub_4D0DE0( 0x12u );
if ( byte_B73250 )
{
byte_B73250 = 0 ;
sub_4D0DE0( 0x12u );
}
}
msleep( 800 );
if ( !dword_B4FC50 ) / / 若运行环境不安全则退出 while 循环
break ;
v5 = byte_B73250;
v6 = 1 ;
}
}
dword_B4FC50 = 0 ;
* (_BYTE * )(qword_B70410 + 122 ) = 0 ;
msleep( 1000 );
return 1LL ;
}
|
接下来的事情就简单了,你可以发挥你的想象来控制dword_B4FC50不变为0。
交叉引用寻找dword_B4FC50的调用点,修改dword_B4FC50的赋值语句,这样做仅修改一个字节即可。
1 2 3 4 5 | void set_env_unsafe()
{
dword_B4FC50 = 0 ; / / set 1 to disable env check
nullsub_16();
}
|
交叉引用set_env_unsafe可以发现有很多情况会导致运行环境不安全,这里就不展开细述,有兴趣可以自己去调一调。
看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~