Baymax Patch Tools x64 使用教程(新功能攻略)
Baymax 的异常补丁是基于事件的补丁工具,当触发事件(断点)时,解析补丁条目并执行相应的补丁操作。x64版不仅集成了x32版的功能,还新增了对数据的存储使用,支持从Ini文件中读取补丁数据,和对补丁数据进行运算等功能。这里我结合 Total Commander 64 来介绍下这些新功能的用法。将数据进行存储和使用是hpindigo(雷神)提出的新建议,为了解决某些程序在断点处需要引用之前曾计算的中间值。即在某地址对数据进行存储,可以在另一个地址使用该存储数据。在此基础上Baymax又对该功能进行了扩展:假若我们存储的数据为DOWRD64(32位下是DWORD四字节)八字节的数据,也可以作为一个内存地址来使用,可修改该地址指向的内存数据。
即存储使用功能分两种情况:
1. 某地址存储数据(类型可为 BYTE\WORD\DWORD\QWORD\HEX\ASCII\UNICODE等),在任意地址使用该数据,如用存储数据打补丁或内存注册机显示该数据。
2. 若存储的数据为DWORD\DWORD64类型,则该存储数据可作为类型一的数据使用,也可以作为一个指向内存的地址来使用。
Total Commander 的验证流程为读取keyfile,截取keyfile中部分数据进行解密,解密后数据分两部分,前0x10字节为第二部分的HASH值,剩余的数据为用户注册信息。若程序验证解密数据的HASH等于第一部分,则认为Keyfile有效,并将用户数据进行展示。
验证流程如下:
0000000000648418 | 48 8D 8D 20 FA FF FF | lea rcx,qword ptr ss: |
000000000064841F | 41 B8 00 00 00 00 | mov r8d,0 |
0000000000648425 | BA 00 00 00 00 | mov edx,0 |
000000000064842A | E8 A1 56 E7 FF | call totalcmd64.4BDAD0 | CreateFileA // 读取 wincmd.key
... ...
00000000006486DA | 4C 8D 4D C0 | lea r9,qword ptr ss: | C
00000000006486DE | 4C 8B 45 F0 | mov r8,qword ptr ss: | N
00000000006486E2 | 48 8B 55 E8 | mov rdx,qword ptr ss: | key
00000000006486E6 | 48 8B 4D C8 | mov rcx,qword ptr ss: | M
00000000006486EA | E8 F1 38 42 00 | call totalcmd64.A6BFE0 | RSA解密
00000000006486EF | 8B 05 4B EB 5F 00 | mov eax,dword ptr ds: |
00000000006486F5 | 83 F8 01 | cmp eax,1 |
00000000006486F8 | 7F 3D | jg totalcmd64.648737 |
00000000006486FA | 4C 8B 05 CF C6 44 00 | mov r8,qword ptr ds: | 0000000000A94DD0:&"Total Commander"
0000000000648701 | 48 8D 15 88 BF 4B 00 | lea rdx,qword ptr ds: |
0000000000648708 | 41 B9 10 00 00 00 | mov r9d,10 |
000000000064870E | 48 B9 00 00 00 00 00 00 00 0 | mov rcx,0 | rcx:"D:\\Program Files\\totalcmd\\wincmd.key"
0000000000648718 | E8 63 99 E1 FF | call totalcmd64.462080 |
000000000064871D | 48 C7 05 C8 71 45 00 00 00 0 | mov qword ptr ds:,0 |
0000000000648728 | B9 01 00 00 00 | mov ecx,1 | ecx:"D:\\Program Files\\totalcmd\\wincmd.key"
000000000064872D | E8 DE 9D DC FF | call totalcmd64.412510 |
0000000000648732 | E9 D6 0A 00 00 | jmp totalcmd64.64920D |
0000000000648737 | 48 8D 95 58 FF FF FF | lea rdx,qword ptr ss: |
000000000064873E | 48 8B 4D C0 | mov rcx,qword ptr ss: | Rsa_C
0000000000648742 | 41 B8 67 00 00 00 | mov r8d,67 | 67:'g'
0000000000648748 | E8 D3 3D 42 00 | call totalcmd64.A6C520 |
000000000064874D | 48 8D 8D 58 FF FF FF | lea rcx,qword ptr ss: | RCX 中传入保存解密数据的地址
0000000000648754 | 41 B8 66 00 00 00 | mov r8d,66 | 66:'f'
000000000064875A | BA BC A4 20 00 | mov edx,20A4BC | 20A4BC:L"ru"
000000000064875F | E8 0C F7 FF FF | call totalcmd64.647E70 | 二次解密
0000000000648764 | 48 8D 15 6D F7 54 00 | lea rdx,qword ptr ds: | 在这里赋值
000000000064876B | 49 B8 00 00 00 00 00 00 00 0 | mov r8,0 |
...
00000000006487CC | E8 7F 5B 2B 00 | call totalcmd64.8FE350 | MD5x inIT
00000000006487D1 | 48 8B 8D 48 FF FF FF | mov rcx,qword ptr ss: |
00000000006487D8 | BA 00 00 00 00 | mov edx,0 |
00000000006487DD | E8 7E 6C 2B 00 | call totalcmd64.8FF460 |
00000000006487E2 | 48 8B 8D 48 FF FF FF | mov rcx,qword ptr ss: |
00000000006487E9 | E8 C2 6D 2B 00 | call totalcmd64.8FF5B0 |
00000000006487EE | 48 8B 8D 48 FF FF FF | mov rcx,qword ptr ss: |
00000000006487F5 | E8 96 66 DC FF | call totalcmd64.40EE90 |
00000000006487FA | C7 44 24 20 01 00 00 00 | mov dword ptr ss:,1 |
0000000000648802 | 4C 8D 85 28 FB FF FF | lea r8,qword ptr ss: |
0000000000648809 | 48 8D 8D 08 EB FF FF | lea rcx,qword ptr ss: |
0000000000648810 | 49 B9 0F 00 00 00 00 00 00 0 | mov r9,F |
000000000064881A | 48 BA FF 00 00 00 00 00 00 0 | mov rdx,FF |
0000000000648824 | E8 E7 D6 DB FF | call totalcmd64.405F10 | 这里计算 hash 1
0000000000648829 | 48 8D 9D 08 EB FF FF | lea rbx,qword ptr ss: |
0000000000648830 | C7 44 24 20 01 00 00 00 | mov dword ptr ss:,1 |
0000000000648838 | 4C 8D 85 58 FF FF FF | lea r8,qword ptr ss: |
000000000064883F | 48 8D 8D 08 EA FF FF | lea rcx,qword ptr ss: | Patch 1
0000000000648846 | 49 B9 0F 00 00 00 00 00 00 0 | mov r9,F |
0000000000648850 | 48 BA FF 00 00 00 00 00 00 0 | mov rdx,FF |
000000000064885A | E8 B1 D6 DB FF | call totalcmd64.405F10 |
000000000064885F | 48 8D 95 08 EA FF FF | lea rdx,qword ptr ss: |
0000000000648866 | 48 89 D9 | mov rcx,rbx | RCX ==> RDXLEN = 0x11
0000000000648869 | E8 B2 D5 DB FF | call totalcmd64.405E20 | 比较HASH值
000000000064886E | 85 C0 | test eax,eax |
0000000000648870 | 0F 84 DE 01 00 00 | je totalcmd64.648A54 | NOT JMP
所以关键点在这里:当二次解密后,我们要将解密后数据的地址进行存储。
01.
000000000064875Fcall totalcmd64.647E70 // RCX 传入存储解密数据的BUFFER
0000000000648764lea rdx,qword ptr ds:// 这里数据解密完成
0000000001CCE4A847 06 76 FA 9A 89 27 E6 CF 40 20 E8 00 B1 D0 65// 前0x10 为后续数据的HASH值
0000000001CCE4B883 4F F4 9A E3 48 AD 4E B5 BC EF CC 5F B9 AC F7
0000000001CCE4C85B 6A A6 BA BC 14 04 43 BB BD 86 0E B9 77 11 D7
0000000001CCE4D800 F1 C1 E2 48 51 F2 07 1E DC 67 A3 45 48 31 1A
0000000001CCE4E874 32 36 8D F9 E7 53 04 E9 D5 9D 59 3F 55 E2 9E
0000000001CCE4F81B D7 84 26 8C BF 29 30 DC 32 2B 19 32 FC FA 03
0000000001CCE5082F 12 C8 A2 36 DF BC 00
02.
0000000000648869call totalcmd64.405E20 | 比较HASH值 RCX 和 RDX 为比较参数
----------------------------------------------------------
方案一:
01、我们在 RIP = 64875F 处,直接存储 RCX 值。将该存储数据起名为 ID_SAVENAME_USERINFO .
02、在 RIP = 648764 处,修改 ID_SAVENAME_USERINFO 地址偏移 0x10 处,为我们定义的用户数据(自定义数值,HEX类型) :
我们自己计算一组HEX数据:
0A 2A 2C 10 27 00 00 50 59 47 42 61 79 6D 61 78 20 50 61 74 63 68 20 54 6F 6F 6C 73 7C 63 68 69 6E 61 70 79 67 40 70 79 67 2E 63 6F 6D 00
替换内存位置:
Byamax 中操作步骤:
设置偏移地址和补丁数据:
03、
在 RIP = 648869 处,为第一次HASH值比较。
在 RIP = 64919C 处,为第二次HASH值比较(文件的HASH值)。
这两次比较修改方案很多,比如修改寄存器(参数相同),修改返回值,修改跳转等,这里我们实验一下存储使用功能:先将 RCX 中的HASH数据,HEX数值进行存储,然后用存储数据替换 RDX 中的数据,使其比较数据相同。
0000000001CCD05810 76 DD 7B C4 AF 0D B6 EE E6 65 50 5E 3D 77 38
0000000001CCD0686B
第一个字节 10 为 HASH 长度,之后的0x10 个数据为 HASH值,所以我们存储 0x11 个字节。存储标号处填入存储名称,HEX字节0x11。
然后在该地址使用刚存储的数据,补丁RDX指向的内存:
完成第一处HASH比较。
第二处比较 RIP = 64919C 处,我们之间修改寄存器就好。
BPT 工程文件:
// 这是 Baymax Patch Tools x64 创建的补丁方案,请勿修改!!!
PROCESS = D:\Program Files\totalcmd\TOTALCMD64.EXE
TITLE =
AUTHOR =
ITEMCOUNT = 1
VERSION = 2
OPTION = 0
PATCHTYPE = 异常中断补丁
PROCESS = D:\Program Files\totalcmd\TOTALCMD64.EXE
MODULE = D:\Program Files\totalcmd\TOTALCMD64.EXE
PROCESSCHECK = 0
MODULECHECK = 0
SHOWNAME = TOTALCMD64.EXE(TOTALCMD64.EXE)
SHOWINFO = SD::S,ID_SAVENAME_USERINFO,R,Q,RCX
HOOKTYPE = 0
PATCHCOUNT = 5
PATCH_VA_0 = 2393951
PATCH_SRC_0 = N/A
PATCH_DEST_0 = SD::S,ID_SAVENAME_USERINFO,R,Q,RCX
PATCH_NOTE_0 =
PATCH_VA_1 = 2393956
PATCH_SRC_1 = N/A
PATCH_DEST_1 = SA,10::U,ID_SAVENAME_USERINFO,I,H,0A 2A 2C 10 27 00 00 50 59 47 42 61 79 6D 61 78 20 50 61 74 63 68 20 54 6F 6F 6C 73 7C 63 68 69 6E 61 70 79 67 40 70 79 67 2E 63 6F 6D 00
PATCH_NOTE_1 =
PATCH_VA_2 = 2394217
PATCH_SRC_2 = N/A
PATCH_DEST_2 = SD::S,ID_SAVENAME_HASH1,M,H,11,RCX,0
PATCH_NOTE_2 =
PATCH_VA_3 = 2394217
PATCH_SRC_3 = N/A
PATCH_DEST_3 = RDX,0::U,H,ID_SAVENAME_HASH1
PATCH_NOTE_3 =
PATCH_VA_4 = 2396572
PATCH_SRC_4 = N/A
PATCH_DEST_4 = RCX::R,Q,RDX
PATCH_NOTE_4 =
方案二:
0000000000648754 | 41 B8 66 00 00 00 | mov r8d,66 | 66:'f'
000000000064875A | BA BC A4 20 00 | mov edx,20A4BC |
000000000064875F | E8 0C F7 FF FF | call totalcmd64.647E70 | 二次解密
... ...
0000000000647E70 | 55 | push rbp | F7跟进二次解码函数 RCX 用于接收解密后的数据
0000000000647E71 | 48 89 E5 | mov rbp,rsp |
0000000000647E74 | 48 83 EC 50 | sub rsp,50 |
我们也可以一步到位将解密后的用户数据进行修改,跟进二次解码函数 647E70,在这里设置 “存储当前上下文并在返回时修改修改”,勾选后Baymax将在该地址对我们设置的寄存器(RCX)进行存储,并在函数返回后修改方才存储的RCX指向的内存。
BTW:
"函数返回时修改上下文" 和 “存储当前上下文并在返回时修改修改” 不同在于,前者不存储寄存器,而是等函数返回后再取寄存器值进行寻址补丁。
“函数直接返回后修改上下文”可用在某些我们不希望执行的函数上(如网验)并在函数返回后进行补丁,可设置返回地址栈偏移(根据你设置的地址进行直接返回)和栈调整(用户平衡堆栈)。
沙发支持校长,学习,校长辛苦 学习一下,谢谢校长。 学习一下,支持校长~~~ 内容有点深奥了,没看明白 谢谢详细的教学。
同时建议把工具的下载链接也加进帖子里面。 赞,是更新了新版?好像主帖没更新。不知道调试时上次建议有没有更新 功能越来越强大了,感谢校长 沙发支持校长,校长辛苦
表哥厉害,高大上!
页:
[1]
2