0day安全-part1-chapt1-crack_me

一、实验目标

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

二、实验计划步骤

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

三、实验记录

3.1 IDA分析

  • 定位条件判断跳转语句
    • 定位条件判断跳转语句1
    • 定位条件判断跳转语句2
  • 获取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指令
    • 定位jz判断跳转语句
  • 将je指令修改为jne
    • 原代码
      • 原代码
    • 修改后代码(调试工具自动反汇编,显示jne指令)
      • 修改后代码
    • 通过命令行终端完成修改后的动态测试

3.3 LordPE查看PE文件segment信息

  • jz判断跳转语句的虚拟地址:.text:00000001400014E8
  • 区段表
    • 区段表信息
  • 装载基址:0x0000000140000000
    • 装载基址
  • 计算指令在文件中的偏移地址【重点
    • 确定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
  • 定位待修改字节
    • 定位待修改字节
  • 将jz指令码74修改为jnz指令码75,保存文件,完成软件爆破

四、实验成果

  • 验证程序
    • 理论正确密码
      • 正确密码
    • 输入正确密码后的运行结果
      • 输入正确密码后的运行结果
    • 输入错误密码后的运行结果
      • 输入错误密码后的运行结果

五、实验总结

5.1 PE文件格式

  • 正确清晰地掌握PE文件格式,对Windows下的逆向工程至关重要
    • 拓展:Linux下的ELF文件也需重点掌握,两者同宗同源

5.2 使用工具

  • IDA、x64dbg、UltraEdit、010 Editor

六、知识拓展

6.1 汇编语法

6.1.1 关键字

  • ptr关键字的作用
    • 作用
      • 明确操作的数据长度​
    • 示例
      • ptr关键字使用示例

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

七、源代码

/*****************************************************************************
      To be the apostrophe which changed "Impossible" into "I'm possible"!
		
POC code of chapter 3.7 in book "Vulnerability Exploit and Analysis Technique"
 
file name	: crack_me.c
author		: failwest  
date		: 2006.9.20
description	: used as a simple demo to show how to crack a PE file   
Noticed		: should be complied with VC6.0 and build into release version  
version		: 1.0
E-mail		: failwest@gmail.com
		
	Only for educational purposes    enjoy the fun from exploiting :)
******************************************************************************/

#include <stdio.h>
#include <string.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
	int authenticated;
	authenticated=strcmp(password,PASSWORD);
	return authenticated;
}

void main()
{
	int valid_flag=0;
	char password[1024];
	while(1)
	{
		printf("please input password: ");
		scanf("%s",password);
		valid_flag = verify_password(password);
		if(valid_flag)
		{
			printf("incorrect password!\n\n");
		}
		else
		{
			printf("Congratulation! You have passed the verification!\n");
			break;
		}
	}
}
posted @ 2025-06-05 20:12  宇星海  阅读(63)  评论(0)    收藏  举报