安全矩阵

 找回密码
 立即注册
搜索
查看: 6711|回复: 0

反调试入门篇(1)——花指令

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-12-7 17:08:37 | 显示全部楼层 |阅读模式
本帖最后由 gclome 于 2020-12-7 17:09 编辑

原文链接:反调试入门篇(1)——花指令

0x01 花指令

花指令是一种反静态调试的最基础手段(对于动态调试来说就没有用处),我们可以通过在程序的代码中添加一些不影响程序运行的垃圾机器码,进而影响反汇编结果的准确性,达到程序保护的目的

0x02 花指令分类

1、可执行花指令
见字知其意,即花指令在程序正常运行的时候被执行,通用寄存器的值不发生改变,但不影响程序原有的功能执行


2、不可执行花指令
见字知其意,即花指令在程序正常运行的时候不会被执行,不影响程序原有的功能

0x03 编写花指令

原则:保持堆栈的平衡


0x04 常用花指令

汇编小知识:
  1. mov eax, 1      eax赋值为1
  2. pop 1                 将1从栈顶弹出
  3. pop ebp             将栈顶的值弹出赋给寄存器ebp
  4. push 1              将1压入栈中
  5. push ebp            将ebp的值压入栈中
  6. sub eax, 1      eax的值减1
  7. add eax, 1      eax的值加1
  8. inc eax             eax的值加1
  9. dec eax             eax的值减1
  10. call [x]            调用地址为x的函数,call对应的硬编码为0xE8
  11. jmp x                   跳转到x地址处,jmp对应的硬编码为0xE9
  12. nop                     不做任何事情,相当于python中的pass,对应的硬编码为0x90
  13. _emit                   相当于db,byte类型,1字节
复制代码

以下方式均通过内联汇编实现


0x05 标签方式的花指令


1、单节方式
  1. #include "stdafx.h"


  2. void Test(){
  3. int a[3] = {1, 2, 3};
  4. _asm{
  5. jz Label;
  6. jnz Label;
  7. _emit 0xE8;
  8. }
  9. Label:
  10. a[0] = 2;
  11. a[1] = 5;
  12. a[2] = 6;
  13. printf("%d\n", a[2]);
  14. }


  15. int main(int argc, char* argv[]){
  16. Test();
  17. return 0;
  18. }
复制代码

使用IDA打开,可以看到标红的地方就是花指令,因为call指令的存在,使得后面的4字节数据被错误识别成函数地址,进而导致接下来的分析出错




人工Patch花指令的方式很简单:
选中call指令所在行,点击Edit选项>Patch program>Change byte



将call的硬编码E8改为0x90(nop指令)





2、多节方式

  1. #include "stdafx.h"


  2. void Test(){
  3. int a[3] = {1, 2, 3};
  4. _asm{
  5. jz Label1;
  6. jnz Label1;
  7. _emit 0xE9;
  8. }
  9. Label1:
  10. a[0] = 5;
  11. a[1] = 6;
  12. a[2] = 7;
  13. _asm{
  14. jz Label2;
  15. jnz Label2;
  16. _emit 0xE8;
  17. }
  18. Label2:
  19. a[1] = a[0] + a[2];
  20. a[2] = a[1] + a[0];
  21. printf("%d\n", a[2]);
  22. }


  23. int main(int argc, char* argv[])
  24. {
  25. Test();
  26. return 0;
  27. }
复制代码

3、多层乱序(疯狂套娃)
  1. #include "stdafx.h"


  2. void Test(){
  3. int arr[3] = {1, 2, 3};
  4. _asm{
  5. jz Label3;
  6. jnz Label3;
  7. _emit 0xE8;
  8. }
  9. Label2:
  10. _asm{
  11. jz Label4;
  12. jnz Label4;
  13. _emit 0xE8;
  14. }


  15. Label3:
  16. _asm{
  17. jz Label1;
  18. jnz Label1;
  19. _emit 0xE9;
  20. }
  21. Label1:
  22. _asm{
  23. jz Label2;
  24. jnz Label2;
  25. _emit 0xE9;
  26. }
  27. Label4:
  28. int a = 10;
  29. printf("%d\n",a);


  30. }
  31. int main(int argc, char* argv[])
  32. {
  33. Test();
  34. return 0;
  35. }
复制代码

4.开辟堆栈的花指令
  1. push 1
  2. push ebp
  3. mov ebp, esp
  4. sub esp, 0x8
  5. push eax
  6. push ecx
  7. pop ecx
  8. pop eax
  9. add esp, 0x8
  10. pop ebp
  11. je xxx
  12. jne xxx
复制代码

花指令多的情况就需要自己写个IDA python脚本进行去除

5.花指令免杀

一些反病毒软件依靠特征码来判断文件是否有毒,其识别引擎在文件镜像(filebuffer)一定的偏移范围内进行扫描,比如在0x00001000~0x00006000之间,我们在其中加入一些花指令,使恶意代码偏离引擎识别的偏移范围,再使用工具修改程序入口(OEP),就可以逃避这种方式的特征码识别







回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-9-20 18:53 , Processed in 0.017152 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表