首页
论坛
课程
招聘
[原创]Wibu Codemeter 7.3学习笔记——AxProtector壳初探
2022-12-31 17:00 16852

[原创]Wibu Codemeter 7.3学习笔记——AxProtector壳初探

2022-12-31 17:00
16852

前一篇 [原创]Wibu Codemeter 7.3学习笔记

看完了回个贴呗,你们的关注是我更新的动力

求一个Wibu AxProtector的license,或者是一个能用的AxProtector,后续研究需要

0x00工具

  1. Fake Wibu Codemeter Server

  2. Wireshark

  3. IDA Pro

0x01最近研究的成果,发现

  1. decrypt_telegram函数 可以接受15s以内的通信延迟,因此可以做一个Codemeter协议解析器
    这里我修改了一点Wireshark的源码,让Wireshark将Codemeter的数据包转发给假服务器,这样可以让我们更加清晰直观的观察Codemeter的通讯过程,帮助我们在假服务器上实现那堆API

  2. 存在大量未公开的api 例如
    APICODE 119:用于帮助文档的解析
    APICODE 32 与Codemeter Control Center交换数据
    APICODE 130 添加WibuCmLif

进度

    1.已完成数据包发送函数的构建

    2.已完成数据包解析框架,实现绝大部分的授权,管理API

    3.用Qt简单写了个GUI,未完成

TODO:

Fake Wibu Codemeter Server

  1. 实现CmGetBoxContents2 CmGetInfo(ENTRYDATA ENTRYINFO)等license相关API 

  2. 实现CmCrypt等加密相关API

  3. 实现HCMSE 句柄,及CmContainner CmBox的结构,管理


逆向
CmCalculateSignature的调用

0x02由CodeMeter API的调用简析Axprotector逻辑

观察受AxProtector保护的程序调用Cm API的行为

---------------FAKE-WIBU-CODEMETER-SERVER-BY-ERICYUDATOU------------------------
[*]Set:
[*]    Debug mode:enabled
[*]    Wireshark Plugin mode:disabled
[*]    Single Thread:disabled
[*]    Disable environment check:enabled
[*]Skip WibuCm32 function test
[*]DLL init success
[*]Server bind IP and Port success.
<-------------------------------------------------------------------------------------------------------->
[*][INIT SUCCESS]All tests and init work done.Server ready,listening to port 22350.
[*]Client 127.0.0.1:5112 login,time=23370
[*]Valid Handeshake
[*]Recieved handshake package,length=209,magic=samc?
[*]Encrypted package decrypt:SUCCESS,len:184,time:23370
[*]Function Request:CmAccess
[*][CmAccess] flctrl=0x10000000,mflCtrl=0x00280000,firmcode=0,productcode=0,featurecode=0
[*][CmAccess] mflCtrl resolve:CM_ACCESS_SUBSYSTEM
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 7f 07 00 00
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]0a 00 00 00 00 00 00 10 00 00 28 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 5c 24 00 00
[*]00 00 3d ffffffc0 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:5112 out
[*]Client 127.0.0.1:5624 login,time=23372
[*]Valid Handeshake
[*]Recieved handshake package,length=33,magic=samc!
[*]Encrypted package decrypt:SUCCESS,len:8,time:23372
[*]Function Request:CmRelease
[*][CmRelease]HCMSE:1919 released
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 00 00 00 01
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]0b 00 00 00 7f 07 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:5624 out
[*]Client 127.0.0.1:6136 login,time=23374
[*]Valid Handeshake
[*]Recieved handshake package,length=737,magic=samc?
[*]Encrypted package decrypt:SUCCESS,len:712,time:23374
[*]Function Request:CmAccess2
[*][CmAccess2] flctrl=0x10000012,mflCtrl=0x00000300,firmcode=5000462,productcode=1,featurecode=16384
[*][CmAccess2] mflCtrl resolve:CM_ACCESS_NOUSERLIMIT CM_ACCESS_EXCLUSIVE CM_ACCESS_STATIONSHARE
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 52 ffffffbf 01 00
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]64 00 00 00 12 00 00 10 00 03 00 00 0e 4d 4c 00
[*]01 00 00 00 00 40 00 00 00 00 32 04 00 00 00 00
[*]00 00 00 00 00 00 00 00 01 0e 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 65 64 61 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 5c 24 00 00 3d ffffffc0 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 47 61 73 54 75 72 62 31
[*]34 2e 65 78 65 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 73 68 65 6e 77 65 6e 68
[*]75 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 45 44 41 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:6136 out
[*]Client 127.0.0.1:6648 login,time=23377
[*]Valid Handeshake
[*]Recieved handshake package,length=33,magic=samc!
[*]Encrypted package decrypt:SUCCESS,len:8,time:23377
[*]Function Request:CmGetVersion
[*][CmGetVersion]HCMSE 114514
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 ffffffd4 12 1e 07
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]23 00 00 00 52 ffffffbf 01 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:6648 out
[*]Client 127.0.0.1:7416 login,time=23379
[*]Valid Handeshake
[*]Recieved handshake package,length=49,magic=samc1
[*]Encrypted package decrypt:SUCCESS,len:16,time:23379
[*]Function Request:CmGetInfo
[*][CmGetInfo]HCMSE 114514 flCtrl 1 cbDest 90
[*][CmGetInfo] CM_GEI_BOXINFO
144 144 156
[*][CmSendMessage]Message send(156):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 ffffff90 00 00 00 07 1e ffffffe1 00 49 23 fffffffc ffffff89
[*]07 01 ffffffe9 01 fffffff5 6a ffffffa0 36 fffffffe ffffffff ffffffff ffffffff ffffffb8 58 2c 03
[*]ffffffc7 46 ffffffef 74 ffffffa8 58 2c 03 ffffff94 58 2c 03 ffffffac 58 2c 03
[*]01 00 00 00 ffffff84 59 27 00 78 ffffff9a 4a 01 ffffffb4 58 2c 03
[*]ffffffc8 58 2c 03 ffffffc0 58 2c 03 ffffffb0 58 2c 03 ffffffcc 58 2c 03
[*]28 03 fffffffe 74 28 03 fffffffe 74 ffffff84 59 27 00 28 03 fffffffe 74
[*]ffffffd0 58 2c 03 6c 46 ffffffef 74 24 00 00 00 00 00 00 00
[*]00 00 00 00 04 59 2c 03 fffffff8 58 2c 03 3e 10 27 00
[*]24 00 00 00 00 00 00 00 28 03 fffffffe 74 ffffff84 59 27 00
[*]00 00 00 00 29 ffffff88 54 77 00 00 00 00
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]21 00 00 00 52 ffffffbf 01 00 01 00 00 00 ffffff90 00 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:7416 out
[*]Client 127.0.0.1:7928 login,time=23382
[*]Valid Handeshake
[*]Recieved handshake package,length=49,magic=samc1
[*]Encrypted package decrypt:SUCCESS,len:16,time:23382
[*]Function Request:CmGetInfo
[*][CmGetInfo]HCMSE 114514 flCtrl 55 cbDest 220
[*][CmGetInfo] CM_GEI_COMMUNICATION
544 544 556
[*][CmSendMessage]Message send(556):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 20 02 00 00 01 00 00 00 04 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 44 7b fffffffc 76
[*]ffffffa0 ffffff92 4a 01 00 00 49 01 ffffff98 ffffff9b 4a 01 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]64 00 00 00 00 00 00 00 28 ffffffdc 49 01 1c 00 00 00
[*]00 00 00 00 03 00 1c 00 50 ffffff8c 4a 01 ffffffa0 ffffff92 4a 01
[*]18 ffffffdc 49 01 00 00 49 01 00 00 00 00 ffffffd4 5b 2c 03
[*]ffffffe6 3c fffffff8 76 00 00 00 00 00 00 00 00 00 00 00 00
[*]30 00 00 00 ffffffa0 ffffff92 4a 01 00 00 00 00 ffffffe8 5b 2c 03
[*]ffffffe0 69 fffffff8 77 00 00 49 01 00 00 00 00 ffffffa0 ffffff92 4a 01
[*]fffffff8 5b 2c 03 fffffffd 5d fffffff7 77 58 33 ffffff8c ffffffa2 30 00 00 00
[*]ffffffa0 ffffff92 4a 01 ffffffe0 5c 2c 03 ffffff90 58 fffffff9 77 ffffffff ffffffff ffffffff ffffffff
[*]ffffffec 5c 2c 03 01 00 00 00 43 00 00 00 ffffff98 ffffff9b 4a 01
[*]28 03 fffffffe 74 65 ffffffa5 ffffffa3 ffffff8a 02 00 00 00 65 ffffffa5 ffffffa3 ffffff8a
[*]64 5c 2c 03 2b 47 ffffffef 74 48 03 fffffffe 74 08 47 ffffffef 74
[*]ffffff91 fffffffc 70 41 01 00 00 00 ffffff84 59 27 00 ffffff98 ffffff9b 4a 01
[*]43 00 00 00 38 5c 2c 03 00 00 00 00 ffffffe4 fffffffd 2c 03
[*]ffffffd0 1f fffffff3 74 fffffff5 6a ffffffa0 36 fffffffe ffffffff ffffffff ffffffff ffffffa8 5c 2c 03
[*]ffffffc7 46 ffffffef 74 ffffff98 5c 2c 03 ffffff84 5c 2c 03 ffffff9c 5c 2c 03
[*]01 00 00 00 ffffff84 59 27 00 ffffff98 ffffff9b 4a 01 ffffffa4 5c 2c 03
[*]ffffffb8 5c 2c 03 ffffffb0 5c 2c 03 ffffffa0 5c 2c 03 ffffffbc 5c 2c 03
[*]28 03 fffffffe 74 28 03 fffffffe 74 ffffff84 59 27 00 28 03 fffffffe 74
[*]ffffffc0 5c 2c 03 6c 46 ffffffef 74 24 00 00 00 00 00 00 00
[*]00 00 00 00 fffffff4 5c 2c 03 ffffffe8 5c 2c 03 3e 10 27 00
[*]24 00 00 00 00 00 00 00 28 03 fffffffe 74 ffffff84 59 27 00
[*]00 00 00 00 fffffff4 5c 2c 03 56 5b 00 00
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]21 00 00 00 52 ffffffbf 01 00 37 00 00 00 20 02 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:7928 out
[*]Client 127.0.0.1:8440 login,time=23384
[*]Valid Handeshake
[*]Recieved handshake package,length=209,magic=samc?
[*]Encrypted package decrypt:SUCCESS,len:184,time:23384
[*]Function Request:CmAccess
[*][CmAccess] flctrl=0x10000000,mflCtrl=0x00280000,firmcode=0,productcode=0,featurecode=0
[*][CmAccess] mflCtrl resolve:CM_ACCESS_SUBSYSTEM
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 7f 07 00 00
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]0a 00 00 00 00 00 00 10 00 00 28 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 5c 24 00 00
[*]00 00 3d ffffffc0 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:8440 out
[*]Client 127.0.0.1:8952 login,time=23387
[*]Valid Handeshake
[*]Recieved handshake package,length=33,magic=samc!
[*]Encrypted package decrypt:SUCCESS,len:8,time:23387
[*]Function Request:CmGetVersion
[*][CmGetVersion]HCMSE 1919
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 ffffffd4 12 1e 07
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]23 00 00 00 7f 07 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:8952 out
[*]Client 127.0.0.1:9720 login,time=23389
[*]Valid Handeshake
[*]Recieved handshake package,length=33,magic=samc!
[*]Encrypted package decrypt:SUCCESS,len:8,time:23389
[*]Function Request:CmRelease
[*][CmRelease]HCMSE:1919 released
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 00 00 00 01
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]0b 00 00 00 7f 07 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:9720 out
[*]Client 127.0.0.1:10232 login,time=23391
[*]Valid Handeshake
[*]Recieved handshake package,length=33,magic=samc!
[*]Encrypted package decrypt:SUCCESS,len:8,time:23391
[*]Function Request:CmGetVersion
[*][CmGetVersion]HCMSE 114514
[*][CmSendMessage]Message send(8):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 ffffffd4 12 1e 07
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]23 00 00 00 52 ffffffbf 01 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:10232 out
[*]Client 127.0.0.1:10744 login,time=23393
[*]Valid Handeshake
[*]Recieved handshake package,length=241,magic=samc?
[*]Encrypted package decrypt:SUCCESS,len:212,time:23393
[*]Function Request:CmCalculateSignature
[*][CmSendMessage]Message send(200):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]SEND SUCCESS
[*]Printing Decrypted Request:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]5a 00 00 00 52 ffffffbf 01 00 02 00 00 00 ffffff88 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]69 ffffffbd 01 ffffff83 0a 1f ffffffce 55 2f ffffffa2 1d ffffff99 ffffffd4 5d 17 1e
[*]ffffff87 ffffff9f 63 54 7d 6f ffffffd4 ffffffbb ffffffb6 ffffff8a 72 09 ffffffd4 27 7e 02
[*]40 00 00 00
[*]----------------------------------------------END------------------------------------------------------
[*]Client 127.0.0.1:10744 out

