首页
社区
课程
招聘
[分享]ECC替换公钥实践(下篇)
发表于: 2014-9-14 08:36 29536

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

2014-9-14 08:36
29536

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (44)
雪    币: 484
活跃值: (269)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
我们接下去看怎么手工替换公钥,又怎样用程序实现自动替换。

(a)FlexLM SDK v9.2 ECC公钥替换

再回头看看v9.2版本SDK编译产生的testlmd.exe里第一个出现的5D怎么来的。
00403C0A  |.  0305 30775200 ADD EAX,DWORD PTR DS:[527730]
00403C10  |.  8B4D 0C       MOV ECX,DWORD PTR SS:[EBP+C]
00403C13  |.  8881 AA000000 MOV BYTE PTR DS:[ECX+AA],AL

第一个pubkey的值出现的是在.text:403C0A,然后在.text:00403C13往内存0012F196处写5D

插入图

看下信息窗口里的内容
AL=5D (']')
堆栈 DS:[0012F196]=00

ECX的值是0012F0EC,

所以内存[0012F184 - 0012F1A2]分别对应
[ECX + 98h] => 十进制 [ecx + 152]
......
[ECX + B6h] => 十进制 [ecx + 182]
请注意理解这里的(152 ~ 182),后面的不同的SDK版本的ECC pubkey替换仍然要用到这个方法。

我们把sub_401E60 (即_l_n36_buf)F5转伪代码截取memset开始到末尾的一段(见附件ida_f5.txt)
从中很容易(可以用编程脚本提取)出pubkey存储的位置。

                        *((_BYTE *)Dst + 152) += dword_526E30;  =>        526E30存放76
                        *((_BYTE *)Dst + 153) += dword_527D1C;  =>        527D1C存放9d
                        *((_BYTE *)Dst + 154) += dword_527634;  =>        527634存放e2
                        *((_BYTE *)Dst + 155) += dword_5275C8;  =>        5275C8存放ab
                        *((_BYTE *)Dst + 156) += dword_527EA4;  =>        527EA4存放3b
                        *((_BYTE *)Dst + 157) += dword_527824;  =>        527824存放42
                        *((_BYTE *)Dst + 158) += dword_527344;  =>        527344存放d7
                        *((_BYTE *)Dst + 159) += dword_527AD4;  =>        527AD4存放6b
                        *((_BYTE *)Dst + 160) += dword_526E7C;  =>        526E7C存放20
                        *((_BYTE *)Dst + 161) += dword_5277B8;  =>        5277B8存放b5
                        *((_BYTE *)Dst + 162) += dword_527864;  =>        527864存放46
                        *((_BYTE *)Dst + 163) += dword_527314;  =>        527314存放39
                        *((_BYTE *)Dst + 164) += dword_527624;  =>        527624存放ed
                        *((_BYTE *)Dst + 165) += dword_527DF4;  =>        527DF4存放bc
                        *((_BYTE *)Dst + 166) += dword_52707C;  =>        52707C存放a0
                        *((_BYTE *)Dst + 167) += dword_527A8C;  =>        527A8C存放d1
                        *((_BYTE *)Dst + 168) += dword_5277C4;  =>        5277C4存放cb
                        *((_BYTE *)Dst + 169) += dword_526E1C;  =>        526E1C存放0b
                        *((_BYTE *)Dst + 170) += dword_527730;  =>        527730存放5d
                        *((_BYTE *)Dst + 171) += dword_5274B0;  =>        5274B0存放65
                        *((_BYTE *)Dst + 172) += dword_527180;  =>        527180存放dc
                        *((_BYTE *)Dst + 173) += dword_5278E4;  =>        5278E4存放e5
                        *((_BYTE *)Dst + 174) += dword_527178;  =>        527178存放39
                        *((_BYTE *)Dst + 175) += dword_527540;  =>        527540存放63
                        *((_BYTE *)Dst + 176) += dword_527AC8;  =>        527AC8存放44
                        *((_BYTE *)Dst + 177) += dword_52766C;  =>        52766C存放80
                        *((_BYTE *)Dst + 178) += dword_527A54;  =>        527A54存放cd
                        *((_BYTE *)Dst + 179) += dword_527070;  =>        527070存放78
                        *((_BYTE *)Dst + 180) += dword_527140;  =>        527140存放27
                        *((_BYTE *)Dst + 181) += dword_5278F4;  =>        5278F4存放8c
                        *((_BYTE *)Dst + 182) += dword_5270F0;  =>        5270F0存放17

