找回密码
 立即注册
首页 业界区 业界 0day安全-chapt1-crack_me

0day安全-chapt1-crack_me

吕梓美 3 天前
一、实验目标


  • 修改crack_me.exe文件源代码,实现“即使输入错误密码,也将通过验证”目标【软件爆破】
二、实验计划步骤


  • 使用IDA工具完成如下任务

    • 利用IDA打开crack_me.exe文件
    • 定位main函数中条件判断并跳转指令

  • 依据指令虚拟地址及文件加载地址计算指令在文件中的偏移地址
  • 使用动态调试软件动态观察跳转分支逻辑并进行动态修改测试
  • 利用二进制相关软件修改判断条件的指令码,使其完成“密码不相等时判定正确”任务,达到输入错误密码反而成功验证的目的
三、实验记录

3.1  IDA分析


  • 定位条件判断跳转语句

    • 1.png

    • 2.png


  • 获取jz指令虚拟地址:.text:00000001400014E8

    • 注意:jz(Jump if Zero)和 je(Jump if Equal)​​本质上是同一条指令的两种不同写法​​,功能完全相同

3.2  x64dbg动态调试


  • 使用x64dbg打开crack_me.exe文件
  • 定位je判断跳转语句

    • 注意:由于EXE文件加载时采用了ASLR(Address Space Layout Randomization地址空间布局随机化)技术,因此无法通过直接搜索程序地址定位目标je指令
    • 3.png


  • 将je指令修改为jne

    • 原代码

      • 4.png


    • 修改后代码(调试工具自动反汇编,显示jne指令)

      • 5.png


    • 通过命令行终端完成修改后的动态测试

3.3  LordPE查看PE文件segement信息


  • jz判断跳转语句的虚拟地址:.text:00000001400014E8
  • 区段表

    • 6.png


  • 装载基址:0x0000000140000000

    • 7.png


  • 计算指令在文件中的偏移地址【重点

    • 确定RVA(Relative Virtual Address相对虚拟地址)

      • RVA = VA(指令虚拟地址) - ImageBase(可执行映像文件的加载基址) = 0x00000001400014E8 - 0000000140000000 = 0x14E8

    • 确定数据所属段(Section)

      • .text

    • 计算指令的文件偏移FOA(File Offset Address文件偏移地址)

      • FOA = .text.PointerToRawData(段在文件中的起始地址) + (RVA - .text.VirtualOffset) = .text.Roffset(LordPE查看) + (RVA - .text.VirtualOffset) = 0x600 + 0x14E8 - 0x1000 = 0xAE8


3.4  UltraEdit修改EXE二进制文件,完成文件判断逻辑修改


  • 使用CTRL + G,输入待查找文件偏移0xAE8
  • 定位待修改字节

    • 8.png


  • 将jz指令码74修改为jnz指令码75,保存文件,完成软件爆破
四、实验成果


  • 验证程序

    • 理论正确密码

      • 9.png


    • 输入正确密码后的运行结果

      • 10.png


    • 输入错误密码后的运行结果

      • 11.png



五、实验总结

5.1  PE文件格式


  • 正确清晰地掌握PE文件格式,对Windows下的逆向工程至关重要

    • 拓展:Linux下的ELF文件也需重点掌握,两者同宗同源

5.2  使用工具


  • IDA、x64dbg、UltraEdit、010 Editor
六、知识拓展

6.1  汇编语法

6.1.1  关键字


  • ptr关键字的作用

    • 作用

      • 明确操作的数据长度​

    • 示例

      • 12.png



6.1.2  普通指令


  • lea

    • 结构:LEA 寄存器, 内存操作数
    • 功能:计算一个内存地址,并将该地址存储到指定的寄存器中

6.1.3  跳转相关指令


  • test

    • 结构:test eax, eax
    • 功能:对两个操作数进行按位逻辑与操作,操作结果影响标志位,不影响寄存器中存储值

      • 影响ZF

        • 如果操作结果为0:ZF=1
        • 如果操作结果为1:ZF=0

      • 影响SF

        • 如果操作结果符号位为1:SF=1
        • 反之:SF=0

      • 影响PF

        • PF位用于指示结果中1的个数的奇偶性



  • cmp

    • 结构:cmp [rbp+3B0h+var_4], 0
    • 功能:比较两值,结果影响标志位,包括溢出标志(OF)、符号标志(SF)、零标志(ZF)、进位标志(CF)、辅助进位标志(AF)和奇偶标志(PF)

      • 影响ZF

        • 相等:ZF为1
        • 不等:ZF为0



  • jmp

    • 结构:jmp [目标地址]
    • 功能:无条件跳转指令

  • jz

    • 结构:jz [目标地址]
    • 功能:

      • ZF=1:跳转到目标地址
      • ZF=0:不跳转

    • 类似

      • jnz:当ZF为0时跳转
      • je:jz(Jump if Zero)和 je(Jump if Equal)​​本质上是同一条指令的两种不同写法​​,功能完全相同,均根据零标志位(ZF)决定是否跳转


6.2  C语言语法

6.2.1  函数语法


  • strcmp()

    • 语法:int strcmp(const char *str1, const char *str2)
    • 功能:比较 str1 所指向的字符串和 str2 所指向的字符串
    • 返回值:

      • 如果返回值小于 0,则表示 str1 小于 str2
      • 如果返回值大于 0,则表示 str1 大于 str2
      • 如果返回值等于 0,则表示 str1 等于 str2


七、源代码
  1. /*****************************************************************************
  2.       To be the apostrophe which changed "Impossible" into "I'm possible"!
  3.                
  4. POC code of chapter 3.7 in book "Vulnerability Exploit and Analysis Technique"
  5. file name        : crack_me.c
  6. author                : failwest  
  7. date                : 2006.9.20
  8. description        : used as a simple demo to show how to crack a PE file   
  9. Noticed                : should be complied with VC6.0 and build into release version  
  10. version                : 1.0
  11. E-mail                : failwest@gmail.com
  12.                
  13.         Only for educational purposes    enjoy the fun from exploiting :)
  14. ******************************************************************************/
  15. #include <stdio.h>
  16. #include <string.h>
  17. #define PASSWORD "1234567"
  18. int verify_password (char *password)
  19. {
  20.         int authenticated;
  21.         authenticated=strcmp(password,PASSWORD);
  22.         return authenticated;
  23. }
  24. void main()
  25. {
  26.         int valid_flag=0;
  27.         char password[1024];
  28.         while(1)
  29.         {
  30.                 printf("please input password: ");
  31.                 scanf("%s",password);
  32.                 valid_flag = verify_password(password);
  33.                 if(valid_flag)
  34.                 {
  35.                         printf("incorrect password!\n\n");
  36.                 }
  37.                 else
  38.                 {
  39.                         printf("Congratulation! You have passed the verification!\n");
  40.                         break;
  41.                 }
  42.         }
  43. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册