在调用CmCalculateSignature之后程序退出。因为目前没有对CmCrypt CmCryptSim CmCalculateSignature等API进行实现。

(未完,楼下续)



[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2023-1-27 00:36 被ericyudatou编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (19)
雪    币: 6638
活跃值: 活跃值 (46282)
能力值: (RANK:115 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 2022-12-31 19:07
2
0
期待完整版
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2022-12-31 20:47
3
0

0x02 初步分析


从样本一进行跟踪分析,CmCalculateSignature发现在这里被调用

  ……
  memset((__m128i *)&cmAuth, 0, sizeof(cmAuth));
  v15 = v4[1];
  if ( v15 == 512 )
  {
    mflCtrl = cmAuth.mflCtrl;
    cmAuth.mulKeyExtType = 0;
    if ( v23 )
      mflCtrl = 5;
    cmAuth.mflCtrl = mflCtrl;
  }
  else if ( v15 == 1024 )
  {
    cmAuth.mflCtrl = 2;
    cmAuth.mulKeyExtType = 136;
  }
  pbPubKey = (unsigned int)(v11 + 8);
  memcpy(v21[190], cmAuth.mabDigest, 32);
  if ( !sub_25971B0(v4) )
    return 0;
  v17 = sub_2596C00();
  hcmse = v20[1];
  memset(pbSignature, 0, sizeof(pbSignature));
  if ( !(*(int (__cdecl **)(int, CMAUTHENTICATE *, __m128i *, int))(v17 + 56))(hcmse, &cmAuth, pbSignature, 64) )// cm_calc_signature
  {
    v4[42] = sub_269E220(v17, hcmse);
    return 0;
  }
  if ( (*(int (__cdecl **)(CMAUTHENTICATE *, __m128i *, int, unsigned int, int))(v17 + 60))(// CmValidateSignature
         &cmAuth,
         pbSignature,
         64,
         pbPubKey,
         64) )
  {
    return 0;
  }
  result = sub_269E220(v17, hcmse);
  v4[42] = result;
  return result;
}

在通过服务器计算签名后在本地用CmValidateSignature验证签名。根据相关帮助文档易知CmValidateSignature运用SHA256 - ECDSA算法

CmCrypt在这里调用

    v40 = a5;
    v38 = v16 & 0xFF00FFFF;
    if ( sub_108F760((char *)&v26, pvDest_, 16) )
    {
      CmCrypt = (int (__cdecl *)(int, _DWORD, CMCRYPT2 *, __int128 *, int))this[5];
      if ( CmCrypt && len >= 0x41E )
      {
        memset((__m128i *)&pcmCrypt_40, 0, sizeof(pcmCrypt_40));
        pcmCrypt_40.mcmBaseCrypt.mulEncryptionCode = EncryptionCode;
        pcmCrypt_40.mcmBaseCrypt.mulEncryptionCodeOptions = v31 ^ v38;
        pcmCrypt_40.mcmBaseCrypt.mflCtrl = 0x6000000;
        pcmCrypt_40.mcmBaseCrypt.mulFeatureCode = v37 ^ v28;
        cbDest = sub_10907A0(&v26);
        res = CmCrypt(hcmse, 0, &pcmCrypt_40, pvDest, cbDest);// CM_CRYPT_DIRECT_ENC
      }
      else
      {
        if ( !v29 || (cbDest_1 = 56, v33 == 0x3000000) )
          cbDest_1 = 40;
        *(_QWORD *)&pcmCrypt.mcmBaseCrypt.mflCtrl = 0i64;
        pcmCrypt.mcmBaseCrypt.mulEncryptionCode = EncryptionCode;
        pcmCrypt.mcmBaseCrypt.mulEncryptionCodeOptions = v31 ^ v38;
        memset(&pcmCrypt.mcmBaseCrypt.mulFeatureCode, 0, 24);
        pcmCrypt.mcmBaseCrypt.mulFeatureCode = v37 ^ v28;
        CmCrypt2 = (int (__cdecl *)(int, _DWORD, CMCRYPT *, __int128 *, int))this[4];
        pcmCrypt.mcmBaseCrypt.mflCtrl = 0x6000000;
        res = CmCrypt2(hcmse, 0, &pcmCrypt, pvDest, cbDest_1);// CM_CRYPT_DIRECT_ENC
      }
      res_ = res;
      if ( res )
      {
        sub_FF3DB0((int)aes);
        *pvDest_ = pvDest[0];
      }
    }

让这两个函数在此地不要走动,咱们解决了这些加密API再来找她

雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2022-12-31 23:06
4
0

0x03 授权 & 加密 API分析

这些API,咱一个个来

CmCalculateDigest

CODEMETER_API int CMAPIENTRY CmCalculateDigest(const CMBYTE *pbInput, CMUINT cbInput,
    CMBYTE *pbDigest, CMUINT cbDigest);

本地实现,不需要服务器。输入一个二进制串,返回唯一对应的32位二进制串。

int __thiscall CmCalculateDigest_0(int *this, BYTE *pbInput, int cbInput, BYTE *pbDigest, unsigned int cbDigest)
{
  int v6; // eax
  _DWORD v8[5]; // [esp+0h] [ebp-98h] BYREF
  int sha256[33]; // [esp+14h] [ebp-84h] BYREF

  sha256[29] = (int)v8;
  v6 = *this;
  v8[4] = this;
  (*(void (__thiscall **)(int *, _DWORD))(v6 + 4))(this, 0);
  if ( cbDigest >= 0x20 )
  {
    sha256[32] = 0;
    memset(sha256, 0, 112u);
    init_sha256((int)sha256);
    sha256_update(sha256, pbInput, cbInput);
    sha256_final(pbDigest, (int)sha256);
  }
  else
  {
    (*(void (__thiscall **)(int *, int))(*this + 4))(this, 112);// 传递给CodeMeter驱动程序的数据段太小, 错误 112.
  }
  return 32;
}

平淡无奇的sha256套皮,没什么可说的。

CmCalculateSignature

需要用服务器,核心科技在CodeMeter.exe上,咱先分析一下客户端上的

#define CM_DIGEST_LEN                 32
typedef struct __CMAUTHENTICATE {
  CMULONG mflCtrl;
  CMULONG mulKeyExtType;
  CMULONG mulFirmCode;
  CMULONG mulProductCode;
  CMULONG mulEncryptionCodeOptions;
  CMULONG mulFeatureCode;
  CMBOXINFO mcmBoxInfo;
  CMBYTE mabDigest[CM_DIGEST_LEN];
} CMAUTHENTICATE;

CODEMETER_API int CMAPIENTRY CmCalculateSignature(HCMSysEntry hcmse,
    const CMAUTHENTICATE *pcmAuth, CMBYTE *pbSignature, CMUINT cbSignature);

功能:通过CmDongle(狗)中的私钥用ECDSA算法对一个32位的二进制串进行签名,返回签名,不唯一,长度64位

客户端:

// CODEMETER_API int CMAPIENTRY CmCalculateSignature(HCMSysEntry hcmse,
//     const CMAUTHENTICATE *pcmAuth, CMBYTE *pbSignature, CMUINT cbSignature);
int __thiscall CmCalculateSignature_1(
        LPCRITICAL_SECTION *this,
        HCMSysEntry hcmse,
        CMAUTHENTICATE *pcmAuth,
        BYTE *pbSignature,
        int cbSignature)
{
  int cbSignature_1; // eax
  _OWORD *v7; // eax
  _DWORD *v8; // eax
  unsigned int Ticket_2; // eax
  int res; // esi
  size_t newsize; // [esp+18h] [ebp-120h]
  HCMSysEntry hcmse_1; // [esp+20h] [ebp-118h] BYREF
  int buf[65]; // [esp+24h] [ebp-114h] BYREF
  int v16; // [esp+134h] [ebp-4h]

  hcmse_1 = hcmse;
  if ( !isBadHandle(this, &hcmse_1) || !isBadAddress(this, pcmAuth, 0xC8u) )
    return 0;
  if ( (unsigned int)cbSignature < 0x40 || !pbSignature )
  {
    ((void (__thiscall *)(LPCRITICAL_SECTION *, int))(*this)->LockCount)(this, 105);
    return 0;
  }
  cbSignature_1 = 64;
  if ( (unsigned int)cbSignature <= 0x40 )
    cbSignature_1 = cbSignature;
  newsize = cbSignature_1;
  if ( !isBadAddress(this, pbSignature, cbSignature_1) )
    return 0;
  memset(buf, 0, sizeof(buf));
  buf[1] = -1;
  buf[2] = 0;
  LOBYTE(buf[3]) = 0;
  buf[4] = 0;
  buf[5] = 0;
  buf[6] = -1;
  buf[7] = 0;
  LOBYTE(buf[8]) = 0;
  v16 = 0;
  buf[0] = (int)&YS0039::`vftable';
  LOBYTE(buf[9]) = 90;
  memset(&buf[10], 0, 0xD8u);
  v7 = operator new(0x24u);
  LOBYTE(v16) = 1;
  if ( v7 )
  {
    *v7 = 0i64;
    v7[1] = 0i64;
    *((_DWORD *)v7 + 8) = 0;
    v8 = sub_67602DB0(v7, 1u, 0);
  }
  else
  {
    v8 = 0;
  }
  buf[64] = (int)v8;
  v16 = 2;
  Ticket_2 = CmGetTicket_2(this + 23, (unsigned __int16)hcmse_1);
  buf[10] = Ticket_2 | (unsigned int)hcmse_1;
  qmemcpy(&buf[11], pcmAuth, 0xC8u);
  buf[61] = newsize;
  reallocateMem((struct_reallocateMem *)buf[64], newsize);
  if ( *(_DWORD *)(buf[64] + 8) )
    buf[63] = *(_DWORD *)(buf[64] + 4);
  else
    buf[63] = 0;
  if ( send_cm_socket_Req(this + 6, buf, 0xD4u, newsize + 12, 0) )// 发出请求
  {
    memmove(pbSignature, (const void *)buf[63], buf[61]);
    res = buf[62];
    FREE(buf);
    return res;
  }
  else
  {
    FREE(buf);
    return 0;
  }
}

也没什么能说的,捣鼓捣鼓参数塞请求包里。结构如下

struct{
    int apicode;//90
    HCMSysEntry hcmse;
    CMAUTHENTICATE *pcmAuth;
    CMUINT cbSignature;
}

服务端:(**占位**)

CmGetPublicKey

CODEMETER_API int CMAPIENTRY CmGetPublicKey(HCMSysEntry hcmse,
    const CMAUTHENTICATE *pcmAuth, CMBYTE *pbPubKey, CMUINT cbPubKey);

CmContainner中获得公钥,因为CmContainner中只存放私钥故需要通过私钥计算公钥

int __thiscall CmGetPublicKey_1(
        LPCRITICAL_SECTION *this,
        HCMSysEntry hcmse,
        CMAUTHENTICATE *pcmAuth,
        char *pbPubKey,
        int cbPubKey)
{
  int cbPublicKey; // edi
  unsigned int v7; // eax
  unsigned int keysrc; // ecx
  LPCRITICAL_SECTION v9; // ecx
  int Ticket_2; // eax
  int v12; // esi
  void *v13; // ecx
  unsigned __int16 mulKeyExtType; // [esp-8h] [ebp-2Ch]
  int mulEncryptionCodeOptions; // [esp-4h] [ebp-28h]
  HCMSysEntry hcmse_1; // [esp+24h] [ebp+0h] BYREF
  int buf[67]; // [esp+28h] [ebp+4h] BYREF
  void *Src[2]; // [esp+134h] [ebp+110h] BYREF
  int v19; // [esp+13Ch] [ebp+118h]

  hcmse_1 = hcmse;
  if ( !isBadHandle(this, &hcmse_1) )
    return 0;
  if ( !isBadAddress(this, pcmAuth, 0xC8u) )
    return 0;
  cbPublicKey = cbPubKey;
  if ( !isBadAddress(this, pbPubKey, cbPubKey) )
    return 0;
  v7 = 64;
  keysrc = pcmAuth->mflCtrl & 7;                // Key Source
  if ( keysrc == 6 )                            // CM_AUTH_UNIVERSALDATA
    v7 = 1044;
  if ( cbPubKey <= v7 )
  {
    if ( cbPubKey < v7 )
    {
LABEL_22:
      ((void (__thiscall *)(LPCRITICAL_SECTION *, int))(*this)->LockCount)(this, 105);// Message Text
                                                // 
                                                // The specified parameter is invalid, Error 105.
      return 0;
    }
  }
  else
  {
    cbPublicKey = v7;
  }
  if ( !pbPubKey )
    goto LABEL_22;
  if ( keysrc == 6 )                            // CM_AUTH_UNIVERSALDATA
  {
    mulEncryptionCodeOptions = pcmAuth->mulEncryptionCodeOptions;
    v9 = this[111];
    mulKeyExtType = pcmAuth->mulKeyExtType;
    *(_QWORD *)Src = 0i64;
    v19 = 0;
    sub_676388E0(v9, Src, (int)hcmse_1, mulKeyExtType, mulEncryptionCodeOptions); //UVD Get Public Key
    if ( Src[0] == Src[1] )
    {
      free(Src);
      return 0;
    }
    else
    {
      memmove(pbPubKey, Src[0], Src[1] - Src[0]);
      free(Src);
      return 1;
    }
  }
  else
  {
    memset(buf, 0, sizeof(buf));
    buf[1] = -1;
    buf[2] = 0;
    LOBYTE(buf[3]) = 0;
    buf[4] = 0;
    buf[5] = 0;
    buf[6] = -1;
    buf[7] = 0;
    LOBYTE(buf[8]) = 0;
    buf[0] = (int)&YS0038::`vftable';
    memset(&buf[10], 0, 228);
    LOBYTE(buf[9]) = 91;
    Ticket_2 = CmGetTicket_2(this + 23, (unsigned __int16)hcmse_1);
    sub_67614390(buf, (int)hcmse_1, pcmAuth, cbPublicKey, Ticket_2);
    if ( send_cm_socket_Req(this + 6, buf, 0xD4u, cbPublicKey + 12, 0) )
    {
      memmove(pbPubKey, (const void *)buf[66], buf[64]);
      v12 = buf[65];
    }
    else
    {
      v12 = 0;
    }
    v13 = (void *)buf[10];
    if ( buf[10] )
    {
      if ( (unsigned int)(buf[12] - buf[10]) >= 0x1000 )
      {
        v13 = *(void **)(buf[10] - 4);
        if ( (unsigned int)(buf[10] - (_DWORD)v13 - 4) > 0x1F )
          _invalid_parameter_noinfo_noreturn();
      }
      sub_67690A3E(v13);
      memset(&buf[10], 0, 12);
    }
    sub_6763FEC0(buf);
    return v12;
  }
}