请注意上面的(152,153......182)的排序,IDA F5的输出不是这样的,这里排好序是为了后面脚本处理时,原pubkey和要替换的pubkey比较容易一一对应上。
但是替换时,必须要按地址存放顺序搜索、替换,呵呵这个稍微想一下,应该不难理解。

这样排序后,原来的pubkey和将要替换的pubkey就很容易一一对应上了
org_pubkey = '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'
rep_pubkey = '76 e5 b4 61 32 35 26 f4 6d 28 d8 28 c4 8d 4c 73 bb dc fe 5f 0f 90 ad 24 97 83 0b 0c 47 e5 ff'

手工替换,就找到相应的地址,手工输入替换就可以了。

至于自动替换,这里是用ruby脚本实现的。

在编程脚本里很容易再按地址排序,并将org_pubkey和rep_pubkey随之相应按地址一一对应如下

526E1C  0b      dc
526E30  76      76
526E7C  20      6d
527070  78      0c
52707C  a0      4c
5270F0  17      ff
527140  27      47
527178  39      ad
527180  dc      0f
527314  39      28
527344  d7      26
5274B0  65      5f
527540  63      24
5275C8  ab      61
527624  ed      c4
527634  e2      b4
52766C  80      83
527730  5d      fe
5277B8  b5      28
5277C4  cb      bb
527824  42      35
527864  46      d8
5278E4  e5      90
5278F4  8c      e5
527A54  cd      0b
527A8C  d1      73
527AC8  44      97
527AD4  6b      f4
527D1C  9d      e5
527DF4  bc      8d
527EA4  3b      32

这时就可以搜索、替换了,整个的搜索、替换的规律如下

0b......76......20...... ......9d......bc......3b
=>
dc......76......6d...... ......e5......8d......32

由于数据不是连续存放的,中间“......”对应的数据必须原封不动的保留。

你可以将脚本里得到的total_search输出
total_search = total_search(address, save)

0b(.{38})76(.{150})20(.{998})78(.{22})a0(.{230})17(.{158})27(.{110})39(.{14})dc(.{806})39(.{94})d7(.{726})65(.{286})63(.{270})ab(.{182})ed(.{30})e2(.{110})80(.{390})5d(.{270})b5(.{22})cb(.{190})42(.{126})46(.{254})e5(.{30})8c(.{702})cd(.{110})d1(.{118})44(.{22})6b(.{1166})9d(.{430})bc(.{350})3b

(.{38}) => 0b和76间有38个其他数字,这里38是程序根据0b和76的存放地址的差(526E30 - 526E1C)自动计算出来的

作为参考,公钥替换脚本见附件testlmd_replace_pubkey_v9.2.rb,是一个ruby脚本,可以用testlmd_replace_pubkey_v9.2.rb ida_f5.txt testlmd.exe替换testlmd.exe里的公钥,输出文件为outfile。

声明:这里的脚本只是实现了功能,性能上未作优化(修改大的应用文件会很慢),仅供参考。从实用的角度而言,优化下这个脚本是可行的,如果懒得优化的话,可以从这个脚本输出seatch/replace文本,然后用sfk(Swiss File Knife)全目录自动替换。

稍后看下11.9.1和11.11.1.1的ECC公钥替换
......
上传的附件:
2014-9-14 08:37
0
雪    币: 47147
活跃值: (20455)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
编辑了一下帖子,加上了上篇的链接。
上下2篇只设一个精华,上篇设精华,下篇设“优秀”
2014-9-14 08:48
0
雪    币: 484
活跃值: (269)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
谢谢老大鼓励:)
2014-9-14 09:28
0
雪    币: 150
活跃值: (74)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
占楼备用
2014-9-14 10:05
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
6
good job~
ECC替换公钥,学习了~
2014-9-14 17:13
0
雪    币: 484
活跃值: (269)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
2楼更新: 用脚本自动替换公钥
2014-9-15 17:58
0
雪    币: 0
活跃值: (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
有心人,很详细,非常不错,不过无法对其他软件通用,我也写了个通用公钥替换程序(自动生成公钥,提取公钥,再替换公钥),能适用于大部分软件,但不同编译器编译生成汇编代码都有差异,vc6与vc2010都不一样,tanker那个不知道是否更牛?
2014-9-16 13:04
0
雪    币: 484
活跃值: (269)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
9
嗯,这里主要是分享下分析的过程,修改公钥最好还是自己完全了解,否则改错了而自己都不知道就麻烦了,而且这个东西随着SDK版本升级可能一直会变,依靠别人的程序会比较麻烦:)
2014-9-16 13:47
0
雪    币: 0
活跃值: (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
目前windows版软件,基本都可以自动查找,提取,替换,由于替换的是数据区,不存在改程序问题,整个过程自动完成,基本秒杀了,…手工找1个小时都跟不下来,你再往前走一步就可以通用自动替换了。
2014-9-16 15:13
0
雪    币: 484
活跃值: (269)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
11
嗯,只要自己知道改了什么就好~

到11.11.1.1,就转到.text,不在.data区了~

> 手工找1个小时都跟不下来
这个不用这么久,熟悉了,半小时就差不多了,当然不包括写程序的时间:)

