首页
社区
课程
招聘
[原创]一次对二次加密的股票期货指标逆向记录
发表于: 2024-2-19 09:59 2323

[原创]一次对二次加密的股票期货指标逆向记录

2024-2-19 09:59
2323

春节期间,看到某视频平台上直播间在售卖一个量化指标系统,看着很是神奇,可以使用体验3天,看着很是高大上,看着主播滔滔不绝的讲解,很是诱人。(本人是从不相信天上掉馅饼的事情的,特别是股市期货市场,如果你有一个绝招可以挣钱,闷声发财就行了,为什么会拿出来分享呢),在网络上搜索相关的内容也很少,有人1W米出售源码,证明加密确实做的不错。一时技痒,忍不住拿来研究一番。

总体的逻辑是,将指标公式二次加密,客户端身份验证通过后,启动WH行情软件,通过进程注入,将公式解密,同时屏蔽行情软件的指标管理器功能。

正常的加密指标

图片描述

加密的量化指标

图片描述

既然是定制化的加密,直接破解难度很大,客户端的身份验证也是通过验证,反调试也是一套一套的,很是麻烦。

作为外挂系统,数据总要解密,行情交易软件才能正常读取试用,找到该系统的核心DLL whnloader.dll,也就是注入到WH行情软件中。
经过分析在DLLMAIN函数中发现了端倪,该DLL是对CreateFileA、ReadFile、WriteFile三个API函数下了钩子

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
000000018000694C | 48:8B0D 3D180100         | mov rcx,qword ptr ds:[<&ReadFile>]                | HOOK ReadFile
0000000180006953 | 4C:8D05 06A80100         | lea r8,qword ptr ds:[0x180021160]                 |
000000018000695A | 48:8D15 7FEFFFFF         | lea rdx,qword ptr ds:[<sub_1800058E0>]            | XTRD文件解密 函数
0000000180006961 | E8 DEADFFFF              | call <whnloader.begin of sub_180001744>           |
0000000180006966 | 85C0                     | test eax,eax                                      |
0000000180006968 | 0F85 99FCFFFF            | jne whnloader.180006607                           |
000000018000696E | 48:8B0D 1B180100         | mov rcx,qword ptr ds:[<&ReadFile>]                | 
0000000180006975 | E8 72B0FFFF              | call <whnloader.begin of sub_1800019EC>           | hook ReadFile
000000018000697A | 85C0                     | test eax,eax                                      |
000000018000697C | 0F85 85FCFFFF            | jne whnloader.180006607                           |
0000000180006982 | 48:8B0D A7160100         | mov rcx,qword ptr ds:[<&CreateFileA>]             | Hook CreateFileA
0000000180006989 | 4C:8D05 E8A70100         | lea r8,qword ptr ds:[0x180021178]                 |
0000000180006990 | 48:8D15 09E8FFFF         | lea rdx,qword ptr ds:[<begin of sub_1800051A0>]   | 调用 内存解密
0000000180006997 | E8 A8ADFFFF              | call <whnloader.begin of sub_180001744>           |
000000018000699C | 85C0                     | test eax,eax                                      |
000000018000699E | 0F85 63FCFFFF            | jne whnloader.180006607                           |
00000001800069A4 | 48:8B0D 85160100         | mov rcx,qword ptr ds:[<&CreateFileA>]             | 
00000001800069AB | E8 3CB0FFFF              | call <whnloader.begin of sub_1800019EC>           | hook CreateFileA
00000001800069B0 | 85C0                     | test eax,eax                                      |
00000001800069B2 | 0F85 4FFCFFFF            | jne whnloader.180006607                           |
00000001800069B8 | 48:8B0D 49170100         | mov rcx,qword ptr ds:[<&WriteFile>]               | HOOK WriteFile
00000001800069BF | 4C:8D05 BAA70100         | lea r8,qword ptr ds:[0x180021180]                 |
00000001800069C6 | 48:8D15 C3E9FFFF         | lea rdx,qword ptr ds:[<sub_180005390>]            |
00000001800069CD | E8 72ADFFFF              | call <whnloader.begin of sub_180001744>           |
00000001800069D2 | 85C0                     | test eax,eax                                      |
00000001800069D4 | 0F85 2DFCFFFF            | jne whnloader.180006607                           |
00000001800069DA | 48:8B0D 27170100         | mov rcx,qword ptr ds:[<&WriteFile>]               | 
00000001800069E1 | E8 06B0FFFF              | call <whnloader.begin of sub_1800019EC>           | hook WriteFile
00000001800069E6 | 85C0                     | test eax,eax                                      |
00000001800069E8 | 0F85 19FCFFFF            | jne whnloader.180006607                           |