整体上大同小异,数据包跟CmCalculateSignature一样

struct{
    int apicode;//91
    HCMSysEntry hcmse;
    CMAUTHENTICATE *pcmAuth;
    CMUINT cbPublicKey;
}

当Key Source 为 Universal Data时会转发到CmGetPublicKeyUVD,处理流程不太一样,后面说CmGetPublicKeyUVD再提

CmValidateSignature

CODEMETER_API int CMAPIENTRY CmValidateSignature(const CMAUTHENTICATE *pcmAuth,
    const CMBYTE *pbSignature, CMUINT cbSignature,
    const CMBYTE *pbPubKey, CMUINT cbPubKey);

本地实现,用ECDSA验证签名,签名由CmCalculateSignature生成,pcmAuth-->mabDigest(被签名的sha256值)必须存在

int __thiscall CmValidateSignature(
        int *this,
        CMAUTHENTICATE *pcmAuth,
        BYTE *pbSignature,
        unsigned int cbSignature,
        BYTE *pbPubKey,
        unsigned int cbPubKey)
{
  int v7; // eax
  void *v8; // eax
  CMBOXINFO *boxinfo_1; // eax
  bool res; // al
  int mulEncryptionCodeOptions; // [esp-4h] [ebp-20Ch]
  int v13; // [esp+0h] [ebp-208h] BYREF
  CMBOXINFO boxinfo; // [esp+10h] [ebp-1F8h] BYREF
  int *pbPubKey_1; // [esp+A0h] [ebp-168h]
  void *v16[65]; // [esp+A4h] [ebp-164h] BYREF
  int signature[17]; // [esp+1A8h] [ebp-60h] BYREF
  int len; // [esp+1ECh] [ebp-1Ch] BYREF
  int key_source[3]; // [esp+1F0h] [ebp-18h] BYREF
  int v20; // [esp+204h] [ebp-4h]

  key_source[2] = (int)&v13;
  pbPubKey_1 = (int *)pbPubKey;
  v7 = *this;
  boxinfo.mulExtendedSerial = (unsigned int)this;
  (*(void (__thiscall **)(int *, _DWORD))(v7 + 4))(this, 0);
  if ( cbPubKey < 0x40 || cbSignature < 0x40 )
  {
    (*(void (__thiscall **)(int *, int))(*this + 4))(this, 105);// 指定了一个无效的参数, 错误 105.
  }
  else
  {
    memset(signature, 0, sizeof(signature));
    v8 = sub_6760F7E0();
    sub_67656310((int)signature, (int)v8);
    v20 = 0;
    init_this((int)v16);
    LOBYTE(v20) = 1;
    boxinfo_1 = copy_boxinfo(&boxinfo, &pcmAuth->mcmBoxInfo);
    copy_boxinfo_to_this((int)v16, boxinfo_1);
    copy_firm_code_to_this((int)v16, pcmAuth->mulFirmCode, 0, 0, 0);
    sub_676588C0(signature, (int)v16);
    len = 0;
    key_source[0] = 0;
    if ( explain_mflCtrl(pcmAuth->mflCtrl, &len, key_source) )
    {
      mulEncryptionCodeOptions = pcmAuth->mulEncryptionCodeOptions;
      LOBYTE(v20) = 2;
      res = doValidateSignature(
              signature,
              len,
              pcmAuth->mabDigest,
              (int)pbSignature,
              key_source[0],
              pbPubKey_1,
              pcmAuth->mulProductCode,
              pcmAuth->mulFeatureCode,
              mulEncryptionCodeOptions);
      v20 = 1;
      if ( res )
      {
        clean_s(v16);                           // 成功
        clean_s_0(signature);
        return 1;
      }
      (*(void (__thiscall **)(int *, int))(*this + 4))(this, 202);// 对该序列的加/解密操作失败, 错误 202.
    }
    else
    {
      (*(void (__thiscall **)(int *, int))(*this + 4))(this, 105);// 指定了一个无效的参数, 错误 105.
    }
    clean_s(v16);
    clean_s_0(signature);
  }
  return 0;
}
bool __thiscall doValidateSignature(
        int *signature,
        int len,
        _OWORD *mabDigest,
        unsigned __int8 *pbSignature,
        int key_source,
        int *pbPubKey,
        int productCode,
        int featureCode,
        int mulEncryptionCodeOptions)
{
  int *pubKey; // ebx
  int v11; // eax
  __int128 v12; // xmm0
  int v13; // eax
  int v15[35]; // [esp+Ch] [ebp-20Ch] BYREF
  int arr[31]; // [esp+98h] [ebp-180h] BYREF
  int ecdsa[24]; // [esp+114h] [ebp-104h] BYREF
  int pubkey[16]; // [esp+174h] [ebp-A4h] BYREF
  int mabDigest_1[4]; // [esp+1B4h] [ebp-64h] BYREF
  __int128 v20; // [esp+1C4h] [ebp-54h]
  int v21[16]; // [esp+1D4h] [ebp-44h] BYREF

  pubKey = pbPubKey;
  *(_OWORD *)mabDigest_1 = *mabDigest;
  v20 = mabDigest[1];
  memset(v21, 0, sizeof(v21));
  memset(pubkey, 0, sizeof(pubkey));
  if ( len == 16 || len == 32 || len == 64 )
  {
    memset(&arr[1], 0, 0x77u);                  // 16
    v11 = *signature;
    arr[0] = 55;
    arr[5] = *(_DWORD *)((*(int (__thiscall **)(int *))(v11 + 40))(signature) + 4);
    arr[6] = productCode;
    *(_OWORD *)&arr[1] = *(_OWORD *)mabDigest_1;
    *(_OWORD *)((char *)&arr[10] + 3) = v20;
    if ( len == 16 || len == 64 )               // 64
    {
      arr[7] = featureCode;
      arr[9] = mulEncryptionCodeOptions;
      calcSHA256((BYTE *)arr, (BYTE *)mabDigest_1);
      if ( len == 64 )
      {
        v12 = *(_OWORD *)pbPubKey;
        pubkey[6] = pbPubKey[6];
        v13 = pbPubKey[14];
        *(_OWORD *)pubkey = v12;
        pubkey[13] = v13;
        *(_QWORD *)&pubkey[4] = *((_QWORD *)pbPubKey + 2);
        *(_OWORD *)&pubkey[7] = *((_OWORD *)pbPubKey + 2);
        *(_QWORD *)&pubkey[11] = *((_QWORD *)pbPubKey + 6);
        sub_67687130((unsigned int *)ecdsa, (unsigned __int8 *)pubkey, 1, (int)v21);
        pubKey = pubkey;
        pubkey[6] = v21[6];
        *(_OWORD *)pubkey = *(_OWORD *)v21;
        pubkey[7] = 0;
        *(_QWORD *)&pubkey[4] = *(_QWORD *)&v21[4];
        pubkey[14] = v21[13];
        pubkey[15] = 0;
        *(_OWORD *)&pubkey[8] = *(_OWORD *)&v21[7];
        *(_QWORD *)&pubkey[12] = *(_QWORD *)&v21[11];
      }
    }
    else
    {
      qmemcpy(v15, (const void *)(*(int (__thiscall **)(int *))(*signature + 44))(signature), sizeof(v15));// 32
      arr[7] = v15[0];
      LOWORD(arr[8]) = v15[1];
      arr[9] = mulEncryptionCodeOptions;
      calcSHA256((BYTE *)arr, (BYTE *)mabDigest_1);
    }
  }
  return checkECDSASignature((char *)ecdsa, (unsigned __int8 *)pubKey, pbSignature, (unsigned __int8 *)mabDigest_1);
}

逻辑很简单,爆掉checkECDSASignature即可

最后于 2023-1-3 19:04 被ericyudatou编辑 ,原因:
雪    币: 2433
活跃值: 活跃值 (1141)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiwushgya 活跃值 2023-1-7 14:08
5
0
高手,明白一下大神
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-7 23:46
6
0

CmCrypt加密相关

在我们干掉Axprotector的CmValiateSignature校验之后,程序在进行一次CmCrypt2请求之后紫砂,请求如下

客户端CmCrypt2下断

int __thiscall func_0(
        _DWORD *this,
        void *hcmse,
        unsigned int a3,
        _DWORD *key,
        int a5,
        unsigned int a6,
        int a7,
        int a8,
        int a9,
        _OWORD *a10,
        int mulEncryptionCode_1,
        char a12)
{
  _DWORD *v12; // edi
  int v13; // esi
  int v14; // edi
  __int128 v15; // xmm0
  unsigned int v16; // esi
  int (__cdecl *cmcrypt2)(HCMSysEntry, int, CMCRYPT2 *, void *, int); // esi
  int cbDest; // eax
  int len; // eax
  int v20; // ecx
  int (__cdecl *v21)(void *, _DWORD, CMCRYPT *, __int128 *, int); // eax
  int len_1; // esi
  int (__cdecl *v23)(void *, unsigned int, int *, _OWORD *, int); // eax
  _BYTE *v26; // [esp+24h] [ebp-29Ch] BYREF
  __m128i v27[19]; // [esp+28h] [ebp-298h] BYREF
  int v28; // [esp+158h] [ebp-168h]
  int v29; // [esp+15Ch] [ebp-164h]
  int v30; // [esp+160h] [ebp-160h]
  int v31; // [esp+164h] [ebp-15Ch]
  unsigned int v32; // [esp+168h] [ebp-158h]
  unsigned int v33; // [esp+16Ch] [ebp-154h]
  int v34; // [esp+170h] [ebp-150h]
  int v35; // [esp+174h] [ebp-14Ch]
  unsigned int mulEncryptionCode; // [esp+178h] [ebp-148h]
  unsigned int v37; // [esp+17Ch] [ebp-144h]
  unsigned int v38; // [esp+180h] [ebp-140h]
  __int128 v39; // [esp+184h] [ebp-13Ch]
  int v40; // [esp+194h] [ebp-12Ch]
  CMCRYPT v41; // [esp+198h] [ebp-128h] BYREF
  CMCRYPT2 pmacc; // [esp+1C0h] [ebp-100h] BYREF
  __int128 pbDest[3]; // [esp+250h] [ebp-70h] BYREF
  int v44[5]; // [esp+288h] [ebp-38h] BYREF
  __int64 v45; // [esp+29Ch] [ebp-24h]
  __int64 v46; // [esp+2A4h] [ebp-1Ch]
  int v47; // [esp+2ACh] [ebp-14h]
  int v48; // [esp+2BCh] [ebp-4h]

  v12 = this;
  if ( a12 )
  {
    memset((__m128i *)&v26, 0, 0x264u);
    LOBYTE(v26) = 0;
    v13 = key[6];
    v14 = key[5];
    memset(v27, 0, 0x128u);
    init_aes(v27, 0);
    sub_269EAB0((int)&v26, v14, v13);
    v12 = this;
    v15 = *(_OWORD *)(mulEncryptionCode_1 + 4);
    mulEncryptionCode = *(_DWORD *)mulEncryptionCode_1;
    v28 = a7;
    v48 = 0;
    v39 = v15;
    v34 = 0;
    v29 = key[8];
    v30 = a8 ^ this[21];
    v31 = a9;
    v32 = a3 & 1;
    v33 = ((a3 >> 8) & 1) << 26;
    v35 = 0;
    v16 = sub_25FA190(a5, -1);
    v37 = sub_25FA190(a5, -1);
    v40 = a5;
    v38 = v16 & 0xFF00FFFF;
    if ( sub_269DE30((char *)&v26, a10, 16) )
    {
      cmcrypt2 = (int (__cdecl *)(HCMSysEntry, int, CMCRYPT2 *, void *, int))this[5];
      if ( cmcrypt2 && a6 >= 0x41E )
      {
        memset((__m128i *)&pmacc, 0, sizeof(pmacc));
        pmacc.mcmBaseCrypt.mulEncryptionCode = mulEncryptionCode;
        pmacc.mcmBaseCrypt.mulEncryptionCodeOptions = v31 ^ v38;
        pmacc.mcmBaseCrypt.mflCtrl = 0x6000000;
        pmacc.mcmBaseCrypt.mulFeatureCode = v37 ^ v28;
        cbDest = sub_269EE70(&v26);
        len = cmcrypt2(hcmse, 0, &pmacc, pbDest, cbDest);// cmcrypt2
      }
      else
      {
        if ( !v29 || (v20 = 56, v33 == 0x3000000) )
          v20 = 40;
        *(_QWORD *)&v41.mcmBaseCrypt.mflCtrl = 0i64;
        v41.mcmBaseCrypt.mulEncryptionCode = mulEncryptionCode;
        v41.mcmBaseCrypt.mulEncryptionCodeOptions = v31 ^ v38;
        memset(&v41.mcmBaseCrypt.mulFeatureCode, 0, 24);
        v41.mcmBaseCrypt.mulFeatureCode = v37 ^ v28;
        v21 = (int (__cdecl *)(void *, _DWORD, CMCRYPT *, __int128 *, int))this[4];
        v41.mcmBaseCrypt.mflCtrl = 100663296;
        len = v21(hcmse, 0, &v41, pbDest, v20);
      }
      len_1 = len;
      if ( len )
      {
        sub_25F97F0((int)v27);                  // success
        *a10 = pbDest[0];                       // pDest
      }
    }
    else
    {
      len_1 = 0;
    }
    sub_269EAB0((int)&v26, 0, 0);
    v48 = 1;
    aes_final((int)v27);
    v48 = -1;
  }
  else
  {
    v44[2] = a8 ^ this[21];
    v44[3] = a9;
    v44[4] = a7;
    v23 = (int (__cdecl *)(void *, unsigned int, int *, _OWORD *, int))this[4];
    v44[1] = 0;
    v45 = 0i64;
    v46 = 0i64;
    v47 = 0;
    v44[0] = ((a3 >> 8) & 1) << 26;
    len_1 = v23(hcmse, a3 & 1, v44, a10, 16);
  }
  if ( !len_1 )
    return sub_269E220((int)v12, (int)hcmse);
  *(_BYTE *)a10 ^= *((_BYTE *)v12 + 84);
  return 0;
}