呵呵,再强调下,我这里只是分享分析的经验,所写的脚本也只是供参考,不推荐大家直接拿去用。当然理解了方法,修改下自己用也是可以的。
2014-9-16 16:18
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
girlmore能不能分享一下你的工具啊,让我们这些菜鸟也学习一下
2014-9-27 07:51
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
期待。。。。。。。。。。。。。。。。

稍后看下11.9.1和11.11.1.1的ECC公钥替换
2014-9-27 11:04
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
14
学习了!!!!
2014-9-28 14:20
0
雪    币: 484
活跃值: (269)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
15
前辈客气了,学习您的帖子收获很多:)
2014-9-29 10:28
0
雪    币: 0
活跃值: (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
你用tanker的工具即可,我只是自己重新研究写了个通用工具而已,纯属研究自动提取,生成并替换公钥匙
2014-9-30 23:27
0
雪    币: 57
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
bridgeic, good job..!!!
And about the version v11.11 and v11.12, you're right.. Flexera has changed the obfuscation schema that's hide the private and the public key. So now it's very hard to inject your pubkey...
The PubKey Replacer v1.70 work only till the v11.10. But in some vendors the tool cannot change properly the pubkey, so you need to change manually...

Could be good to have a tool to change the pubkey in the lmcrypt.exe instead  the vendor/exe/dll target.. You can easly find the pubkey in the lmcrypt by building your test with different lmseeds...
If you can make a video or write a pdf in english will be very usefull...
2014-10-4 03:58
0
雪    币: 6126
活跃值: (6766)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
18
ECC替换公钥实践.doc学习中,在这里见到了很多传说中的大神!  谢谢!

经实践,对v9.x,v10.x好用。非常期待替换v11.x的方法。附件是本人学习本帖过程中的心得备注,供初学者参考。以此感谢楼主的无私奉献!

====================================================
查看0041D5C4处,edx里对应的就是public key  (Myron备注:这个地址可以根据规律找到:用W32Dasm找到第一个FFFFF8FFFFFF后,往回找到第二个call,再往回找到第二个push的位置就是,注意它的上面是“add e%x 00000044“)
===================================================
上传的附件:
2014-10-22 10:05
0
雪    币: 6126
活跃值: (6766)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
19
ECC替换公钥实践.doc注意附件在楼下,新版附件
上传的附件:
2014-11-1 20:31
0
雪    币: 6126
活跃值: (6766)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
重新修改了确定追踪内存段的原理和通用方法,适合于所有版本。请下载过的朋友注意更新

=====================================================
(Myron备注:这里0012F184怎么来的?我们由下图可以看到EAX由[ESI+ECX*4-1C] = [00A66744]赋值而来,而[00A66744]通过追踪是由[00A54848] 赋值而来,继续追踪[00A54848],直到找到[0012F184]是从硬盘数据读来的。最终的赋值关系如下:
EDI+ECX*4-1C=[00C93B3C] <== ESI+ECX*4-1C=[00A66744] <== [00A54848]  <== [00A544F8] <== [0012F184] <== [直接读硬盘数据]


=====================================================
上传的附件:
2014-11-2 19:03
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
精彩,希望楼主继续更新11.x的分析
2014-11-3 00:13
0
雪    币: 211
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
Thanks

Good job
2014-12-5 15:07
0
雪    币: 321
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
非常不错,期待11.11
2014-12-8 13:34
0
雪    币: 1
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
I hope anyone can help me a working lmcrypt and public key for 11.12 target

http://filecloud.io/download.html
2014-12-22 18:24
0
雪    币: 318
活跃值: (158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
收藏学习了,谢谢楼主
2015-2-28 00:38
0
游客
登录 | 注册 方可回帖
返回
//