天草壳世界学习笔记:
1.OD的查找支持模糊查找 ?? 比如 要查找 E82091FBFFA1B8 可模糊查找:E8??91FBFF??B8
2.OD的插件idaficator 可以支持回滚 就是记录你的操作记录往回走 相当于一个跳转或者CALL以后 可以跳回去看 鼠标左键 ESC 可以回滚上一步 鼠标右键可以回滚下一步
3.StrongOD插件的二进制无空格复制功能 在OD中选中代码 ctrl+shift+x 复制二进制无空格字节 8B45EC8B088B09894D985051 如果是OD自身二进制复制如下8B 45 EC 8B 08 8B 09 89 4D 98 50 51是有空格的
4.OD中的跳转修改 不用修改代码 直接修改标志寄存器标志Z就可以 双击修改
5.StrongOD复制地址功能 ctrl+x
6.利用ctrl+B二进制搜索 多观察多搜索 各个编译器的开头OEP(Original Entry Point)特征便于定位
7.OD脚本利用 用于脱壳等一切动作
8.找OEP的一个方法 寻在程序结尾时的ExitProcess 因为结尾附近就是OEP 根据编译语言特点观察一下就可以找到OEP
9.StrongOD填充NOP 键盘1是填充1个NOP 2是填充2个NOP 3是填充3个NOP 以此类推
10.softDefender加密壳 一般有这样几步骤 1.先加载dll得到函数地址存放在内存上 2.再进行相应的地址加密 3.把加密后的地址放入IAT 所以最好的时机就是在2-3之间 这里既有IAT的地址 又有加密的地址 又有真实的地址 修改部分判断就可以达到不加密的结果
11.OD中更新的内容会变红 这样不方便看 可以用右键备份-》更新备份 来取消变红 有时候为了追踪SMC代码自修改,也需要让它变红,这个时候可以在该段中,修改一些指令,修改后的指令就会变红,单步SMC变化的代码也会变红,再撤销先前修改的,这时候每个SMC的代码都会继续变红了,方便观察。12.ACProtect壳的乱序系统,把OEP开头处的代码分布执行了 在它壳里边绕来绕去 但是最终还是执行了这么几条指令 可以对代码段下内存断点 这样可以找出程序本身的call
13.IDAFicator的多行汇编功能Rote 可以将多行汇编代码写入OD中 但是版本是1.2 如果用最新的2.0 2.0需要配置RadAsm 这个比较复杂 期待2.0的配置
14.在OD脚本中有许多功能没有脚本指令 可以用模拟键盘的方式来执行 比如ctrl+f2重新载入 本来的脚本命令式reset 可以用key 71,0,1来代替 但是这里重新载入以后脚本也跟着载入了 感觉这个命令没什么用处
15.因为脱壳逆向的工具比较多 比较杂乱 所以所有的工具可以用 音速启动 这个软件进行归类
16.在OD中需要分析一个函数的时候 可以把EIP设置到这个函数执行 但是应该把EIP设置到这个函数的call而不是这里函数里边 这个原因很好理解 比如EIP停在OEP开头就好比在执行代码第一句话 现在需要分析一个函数的细节 当然是直接跳到这个函数的执行的语句 然后再进入这个函数分析 如果直接把EIP指向这个函数里边 会造成栈的不平衡
17.StrongOD有个创建内存空间的功能快捷键是ALT+Q 在临时运行一些测试代码的时候可以用到18.在寻找OEP时 如果壳已经做了变化 比如多态代码 这个时候就可以用相应工具环境创建一个无壳的程序 进行对比解密
19.有些壳修改了段属性从而控制访问权限 比如没有写属性 OD的CTRL+B就不好用了 所以需要在 Memory map中把需要用到的段属性进行修改
20.OD中 在使用ctrl+B搜索时 如果是对反汇编窗口进行的它只会对该段进行搜索 如果实在Memory map中搜索的 它会从指定段往后搜索其他段
21.如果遇见花指令的时候 可以通过 花指令去除器 来去除花指令 但是需要注意的是 1.壳是否有检查花指令的代码,如果有检测去除以后要出错 2.花指令所要不然去除权限为完全访问 在去除花指令 防止去除花指令后程序崩溃
22.对于有重定位功能的壳 可以使用 1.补区段的方法 2.跳过重定位代码 dump段 补充PE头 补充资源 方法1步骤比较少但不完美 方法2步骤比较多相对完美
23.Obsidium这样的壳IAT修复可以使用函数跟进的方法 就是把EIP设置到这个模拟函数的开头 然后一步一步跟进得到真实的函数 这个和10点中的IAT解密方法不同
24.在OD中如果需要定位某个系统函数入口点 只需要直接CTRL+G输入API名称 比如需要定位VirtualProtect 只需要直接ctrl+G 就可以到达VirtualProtect入口点
25.在OD中使用ctrl+g可以跟随到相应地址 但是有时候如果是A-F开头的 会显示 未知标示符 这个时候需要在字母前补充0来说明这个标示符是一个十六进制的地址
26.在执行OD脚本中 在脚本暂停状态下 双击相应的行 执行点将设置到这行 如果按下ESC 脚本将重新停在开头处 所有变量值全部清空
27.在执行OD脚本时,如果缩小OD窗口 或最小化窗口 可以加快OD脚本的执行速度 这里很容易理解 界面刷新开销减少了 速度自然快了
28.有时候用OD调试程序的时候 出现程序崩溃 并不一定是程序的验证 有可能是OD或者插件的问题造成的 这个时候应该尽量保证OD及其插件的更新
29.OD插件的编写如果实在比较高的平台比如WIN8 VS2012等 写出的差价不能再XP上运行 因为需要MSVCR110.DLL 但是XP最多支持MSVCR100.DLL 所以可能的话用VS2010编写应该可以解决
30.OD插件bookmark可以使用 比较方便 设置一个地址为书签0 书签1 然后ALT+0 ALT+1 可以切换到书签所在的地址 设置一个书签的快捷键是ALT+SHIFT+数字 感觉像星际争霸里边的编队一样 很方便
31.在解决加密IAT时 一般找到了一处加密的特征码后可以直接在OD中搜索这个特征码 看看其他地方还有没有 这是因为写程序的时候各个加密IAT的最后一个功能一般都是覆盖 这样一来很可能是一样的代码形式 所以编译成汇编代码也是一样 典型的例子就是The Enigma Protector v1.65的 mov dword ptr ds:[edx+eax*4+4],ecx 特征码
32.在使用OD的memory map时需要注意 列出的地址 大小有可能是通过2次或者多次 VirtualAlloc得到的结果 比如当看到结果是 地址=01730000 大小=00024000时如果只监视VirtualAlloc 分配size=00024000时 这样很可能找不到匹配的 但最后又的确存在这块内存 这就是因为这块内存是由2次分配完成的 第一次 addr=01730000 size=4000 第二次 addr=1734000 size=20000 最后在OD memory map中就看到了 addr=01730000 size=24000 还有就是因为内存对齐的作用如果用VirtualAlloc申请内存12CD0 会看到13000的大小结果 这点也要注意观察
33.在一些非汇编写或SDK直接编写的程序中 一般不会直接调用系统API 所以断点API一般是在编程语言所封装的函数中 如delphi MFC 这个时候如果要替换函数或者修改函数 一定要找到外层调用 也就是源代码中的调用地址 如果是加壳程序这个call一般会被替换掉 总之是找不到这个call的调用点 这个call retn后也是在加密代码中 这样可以确定源代码和编程语言框架的一个分界点 这也是外层调用点
34.有些时候针对程序弹出一个对话框设置断点时需要注意,程序很多时候弹出的不是对话框 是窗口这个时候用创建对话框的API断不下来的,所以需要对窗口的ShowWindow进行断点
35.在使用OD断点时 入F2 硬件 及其内存断点 需要明白其原理 F2断点就是int3 这个壳程序是可以检测的 如果是硬件断点 就是硬件断点寄存器dr0-dr3 简称drx 这个壳程序也是可以清除的 虽然OD的插件如PhantOm可以保护硬件断点 但是这期间需要时间的 很可能在这段时间EIP已经走过了断点处 所以这个时候如果在其前边下一个F2这样就可以给 OD插件充足时间来重新保护drx(双断点法的原理~OD插件会保护调试寄存器,也就是保护硬件断点,但是不能在异常清除以后马上恢复,需要时间,双断点法就是要程序用API的F2断点不断中断下来 给OD插件恢复硬件断点的时间~) 当然如果用内存断点就不会出现这个对抗了 但是会比较慢 因为每次OD都会对比
36.Process Monitor用于观察程序行为很方便,通过查看每条记录的堆栈信息可以得到API的调用情况
37.在OD中查找字符串 OD插件Ultra String不一定什么时候都好用 可以结合OD自带的字符串参考来用
38.一般一个支持多语言的软件 它都有各种语言的语言文件 如果是需要根据字符串定位 就需要找到相应的语言文件 在看对应的ID是多少比如
<message>39.定位程序的某些特征码时应该先考虑 文本形式的特征码 代码形式的特征码容易发现变化
40.有些EXE中捆绑了DLL 可以用Exeinfo PE来提取DLL 具体步骤:Rip->Ripper(search EXE PE inside EXE)执行以后 EXE存在的DLL就会被提取到EXE所在目录,同时这个工具也是一个很好的查壳软件和PEID互相搭配效果不错
41.关于脱壳后的优化可以参考http://blog.csdn.net/whatday/article/details/8785778 这篇文章 步骤比较多 优化的地方比较多 一个总的原则就是尽量让脱壳后的文件和没加壳的原文件一样PE头一样 各个区段一样
42.观察一个DLL是否可以正常运行可以用OD载入来测试,也可以用Dll LoadEx这个工具来测试
43.修改PE文件的基地址可以用PE32.Relocate工具 PE文件的基地址是在编译的时候就设定好了的 如果直接用PE编辑工具修改基地址会造成 重定位的代码无效 这个工具可以把每次需要重定位的地方进行相应的修改
44.对于绑定了DLL的壳来说,如果要解除捆绑 第一步,让程序完全跑起来,dump DLL所在的内存,Exeinfo提取DLL,这个时候虽然提取的DLL可能不完整或者被加密,但是可以通过Exeinfo的日志看到有几个DLL其RVA是多少。第二步,分别在DLL的RVA下断点 得到解码后的完整DLL,这个时候可以单独分析DLL文件了
45.查找一般IAT加密的方法:1.来到一个替换后的CALL(比如004069F4-FF25 48DDC901 jmp dword ptr [0x1C9DD48]),记录起地址设为A(004069F4),重载OD,在地址A+2下内存写入断点(A+2是[]中的值设为B),运行监测得到写入B时的代码地址。 2.设该代码所在的函数设为C,在C的开头部分可以看到一个列表首地址(mov ebp,0xB203D4 mov eax, dword ptr [ebp])设这个地址为D(0xB203D4),这个列表就是需要替换的函数地址列表,这个和导入表原理类似,重载OD,在D下内存写入断点,运行。 3.这个时候可以得到 一个申请完D列表的内存未写入值的 时机,在D下内存写入断点,就可以来到 IAT加密的函数了。
46.test汇编指令需要注意和cmp的区别,test是and的意思,具体要换成二进制来看,有时候也可以取巧的分析,比如test edi,0x1 je 00AF9C55这种情况下更多可以看成cmp edi,0x1 jne 00AF9C55,je jne容易混淆出错。
47.对于IAT比较大比较零散的情况下 如果直接用ImportREC进行重建IAT会增大脱壳后的文件,Universal Import Fixer(UIF)可以把零散的IAT重新放到新的位置上 并且合并起来 这样有效的利用空间 更有利于脱壳后的使用。
48.在OD界面上对着IDAFicator插件的按钮点右键 可以自定义按键功能,加入IDAFicator插件后,在OD的工具栏上会出现"工具" "常用断点"两个菜单项。 不是所有的插件最新就好,最新的版本有可能有各种bug,在更新插件的时候一定要先备份现有的插件
49.在内存中抓取DLL 有2种 一种是被内存映射了的,一种是原始的,内存映射的过程 一般是原始文件把PE头复制给映射文件,再把每个区段复制,原始文件的好处的原始的大小,内存映射文件的好处是最后都修改为了 SectionAlignment == FileAlignment == 1000 这样一来方便以后的操作不用换算 但是大小增大,多了修改节区的操作
50.很多从内存提取的文件,比如资源文件都是二进制的,可以用 010 Editor直接 "编辑->粘贴自->十六进制文本"(ctrl+shift+v) 来写入,在保存文件的时候还可以保存没有文件名的文件比如 .messages 这个文件资源管理器是不能创建的,010 Editor这个软件就可以创建.
51.在修复IAT的时候如果比较分散或者不是FF25的形式(jmp [xxx]),可以用UIF修复一下,UIF可以把API调用的地方搜索搜集起来在一个内存段新建一张IAT表,然后把程序中的代码都改为FF25调用这个IAT的形式,所以也要在UIF以后才能dump,有了完整的IAT表,importREC也便于修复了。
52.有时候脱了壳,用PEID还是显示Nothing found *,有可能是PE可选头中的连接器版本号修改造成的,程序可以运行,但查壳查不到,可以PE Tools修改PE Optional,如果是Delphi程序可修改为主链接器02副链接器19 这个具体值可以通过查看相应编译器的正常程序获得。
53.code replace的跟踪,如果是一次偷取一条指令(比如 RLPack),可以观察堆栈和寄存器的变化,有些指令是操作的内存比如MOV,所以也可以跟踪下看看具体做了什么,发生了什么改变,从而推算出这条指令是什么。
54.在使用OD脚本的asm命令写指令时发现 它生成的编码和在OD里边直接写汇编指令的编码有些不一样,比如"mov dword ptr [0x44F664], eax",用asm生成的结果是 0044CABE 8905 64F64400 mov dword ptr [0x44F664], eax 如果是在OD里边直接写是0044CABE A3 64F64400 mov dword ptr [0x44F664], eax 一个是8905 一个是A3 因为指令长度不一样这点造成很多问题,在还原code replace时就不能还原为原始的指令,解决方法是用wrta写到文件,然后自己手动用OD写入,如果代码多可以用IDAFicator写入。
55.一些壳脱壳后需要修改段属性,比如RLPack,这里指的是不完美脱壳,区段属性一般写改为。
56.对于原始区段没有被删除的加密后的软件来说,可以用标准的方法跑OEP,1,内存写入断点输入表段,2,内存访问断点代码段,这样一般就可以到OEP了。
57.Trial Reset这个软件可以清除壳软件的注册信息,便于反复实验破解。
58.pespin壳的指令变形比较有亮点,主要用于控制流程,如下:
dec ecx ;每次减一59.双进程的壳(比如pespin)的分离,可以对CreateMutexA进行断点(原理是两个进程通过一个约定好的有名称的互斥量,来探知对方的存在),然后修改结果让其认为已启动了进程,这样流程就不会执行CreateProcessA,流程改变了有可能到异常的代码上(比如 INT1 INT3等),这时有2个方法解决 第一,可以想象成在一个函数中,直接跳处函数,这样就跳过错误代码,返回点在栈里边可以找到。第二,可以想象成是一个if语句,让流程不执行里边的语句 所以跳过这些语句继续执行,这个执行点一般就在异常点后边不远处。建议使用第二种方法,直接返回函数有些操作没有执行到有可能发生错误。
60.有些壳中使用SEH改变流程来屏蔽调试,原理是:注册SEH后壳程序故意造异常,如果有调试器则中断到调试器,不会进入异常回调,恰好异常回调就是程序的流程,这样一来程序就终止了,让人不能一下跟踪到流程,解决方法是回调函数下断,shift+F9 避免了调试中断异常。
61.关于多线程壳验证注意事项,A.分析多线程可以设置 OD设置->事件->中断于新线程,勾选上后调式多线程立马方便了,出来一个线程od就断下,然后慢慢跟踪,跑OD脚本不要勾选,因为流程随时会因为新线程创建而改变。B.patch代码比OD脚本效率高很多,OD脚本修改代码有可能被多线程检测出来,但patch代码效率高,在多线程检查前就结束了。
62.OD中的ctrl+g输入API名称可直达API地址,StrongOD加强了它的选项功能,但输入API时需要注意,有些API在多个DLL中都存在,比如Kernel32.CreateThread和KernelBa.CreateThread,同时存在于2个dll中,但最终都调用的KERNELBA.CreateRemoteThreadEx,如果用ctrl+g定位CreateThread就会来到KernelBa中,但程序中大多调用的是kernel32的,所以这里设置断点就断不下来,方法1,这种情况可以再跟进一层API比如在CreateRemoteThreadEx中设置断点,这样就能断下来了。从而也可以发现程序本身调用的哪个API,也可以直接修改代码 比如 call kernel32.CreateFileA这样也能看到API地址,然后在撤销修改。方法2,直接ctlr+g 输入kernel32.CreateThread就会到达kernel32中的那个CreateThread了。
63.在执行比较大的OD脚本时,有可能出现不稳定或BUG或终止进程,这时尽量把脚本写得高效,少断点少比较,或者分成多个脚本运行,避免OD或脚本插件出现类似于堆栈溢出的问题而崩溃。
64.PE文件脱壳运行如果出错按照顺序排错,导入表 资源表 TLS查看是否正确 清除重定位表-》查看PE头中数据是否正确-》OD跟踪PE文件找出原因。
65.对壳中的地址定位最好不要使用硬编码,因为硬件软件的不同会造成地址改变,地址定位用特征码比较好。脚本中定位DLL硬编码代码的方法:
gpi CURRENTDIR //得到目录66.在壳中对验证代码的修改,找到一处以后可以通过此处特征码搜索,有可能有多个地方都用了这个验证,这样到达一劳永逸,不漏掉的效果。
67.SMC的patched法主要是说:在不脱壳的情况下进行破解,加密的程序代码是被加密了的,等待它解密以后才能进行修改,解码后地址就是一个问题,我们的破解补丁是肯定基于地址的,所以要修改我们自己的破解代码,如果解码函数是多重解码,比如A地址解码到B地址,B解码到C。。。等等,这样我们追踪地址也需要一重一重跟踪,每次都需要修改我们的代码,SMC由此而得,虽然写的是补丁代码,但是由于地址不确定还需要写段代码来修改补丁代码,所以叫做SMC法。
68.OD脚本的find命令和findmem命令的区别在于 前者只能查找一个内存段内的数据,后者查找所有内存段,前者查找对于变量的解析成字符串,后者对变量解析成十六进制。
69.善用栈信息窗口,OD栈窗口可以看出执行过的系统API,虽然不像WinDbg这样直接,在栈窗口中不断往对起始地址查看就能看到从启动EXE到现在执行的API了,当然前提是这个线程,不同线程栈也不一样的。除了系统API可以看到执行的函数及其返回点,一般的壳变形花指令 流程跳转等等的确在反汇编窗口跟踪容易混乱,但是这些招数对于栈窗口是无效的,栈窗口中的返回点 和系统API点都是标红了的很容易区分,监控这些返回点也可以掌握整个程序的流程了,至少ZProtect1.49壳是这样的.
70.查看/修改 Winlicense/Themida 保护过文件的水印,可以用“Winlicense/Themida Watermark Manager [1.1]” 这个软件。
更新中。。。