发现是在

len = cmcrypt2(hcmse, 0, &pmacc, pbDest, cbDest);

处调用,观察CmCrypt2函数的参数会发现有几个疑点(这几个疑点将在服务端分析上揭晓)

  1. mcmBaseCrypt.mflCtrl = 0x6000000; 查看手册发现Wibu并未开放这个算法,姑且称之为AxProtector解密算法

  2. mcmBaseCrypt.mulEncryptionCodeOptions  mcmBaseCrypt.mulFeatureCode并未传入相应数据,推测为AxProtector解密算法的私有参数

  3. IV key,AES Decrypt Key均未设置,cbDest长度恒为40,mcmBaseCrypt.mulEncryptionCode为固定值0x1337

现在有两个方向,向上去找对func_0的调用过程,向下通过CmCrypt2去服务端上找实现的算法

实际运行抓包发现

  1. 这是壳启动阶段最后两次调用Codemeter API,在调用完两次CmCrypt2之后程序即可启动,胜利就在眼前

  2. CmCrypt2请求时附加了长度为0x28的待加密数据,服务器返回长度0x10的加密后的数据,加密后的数据覆盖在之前的数据上

最后于 2023-1-9 00:08 被ericyudatou编辑 ,原因:
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-9 00:08
7
0

AxProtectot所特有的0x600000Cmcrypt在服务器上的行为分析

参见Wibu Codemeter 7.3学习笔记——Codemeter服务端在api_cm_crypt处下断

