1、申 请 I D:zyjsuper
2、个人邮箱:zyj_super2@163.com
3、原创技术文章:使用Radare2+Hopper破解Hopper Demo限制
声明:为方便各位破解爱好者使用Hopper,所以公布此文,此前未做任何公布。仅限个人使用,勿做商业用途,为更好的长期的使用Hopper,请做好保密工作。
软件版本:Hopper Disassember 4.5.11 Demo x86_64(4.5.12已测可过)
操作系统:Linux通用软件运行时会提示注册窗口,选择一个License文件注册,或者使用试用版。点击Try the Demo后,会进入软件页面,保存修改后的文件时会提示如下窗口,试用版不支持此功能。 使用Ghidra或者IDA查找"You cannot export a patched executable with the demo version" 这条信息,本人使用Demo版本的Hopper来做演示,以子之矛,攻子之盾。搜索“demo”字符串可以得到下面的结果。 右击右侧窗口对应的字符串地址,如图所示,选择“References to......”得到下图的结果,表示此处调用该字符串,双击该地址自动跳转到该地址所在的汇编代码。代码如下:
12345678910111213141516171819 | sub_63dd48:000000000063dd48 lea rdi, qword [aError] ; argument #1 for method j__ZN7QString16fromAscii_helperEPKci, "Error", CODE XREF=sub_63dd20+15000000000063dd4f mov esi, 0x5 ; argument #2 for method j__ZN7QString16fromAscii_helperEPKci000000000063dd54 call j__ZN7QString16fromAscii_helperEPKci ; QString::fromAscii_helper(char const*, int)000000000063dd59 mov qword [rsp+arg_8], rax000000000063dd5e lea rdi, qword [aYouCannotExpor_685539] ; argument #1 for method j__ZN7QString16fromAscii_helperEPKci, "You cannot export a patched executable with the demo version"000000000063dd65 mov esi, 0x3c ; argument #2 for method j__ZN7QString16fromAscii_helperEPKci000000000063dd6a call j__ZN7QString16fromAscii_helperEPKci ; QString::fromAscii_helper(char const*, int)000000000063dd6f mov qword [rsp+arg_0], rax000000000063dd74 lea rsi, qword [rsp+arg_8] ; argument #2 for method j__ZN11QMessageBox8criticalEP7QWidgetRK7QStringS4_6QFlagsINS_14StandardButtonEES6_000000000063dd79 lea rdx, qword [rsp+arg_0] ; argument #3 for method j__ZN11QMessageBox8criticalEP7QWidgetRK7QStringS4_6QFlagsINS_14StandardButtonEES6_000000000063dd7e mov ecx, 0x400 ; argument #4 for method j__ZN11QMessageBox8criticalEP7QWidgetRK7QStringS4_6QFlagsINS_14StandardButtonEES6_000000000063dd83 xor r8d, r8d ; argument #5 for method j__ZN11QMessageBox8criticalEP7QWidgetRK7QStringS4_6QFlagsINS_14StandardButtonEES6_000000000063dd86 mov rdi, rbx ; argument #1 for method j__ZN11QMessageBox8criticalEP7QWidgetRK7QStringS4_6QFlagsINS_14StandardButtonEES6_000000000063dd89 call j__ZN11QMessageBox8criticalEP7QWidgetRK7QStringS4_6QFlagsINS_14StandardButtonEES6_ ; QMessageBox::critical(QWidget*, QString const&, QString const&, QFlags<QMessageBox::StandardButton>, QMessageBox::StandardButton)000000000063dd8e mov rdi, qword [rsp+arg_0]000000000063dd93 mov eax, dword [rdi]000000000063dd95 cmp eax, 0xffffffff000000000063dd98 je loc_63ddc2 | 使用"References to....."没有找到从何处跳转到该处,我们可以顺着该段代码向上分析,得到关键函数如下:在“je sub_63dd48”之前有一处函数调用“call sub_504550”
12345678910111213141516171819 | ; ================ B E G I N N I N G O F P R O C E D U R E ================ sub_63dd20:000000000063dd20 push rbx ; Begin of unwind block (FDE at 0x83ee14), Begin of try block, CODE XREF=sub_661720+339000000000063dd21 sub rsp, 0x20000000000063dd25 mov rbx, rdi000000000063dd28 call sub_504550 ; sub_504550000000000063dd2d test al, al000000000063dd2f je sub_63dd48 ; sub_63dd48 000000000063dd31 mov rdi, qword [rbx+0x40]000000000063dd35 test rdi, rdi000000000063dd38 je sub_63dd48+174 000000000063dd3e add rsp, 0x20000000000063dd42 pop rbx000000000063dd43 jmp sub_5b7ba0 ; sub_5b7ba0 ; endp | 双击"sub_504550"得到该函数的汇编代码如下:
1234567891011121314151617181920 | ; ================ B E G I N N I N G O F P R O C E D U R E ================ sub_504550:0000000000504550 push rax ; Begin of unwind block (FDE at 0x828a2c), CODE XREF=sub_5b7850+70, sub_5ecc10+1195, sub_637fc0+89, sub_637fc0+129, sub_63ca60+18, sub_63cf10+10, sub_63d640+8, sub_63d7a0+8, sub_63d900+8, sub_63da60+8, sub_63dbc0+80000000000504551 call sub_5024e0 ; sub_5024e00000000000504556 cmp eax, 0x30000000000504559 jne loc_504565 000000000050455b call sub_502e70 ; sub_502e700000000000504560 call sub_5024e0 ; sub_5024e0 loc_504565:0000000000504565 dec eax ; CODE XREF=sub_504550+90000000000504567 cmp eax, 0x2000000000050456a setb al000000000050456d pop rcx000000000050456e ret ; endp000000000050456f align 16 | 使用"References to..."可以查看到很多调用函数,这些函数都是以sub_504550的返回值作为判断依据, 返回到“sub_63dd20”这个函数,我们可以看到"test al,al je sub_63dd48",只要sub_504550的返回值为1时,此处不跳转。那么我们将sub_504550修改成如下即可:
12345678 | sub_504550:0000000000504550 mov rax,0x1 ; Begin of unwind block (FDE at 0x828a2c), CODE XREF=sub_5b7850+70, sub_5ecc10+1195, sub_637fc0+89, sub_637fc0+129, sub_63ca60+18, sub_63cf10+10, sub_63d640+8, sub_63d7a0+8, sub_63d900+8, sub_63da60+8, sub_63dbc0+80000000000504551 ret ; sub_5024e00000000000504556 cmp eax, 0x30000000000504559 jne loc_504565 000000000050455b call sub_502e70 ; sub_502e700000000000504560 call sub_5024e0 <br>.......... | 在0x00504550这个地址处点击"alt+a",直接顺序输入mov rax,0x1 和 ret即可完成修改以下是使用radare2的修改方法。# r2 -Aw /opt/hopper-v4/Hopper[0x00504550]> wa mov rax,0x1 @ 0x00504550[0x00504550]> wa ret @ 0x00504557
使用r2pipe完成代码如下:(pip install r2pipe时有报错,有其他方案可以安装,此处不做赘述)
123456789 | import osos.system("pip install r2pipe")import r2pipeos.system("cp /opt/hopper-v4/bin/Hopper /opt/hopper-v4/bin/Hopper.backup")r2 = r2pipe.open("/opt/hopper-v4/bin/Hopper",['-w'])r2.cmd("wa mov rax,0x1 @ 0x00504550")r2.cmd("wa ret @ 0x00504557")r2.cmd("quit")os.system("/opt/hopper-v4/bin/Hopper") |
|