欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[分享]ECC替换公钥实践(上篇)

[分享]ECC替换公钥实践(上篇)

下篇:http://bbs.pediy.com/showthread.php?t=192245
这段时间花了点时间研究了下怎么替换ECC公钥(v9.2 ~ v11.11.1.1),在这里与感兴趣的朋友分享下。
==================================
生成用自定义公钥、私钥的keygen
==================================
要生成120位SIGN2的ECC license,只要在lm_code.h里加上
#define LM_SIGN_LEVEL LM_SIGN2
#define LM_STRENGTH LM_STRENGTH_239BIT
然后选定一组LM_SEED1,2,3(可以由lmrand1 -seed产生,这里我用的下面这组数),然后编译SDK就可以了。
#define LM_SEED1 0x11111111
#define LM_SEED2 0x22222222
#define LM_SEED3 0x33333333
作为参考,产生的lmcrypt.exe, testlmd.exe见附件,这里选用的是9.2版的SDK,因为有源码,讲解和调试起来都比较方便。
========================================
lmnewgen可以产生lmpubkey.h和lmprikey.h
========================================
请注意下lmprikey.h里的内容,后面会用到
static unsigned char lm_pubkey[2][3][40] = {{{0x77, 0x9c, 0x40, 0xa, 0x58, 0xe2, 0x7c, 0xef, 0xc3, 0xed, 0x93, 0x71, 0x20, 0xe0, 0x97, 0x36},
  {0x76, 0xa1, 0xdd, 0x41, 0x32, 0x8c, 0x52, 0xb9, 0x2b, 0x9d, 0x5b, 0x68, 0xbf, 0x37, 0xbe, 0xa5, 0x82, 0x3f, 0x76, 0xca, 0x92, 0xd2},
  {0x76, 0x9d, 0xe2, 0xab, 0x3b, 0x42, 0xd7, 0x6b, 0x20, 0xb5, 0x46, 0x39, 0xed, 0xbc, 0xa0, 0xd1, 0xcb, 0xb, 0x5d, 0x65, 0xdc, 0xe5, 0x39, 0x63, 0x44, 0x80, 0xcd, 0x78, 0x27, 0x8c, 0x17}}
,
  {{0x77, 0x9b, 0x2f, 0xbb, 0x1f, 0x8, 0x7c, 0x42, 0x93, 0xb6, 0xcb, 0x1, 0x4c, 0x68, 0x8d, 0xb0},
  {0x76, 0x9f, 0xeb, 0xa9, 0x94, 0x3d, 0x5a, 0xba, 0xc, 0x97, 0x1, 0x4a, 0xc8, 0xc2, 0x9f, 0x43, 0xdc, 0xe4, 0xd1, 0x5, 0xf9, 0x84},
  {0x76, 0x9e, 0x6a, 0x55, 0xc2, 0x34, 0xfd, 0x24, 0xf, 0x95, 0xd1, 0x29, 0xbb, 0xf9, 0x1, 0x85, 0x1, 0x3a, 0x53, 0x17, 0x2a, 0x98, 0xbf, 0xb3, 0x62, 0x76, 0xec, 0x9a, 0x87, 0x69, 0x53}}
};
    
static unsigned int lm_pubsize[2][3] = {{0x10, 0x16, 0x1f}
,
  {0x10, 0x16, 0x1f}
};
==============================================================================
1.我们先从获取public key开始(这里以testlmd为例,对实际应用,方法是一样的)
==============================================================================
打开SDK里src\l_prikey.c可以看到下面这段,那么第二个参数(&m->publicKey)存放的就应该是public key了。  
if ((returnValue = sb_ecdsaVerifyEnd( m->global_data, &m->publicKey,
     &ecc_sig, &verifyContext, &verificationResult)) != SB_SUCCESS) 
  {
    l_pubkey_err(job, 10544, returnValue);
    ret = LM_PUBKEY_ERR;
    goto exit_verify;
  }
OD里找到对应的位置下断,
.text:0041D5A9 loc_41D5A9:                             ; CODE XREF: _l_pubkey_verify+7A6j
.text:0041D5A9                                         ; _l_pubkey_verify+7D6j
.text:0041D5A9                 lea     edx, [ebp+verificationResult]
.text:0041D5AC                 push    edx
.text:0041D5AD                 lea     eax, [ebp+verifyContext]
.text:0041D5B3                 push    eax
.text:0041D5B4                 lea     ecx, [ebp+ecc_sig]
.text:0041D5BA                 push    ecx
.text:0041D5BB                 mov     edx, [ebp+m]
.text:0041D5C1                 add     edx, 44h
.text:0041D5C4                 push    edx        <= check edx, will get the public key
.text:0041D5C5                 mov     eax, [ebp+m]
.text:0041D5CB                 mov     ecx, [eax+4]
.text:0041D5CE                 push    ecx
.text:0041D5CF                 call    _sb_ecdsaVerifyEnd
查看0041D5C4处,edx里对应的就是public key
02 02 6F DF CF AF 73 DF BB C6 D2 A5 80 20 2C B4 58 7F F1 D2 78 91 D4 D6 D0 EC 60 1C B3 F1 A4

==================================
2.看看公钥在文件里是怎么存储的
==================================
函数_sb_ecdsaVerifyEnd是被_l_pubkey_verify调用的,好,我们回到函数l_pubkey_verify的起始点开始追踪[00C93B3C~00C93B5E]处是怎么变成public key的。
run过0041D143后,这块内存区域清零
0041D143  |.  E8 E82A0100   CALL testlmd.l_malloc                    ; \l_malloc

在此处下内存写断点,如下图所示,