void __cdecl api_cm_crypt2(
        int flctrl,
        CMCRYPT2 *cmcrypt2,
        HCMSysEntry hcmse,
        size_t cbDest,
        size_t *a5,
        void *pbDest,
        void *pbDest_1,
        int *a8,
        char a9)
{
  unsigned int len_1; // esi
  int v10; // ecx
  unsigned int v11; // edx
  int v12; // eax
  int *v13; // ecx
  int mulKeyExtType; // esi
  int *v15; // eax
  int *v16; // esi
  struct_cmcrypt *v17; // eax
  bool v18; // zf
  int v19; // ecx
  int v20; // eax
  __m128d v21; // xmm1
  void *v22; // eax
  _DWORD *v23; // eax
  __int128 v24; // xmm0
  void (__thiscall ***v25)(_DWORD, int); // ecx
  _BYTE *v26; // ecx
  size_t v27; // esi
  void *v28; // eax
  _DWORD *v29; // eax
  void *v30; // edi
  void ***v31; // eax
  void ***v32; // eax
  void ***v33; // eax
  void ***v34; // eax
  void ***v35; // eax
  void ***v36; // eax
  void ***v37; // eax
  void ***v38; // esi
  void ***v39; // edi
  void ***v40; // eax
  int errcode; // eax
  void ***v42; // eax
  HCMSysEntry hcmse_1; // [esp-10h] [ebp-794h]
  int v44; // [esp-10h] [ebp-794h]
  int v45; // [esp-Ch] [ebp-790h]
  void *v46; // [esp-Ch] [ebp-790h]
  void *v47; // [esp-Ch] [ebp-790h]
  void ***v48; // [esp-Ch] [ebp-790h]
  void ***v49; // [esp-Ch] [ebp-790h]
  void ***v50; // [esp-Ch] [ebp-790h]
  void ***v51; // [esp-Ch] [ebp-790h]
  void ***v52; // [esp-Ch] [ebp-790h]
  void ***v53; // [esp-Ch] [ebp-790h]
  void ***v54; // [esp-Ch] [ebp-790h]
  int v55; // [esp-Ch] [ebp-790h]
  void ***v56; // [esp-Ch] [ebp-790h]
  const void *v57; // [esp-8h] [ebp-78Ch]
  const void *v58; // [esp-8h] [ebp-78Ch]
  void ***v59; // [esp-8h] [ebp-78Ch]
  void ***v60; // [esp-8h] [ebp-78Ch]
  void ***v61; // [esp-8h] [ebp-78Ch]
  void ***v62; // [esp-8h] [ebp-78Ch]
  void ***v63; // [esp-8h] [ebp-78Ch]
  void ***v64; // [esp-8h] [ebp-78Ch]
  void ***v65; // [esp-8h] [ebp-78Ch]
  void ***v66; // [esp-8h] [ebp-78Ch]
  size_t v67; // [esp-4h] [ebp-788h]
  size_t v68; // [esp-4h] [ebp-788h]
  void ***v69; // [esp-4h] [ebp-788h]
  void ***v70; // [esp-4h] [ebp-788h]
  void ***v71; // [esp-4h] [ebp-788h]
  void ***v72; // [esp-4h] [ebp-788h]
  void ***v73; // [esp-4h] [ebp-788h]
  void ***v74; // [esp-4h] [ebp-788h]
  void ***v75; // [esp-4h] [ebp-788h]
  void ***v76; // [esp-4h] [ebp-788h]
  int v77; // [esp+0h] [ebp-784h] BYREF
  char pExceptionObject[140]; // [esp+10h] [ebp-774h] BYREF
  char v79[140]; // [esp+128h] [ebp-65Ch] BYREF
  char v80[140]; // [esp+1B4h] [ebp-5D0h] BYREF
  char v81[140]; // [esp+240h] [ebp-544h] BYREF
  char v82[140]; // [esp+2CCh] [ebp-4B8h] BYREF
  char v83[140]; // [esp+358h] [ebp-42Ch] BYREF
  char v84[140]; // [esp+3E4h] [ebp-3A0h] BYREF
  char v85[140]; // [esp+470h] [ebp-314h] BYREF
  char v86[140]; // [esp+4FCh] [ebp-288h] BYREF
  __int128 v87; // [esp+58Ch] [ebp-1F8h] BYREF
  char v88[24]; // [esp+59Ch] [ebp-1E8h]
  size_t len; // [esp+5B4h] [ebp-1D0h]
  void *pbDest_3; // [esp+5B8h] [ebp-1CCh]
  int v91; // [esp+5BCh] [ebp-1C8h]
  int flctrl_1; // [esp+5C0h] [ebp-1C4h]
  int *v93; // [esp+5C4h] [ebp-1C0h]
  size_t *v94; // [esp+5C8h] [ebp-1BCh]
  _DWORD *hcmse_2; // [esp+5CCh] [ebp-1B8h]
  int v96; // [esp+5D0h] [ebp-1B4h]
  _BYTE v97[356]; // [esp+5D4h] [ebp-1B0h] BYREF
  struct_cmcrypt algorithms; // [esp+738h] [ebp-4Ch] BYREF
  void *v99[2]; // [esp+75Ch] [ebp-28h] BYREF
  void *pbDest_2; // [esp+764h] [ebp-20h] BYREF
  void *encrypt_option; // [esp+768h] [ebp-1Ch] BYREF
  unsigned int hcmse_3[3]; // [esp+76Ch] [ebp-18h] BYREF
  int v103; // [esp+780h] [ebp-4h]

  hcmse_3[2] = (unsigned int)&v77;
  len_1 = cbDest;
  flctrl_1 = flctrl;
  hcmse_1 = *(HCMSysEntry *)hcmse;
  hcmse_2 = hcmse;
  v94 = a5;
  pbDest_2 = pbDest;
  v10 = *(_DWORD *)(global_1360FC4 + 196);
  pbDest_3 = pbDest_1;
  encrypt_option = cmcrypt2;
  len = cbDest;
  v93 = a8;
  v11 = check_hcmse_handle(v10, hcmse_1, 0x10000, 1, 1);
  hcmse_3[0] = v11;
  if ( a9 )
    ++*(_DWORD *)(global_1360FC4 + 460);
  else
    ++*(_DWORD *)(global_1360FC4 + 456);
  *v94 = 0;
  if ( (unsigned __int8)isReleaseMode(v11 + 328) )
  {
    if ( cbDest < 0x10 )                        // 指定了一个无效的参数, 错误 105.cbDest太短
    {
      v70 = sub_BDE030();
      v60 = sub_BDE030();
      v49 = sub_BDE030();
      v32 = sub_BDE030();
      construct_Exception(v86, 105, (int)v32, (int)v49, (int)v60, (int)v70);
      _CxxThrowException(v86, (_ThrowInfo *)&_TI2_AVException_wbs__);
    }
    v91 = sub_BDB5A0((_DWORD *)(hcmse_3[0] + 328));
    sub_C0EC70((_BYTE *)(hcmse_3[0] + 328));
    v12 = v91;
    if ( v91 )
    {
      v13 = *(int **)(v91 + 380);
      v93 = v13;
      v96 = 0;
      hcmse_2 = v13;
      if ( v13 )
      {
        v96 = v13[21];
        v93 = v13;
        hcmse_2 = v13;
      }
    }
    else
    {
      v93 = 0;
      hcmse_2 = 0;
      v96 = 0;
      v12 = 0;
    }
    if ( (*(_DWORD *)(v12 + 56) & 0x200) != 0
      && !sub_BFEE40((_BYTE *)global_1360FC4)
      && (*(_DWORD *)(hcmse_3[0] + 644) & 0x10000) != 0 )// TMP许可不支持此命令, 错误134.
    {
      v71 = sub_BDE030();
      v61 = sub_BDE030();
      v50 = sub_BDE030();
      v33 = sub_BDE030();
      construct_Exception(v85, 134, (int)v33, (int)v50, (int)v61, (int)v71);
      _CxxThrowException(v85, (_ThrowInfo *)&_TI2_AVException_wbs__);
    }
    if ( (cmcrypt2->mcmBaseCrypt.mflCtrl & 0xF) == 8 )// CM_CRYPT_UNIVERSALDATA
    {                                           // UVD加密,不是研究的重点,忽略即可
	/*
      resolve_crypt_alg((unsigned int *)&encrypt_option, cmcrypt2->mcmBaseCrypt.mflCtrl & 0xFF000000);
      mulKeyExtType = cmcrypt2->mcmBaseCrypt.mulKeyExtType;
      sub_C59B10(v91, v99);
      v103 = 0;
      v15 = sub_D46E60((int ***)v99, mulKeyExtType);
      v16 = v15;
      if ( !v15 )                               // 无法找到要求的产品码选项, 错误 26.
      {
        v72 = sub_BDE030();
        v62 = sub_BDE030();
        v51 = sub_BDE030();
        v34 = sub_BDE030();
        construct_Exception(v84, 26, (int)v34, (int)v51, (int)v62, (int)v72);
        _CxxThrowException(v84, (_ThrowInfo *)&_TI2_AVException_wbs__);
      }
      if ( !sub_D478C0((int)v15, (int)encrypt_option) )// 指定的产品码选项参数错误, 错误 25.
      {
        v73 = sub_BDE030();
        v63 = sub_BDE030();
        v52 = sub_BDE030();
        v35 = sub_BDE030();
        construct_Exception(v83, 25, (int)v35, (int)v52, (int)v63, (int)v73);
        _CxxThrowException(v83, (_ThrowInfo *)&_TI2_AVException_wbs__);
      }
      v45 = (int)v16;
      len_1 = len;
      v17 = sub_D46EB0(
              (struct_cmcrypt *)((char *)&v87 + 4),
              flctrl_1,
              cmcrypt2,
              len,
              *(_DWORD *)(*(_DWORD *)(v96 + 244) + 832),
              v45,
              0,
              0);
      v103 = -1;
      algorithms = *v17;
      sub_BF8660(v99);
	  */
    }
    else
    {
		//非UVD正常获取加密算法
      algorithms = *(struct_cmcrypt *)cm_crypt_get_alg(
                                        (int)&v87 + 4,
                                        flctrl_1,
                                        cmcrypt2,
                                        cbDest,
                                        *(_DWORD *)(*(_DWORD *)(v96 + 244) + 832),
                                        0,
                                        0);
    }
    hcmse_3[0] = sub_C0EC30((_DWORD *)(hcmse_3[0] + 328), 0x700);
    encrypt_option = (void *)(cmcrypt2->mcmBaseCrypt.mulEncryptionCodeOptions & 0xF0000);
    if ( sub_BFEE40((_BYTE *)global_1360FC4) )
      goto LABEL_27;
    if ( encrypt_option == (void *)0x20000 )    // CM_CRYPT_SASTATIONSHARE
    {
      v18 = hcmse_3[0] == 768;
    }
    else
    {
      if ( encrypt_option != (void *)0x40000 )
      {
        if ( encrypt_option == (void *)0x80000 )
        {
          v18 = hcmse_3[0] == 512;
          goto LABEL_26;
        }
LABEL_27:
        if ( (cmcrypt2->mcmBaseCrypt.mflCtrl & 0x20000) != 0 )// calc crc
        {
          init_crc(hcmse_3);
          crc32(hcmse_3, (char *)pbDest_3, algorithms.cbDest_);
          cmcrypt2->mcmBaseCrypt.mulCrc = bit_negration(hcmse_3);
        }
        if ( (flctrl_1 & 0xF) == 2 )
        {
          v19 = *(_DWORD *)(v96 + 20);
          if ( !v19 || v19 != v93[1] )
          {
            v75 = sub_BDE030();
            v65 = sub_BDE030();
            v54 = sub_BDE030();
            v37 = sub_BDE030();
            construct_Exception(v81, 123, (int)v37, (int)v54, (int)v65, (int)v75);// CmDongle没有CTSB功能模块, 错误 123.
            _CxxThrowException(v81, (_ThrowInfo *)&_TI2_AVException_wbs__);
          }
        }
        v103 = 1;
        if ( !do_crypt_job(v96, v91, &algorithms, pbDest_2, pbDest_2) ) //进行加解密
        {
          v38 = sub_BDE030();
          v39 = sub_BDE030();
          encrypt_option = sub_BDE030();
          v40 = sub_BDE030();
          v55 = (int)encrypt_option;
          v44 = (int)v40;
          errcode = sub_C4B310(*(_DWORD **)(v96 + 244));
          construct_Exception(v80, errcode, v44, v55, (int)v39, (int)v38);
          _CxxThrowException(v80, (_ThrowInfo *)&_TI2_AVException_wbs__);
        }
        v103 = -1;
        if ( algorithms.algorithms == 2 || algorithms.algorithms == 3 )
          *v94 = len_1;
        else
          *v94 = algorithms.cbDest_;
        if ( (cmcrypt2->mcmBaseCrypt.mflCtrl & 0x10000) != 0 )// CM_CRYPT_CHKCRC
        {
          init_crc(&pbDest_2);
          crc32((unsigned int *)&pbDest_2, (char *)pbDest_3, len_1);
          if ( cmcrypt2->mcmBaseCrypt.mulCrc != bit_negration(&pbDest_2) )
          {
            *v94 = 0;
            v76 = sub_BDE030();
            v66 = sub_BDE030();
            v56 = sub_BDE030();
            v42 = sub_BDE030();
            construct_Exception(v79, 203, (int)v42, (int)v56, (int)v66, (int)v76);// 校验数据检测失败, 错误 203.
            _CxxThrowException(v79, (_ThrowInfo *)&_TI2_AVException_wbs__);
          }
        }
        return;
      }
      if ( !hcmse_3[0] )
        goto LABEL_27;
      v18 = hcmse_3[0] == 1024;
    }
LABEL_26:
    if ( !v18 )
    {
      v74 = sub_BDE030();
      v64 = sub_BDE030();
      v53 = sub_BDE030();
      v36 = sub_BDE030();
      construct_Exception(v82, 223, (int)v36, (int)v53, (int)v64, (int)v74);// 所使用的访问模式与EncryptionCodeOption集冲突, 错误 223.
      _CxxThrowException(v82, (_ThrowInfo *)&_TI2_AVException_wbs__);
    }
    goto LABEL_27;
  }
  if ( !sub_C0ED00((_DWORD *)(hcmse_3[0] + 328)) )
  {
    v69 = sub_BDE030();
    v59 = sub_BDE030();
    v48 = sub_BDE030();
    v31 = sub_BDE030();
    construct_Exception(pExceptionObject, 116, (int)v31, (int)v48, (int)v59, (int)v69);// 给出的句柄指向了一个未定义的子系统, 错误 116.
    _CxxThrowException(pExceptionObject, (_ThrowInfo *)&_TI2_AVException_wbs__);
  }
  v20 = sub_C0EC20((_DWORD *)(hcmse_3[0] + 328));
  *hcmse_2 = v20;
  //Wubu Codemeter内部调试时用的代码,忽略
  /*
  if ( a9 )
  {
    memset(v97, 0, sizeof(v97));
    sub_CCC4F0(v97);
    v103 = 4;
    *(_DWORD *)&v97[40] = *hcmse_2;
    *(_DWORD *)&v97[44] = flctrl_1;
    qmemcpy(&v97[48], cmcrypt2, 0x90u);
    v27 = len;
    *(_DWORD *)&v97[192] = len;
    sub_C37B30(*(int *)&v97[352], len);
    if ( *(_DWORD *)(*(_DWORD *)&v97[352] + 8) )
      v28 = *(void **)(*(_DWORD *)&v97[352] + 4);
    else
      v28 = 0;
    *(_DWORD *)&v97[196] = v28;
    memmove(v28, pbDest_2, *(size_t *)&v97[192]);
    *(_DWORD *)&v97[348] = *(_DWORD *)&v97[196];
    v29 = (_DWORD *)sub_C0EC10((_DWORD *)(hcmse_3[0] + 328));
    cm_client_encrypt_req(v29, v97, 0xA1u, v27 + 164, v27 + 156);
    v68 = *(_DWORD *)&v97[192];
    v58 = *(const void **)&v97[348];
    v30 = encrypt_option;
    v47 = pbDest_3;
    *v93 = *(_DWORD *)&v97[8];
    qmemcpy(v30, &v97[204], 0x90u);
    memmove(v47, v58, v68);
    *(_DWORD *)&v97[348] = 0;
    *(_DWORD *)v97 = &YS0534::`vftable';
    *v94 = *(_DWORD *)&v97[200];
    if ( *(_DWORD *)&v97[352] )
      (***(void (__thiscall ****)(_DWORD, int))&v97[352])(*(_DWORD *)&v97[352], 1);
    *(_DWORD *)&v97[348] = 0;
    v26 = v97;
  }
  else
  {
    memset(&v97[208], 0, 0x94u);
    sub_CCC160();
    v21 = *(__m128d *)cmcrypt2->mabInitKey;
    LODWORD(v87) = cmcrypt2->mcmBaseCrypt.mflCtrl;
    *(_DWORD *)&v88[4] = cmcrypt2->mcmBaseCrypt.mulCrc;
    *((_QWORD *)&v87 + 1) = *(_QWORD *)&cmcrypt2->mcmBaseCrypt.mulEncryptionCode;
    *(_DWORD *)v88 = cmcrypt2->mcmBaseCrypt.mulFeatureCode;
    DWORD1(v87) = cmcrypt2->mcmBaseCrypt.mulKeyExtType;
    *(__m128d *)&v88[8] = v21;
    *(_OWORD *)&v97[256] = v87;
    *(_DWORD *)&v97[248] = *hcmse_2;
    v103 = 3;
    *(_DWORD *)&v97[252] = flctrl_1;
    *(_OWORD *)&v97[272] = *(_OWORD *)v88;
    *(_DWORD *)&v97[296] = cbDest;
    *(_QWORD *)&v97[288] = *(_OWORD *)&_mm_unpackhi_pd(v21, v21);
    sub_C37B30(*(int *)&v97[352], cbDest);
    if ( *(_DWORD *)(*(_DWORD *)&v97[352] + 8) )
      v22 = *(void **)(*(_DWORD *)&v97[352] + 4);
    else
      v22 = 0;
    *(_DWORD *)&v97[300] = v22;
    memmove(v22, pbDest_2, *(size_t *)&v97[296]);
    *(_DWORD *)&v97[348] = *(_DWORD *)&v97[300];
    v23 = (_DWORD *)sub_C0EC10((_DWORD *)(hcmse_3[0] + 328));
    cm_client_encrypt_req(v23, &v97[208], 0xA1u, cbDest + 60, cbDest + 52);
    v67 = *(_DWORD *)&v97[296];
    v57 = *(const void **)&v97[348];
    v46 = pbDest_3;
    *v93 = *(_DWORD *)&v97[216];
    memmove(v46, v57, v67);
    v24 = *(_OWORD *)&v97[332];
    *(_DWORD *)&v97[348] = 0;
    *v94 = *(_DWORD *)&v97[304];
    v25 = *(void (__thiscall ****)(_DWORD, int))&v97[352];
    cmcrypt2->mcmBaseCrypt.mflCtrl = *(_DWORD *)&v97[308];
    cmcrypt2->mcmBaseCrypt.mulCrc = *(_DWORD *)&v97[328];
    cmcrypt2->mcmBaseCrypt.mulEncryptionCode = *(_DWORD *)&v97[316];
    cmcrypt2->mcmBaseCrypt.mulEncryptionCodeOptions = *(_DWORD *)&v97[320];
    cmcrypt2->mcmBaseCrypt.mulFeatureCode = *(_DWORD *)&v97[324];
    cmcrypt2->mcmBaseCrypt.mulKeyExtType = *(_DWORD *)&v97[312];
    *(_DWORD *)&v97[208] = &YS0059::`vftable';
    *(_OWORD *)cmcrypt2->mabInitKey = v24;
    if ( v25 )
      (**v25)(v25, 1);
    *(_DWORD *)&v97[348] = 0;
    v26 = &v97[208];
  }
  */
  sub_D28150(v26);
}
/* Orphan comments:
Key Source FIRMKEY HIDDENDATA SECRETDATA
*/

参数等经过经过简单的处理后被传入do_crypt_job中

