分享

自写脚本脱Themida

 时来运转小概率 2016-02-13
大家好!我是风动鸣教程分析原理 难免会有纰漏 请大家多多指教 多多包涵

今天给大家带来的教程是 自写脚本脱Themida_v2.3.5.10

脱壳环境是:破解论坛VM XP虚拟机
http://www./thread-9253-1-1.html


做教程之前学习了sure 以下这篇教程 非常感谢sure分享
http://www./thread-13373-1-1.html
本教程的课件跟他的一致

脚本是代替人工操作,节省时间,提高效率。
我们是怎么操作的,脚本就怎么操作。
代码逻辑加入了各种判断,以限制脚本按照我们的操作流程走,解放我们的双手。

脚本展示:






每个脚本写了实现原理,和适当的代码注释。
只要你懂原理,知道操作流程,你也一样能写出自己的脚本!

详细的代码赏析 回复可见

本帖隐藏的内容

  1. //              OEP找法                  //
  2. // 下断点bp ZwFreeVirtualMemory          //
  3. // F9 N次 直到edi反复的出现一个值。      //
  4. // 断在ZwFreeVirtualMemory,删除断点。   //
  5. // 在代码段(.code)下内存访问断点       //
  6. // F9运行-到达OEP 记录下eip              //
  7. ///////////////////////////////////////////
  8. //          www.             //
  9. //                                       //
  10. //             by 风动鸣                 //
  11. //                                       //
  12. //          2015年11月17日               //
  13. //                                       //
  14. //---------------定义变量----------------//
  15. var temp
  16. //用来保存edi的值
  17. var CODE
  18. //代码段首地址
  19. var SIZE
  20. //代码段大小
  21. var OEP
  22. //OEP地址

  23. //-----------清除所有断点--------------- //
  24. bc
  25. //清除所有断点
  26. bpmc
  27. //清除内存断点
  28. bphwcall
  29. //清除硬断点

  30. //-------------初始化断点-------------//
  31. bp 7C92D38E
  32. // xp下  bp ZwFreeVirtualMemory     

  33. jmp going
  34. // 跳到going 执行
  35. going:
  36. //初始化次数
  37. esto                     
  38. //Shift+F9 忽略所有异常运行 代替F9
  39. cmp edi,0
  40. //相等
  41. je going
  42. //否则
  43. mov temp,edi
  44. //保存edi的值
  45. esto
  46. //再运一次
  47. cmp temp,edi
  48. //如果变化了 就跳
  49. jnz  going
  50. //否则  edi到了关键地址
  51. msg "edi反复不变 到了关键地址了"
  52. bc
  53. //清除所有断点

  54. //---------根据实际情况 替换 代码段首地址和大小-------------//
  55. mov CODE,00401000
  56. //代码段首地址
  57. mov SIZE,F7000   
  58. //代码段大小
  59. bprm CODE,SIZE         
  60. //代码段下内存写入断点
  61. esto
  62. mov OEP,eip
  63. bpmc
  64. //清除内存断点
  65. msg OEP
  66. ret
复制代码
  1. //          AB特征找法                   //
  2. //    重载 代码段下内存写入断点          //
  3. //    F9 F7 F8                           //
  4. //    F9 直到AB出现 记录下EIP地址        //
  5. //                                       //
  6. //        API赋值代码地址找法            //
  7. //        我已经定位好特特征码了         //
  8. //         12D200FB4140FF31              //
  9. ///////////////////////////////////////////
  10. //          www.             //
  11. //                                       //
  12. //             by 风动鸣                 //
  13. //                                       //
  14. //          2015年11月17日               //
  15. //                                       //
  16. ///////////////////////////////////////////

  17. //---------------定义变量----------------//
  18. var CODE
  19. //代码段首地址
  20. var SIZE
  21. //代码段大小
  22. var ONLYONEAB
  23. //AB特征地址
  24. VAR API
  25. //赋值真实API的代码地址

  26. //-----------清除所有断点-------------//
  27. bc
  28. //清除所有断点
  29. bpmc
  30. //清除内存断点
  31. bphwcall
  32. //清除硬断点

  33. //---------根据实际情况 替换 代码段首地址和大小-------------//
  34. mov CODE,00401000
  35. //代码段首地址
  36. mov SIZE,F7000   
  37. //代码段大小

  38. //-------------初始化断点-------------//
  39. bpwm CODE,SIZE         
  40. //代码段下内存写入断点

  41. esto                     
  42. //Shift+F9 忽略所有异常运行 代替F9
  43. sti                       
  44. //F7 单步步入
  45. sto                       
  46. //F8 单步步过

  47. findAB:
  48. cmp [eip],#AB#,1
  49. //当前将要执行的代码地址 的开头一个字节 是否为 AB
  50. je goOk
  51. esto  
  52. jmp findAB
  53. //跳到findAB开头继续向入执行

  54. goOk:
  55. mov ONLYONEAB,eip
  56. bpmc
  57. //清除内存断点
  58. msg ONLYONEAB

  59. find eip,#12D200FB4140FF31#  //搜索上面那段代码
  60. mov  API,$RESULT //将搜索的eip地址给aa,也就是图上的771f9处
  61. sub API,12
  62. bp API
  63. //赋值的代码地址 处 下断
  64. esto
  65. bc
  66. //清除所有断点
  67. msg API
  68. ret