一路F9很容易来到0041D273处,再来看下内存中的这段数字:
76 9D E2 AB 3B 42 D7 6B 20 B5 46 39 ED BC A0 D1 CB 0B 5D 65 DC E5 39 63 44 80 CD 78 27 8C 17

回头再看下lmpubkey.h里的内容,有点明白了吧?
static unsigned char lm_pubkey[2][3][40] = {{{0x77, 0x9c, 0x40, 0xa, 0x58, 0xe2, 0x7c, 0xef, 0xc3, 0xed, 0x93, 0x71, 0x20, 0xe0, 0x97, 0x36},
  {0x76, 0xa1, 0xdd, 0x41, 0x32, 0x8c, 0x52, 0xb9, 0x2b, 0x9d, 0x5b, 0x68, 0xbf, 0x37, 0xbe, 0xa5, 0x82, 0x3f, 0x76, 0xca, 0x92, 0xd2},
  {0x76, 0x9d, 0xe2, 0xab, 0x3b, 0x42, 0xd7, 0x6b, 0x20, 0xb5, 0x46, 0x39, 0xed, 0xbc, 0xa0, 0xd1, 0xcb, 0xb, 0x5d, 0x65, 0xdc, 0xe5, 0x39, 0x63, 0x44, 0x80, 0xcd, 0x78, 0x27, 0x8c, 0x17}}
,
  {{0x77, 0x9b, 0x2f, 0xbb, 0x1f, 0x8, 0x7c, 0x42, 0x93, 0xb6, 0xcb, 0x1, 0x4c, 0x68, 0x8d, 0xb0},
  {0x76, 0x9f, 0xeb, 0xa9, 0x94, 0x3d, 0x5a, 0xba, 0xc, 0x97, 0x1, 0x4a, 0xc8, 0xc2, 0x9f, 0x43, 0xdc, 0xe4, 0xd1, 0x5, 0xf9, 0x84},
  {0x76, 0x9e, 0x6a, 0x55, 0xc2, 0x34, 0xfd, 0x24, 0xf, 0x95, 0xd1, 0x29, 0xbb, 0xf9, 0x1, 0x85, 0x1, 0x3a, 0x53, 0x17, 0x2a, 0x98, 0xbf, 0xb3, 0x62, 0x76, 0xec, 0x9a, 0x87, 0x69, 0x53}}
};
    
static unsigned int lm_pubsize[2][3] = {{0x10, 0x16, 0x1f}
,
  {0x10, 0x16, 0x1f}
};
好,让我们从0041D273处往回看看这串数字是怎么转换成最终的public key的。
0041D252  |.  0FBE08        |MOVSX ECX,BYTE PTR DS:[EAX]
这里的ECX里的内容是什么:testlmd (daemon name, 对应ASCII码74 65 73 74 6C 6D 64
)
再往下
0041D261  |.  0FB642 48     |MOVZX EAX,BYTE PTR DS:[EDX+48]
EAX里就是上面lmpubkey.h里的第一位数字"76",
0041D265  |.  2BC1          |SUB EAX,ECX
76h- 74h = 02

继续一路下去,
76 9D E2 AB 3B 42 D7 6B 20 B5 46 39 ED BC A0 D1 CB 0B 5D 65 DC E5 39 63 44 80 CD 78 27 8C 17  (lmpubkey.h里的public key)
=>
02 02 6F DF CF AF 73 DF BB C6 D2 A5 80 20 2C B4 58 7F F1 D2 78 91 D4 D6 D0 EC 60 1C B3 F1 A4  (真正的public key)
我们用IDA的F5反汇编可以看到这段转换对应的伪代码
          for ( Gi = 0; Gi < pubkeysize[(_DWORD)offset]; ++Gi )
          {
            if ( !*cp )
              cp = job->vendor;
            if ( Gi % 2 )
            {
              if ( Gi % 3 )
                m[Gi + 72] += *cp++;
              else
                m[Gi + 72] ^= *cp++;
            }
            else
            {
              m[Gi + 72] -= *cp++;
            }
          }
          returnValue = sb_dataSize(ellipticCurve, m + 64);
再直观一点就是:
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 - (第0、2、4......26、28、30位用减法运算,比如第0位76-74=02h)
3 9 15 21 27 ^ (第3、9、15、21、27位用异或运算,例如第3位AB^74=DFh)
1 5 7 11 13 17 19 23 25 29 + (第1、5、7......23、25、29位用加法运算,例如第1位9D+65=02,注意取末两位)
0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  <= 0~30(共31 = (1F)h位
76 9D E2 AB 3B 42 D7 6B 20 B5 46 39 ED BC A0 D1 CB 0B 5D 65 DC E5 39 63 44 80 CD 78 27 8C 17  <= pubkey in pubkey.h
74 65 73 74 6C 6D 64 74 65 73 74 6C 6D 64 74 65 73 74 6C 6D 64 74 65 73 74 6C 6D 64 74 65 73  <= testlmd
02 02 6F DF CF AF 73 DF BB C6 D2 A5 80 20 2C B4 58 7F F1 D2 78 91 D4 D6 D0 EC 60 1C B3 F1 A4  <= real pubkey(for SIGN2=)
存储在硬盘上的是lmpubkey.h里的public key,经过上面的转化变成真正的public key,所以只要找到lmpubkey中key的存放规律,替换公钥就水到渠成了,这个后面再讲。
(未完待续)

上传的附件 lmcrypt.rar
testlmd.rar
lmnewgen.rar
Snap1.jpg
Snap2.jpg
Snap3.jpg
Snap4.jpg
Snap5.jpg

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功