int __thiscall do_crypt_job(int this, int a2, struct_cmcrypt *algorithms, void *len, void *pdest_1)
{
  __int16 *v7; // ebp
  int v8; // ebp
  int v10; // [esp+14h] [ebp-4h]
  int v11; // [esp+1Ch] [ebp+4h]

  if ( a2 )
    v7 = *(__int16 **)(a2 + 380);
  else
    v7 = 0;
  v11 = sub_CAFC00(a2, (unsigned __int8 (__thiscall *)(int))sub_C5B150);
  sub_CAFC00(a2, (unsigned __int8 (__thiscall *)(int))sub_C5B140);
  v10 = *(_DWORD *)(v11 + 16);
  v8 = do_crypt_job_0(
         *(void **)(this + 244),
         *v7,
         *(_WORD *)(a2 + 4),
         algorithms,
         len,
         pdest_1,
         v7 + 8,
         (_DWORD *)(v11 + 16));
  if ( !v8 )
    return v8;
  sub_C58C50(v11);
  sub_C589C0();
  sub_C80590(a2, algorithms, this);
  if ( v10 != *(_DWORD *)(v11 + 16) )
    sub_C0DE40(2048);
  if ( !*(_BYTE *)(this + 241) && !*(_BYTE *)(this + 240) )
    return v8;
  if ( len )
    *(_WORD *)len = 0;
  *(_DWORD *)(*(_DWORD *)(this + 244) + 908) = 21;
  return 0;
}
int __thiscall do_crypt_job_0(
        void *this,
        __int16 a2,
        __int16 a3,
        struct_cmcrypt *algorithms,
        void *len,
        void *pdest_1,
        _WORD *a7,
        _DWORD *a8)
{
  int algorithms_1; // eax
  int v9; // esi
  struct_v18 *v10; // ecx
  unsigned int v11; // eax
  __int16 v12; // si
  __int16 v13; // cx
  __int16 cbDest; // ax
  unsigned int v15; // ecx
  struct_v18 *Block; // [esp+1Ch] [ebp-60h]
  struct_v18 *v18; // [esp+24h] [ebp-58h]
  unsigned int v19; // [esp+28h] [ebp-54h]
  int v21; // [esp+2Ch] [ebp-50h]
  void *Src; // [esp+34h] [ebp-48h]
  char v23; // [esp+3Bh] [ebp-41h]

  v23 = 0;
  (*(void (__thiscall **)(void *))(*(_DWORD *)this + 56))(this);
  algorithms_1 = algorithms->algorithms;
  v9 = algorithms->cbDest + 27;
  if ( (!algorithms->algorithms || algorithms_1 == 1 || algorithms_1 == 5)
    && (algorithms->mulSecondsSince01_01_2000 || (algorithms->mulEncryptionCodeOptions & 0xF00000) == 0x100000) )
  {
    v9 = algorithms->cbDest + 31;
    v23 = 1;
  }
  v19 = (v9 + 19) & 0xFFFFFFF0;
  if ( v19 )
  {
    v10 = (struct_v18 *)operator new[]((v9 + 19) & 0xFFFFFFF0);
    v11 = (v9 + 19) & 0xFFFFFFF0;
  }
  else
  {
    v10 = 0;
    v11 = 0;
  }
  Block = v10;
  if ( !v11 )
    v10 = 0;
  v18 = v10;
  *(_WORD *)v10->gap0 = v9;
  v12 = 1;
  v10->gap0[4] = 2;
  v13 = 1;
  if ( !BYTE2(algorithms->mulKeyExtType) )
    v13 = a3;
  if ( !BYTE2(algorithms->mulKeyExtType) )
    v12 = a2;
  v18->word5 = v12;
  v18->word7 = v13;
  v18->keySource = algorithms->keySource;
  if ( BYTE1(algorithms->mulKeyExtType) )
    v18->keySource |= 0x8000u;
  v18->mulKeyExtType = algorithms->mulKeyExtType;
  v18->algorithms = algorithms->algorithms;
  v18->mulFeatureCode = algorithms->mulFeatureCode;
  v18->mulEncryptionCode = algorithms->mulEncryptionCode;
  v18->mulEncryptionCodeOptions = algorithms->mulEncryptionCodeOptions;
  cbDest = algorithms->cbDest;
  v18->cbDest = cbDest;
  if ( v23 )
  {
    v18->keySource |= 0x4000u;
    v18->cbDest = cbDest + 4;
    *(_DWORD *)&v18->pbDest = algorithms->mulSecondsSince01_01_2000;
    memmove(&v18->pbDest1, pdest_1, algorithms->cbDest);
  }
  else
  {
    memmove(&v18->pbDest, pdest_1, algorithms->cbDest);
  }
  v15 = (algorithms->cbDest_ + 29) & 0xFFFFFFF0;
  Src = (void *)v15;
  if ( v15 )
  {
    if ( v15 > 0x7FFFFFFF )
      sub_BD9DE0();
    sub_BED070(v15);
    memset(0, 0, (size_t)Src);
    v15 = (unsigned int)Src;
  }
  if ( (*(int (__thiscall **)(void *, struct_v18 *, unsigned int, _DWORD, unsigned int, int, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)this + 12))(// cm_encrypt_alg
                                                // func_interested
         this,
         v18,
         v19,
         0,
         v15,
         0x400000,
         0,
         0,
         0,
         0) )
  {
    *a7 = MEMORY[6];
    *a8 = MEMORY[2];
    memmove(len, (const void *)0xA, algorithms->cbDest_);
    v21 = MEMORY[8];
  }
  else
  {
    v21 = 0;
  }
  if ( Block )
    j_j__free(Block);
  sub_BDCCA0();
  return v21;
}

do_crypt_job中做事不多,转交给do_crypt_job_0,再由do_crypt_job_0进行转发至相应的算法。

值得注意的是,在正常的请求下(mflCtrl为CM_CRYPT_AES,CM_CRYPT_ECIES等),会被转发到cm_encrypt_alg。服务端大多数注意安全性的算法都转发到这个函数进行加解密操作。这种正常的CmCrypt之后会在Wibu Codemeter 7.3学习笔记——Codemeter服务端上说

而对于mfCtrl = 0x6000000这个AxProtector壳特有的则被转发到func_interested(暂且这么命名)进行处理。

unsigned int __thiscall func_interested(
        _BYTE *this,
        struct_v18 *a2,
        size_t a3,
        void *a4,
        int a5,
        unsigned int a6,
        int a7,
        char a8,
        int a9,
        char a10)
{
  int v11; // eax
  unsigned int v12; // esi
  int v14; // [esp+0h] [ebp-3Ch] BYREF
  struct_v18 *v15; // [esp+10h] [ebp-2Ch]
  void *v16; // [esp+14h] [ebp-28h]
  int v17; // [esp+18h] [ebp-24h]
  _BYTE *v18; // [esp+1Ch] [ebp-20h]
  int v19; // [esp+20h] [ebp-1Ch] BYREF
  int v20[3]; // [esp+24h] [ebp-18h] BYREF
  int v21; // [esp+38h] [ebp-4h]

  v20[2] = (int)&v14;
  v15 = a2;
  v16 = a4;
  v18 = this;
  v17 = a9;
  if ( !a8 && !this[964] && !(*(unsigned __int8 (__thiscall **)(_BYTE *))(*(_DWORD *)this + 48))(this) )
  {
    v20[0] = 0;
    v11 = *(_DWORD *)this;
    v21 = 0;
    LOBYTE(v19) = 0;
    (*(void (__thiscall **)(_BYTE *, int *))(v11 + 32))(this, &v19);
    sub_D51FD0(v19);
    this[964] = 1;
    v21 = -1;
  }
  v20[0] = 0;
  sub_BE9A20((int)(this + 904));
  v21 = 2;
  v12 = func_1(this, v15, a3, v16, a5, a6, a7, a8, v17, a10);
  sub_BE9A90(v20);
  return v12;
}

而func_interested又转发到func_1(暂且这么命名),这个func_1便是真正做事的地方

(func_1挺大的,过几天更)

最后于 2023-1-9 00:47 被ericyudatou编辑 ,原因:
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-9 00:35
8
0

func_1

大工程,慢慢更

对传入的pbDest下内存断点,断下三次后在对func_1复制过的pbDest下内存断点,跟踪,运行,这里显示的值是pbDest的第一位

在这次运行中,原始传入的40字节pbDest如下图蓝框中,第一位为0x6E

加密后的pbDest如下图,前是16为加密后的结果(红框),后面的则是原始pbDest填充,第一位为0x55

一眼丁真的发现(其实是经历很多测试),加密前后的pbDest是跟内存断点跟踪的结果是相同的,并且是有个这样的过程

0x6E(原始)-->0x64 --->0x59 -->0x55(结果)

大概这个算法分为三个阶段,并且不太可能使用太过复杂的算法

(未完待续)

最后于 2023-1-10 00:37 被ericyudatou编辑 ,原因:
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-16 00:23
9
0

书接上回,通过内存断点发现真正做事的函数func_2,对于func_1和func_1是怎么调用到func_2不必深究,只需要知道ecx+399是pbDest,ecx+397是cbDest即可。整个函数挺大的,不方便贴伪代码贴全。分析可得,整个加密过程分为两轮。因为我也不是专业做逆向的,找不到趁手的跟踪方法,故只能边录屏边F8,视频放最后。

第一轮

         case 7:                               // axprotector  0x6000000 round 1
            p_pbDest_1 = pbDest;
            sub_7FA840(this, 0, 0);
            sub_753900(this->pvoid5E4, this->dword13E);
            sub_753800(this->pvoid5E4, this->arr.mulEncryptionCode);
            sub_753870(this->pvoid5E4, 2);
            nullsub_1(this->pvoid5E4);
            sub_753B00(this->pvoid5E4);
            nullsub_1(this->pvoid5E4);
            arg_interested = sub_7536C0(this->pvoid5E4);
            pbDest_1_1 = p_pbDest;
            *arg_interested = *p_pbDest;
            *(arg_interested + 1) = *(pbDest_1_1 + 4);
            *(arg_interested + 2) = this->dword144;
            *(arg_interested + 3) = this->dword13E;
            sub_7533E0(this->pvoid5E4, arg_interested);
            nullsub_1(this->pvoid5E4);
            nullsub_1(this->pvoid5E4);
            sub_7537E0(arg_interested);         // aes job
            sub_753720(this->pvoid5E4);
            crypt_job_1(this->pvoid5E4, p_pbDest + 8, len_4 - 8);// crypt job 1,进行加密   change round 1 9~40
            nullsub_1(this->pvoid5E4);
            pbDest_4 = p_pbDest;
            this->arr.keySource = *(p_pbDest + 4);  //准备下一轮参数
            this->arr.mulKeyExtType = *(pbDest_4 + 10);
            this->arr.algorithms = *(pbDest_4 + 11);
            this->arr.mulFeatureCode ^= *(pbDest_4 + 12);
            this->arr.mulEncryptionCode = *(pbDest_4 + 16);
            this->arr.mulEncryptionCodeOptions ^= *(pbDest_4 + 20);// init arg for round 2
            len_3 = cbDest_1;
            if ( v116 )
            {
              pbDest = &this->arr.pbDest1;
              cbDest_1 += 65496;
              memmove(&this->arr.pbDest1, (pbDest_4 + 40), (len_3 - 40));
              pbDest_5 = p_pbDest;
              p_pbDest = &this->arr.pbDest1;
              *&this->arr.pbDest = pbDest_5[6];
            }
            else
            {
              pbDest = &this->arr.pbDest;       // here
              cbDest_1 += 65512;
              p_pbDest = &this->arr.pbDest;
              memmove(&this->arr.pbDest, p_pbDest_1 + 24, (len_3 - 24));// changed 2 0~15
                                                // 把后16位复制到前16位
            }
            v131 = -1;                          // changed_1
            nullsub_1(&v121);
            v6 = cbDest_1;
            continue;                           // to round 2

简单的分析可知,round 1做的事就是通过crypt_job_1加密pbDest的9~40位,然后再将操作后的最后16位复制到前16位。并且准备下一轮的参数。

对于其中第一轮加密,首先对一个结构体(暂称之为round1aes1)前55位求SHA256散列值的前16位作为AES加密的密钥,再将pDest前8位拼接Firm Code,Product Code作为明文,进行AES_CBC_128的加密(iv = 0),其结果的前16位作为参数参与到crypt_job_1中

			struct round1aes1{
				DWORD constant1 = 0x77****E5;//<-----------与firm code相关
				DWORD constant2 = 0xB5****9F;
				DWORD constant3 = 0x66****C0;
				DWORD constant4 = 0x52****66;
				DWORD FirmCode = 0;
				DWORD ProductCode = 0;
				DWORD gap1 = 0;
				DWORD EncryptionCode = 0x1337;
				DWORD gap2 = 0;
				DWORD constant_round = 2;
				DWORD gap3 = 0;
				DWORD gap4 = 0;
				DWORD gap5 = 0;
				DWORD gap6 = 0x00000000;
			}round1aes1;

值得注意的是,对于同一个公司的产品(Firm Code相同),所对应的constant1~4相同,不随机器特征码改变,为常量。且不与Firm Code存在关系,为公司指定的(随机生成的)数据。不存在与客户端AxProtector程序上,只存在服务器Codemeter上。因此,对AxProtector保护的程序脱壳必须有一个合法的授权才能对程序进行解密

第一轮:crypt_job_1

void __thiscall crypt_job_1(void *this, _OWORD *pBuf, int len)
{
  char *v3; // ebp
  unsigned int v5; // ebx
  char *v6; // esi
  int v7; // ecx
  int v8; // edx
  char v9; // al
  char *lena; // [esp+Ch] [ebp+8h]

  if ( len )
  {
    v3 = this + 320;
    v5 = ((len - 1) >> 4) + 1;
    lena = this + 2422;
    do
    {
      v6 = sub_5A8310(v3);
      *v6 = *pBuf;
      sub_5A8350(v3);
      v7 = 16;
      v8 = lena - v6;
      do
      {
        v9 = (v6++)[v8];
        *(v6 - 1) ^= v9;
        v6[v8 - 1] = *pBuf;
        *pBuf = *(v6 - 1);
        pBuf = (pBuf + 1);
        --v7;
      }
      while ( v7 );
      --v5;
    }
    while ( v5 );
  }
}

crypt_job_1这个函数比较简单,不多赘述。传入pDest 9~40位(32)和上一步AES加密出来的前16位,简单的位运算,然后准备下一轮的参数,并将pDest最后16位复制到前16位。

            this->arr.keySource = *(p_pbDest + 4);  //准备下一轮参数
            this->arr.mulKeyExtType = *(pbDest_4 + 10);
            this->arr.algorithms = *(pbDest_4 + 11);
            this->arr.mulFeatureCode ^= *(pbDest_4 + 12);
            this->arr.mulEncryptionCode = *(pbDest_4 + 16);
            this->arr.mulEncryptionCodeOptions ^= *(pbDest_4 + 20);// init arg for round 1