一切的数据处理都是在HOOK后的函数中处理,如最关键READFile,sub_1800058E0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
0000000180005931 | 803B 4A                  | cmp byte ptr ds:[rbx],0x4A                        | 4A:'J'
0000000180005934 | 0F85 6F070000            | jne whnloader.1800060A9                           |
000000018000593A | 807B 01 6D               | cmp byte ptr ds:[rbx+0x1],0x6D                    | 6D:'m'
000000018000593E | 0F85 65070000            | jne whnloader.1800060A9                           |
0000000180005944 | 807B 02 38               | cmp byte ptr ds:[rbx+0x2],0x38                    | 38:'8'
0000000180005948 | 0F85 5B070000            | jne whnloader.1800060A9                           |
000000018000594E | 807B 60 BC               | cmp byte ptr ds:[rbx+0x60],0xBC                   |
0000000180005952 | 0F85 51070000            | jne whnloader.1800060A9                           |
0000000180005958 | 807B 61 D3               | cmp byte ptr ds:[rbx+0x61],0xD3                   |
000000018000595C | 0F85 47070000            | jne whnloader.1800060A9                           |
0000000180005962 | 807B 62 C3               | cmp byte ptr ds:[rbx+0x62],0xC3                   |
0000000180005966 | 0F85 3D070000            | jne whnloader.1800060A9                           |
000000018000596C | 807B 63 DC               | cmp byte ptr ds:[rbx+0x63],0xDC                   |
0000000180005970 | 0F85 33070000            | jne whnloader.1800060A9                           |
0000000180005976 | 807B 64 D6               | cmp byte ptr ds:[rbx+0x64],0xD6                   |
000000018000597A | 0F85 29070000            | jne whnloader.1800060A9                           |
0000000180005980 | 807B 65 A7               | cmp byte ptr ds:[rbx+0x65],0xA7                   |
0000000180005984 | 0F85 1F070000            | jne whnloader.1800060A9                           |
000000018000598A | 807B 66 B3               | cmp byte ptr ds:[rbx+0x66],0xB3                   |
000000018000598E | 0F85 15070000            | jne whnloader.1800060A9                           |
0000000180005994 | 807B 67 D6               | cmp byte ptr ds:[rbx+0x67],0xD6                   |
0000000180005998 | 0F85 0B070000            | jne whnloader.1800060A9                           |
000000018000599E | 807B 68 A3               | cmp byte ptr ds:[rbx+0x68],0xA3                   |
00000001800059A2 | 0F85 01070000            | jne whnloader.1800060A9                           |
00000001800059A8 | 807B 69 BA               | cmp byte ptr ds:[rbx+0x69],0xBA                   |
00000001800059AC | 0F85 F7060000            | jne whnloader.1800060A9                           |
00000001800059B2 | 807B 6A D5               | cmp byte ptr ds:[rbx+0x6A],0xD5                   |
00000001800059B6 | 0F85 ED060000            | jne whnloader.1800060A9                           |
00000001800059BC | 807B 6B C5               | cmp byte ptr ds:[rbx+0x6B],0xC5                   |
00000001800059C0 | 0F85 E3060000            | jne whnloader.1800060A9                           |
00000001800059C6 | 807B 6C D4               | cmp byte ptr ds:[rbx+0x6C],0xD4                   |
00000001800059CA | 0F85 D9060000            | jne whnloader.1800060A9                           |
00000001800059D0 | 807B 6D A3               | cmp byte ptr ds:[rbx+0x6D],0xA3                   |
00000001800059D4 | 0F85 CF060000            | jne whnloader.1800060A9                           |
00000001800059DA | 807B 6E B7               | cmp byte ptr ds:[rbx+0x6E],0xB7                   |
00000001800059DE | 0F85 C5060000            | jne whnloader.1800060A9                           |
00000001800059E4 | 807B 6F C9               | cmp byte ptr ds:[rbx+0x6F],0xC9                   |
00000001800059E8 | 0F85 BB060000            | jne whnloader.1800060A9                           |
00000001800059EE | 807B 70 03               | cmp byte ptr ds:[rbx+0x70],0x3                    |
00000001800059F2 | 0F85 B1060000            | jne whnloader.1800060A9                           |
00000001800059F8 | 807B 71 20               | cmp byte ptr ds:[rbx+0x71],0x20                   | 20:' '
00000001800059FC | 0F85 A7060000            | jne whnloader.1800060A9                           |
0000000180005A02 | 807B 72 20               | cmp byte ptr ds:[rbx+0x72],0x20                   | 20:' '
0000000180005A06 | 0F85 9D060000            | jne whnloader.1800060A9                           |
0000000180005A0C | 807B 73 20               | cmp byte ptr ds:[rbx+0x73],0x20                   | 20:' '
0000000180005A10 | 0F85 93060000            | jne whnloader.1800060A9                           |
0000000180005A16 | 807B 74 77               | cmp byte ptr ds:[rbx+0x74],0x77                   | 77:'w'
0000000180005A1A | 0F85 89060000            | jne whnloader.1800060A9                           |
0000000180005A20 | 807B 75 77               | cmp byte ptr ds:[rbx+0x75],0x77                   | 77:'w'
0000000180005A24 | 0F85 7F060000            | jne whnloader.1800060A9                           |
0000000180005A2A | 807B 76 77               | cmp byte ptr ds:[rbx+0x76],0x77                   | 77:'w'
0000000180005A2E | 0F85 75060000            | jne whnloader.1800060A9                           |
0000000180005A34 | 807B 77 2E               | cmp byte ptr ds:[rbx+0x77],0x2E                   | rbx+77:L"ā", 2E:'.'
0000000180005A38 | 0F85 6B060000            | jne whnloader.1800060A9                           |
0000000180005A3E | 807B 78 4A               | cmp byte ptr ds:[rbx+0x78],0x4A                   | 4A:'J'
0000000180005A42 | 0F85 61060000            | jne whnloader.1800060A9                           |
0000000180005A48 | 807B 79 6D               | cmp byte ptr ds:[rbx+0x79],0x6D                   | 6D:'m'
0000000180005A4C | 0F85 57060000            | jne whnloader.1800060A9                           |
0000000180005A52 | 807B 7A 69               | cmp byte ptr ds:[rbx+0x7A],0x69                   | 69:'i'
0000000180005A56 | 0F85 4D060000            | jne whnloader.1800060A9                           |
0000000180005A5C | 807B 7B 38               | cmp byte ptr ds:[rbx+0x7B],0x38                   | 38:'8'
0000000180005A60 | 0F85 43060000            | jne whnloader.1800060A9                           |
0000000180005A66 | 807B 7C 2E               | cmp byte ptr ds:[rbx+0x7C],0x2E                   | 2E:'.'
0000000180005A6A | 0F85 39060000            | jne whnloader.1800060A9                           |
0000000180005A70 | 807B 7D 63               | cmp byte ptr ds:[rbx+0x7D],0x63                   | 63:'c'
0000000180005A74 | 0F85 2F060000            | jne whnloader.1800060A9                           |
0000000180005A7A | 807B 7E 6F               | cmp byte ptr ds:[rbx+0x7E],0x6F                   | 6F:'o'
0000000180005A7E | 0F85 25060000            | jne whnloader.1800060A9                           |
0000000180005A84 | 807B 7F 6D               | cmp byte ptr ds:[rbx+0x7F],0x6D                   | 6D:'m'