复制代码
  1. // 原理:                                //
  2. // 壳把真实的API函数代码写入到自己申请的 //
  3. // 地址 再在代码段里自己来调用           //
  4. // 所以我们要做的就是:                  //
  5. // 在壳在代码段里写入调用自己函数调用后  //
  6. // 替换回真实的调用地址                  //
  7. // 替换后的两种情况:                    //
  8. // call dword ptr ds:[IAT表函数地址]     //
  9. // jmp dword ptr ds:[IAT表函数地址]      //
  10. //                                       //
  11. //          www.             //
  12. //                                       //
  13. //             by 风动鸣                 //
  14. //                                       //
  15. //          2015年11月17日               //
  16. //                                       //
  17. //---------------定义变量----------------//
  18. var REALAPI
  19. //真实的API函数地址
  20. var IATAPI
  21. //IAT表函数地址
  22. var REPLACE
  23. //替换代码的地址
  24. var RECALL
  25. //替换成 call dword ptr ds:[地址] 的特征码
  26. var REJMP
  27. //修改成 jmp dword ptr ds:[地址] 的特征码
  28. var API
  29. //赋值API的代码地址
  30. var CODE
  31. //代码段首地址
  32. var SIZE
  33. //代码段大小
  34. var ONLYONEAB
  35. //AB特征地址
  36. var OEP
  37. //OEP地址

  38. //-----------清除所有断点-------------//
  39. bc
  40. //清除所有断点
  41. bpmc
  42. //清除内存断点
  43. bphwcall
  44. //清除硬断点

  45. //------------替换实际的地址-------------//
  46. mov API,00709E7C
  47. //赋值API的代码地址
  48. mov CODE,00401000
  49. //代码段首地址
  50. mov SIZE,F7000   
  51. //代码段大小
  52. mov ONLYONEAB,00709C55
  53. //独一无二AB特征地址
  54. mov OEP,00466C98
  55. //OEP地址

  56. //-------替换的特征码-------------//
  57. mov RECALL,15FF
  58. mov REJMP,25FF

  59. //-------------初始化断点-------------//
  60. bphws API,"x"        
  61. //赋值api真实地址下硬件断点
  62. bphws OEP,"x"        
  63. //程序入口OEP下硬件断点
  64. bpwm CODE,SIZE         
  65. //代码段下内存写入断点

  66. //-------------开始修复----------------//
  67. esto                     
  68. //Shift+F9 忽略所有异常运行
  69. //异常界面设置好  可以用 run F9 运行 代替】
  70. sti                       
  71. //F7 单步步入
  72. sto                       
  73. //F8 单步步过
  74. esto                  

  75. strat:
  76. mov [IATAPI],REALAPI
  77. //把 真实的API地址 写入 IAT表函数地址
  78. jmp strat2

  79. strat2:
  80. mov REALAPI,eax
  81. //记录下一个 真实的API地址
  82. esto
  83. cmp eip,API
  84. //当前要执行的代码地址 与 将要赋值API的代码地址 做比较
  85. je strat2
  86. //相等就跳
  87. mov IATAPI,edx
  88. //IAT表函数地址
  89. esto
  90. mov [IATAPI],REALAPI
  91. //在 IAT表函数地址 里 填充 真实的API地址
  92. cmp eip,API
  93. je strat
  94. cmp [eip],AA,1
  95. je foriat
  96. cmp eip,OEP
  97. je end
  98. jmp foriat

  99. //循环修复IAT
  100. foriat:
  101. cmp [eip],#880B#,2
  102. je foriat2
  103. cmp eip,OEP
  104. je end
  105. cmp al,e9
  106. je foriate9
  107. cmp al,e8
  108. je foriate8
  109. mov REPLACE,edi
  110. //下一个 替换代码的地址 = edi
  111. esto
  112. cmp al,e8
  113. //修复FF15标签
  114. je foriate8x
  115. //修复FF25标签
  116. jmp foriate9x

  117. foriat2:
  118. mov REPLACE,ebx
  119. cmp al,e8
  120. je iat1
  121. cmp al,e9
  122. je iat2
  123. cmp cl,e8
  124. je iat1
  125. jmp iat2

  126. //修复FF15
  127. iat1:
  128. esto
  129. //运行之后 填充了 E8
  130. esto
  131. //运行之后  填充了 call的地址
  132. //综合效果是 壳生成了自己的函数代码后 在代码段来调用

  133. //下面就到我们来修复了
  134. mov [REPLACE],RECALL
  135. //往 替换代码的地址(目标地址) 替换两字节 为 FF15
  136. add REPLACE,2
  137. //向后移两位
  138. mov [REPLACE],IATAPI
  139. //替换为 IAT函数表的地址
  140. //修改完后的效果为:call dword ptr ds:[0x487600]
  141. cmp eip,API
  142. je strat
  143. cmp eip,OEP
  144. je end
  145. jmp foriat

  146. //同修复FF25
  147. iat2:
  148. esto
  149. esto
  150. mov [REPLACE],REJMP
  151. add REPLACE,2
  152. mov [REPLACE],IATAPI
  153. cmp eip,API
  154. je strat
  155. cmp eip,OEP
  156. je end
  157. jmp foriat

  158. foriate8:
  159. mov REPLACE,edi
  160. esto
  161. esto
  162. mov [REPLACE],RECALL
  163. //替换成 FF 15
  164. //等价于call dword ptr ds:[IAT表函数地址]
  165. add REPLACE,2
  166. //替换代码的地址加2(就是向后移两位)
  167. mov [REPLACE],IATAPI
  168. //替换为IAT表函数的地址
  169. cmp eip,API
  170. je strat
  171. jmp foriat

  172. //循环修复FF15标签 修改完后的效果为:call dword ptr ds:[0x487600]
  173. foriate8x:
  174. esto
  175. //运行之后 壳已经把 E8 写入代码段指定地址 如:【E8 90909090】
  176. esto
  177. //运行之后 壳已经把 真实的API地址 填充到代码段指定地址
  178. //如:【E8 BB087076】 就是 call 76B2A4EE = call winmm.midiStreamOut

  179. //下面就到我们来修复了
  180. mov [REPLACE],RECALL
  181. //往 替换代码的地址(目标地址) 替换两字节 为 FF15
  182. add REPLACE,2
  183. //向后移两位
  184. mov [REPLACE],IATAPI
  185. //替换为 IAT函数表的地址
  186. //修改完后的效果为:call dword ptr ds:[0x487600]
  187. cmp eip,API
  188. je strat
  189. jmp foriat

  190. foriate9:
  191. mov REPLACE,edi
  192. esto
  193. jmp doiate9

  194. doiate9:
  195. esto
  196. cmp eip,ONLYONEAB
  197. jnz doiate9
  198. esto
  199. mov [REPLACE],REJMP
  200. add REPLACE,2
  201. mov [REPLACE],IATAPI
  202. jmp strat

  203. //循环修复FF25标签
  204. foriate9x:
  205. esto
  206. //运行之后 壳已经把 E9 写入代码段指定地址 如:【E9 90909090】
  207. esto
  208. //运行之后 壳已经把 真实的API地址 填充到代码段指定地址
  209. //如:【E9 A7915F71】 就是 jmp 71A23FED

  210. //下面就到我们来修复了
  211. mov [REPLACE],REJMP
  212. //往 替换代码的地址(目标地址) 替换两字节 为 FF25
  213. add REPLACE,2
  214. //向后移两位
  215. mov [REPLACE],IATAPI
  216. //替换为 IAT函数表的地址
  217. //修改完后的效果为:jmp dword ptr ds:[0x487660]
  218. cmp eip,API
  219. je strat
  220. cmp [eip],AA,1
  221. je foriat
  222. cmp eip,OEP
  223. je end
  224. jmp strat

  225. end:
  226. bc
  227. bpmc
  228. bphwcall
  229. MSG "到达OEP IAT修复完毕"
  230. ret
复制代码


具体脱壳流程:









































总结:学脱壳,先学写脚本——这是我的见解
许多大牛都分享了各种脱壳脚本,脚本是脱壳全过程的体现,浓缩了作者的脱壳思路,对壳的实现原理的理解。
所以要重视脚本,别把大牛分享的脚本只当成脱壳工具。
脚本适用范围小,而读懂脚本原理 你就能脱它不能脱的壳,你才是脚本的创作者!

脚本代码我是一步一步跟的,通过耐心跟踪 观察各种数据,总结经验。

希望对大家有所启发。

不怎么会表达 请大家见谅。

课件工具和脚本分享:

本帖隐藏的内容

链接:http://pan.baidu.com/s/1hqlTiAC 密码:tm9j
自写脚本脱Themida_v2.3.5.10.rar (7.93 MB, 下载次数: 53)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多