视频

最后于 2023-1-25 03:13 被ericyudatou编辑 ,原因:
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-25 09:13
10
0

第二轮

……
        if ( !gen_firm_product_code(this, this->arr.word7, this->arr.keySource) )// set seed1 seed2
                                                // 
                                                // seed1 4C4D0Eh 来自firm item
                                                // seed2 100000h
……
LABEL_101:
            gen_aes_constant(this, 0, flag_sd_b_1 ? 59 : 0);// round 2
            set_aes_productcode(*(void **)((char *)&this->aes_job + 2), this->produccode);// product code
            set_aes_featurcode(
              *(void **)((char *)&this->aes_job + 2),
              *(_DWORD *)((char *)&this->arr.mulFeatureCode + 2));
            set_aes_encryptioncode(
              *(void **)((char *)&this->aes_job + 2),
              *(_DWORD *)((char *)&this->mulEncryptionCode + 2));
            set_aes_encryptioncodeoption(
              *(void **)((char *)&this->aes_job + 2),
              *(_DWORD *)((char *)&this->mulEncryptionCodeOptions + 2));
            if ( flag_sd_b_1 )                  // round2 0
              sub_C33950(*(int **)((char *)&this->aes_job + 2), *(_DWORD *)&this->arr.gap1C[1]);
            if ( this->algorithms == 5 )
              set_aes_type_constant(*(void **)((char *)&this->aes_job + 2), 1);
            v32 = *(void **)((char *)&this->aes_job + 2);
            if ( *(__int16 *)&this->arr.mulKeyExtType >= 0 )
            {
              nullsub_1(v32);
              aes_job_1 = *(BYTE **)((char *)&this->aes_job + 2);
              if ( algorithms_3 )
              {
                if ( this->algorithms == 5 )
                  doAesKeySHA_0(aes_job_1, this->constant_round2aes1);
                else
                  doAesKeySHA(aes_job_1);
              }
              else
              {
                doAesKey(aes_job_1);
              }
              if ( (*(_DWORD *)((_BYTE *)&this->mulEncryptionCodeOptions + 2) & 0x200000) != 0 )
              {
                v35 = *(void **)((char *)&this->aes_job + 2);
                this->word4E = 40;
                nullsub_1(v35);
                nullsub_1(&v122);
                return;
              }
              if ( this->algorithms == 5 && func_key_changed_3(pbDest, (int)this->constant_round2aes1, 16) )
              {
                *(_WORD *)this->gap166 = 0;
                gen_rand_arr(pbDest, 0x10u);    // fuck up
              }
              func2_aes_encrypt(*(char **)((char *)&this->aes_job + 2), pbDest);
              nullsub_1(*(void **)((char *)&this->aes_job + 2));
            }
            else
            {
              nullsub_1(v32);
              aes_job_2 = *(int (__cdecl ***)(int, int, int, int, int))((char *)&this->aes_job + 2);
              if ( algorithms_3 )
              {
                if ( this->algorithms == 5 )
                  doAesKeySHA_2((int)aes_job_2, this->constant_round2aes1);// here
                else
                  doAesKeySHA_1((int)aes_job_2);
              }
              else
              {
                sub_C33AC0(aes_job_2);
              }
              func_key_changed_2(*(char **)((char *)&this->aes_job + 2), pbDest);// round2 key change 1 前16位
              nullsub_1(*(void **)((char *)&this->aes_job + 2));
              if ( this->algorithms == 5 && func_key_changed_3(pbDest, (int)this->constant_round2aes1, 16) )
              {
                *(_WORD *)this->gap166 = 0;
                gen_rand_arr(pbDest, 0x10u);    // fuck up
              }
            }
            if ( algorithms_org == 7 )
            {
              key2 = sub_C336C0(*(char **)((char *)&this->aes_job + 2));// final
              nullsub_1(*(void **)((char *)&this->aes_job + 2));
              set_aes_key(*(int (__cdecl ***)(int, int, int, int, int))((char *)&this->aes_job + 2), (int)key2);
              nullsub_1(*(void **)((char *)&this->aes_job + 2));
              pbDest = p_pbDest;
              func_key_changed_2(*(char **)((char *)&this->aes_job + 2), p_pbDest);// round2 key change 2
              nullsub_1(*(void **)((char *)&this->aes_job + 2));
            }
 crypt_job_2(this, pbDest, *(unsigned __int16 *)len_5);
 sub_CD8B20(this);
 LOBYTE(this->aes_job) = 0;
 return;

crypt_job_2并没有参与到加密数据的加密过程中,故不研究

首先还是声明一个结构体round2aes1,对其前55位求SHA256散列值,取散列值前16位作为第一次AES解密的密钥

接着是对pDest前16位进行第一次AES_CBC_128解密(iv=0),密钥为散列值前16位。

坠吼是对pDest前16位进行第一次AES_CBC_128解密(iv=0),密钥为第一轮第一次AES加密所生成的密文的前16位。

此时pDest的前16位就是我们想要的数据了。

			struct round2aes1 {
				DWORD constant1 = 0x4E****74; //CmAct私钥
				DWORD constant2 = 0x4E****7C;
				DWORD constant3 = 0x78****C1;
				DWORD constant4 = 0xFE****22;
				DWORD FirmCode = 0;
				DWORD ProductCode = 0;
				DWORD FeatureCode = 0;
				DWORD EncryptionCode = 0;
				DWORD EncryptionCodeOption = 0;
				DWORD constant_round = 1;
				DWORD gap3 = 0;
				DWORD gap4 = 0;
				DWORD gap5 = 0;
				DWORD gap6 = 0x80000000;
			}round2aes1;

需要注意的是这里的FirmCode,Product Code等参数都是经过第一轮加密变换的。

值得注意的是,对于同一个公司的同一个产品(Firm Code,Product Code相同),所对应的constant1~4相同,为这个产品的ECDSA私钥前16位。

AxProtectot-Codemeter保护系统的强度不体现在其纸老虎似的ECDSA,唬人的反调试,哈人的"毁狗",还是那略显迷惑的通信算法,而是在于公司的私钥和产品的私钥。

这两个私钥不仅仅参与到他们所对应的非对称加密算法(ECDSA),还参与到普通的对称加密算法,可执行文件的解密过程中,使得没有可用授权的破解变为不可能,破解这个AxProtectot-Codemeter保护系统必须得有一个可用的授权

附加一份加密过程的日志

[*]Client encrypted package
[*]Encrypted package decrypt:SUCCESS,len:204,time:47754
[*]Function Request:CmCrypt2
[*]HCMSE 2,flCtrl 0,mflCtrl 06000000,feature code 2924a1dd,crc 0,mulEncryptionCode 00001337 mulEncryptionCodeOptions 51023a51
[*]pDest:(40)
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffc2 ffffffe1 ffffffd4 34 30 47 ffffffa9 ffffff94 ffffff99 40 ffffffe2 26 ffffffd3 ffffffcd 75 ffffffcb
[*]ffffffe3 ffffff96 ffffffe0 67 0d ffffffc2 21 ffffffba 23 44 fffffff6 ffffff95 0b 7c ffffffa2 ffffffb4
[*]3f ffffff91 72 25 4b 7a 28 ffffffd1
[*]----------------------------------------------END------------------------------------------------------
[*]InitKey:(16)
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*]DirectAesKey:(16)
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*]Mode:Direct encryption
[*]Key Source: Firmware Key
[*]Encryption Algorithm: Unknown 100663296
[*][CmCrypt2]AxProtectot CmCrypt 0x6000000 function start,Firm Code 5000462,Product Code 3
[*][CmCrypt2]AxProtectot C6F Round 1 AES JOB 1 Start
[*][CmCrypt2]AxProtectot C6F Round 1 AES JOB 1 SHA256
[*][CmCrypt2]AxProtectot C6F Round 1 AES JOB 1 AES key:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]3e fffffffb 7d 2e ffffff95 21 ffffff96 7d ffffffa5 1e ffffff82 ffffffa5 ffffffdc 5a 5f 4b
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 AES JOB 1 AES plain text:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffc2 ffffffe1 ffffffd4 34 30 47 ffffffa9 ffffff94 0e 4d 4c 00 03 00 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 AES JOB 1 AES result(Also Round 1 AES JOB 2 Key):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffc0 69 ffffffe1 ffffffa2 ffffffd1 ffffffa6 51 ffffffc9 16 ffffffb2 68 58 41 ffffffa4 0c 59
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 start
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Start
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffff99 40 ffffffe2 26 ffffffd3 ffffffcd 75 ffffffcb ffffffe3 ffffff96 ffffffe0 67 0d ffffffc2 21 ffffffba
[*]23 44 fffffff6 ffffff95 0b 7c ffffffa2 ffffffb4 3f ffffff91 72 25 4b 7a 28 ffffffd1
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 1 AES reslut->pplaintext
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 ffffff80 00 05 ffffffdd ffffffa3 24 29 11 ffffff84 6b 36 51 3a 00 51
[*]00 ffffff80 00 05 ffffffdd ffffffa3 24 29 11 ffffff84 6b 36 51 3a 00 51
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 1 Result->pInBufOrg
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 ffffff80 00 05 ffffffdd ffffffa3 24 29 11 ffffff84 6b 36 51 3a 00 51
[*]23 44 fffffff6 ffffff95 0b 7c ffffffa2 ffffffb4 3f ffffff91 72 25 4b 7a 28 ffffffd1
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 1 Result->pplaintext
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 ffffff80 00 05 ffffffdd ffffffa3 24 29 11 ffffff84 6b 36 51 3a 00 51
[*]45 ffffffe8 ffffff9b ffffffd6 08 fffffffb 2c 03 ffffffd5 ffffff83 1d 00 fffffff4 fffffffa 2c 03
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 1 Result->pbuf
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffff99 40 ffffffe2 26 ffffffd3 ffffffcd 75 ffffffcb ffffffe3 ffffff96 ffffffe0 67 0d ffffffc2 21 ffffffba
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 2 AES reslut->pplaintext
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffc9 0b 32 ffffff92 27 47 71 54 ffffffd4 ffffffc0 26 ffffff8a 7a 78 ffffffc6 46
[*]ffffffc9 0b 32 ffffff92 27 47 71 54 ffffffd4 ffffffc0 26 ffffff8a 7a 78 ffffffc6 46
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 2 Result->pInBufOrg
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 ffffff80 00 05 ffffffdd ffffffa3 24 29 11 ffffff84 6b 36 51 3a 00 51
[*]50 4b ffffffd0 ffffffb4 fffffff4 ffffff8a 04 ffffff9f 37 56 ffffffc6 ffffffed 77 ffffffba ffffffe7 fffffffc
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 2 Result->pplaintext
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]45 ffffffe8 ffffff9b ffffffd6 08 fffffffb 2c 03 ffffffd5 ffffff83 1d 00 fffffff4 fffffffa 2c 03
[*]7c fffffff2 2c 03 20 00 00 00 10 41 1d 00 10 41 1d 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 Round 2 Result->pbuf
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]23 44 fffffff6 ffffff95 0b 7c ffffffa2 ffffffb4 3f ffffff91 72 25 4b 7a 28 ffffffd1
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 crypt_job_1 done!result:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffc2 ffffffe1 ffffffd4 34 30 47 ffffffa9 ffffff94 00 ffffff80 00 05 ffffffdd ffffffa3 24 29
[*]11 ffffff84 6b 36 51 3a 00 51 50 4b ffffffd0 ffffffb4 fffffff4 ffffff8a 04 ffffff9f
[*]37 56 ffffffc6 ffffffed 77 ffffffba ffffffe7 fffffffc
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 1 result:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]50 4b ffffffd0 ffffffb4 fffffff4 ffffff8a 04 ffffff9f 37 56 ffffffc6 ffffffed 77 ffffffba ffffffe7 fffffffc
[*]11 ffffff84 6b 36 51 3a 00 51 50 4b ffffffd0 ffffffb4 fffffff4 ffffff8a 04 ffffff9f
[*]37 56 ffffffc6 ffffffed 77 ffffffba ffffffe7 fffffffc
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 2 Start,keySource 8000 KeyExtType 00 FeatureCode 200 EncryptionCode 366b8411 EncryptionCodeOptions 20000 alogrithm 05
[*][CmCrypt2]AxProtectot C6F Round 2 Serving Gasturb Smooth C
[*][CmCrypt2]AxProtectot C6F Round 2 AES JOB 1 SHA256
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffcc ffffff8e 62 60 ffffffae ffffff8c ffffffad ffffff91 ffffffca 3b ffffffbd ffffffa8 fffffff4 7d 31 ffffffa5
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 2 AES JOB 1 pDest (16):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]50 4b ffffffd0 ffffffb4 fffffff4 ffffff8a 04 ffffff9f 37 56 ffffffc6 ffffffed 77 ffffffba ffffffe7 fffffffc
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 2 AES JOB 1 Result:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]17 fffffff0 7c ffffff99 ffffffca ffffffca ffffffbf 25 10 54 ffffffd0 46 ffffffe4 ffffffa2 63 ffffff94
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 2 AES JOB 2 Key:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffc0 69 ffffffe1 ffffffa2 ffffffd1 ffffffa6 51 ffffffc9 16 ffffffb2 68 58 41 ffffffa4 0c 59
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 2 AES JOB 2 pDest (16):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]17 fffffff0 7c ffffff99 ffffffca ffffffca ffffffbf 25 10 54 ffffffd0 46 ffffffe4 ffffffa2 63 ffffff94
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmCrypt2]AxProtectot C6F Round 2 AES JOB 2 Result (16),AxProtectot C6F END,16 byte payload:
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]ffffffd8 ffffffc9 2c 56 61 ffffff90 ffffffbd ffffff94 0f 1c 64 4c 5f ffffff80 21 ffffffa2
[*]
[*]----------------------------------------------END------------------------------------------------------
[*][CmSendMessage]ENCRYPT SUCCESS
[*][CmSendMessage]Message send(196):
[*]-------------------------------------------PRINT HEX---------------------------------------------------
[*]00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
[*]-------------------------------------------------------------------------------------------------------
[*]00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[*]00 00 00 00 00 00 00 00 ffffffd8 ffffffc9 2c 56 61 ffffff90 ffffffbd ffffff94
[*]0f 1c 64 4c 5f ffffff80 21 ffffffa2 ffffffe3 ffffff96 ffffffe0 67 0d ffffffc2 21 ffffffba
[*]23 44 fffffff6 ffffff95 0b 7c ffffffa2 ffffffb4 3f ffffff91 72 25 4b 7a 28 ffffffd1
[*]00 00 00 00
[*]----------------------------------------------END------------------------------------------------------