该函数接管ReadFile后先判断,文件的头部是否有加密的特征数据,符合要求,同时又进行了一番时间校验和反调试判断,才进行解密。
数据处理的逻辑清楚了,想拿到源码就简单了。

解决思路

写一个DLL,也注入到行情软件中,依次执行读取二次加密文件的动作,自然就触发了ReadFile,因为这一切都是在系统中运行,也就理所当然的拿到解密后代码了,因为系统对WriteFile也下了钩子,可以将数据发送到进程外面保存即可。

获取到数据

图片描述
看到了标准的系统加密数据
想看源码,没有查看密码,这也容易
在公式管理器中输入错误密码,在主程序模块中,查找字符串"密码输入错误,可能有多个地方,断点跟踪一下,就找到了

1
2
3
4
5
6
7
8
9
10
11
0000000140EFB574 | 85D2                     | test edx,edx                                |
0000000140EFB576 | 0F85 7F000000            | jne mytrader_whsp.140EFB5FB                 |  将je 修改为jne 即可跳过设置密码
0000000140EFB57C | 45:33C9                  | xor r9d,r9d                                 |
0000000140EFB57F | 4C:8D05 42F14500         | lea r8,qword ptr ds:[14135A6C8]             | 000000014135A6C8:"提示"
0000000140EFB586 | 48:8D15 F3155C00         | lea rdx,qword ptr ds:[1414BCB80]            | 00000001414BCB80:"密码输入错误,请重新输入"
0000000140EFB58D | 48:8BCB                  | mov rcx,rbx                                 |
0000000140EFB590 | 48:83C4 20               | add rsp,20                                  |
0000000140EFB594 | 5B                       | pop rbx                                     |
0000000140EFB595 | E9 4E1AC4FF              | jmp mytrader_whsp.140B3CFE8                 |
0000000140EFB59A | 48:8B83 30010000         | mov rax,qword ptr ds:[rbx+130]              |
0000000140EFB5A1 | 4C:8B83 48010000         | mov r8,qword ptr ds:[rbx+148]               |

剩下就一切水到渠成了。

示例中二次加密的指标公式就一行代码。
DRAWBKBMP(1,'说明书');

看到代码,你还觉得神奇吗?


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 2
支持
分享
打赏 + 50.00雪花
打赏次数 1 雪花 + 50.00
 
赞赏  mb_enuggacv   +50.00 2024/10/02 感谢分享~
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//