标题: OSForensics 9 逆向工程闲谈 创建: 2022-04-27 20:49 更新: 2022-04-29 09:41 链接: https://scz.617.cn/misc/202204272049.txt https://www.52pojie.cn/thread-1629107-1-1.html -------------------------------------------------------------------------- 目录: ☆ 背景介绍 ☆ OSForensics 8.0.1000 受限破解 ☆ BinDiff得到 OSForensics 9.1.1012 无效破解 ☆ 遭遇"Code Virtualizer" ☆ "Time Travel Debugging" (TTD) vs "Code Virtualizer" (CV) ☆ 反"反调试" 1) x64dbg 1.1) 修改指定内存的字节流 1.2) 修改指定内存的字符串 1.3) 查看内存 1.4) 反汇编窗口(CPU)光标移到指定地址 1.5) 查看调用栈回溯 1.6) 断点命中时修正CIP并继续执行 2) windbg ☆ OSForensics 9.1.1012 凑合破解 -------------------------------------------------------------------------- ☆ 背景介绍 看NTFS ADS时搜到这个 How to view files with NTFS streams https://www.osforensics.com/faqs-and-tutorials/how-to-view-files-with-ntfs-streams.html 挺喜欢OSForensics的"File System Browser"功能。 https://www.osforensics.com/download.html https://osforensics.com/downloads/osf.exe 这是款商业软件,有30天受限试用,截至本文写作时最新版是9.1.1012。 ☆ OSForensics 8.0.1000 受限破解 https://pan.baidu.com/s/1140djZBPHheqj-75Yl9J-Q (提取码:aqbk) 之前网上瞎找的,事后发现标题党,版本并不是9.0.1002,而是8.0.1000。二次分发 者应该是个祖上缺了大德的,玩这种把戏。 该受限破解版包含原始安装包及用于替换的osf64.exe。官方不再提供8.0.1000版安 装包。osf64.exe有108MB,单个PE这么大,相当丧心病狂,后来才明白,这是原厂商 为了反逆向工程。 安装完桌面有个快捷方式到此程序 "C:\Program Files\OSForensics\OSForensics.exe" 它只是个loader,根据CPU位数调用osf32.exe或osf64.exe,后二者才是干活的。受 限破解版实际替换 C:\Program Files\OSForensics\osf64.exe 未加小木马,就是几处静态Patch $ fc /b osf64_old.exe osf64_new.exe 0182B98A: E8 90 0182B98B: B1 90 0182B98C: E1 90 0182B98D: FF 90 0182B98E: FF 90 0182BFF6: 84 85 0182C9DA: 0F E9 0182C9DB: 84 D7 0182C9DC: D6 00 0182C9DF: 00 90 018B6497: 75 EB 该受限破解只是表面上将30天试用版变成Pro版,不再弹框提示试用版快到期,但应 用该破解后仍然无法使用Pro版才有的功能。我没有仔细测试,不确定是否有暗桩未 拔。 ☆ BinDiff得到 OSForensics 9.1.1012 无效破解 前面说了,8.0.1000受限破解二次分发者玩了个标题党,写成9.0.1002破解,心想这 与9.1.1012离得不远,BinDiff可以快速找出新Patch点。 以前碰上有old版crack,想求new版crack,不一定动用BinDiff。IDA看看old中Patch 点附近的特征字符串,若new与old版本接近,很容易定位new中Patch点。但搞osf64 时,未能这样简单得手,于是动用BinDiff。也挺烦的,因为osf64非常大,上百兆。 参看 《BinDiff二进制比较简介》 https://scz.617.cn/misc/202109131335.txt 先打开9.1.1012的i64,再BinDiff打开8.0.1000的i64,整个过程肉眼可见的耗时, 可以扔那儿去干点别的事。由于old与new版本相差较大,BinDiff受限。此外,后来 才知道OSForensics动用了"Code Virtualizer",进一步限制了BinDiff。 最后能在new中找到3个Patch点,其中一个动态调试发现无需Patch,其余两个Patch 点见下 -------------------------------------------------------------------------- WinMain 0000000141960B9E 33 C9 xor ecx, ecx /* * nop掉 */ 0000000141960BA0 E8 DB E1 FF FF call sub_14195ED80 -------------------------------------------------------------------------- sub_1419F55A0 00000001419F55E0 66 3B 05 B5 FC 56 04 cmp ax, cs:word_145F6529C /* * 将jnz换成无条件跳转jmp */ 00000001419F55E7 75 1E jnz short loc_1419F5607 -------------------------------------------------------------------------- 应用上述各Patch后直接进OSF主界面,显示Pro版。其实是假Pro版,且有暗桩未拔, 使用"File System Browser"时会闪退,x64dbg调试发现有未处理异常抛出。 可能这种破解方案适用于8.0.1000,但绝对不适用于9.1.1012。 需要指出的是,利用BinDiff从旧版破解获取新版破解,是一种通用手段,尽管具体 到本例失败了。 ☆ 遭遇"Code Virtualizer" 碰上OSForensics之前,我从未遭遇过"Code Virtualizer",没有早早意识到CV的存 在,只是觉得OSF挺结实,做了不少反静态分析对抗。事后简单复盘,避免反复踩坑。 OSForensics 9.1.1012可能用CV进行保护,用IDA反汇编osf64.exe验证之。 IDA中Shift-F7,如果看到有".vlizer",很可能用"Code Virtualizer"保护过。IDA 中在指定地址处Ctrl-S,若该地址属于".vlizer",表示指定地址位于CV虚拟机中, 如既无长期经验积累又无强烈刚需,不建议调试CV虚拟机,弃坑走人为上。或许识别 CV有成熟方案,这里只是个人不成熟的经验。 CV处理过OSF后,IDA的Strings窗口很可能找不到某些字符串,"(Pro only)"就是一 例。若Strings窗口找不到,最好字节流搜一下,比如 $ python3 -c "import sys,hexdump;print(hexdump.dump(bytes(sys.argv[1],encoding='utf-16')[2:]))" "(Pro only)" 28 00 50 00 72 00 6F 00 20 00 6F 00 6E 00 6C 00 79 00 29 00 在"Hex View"窗口中Alt-B搜索。 下面是网上公开流传过的"Code Virtualizer"逆向工程资料汇集 -------------------------------------------------------------------------- Inside Code Virtualizer v1.0.1.0 - scherzo [2007-02-16] https://forum.tuts4you.com/files/file/1933-inside-code-virtualizer-v1010/ https://github.com/lmy375/awesome-vmp/blob/master/note/2007_scherzo_Inside_Code_Virtualizer.pdf (Inside Code Virtualizer v1.0.1.0.rar) (SB百度文库还收费) Code Virtualizer的一点分析和还原 - Ryosuke [2008-04-03] https://bbs.pediy.com/thread-62447.htm Code Virtualizer 1.3.8.0小窥 - 朱季峰(neineit) [2010-11-20] https://bbs.pediy.com/thread-125140.htm 关于Code Virtualizer pcode解密的一种方法 - vasthao [2011-7-16] https://bbs.pediy.com/thread-137265.htm DeCV a decompiler for Code Virtualizer by Oreans - pakt [2012-10-03] https://gdtr.wordpress.com/2012/10/03/decv-a-decompiler-for-code-virtualizer-by-oreans/ https://github.com/pakt/decv (Decompiler for Code Virtualizer 1.3.8) Code Virtualizer虚拟机代码还原 - vasthao [2013-03-09] https://bbs.pediy.com/thread-163843.htm Code Virtualizer虚拟机保护初探 - 董阳(robinh00d) [2014-06-09] https://www.nsfocus.com.cn/upload/contents/2015/03/o_19fepsr5ut2s59f18bt1ejt4psb.pdf Code Virtualizer 2.2.2.0 - [2018-02-21] https://www.52pojie.cn/thread-700779-1-1.html https://pan.baidu.com/s/1mkeiAWo 两个OllyDbg插件 VMSweeper Oreans UnVirtualizer -------------------------------------------------------------------------- 董阳那篇最有感触,好不容易在网上找到带图版,居然是NSFOCUS技术内刊版。和他 聊起后才发现8年前在四楼小会议室里他讲过一遍,于是我又重新看了一遍。 我只是大致看了这批CV资料,并未在OSF逆向工程中实践之,耗不起。 ☆ "Time Travel Debugging" (TTD) vs "Code Virtualizer" (CV) OSF没有考虑到TTD技术的出现,其反调试措施没有针对TTD记录。 参看 《MSDN系列(46)--WinDbg Preview TTD入门》 https://scz.617.cn/windows/202201251528.txt https://scz.617.cn/windows/MSDN_46.docx TTD.exe -out osf64.run -launch osf64.exe TTD.exe -out osf64.run -attach TTD.exe -stop TTD.exe -stop all DbgX.Shell.exe osf64.run windbgx osf64.run 提醒一句,不需要在OSF所在环境安装"WinDbg Preview",系统很可能自带tttracer, 得到.run文件后弄到其他更方便的环境中慢慢鞭尸。 TTD技术用于破解软件确实是个超级利器,属于降维打击,时间维度上的任意操控。 但是,OSF有CV技术加持,相当程度抵消了TTD。尽管TTD可以操控时间,但CV让整个 时间线呈现出混沌,除非对CV有持续经验积累,否则即使动用TTD,也大大受限。 看过《十三度凶间》的可以类比一下,TTD是最外层的监控者,CV将信息藏到最内层 虚拟世界,除非进入最内层世界,否则最外层监控者无法直接获取被藏起来的信息。 OSF经CV加持后,wt这类命令完全陷入混沌,事实上不可用。但TTD可以操控时间,换 个角度看,也部分抵消了CV。若对CV有过经验积累,再动用TTD,效果必定杠杠的。 某些调试、测试或静态Patch导致OSF调"USER32!MessageBoxA"弹框,既往经验是看调 用栈回溯,向call的低址方向寻找条件跳转指令,对之Patch。但TTD调试OSF时,kpn 得不到MessageBoxA的主调位置。用x64dbg动态调试,一样。一度怀疑OSF用到 "ntdll!NtContinue"反调试技巧,后来发现,只是利用ret转移过来。此间有个重要 经验分享,停在MessageBoxA入口时,用"Step Over Back"会跑飞,回到当前线程的 初始阶段,用"Step Out Back"也会跑飞,应该用"Step Into Back"。换句话说,用 "p-"、"g-u"跑飞时,换用"t-"试试,或者"!tt"指定值减1。此坑与ret转移强相关, 也与CV虚拟机强相关,若目标是普通正经程序,无此坑。 找到了MessageBoxA的主调位置,发现位于CV虚拟机中,无前期积累的情况下未能找 到关键分叉点,这就是我说的CV部分抵消了TTD。 ☆ 反"反调试" 一般用IDA静态看,并不用IDA动态调,这是个人习惯问题。TTD调试只能鞭尸,验证 Patch方案还是得实时动态调试。 cdb.exe -noinh -snul -hd -o osf64.exe 从ibp g之后进程结束,看不到OSF主界面,后来确认OSF有一些反调试机制。 跟bluerust抱怨windbg没有趁手的反"反调试"插件,他推荐了ScyllaHide https://github.com/x64dbg/ScyllaHide 1) x64dbg ScyllaHide有现成的x64dbg插件,用"x64dbg+ScyllaHide"反"反调试"成功 https://github.com/x64dbg/x64dbg 下载ScyllaHide后复制相应文件到x64dbg相应目录,启动x64dbg时自动加载相应插件 ScyllaHide\x64dbg\x32\plugins\ x64dbg\x32\plugins\ HookLibraryx86.dll ScyllaHideX64DBGPlugin.dp32 scylla_hide.ini ScyllaHide\x64dbg\x64\plugins\ x64dbg\x64\plugins\ HookLibraryx64.dll ScyllaHideX64DBGPlugin.dp64 scylla_hide.ini Plugins->ScyllaHide->Options 此处有非常全面的反"反调试"措施,默认用"VMProtect x86/x64" 这是平生第一次用x64dbg,因为不玩破解,正经调试用windbg,x64dbg类似OllyDbg 的GUI。按自己调试需求整理《x64dbg速查手册》,最后发现把"x64dbg.chm"遍历一 下即可。 分享其中几个小操作 1.1) 修改指定内存的字节流 set r9, #A0# set r9, #A0 13# set r9, #A0 13 E4 6A FA FF FF FF# set r9, #A013E46A# 将r9指向的内存写成指定字节流,可以无空格。该法普适,可修改.text、.data。 1.2) 修改指定内存的字符串 其实上一小节的内容就可以满足需求,但有其他方法。 strset $tmp, "foo bar blah blah" strcpy rdx, $tmp vardel $tmp 将rdx指向的内存写成指定字符串,该字符串没有结尾的\0,只支持ASCII,不支持 UNICODE。strset/strcpy是未公开命令。 上面这种办法太受限了,为了写UNICODE字符串,还是动用set吧。 写UNICODE字符串 $ python3 -c "import sys,hexdump;print(hexdump.dump(bytes(sys.argv[1],encoding='utf-16')[2:],sep=''))" "foo bar blah blah" 66006F006F002000620061007200200062006C0061006800200062006C0061006800 set rdx, #66006F006F002000620061007200200062006C0061006800200062006C0061006800# 写ASCII字符串 $ python3 -c "import sys,hexdump;print(hexdump.dump(bytes(sys.argv[1],encoding='utf-8'),sep=''))" "foo bar blah blah" 666F6F2062617220626C616820626C6168 set rdx, #666F6F2062617220626C616820626C6168# 1.3) 查看内存 不说GUI,命令行法 dump 1.4) 反汇编窗口(CPU)光标移到指定地址 不说GUI,命令行法 d [addr] 不指定[addr]时,相当于"d rip",相当于按星号,回到rip处 d USER32.DialogBoxParamW d USER32:DialogBoxParamW 用点号或冒号分隔模块名与函数名,不用惊叹号分隔,与windbg不同 1.5) 查看调用栈回溯 View->Call Stack (Alt-K) 呼出"Call Stack"窗口,当前线程的"Thread"列高亮显示 缺省是"Active Call Stack Frame",就是常规调用栈回溯算法,若目标PE做过反静 态分析处理,这种调用栈回溯很容易中断,看不到主调位置。 "Call Stack"窗口右键菜单->Show Suspected Call Stack Frame 启用"Suspected Call Stack Frame"后会进行启发式调用栈回溯,对付做过反静态分 析处理的PE时,颇有奇效。 1.6) 断点命中时修正CIP并继续执行 假设要实现这种效果,断在时自动跳到继续执行,可能有很多办法 达到此目的,其中一种办法是 bp ;bpgoto , bpgoto是针对bp的补充设置,bpgoto不能直接设断,处断点命中后跳到 继续执行,并不会停在。 2) windbg ScyllaHide没有现成的windbg插件,但ScyllaHide有独立运行版本,理论上可与任意 调试器配合使用,实现反"反调试"。 cdb.exe -noinh -snul -hd -o osf64.exe 假设停在ibp,"? @$tpid"获取目标PID,在另一个cmd中执行 "X:\path\ScyllaHide\InjectorCLIx64.exe" pid:2372 "X:\path\ScyllaHide\HookLibraryx64.dll" nowait 成功时会输出 -------------------------------------------------------------------------- Loaded VA for NtUserBlockInput = 0x00007FFD2FAC7870 Loaded VA for NtUserQueryWindow = 0x00007FFD2FAC1290 Loaded VA for NtUserGetForegroundWindow = 0x00007FFD2FAC1810 Loaded VA for NtUserBuildHwndList = 0x00007FFD2FAC1410 Loaded VA for NtUserFindWindowEx = 0x00007FFD2FAC1E30 Loaded VA for NtUserGetClassName = 0x00007FFD2FAC1FD0 Loaded VA for NtUserInternalGetWindowText = 0x00007FFD2FAC1CD0 Loaded VA for NtUserGetThreadState = 0x00007FFD2FAC1090 PID : 2372 0x944 DLL Path: X:\path\ScyllaHide\HookLibraryx64.dll Hook injection successful, image base 0000000000170000 -------------------------------------------------------------------------- 回到cdb的ibp处继续执行,这次OSF没有退出,可以看到GUI。 "X:\path\ScyllaHide\scylla_hide.ini"默认用"VMProtect x86/x64",可以对付绝 大多数情况。 更多讨论参看 《让windbg反"反调试"》 https://scz.617.cn/windows/202204281326.txt ☆ OSForensics 9.1.1012 凑合破解 不打算跟OSF中的CV耗,凑合着搞了个部分破解。 $ fc /b osf64_old.exe osf64_new.exe 0195E776: 7F EB 064BE1ED: 84 85 改2个字节,第一个字节由朱季峰提供,第二字节由scz提供,一人剁一个字节。可以 无限试用,我最想用的"File System Browser"部分解锁Pro版功能,未能完全解锁。 没有key.dat,OSF绿色化失败,这是厂商故意的。 没有动力与CV磕,投入产出不成比例,就这样吧。