最后于 2023-1-25 09:20 被ericyudatou编辑 ,原因:
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-25 11:00
11
0
吃羊杂去了,晚上更过自校验
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ericyudatou 活跃值 2 2023-1-26 11:59
12
0

自校验

在实现了CmCrypt2 Axprotector 0x6000000之后,理论上程序可以运行。但一旦设了(软)断点或者是修改了代码,程序就跑不起来,报错说代码完整性检查失败。

随便在代码段设个硬件断点

发现断在memmove,简单的看了一下,发现调用链如下

doMemCheck->memcheck_doSha_0->memcheck_doSha->sha256_update->memmove

bool __thiscall doMemCheck(int this, int a2, unsigned __int8 *a3, int a4, int a5, int a6, int a7)
{
  unsigned __int8 *v7; // esi
  _DWORD *v10; // edx
  unsigned int v11; // esi
  int *v12; // ecx
  bool v13; // cf
  bool v14; // bl
  _DWORD *v15; // [esp+Ch] [ebp-90h]
  int v16[4]; // [esp+18h] [ebp-84h] BYREF
  __int128 v17; // [esp+28h] [ebp-74h]
  char v18[96]; // [esp+38h] [ebp-64h] BYREF

  v7 = a3;
  if ( !a4 || !(unsigned __int8)sub_A01D00(a2, a4) )
    return 0;
  v15 = (_DWORD *)(this + 88);
  if ( (unsigned __int8)memcheck_doSha_0(a5, a6, this + 88) )
  {
    *(_OWORD *)v16 = 0i64;
    v17 = 0i64;
    sub_B13040(this + 88, v16);
    *(_DWORD *)(this + 92) = *(_DWORD *)(this + 88);
    if ( *(_BYTE *)(this + 4) )
    {
      memset(v18, 0, sizeof(v18));
      if ( !a3 )
        v7 = (unsigned __int8 *)(this + 5);
      v14 = checkECDSASignature(v18, v7, (unsigned __int8 *)(a4 + 64), (unsigned __int8 *)v16);
    }
    else
    {
      v10 = (_DWORD *)(a4 + 128);
      v11 = 28;
      v12 = v16;
      while ( *v12 == *v10 )
      {
        ++v12;
        ++v10;
        v13 = v11 < 4;
        v11 -= 4;
        if ( v13 )
        {
          v14 = 1;
          goto LABEL_15;
        }
      }
      v14 = 0;
    }
LABEL_15:
    LOBYTE(v15) = v14;
    nullsub_6(a7, a5, a6, v15, a4 + 128, v16);
    return v14;
  }
  else
  {
    *(_DWORD *)(this + 92) = *v15;
    return 0;
  }
}
char __thiscall memcheck_doSha_0(_DWORD *this, int a2, int a3, _DWORD *a4)
{
  int v5; // ebx
  unsigned int v6; // ecx
  unsigned int v7; // eax
  int v8; // edi
  _OWORD *v9; // eax
  __int128 v11; // [esp+18h] [ebp-94h] BYREF
  __int128 v12; // [esp+28h] [ebp-84h]
  char v13[112]; // [esp+38h] [ebp-74h] BYREF

  memset(v13, 0, sizeof(v13));
  init_sha256((int)v13);
  v5 = this[4];
  v6 = (v5 - this[3]) >> 4;
  v7 = (a4[2] - *a4) >> 5;
  v11 = 0i64;
  v12 = 0i64;
  if ( v6 > v7 )
  {
    if ( v6 > 0x7FFFFFF )
      sub_9FAD60();
    sub_9FA900(v6);
    v5 = this[4];
  }
  v8 = this[3];
  if ( v8 == v5 )
    return 1;
  while ( 1 )
  {
    init_sha256((int)v13);
    if ( !(*(unsigned __int8 (__thiscall **)(_DWORD *, int, int, int, char *, _DWORD, _DWORD))(*this + 28))(
            this,
            v8,
            a2,
            a3,
            v13,
            0,
            0) )
      break;
    sha256_final((BYTE *)&v11, (int)v13);
    v9 = (_OWORD *)a4[1];
    if ( v9 == (_OWORD *)a4[2] )
    {
      sub_B12D10(v9, &v11);
    }
    else
    {
      *v9 = v11;
      v9[1] = v12;
      a4[1] += 32;
    }
    v8 += 16;
    if ( v8 == v5 )
      return 1;
  }
  return 0;
}
char __thiscall memcheck_doSha(_DWORD *this, int a2, __int64 a3, int *a4, int a5, int a6)
{
  int *v7; // ecx
  int v8; // ebp
  unsigned int v9; // edi
  int (__thiscall *v10)(_DWORD *); // esi
  unsigned int v11; // ebx
  unsigned int v12; // edi
  _QWORD *v13; // esi
  unsigned int v14; // ebx
  unsigned int v15; // edx
  unsigned int v16; // ebp
  int (__thiscall *v17)(_DWORD *); // edi
  int v18; // eax
  int (__thiscall *v19)(_DWORD *); // edi
  int (__thiscall *v20)(_DWORD *); // edi
  int v21; // eax
  int (__thiscall *v22)(_DWORD *); // edi
  unsigned int v23; // edi
  int (__thiscall *v24)(_DWORD *); // esi
  BYTE *v25; // eax
  char result; // al
  int (__thiscall *v27)(_DWORD *); // esi
  BYTE *v28; // [esp-10h] [ebp-3Ch]
  unsigned int v29; // [esp-Ch] [ebp-38h]
  unsigned int v30; // [esp+8h] [ebp-24h]
  _DWORD *v31; // [esp+Ch] [ebp-20h]
  int *v32; // [esp+18h] [ebp-14h]
  int v33; // [esp+1Ch] [ebp-10h] BYREF
  __int64 v34; // [esp+20h] [ebp-Ch] BYREF

  v7 = &dword_B92C80;
  v8 = a2;
  if ( this[14] )
    v7 = (int *)this[14];
  v31 = this;
  v32 = v7;
  if ( *v7 == v7[1] )
  {
    v9 = *(_DWORD *)(a2 + 12);
    v10 = *(int (__thiscall **)(_DWORD *))(*this + 8);
    nullsub_1();
    v28 = (BYTE *)(*(_DWORD *)(a2 + 4) + v10(v31));
    sha256_update(a4, v28, v9);
    return 1;
  }
  v11 = *(_DWORD *)(a2 + 4);
  v33 = 0;
  v12 = v11;
  v34 = 0i64;
  v13 = (_QWORD *)*v7;
  v30 = v11;
  if ( *v7 == v7[1] )
  {
LABEL_15:
    v23 = *(_DWORD *)(v8 + 12) + v12;
    if ( v23 <= v11 )
      return 1;
    v24 = *(int (__thiscall **)(_DWORD *))(*this + 8);
    nullsub_1();
    v25 = (BYTE *)(v11 + v24(v31));
    v29 = v23 - v11;
LABEL_17:
    sha256_update(a4, v25, v29);
    return 1;
  }
  while ( 1 )
  {
    v14 = (*v13 >> 4) ^ ((unsigned __int16)*(_DWORD *)v13 ^ (unsigned __int16)(*v13 >> 4)) & 0xFFF;
    v15 = *(_DWORD *)(v8 + 4);
    if ( v14 >= v15 )
      break;
LABEL_12:
    v11 = v30;
LABEL_13:
    if ( ++v13 == (_QWORD *)v32[1] )
    {
      v12 = *(_DWORD *)(v8 + 4);
      this = v31;
      goto LABEL_15;
    }
  }
  v16 = v15 + *(_DWORD *)(v8 + 12);
  if ( v14 >= v16 )
  {
    if ( v16 <= v30 )
      return 1;
    v27 = *(int (__thiscall **)(_DWORD *))(*v31 + 8);
    nullsub_1();
    v25 = (BYTE *)(v30 + v27(v31));
    v29 = v16 - v30;
    goto LABEL_17;
  }
  switch ( (*v13 >> 12) & 0xF )
  {
    case 0i64:
    case 1i64:
    case 2i64:
    case 4i64:
    case 9i64:
      v8 = a2;
      goto LABEL_12;
    case 3i64:
      v17 = *(int (__thiscall **)(_DWORD *))(*v31 + 8);
      nullsub_1();
      v18 = v17(v31);
      sha256_update(a4, (BYTE *)(v30 + v18), v14 - v30);
      v19 = *(int (__thiscall **)(_DWORD *))(*v31 + 8);
      nullsub_1();
      v33 = a3 + *(_DWORD *)(v19(v31) + v14);
      sha256_update(a4, (BYTE *)&v33, 4u);
      v8 = a2;
      v11 = v14 + 4;
      v30 = v11;
      goto LABEL_13;
    case 0xAi64:
      v20 = *(int (__thiscall **)(_DWORD *))(*v31 + 8);
      nullsub_1();
      v21 = v20(v31);
      sha256_update(a4, (BYTE *)(v30 + v21), v14 - v30);
      v22 = *(int (__thiscall **)(_DWORD *))(*v31 + 8);
      nullsub_1();
      v34 = *(_QWORD *)(v22(v31) + v14) + a3;
      sha256_update(a4, (BYTE *)&v34, 8u);
      v8 = a2;
      v11 = v14 + 8;
      v30 = v11;
      goto LABEL_13;
    default:
      result = 0;
      break;
  }
  return result;
}

发现其对代码段分段求SHA256散列值,再将上一步的散列值再进行一次SHA256,然后用ECDSA验证签名

定位方法:

查看checkECDSASignature串式参考,就两个引用。除开CmValiateSignature以为另外一个就是doMemCheck

和谐方法:

把最后的堆栈检查函数改成mov   eax,1

雪    币: 162
活跃值: 活跃值 (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
CHYX 活跃值 6天前
13
0
硬件狗内的授权可以提取吗?实现脱狗行。
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
14
0
CHYX 硬件狗内的授权可以提取吗?实现脱狗行。
理论上可行 我手头没狗做不了测试 但有那两组秘钥就应该能做
雪    币: 162
活跃值: 活跃值 (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
CHYX 活跃值 6天前
15
0
是checkECDSASignature的密钥,还是,我感觉这里可以伪造一个,暴破checkECDSASignature应该就可以过了。对于后面的自校验,感觉应该是针对调试器而引起的软件不能正常开启吧。
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
16
0
CHYX 是checkECDSASignature的密钥,还是,我感觉这里可以伪造一个,暴破checkECDSASignature应该就可以过了。对于后面的自校验,感觉应该是针对调试器而引起的软件不能正常开启吧 ...
对,理论上把checkECDSASignature这个函数伪造了就可以无补丁运行,但我是懒狗,实现有、麻烦
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
17
0
调试器不下断点就没事,下了断点解完密就自杀
雪    币: 12
活跃值: 活跃值 (150)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whshizy 活跃值 6天前
18
0
大神,能否分享一下您修改的Wireshark
雪    币: 162
活跃值: 活跃值 (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
CHYX 活跃值 6天前
19
0
谢谢,估计如果脱壳的话,还有很常的路要走。
雪    币: 4213
活跃值: 活跃值 (3235)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
20
0

想要研究CodeMeter的话可以连上ookkaa 搭建的lumina服务器

分享一个搭好的ida lumina服务器
pull request,我把Codemeter 7.2的分析结果都推上去了

游客
登录 | 注册 方可回帖
返回