CrackMe001汇编基础练习

CrackMe 001

一直在搞开发,许久没有碰二进制逆向了,今日突然来了兴致,就做了一个入门级的crackme。做题是假

,温习是真。主要借着题目复习一些汇编相关知识点。

首先,打开图片

{96BADB16-3B54-44a0-B46F-24BD23E89E4B}

看到出现错误提示--------->查找所有参考字符串----------->跟踪定位到错误字符串提示处

{3E8D3218-7120-45dd-A610-0D5DF2F50B4D}

计算机储存信息基本单元

计算机存储信息的基本单元是位(bit)和字节(byte)。下面是它们及其单位的转换关系:

  1. 位(bit):计算机中最小的存储单元,只能存储0或1。8个位构成一个字节。
  2. 字节(byte):通常用于表示存储容量,是计算机中常见的基本存储单位。1字节等于8位。
  3. 1 字(word)= 2 字节
  4. 1 双字(dword)= 4 字节
  5. 1 四字(qword)= 8 字节

常见的存储单位及其转换关系如下:

  • 1 字节(byte) = 8 位(bit)
  • 1 千字节(KB) = 1024 字节
  • 1 兆字节(MB) = 1024 KB
  • 1 千兆字节(GB) = 1024 MB
  • 1 太字节(TB) = 1024 GB
  • 1 拍字节(PB) = 1024 TB

需要注意的是,存储容量的单位通常采用二进制计量单位,即以2的幂为基准进行换算。例如,1 KB = 1024 字节,而不是1000字节。

寄存器

00401E82   .  8D4D C4       lea ecx,dword ptr ss:[ebp-0x3C]
00401E85   .  C745 8C E01A4>mov dword ptr ss:[ebp-0x74],Andréna.00401AE0       ;  UNICODE "Leider Falsch !  Schau noch mal genau nach ..."
00401E8C   .  895D 84       mov dword ptr ss:[ebp-0x7C],ebx

计算机的寄存器是中央处理器(CPU)内部的一种快速存储单元,用于临时存储数据和指令。在不同的CPU架构中,寄存器的类型和数量会有所不同。以下是几种主要的寄存器类型,基于常见的x86架构和一些其他架构的:

2013-06-04-1

通用寄存器

16位模式下,寄存器的大小为16位,如ax, bx, cx, dx, si, di, sp, bp

x86架构(32位)
  • EAX(累加寄存器,Accumulator):用于算术运算和I/O操作。
  • EBX(基址寄存器,Base):用于基址寻址。
  • ECX(计数寄存器,Counter):用于循环计数。
  • EDX(数据寄存器,Data):用于I/O操作和乘法/除法指令。
  • ESI(源索引寄存器,Source Index):用于字符串操作。
  • EDI(目的索引寄存器,Destination Index):用于字符串操作。
  • EBP(基址指针寄存器,Base Pointer):用于指向当前栈帧的基址。
  • ESP(栈指针寄存器,Stack Pointer):指向栈顶。
x86_64架构(64位)

在x86_64架构中,寄存器的前缀变为R,且有更多的寄存器可用:

  • RAX, RBX, RCX, RDX:与32位寄存器类似,用于通用目的。
  • RSI, RDI, RBP, RSP:与32位寄存器类似,但扩展为64位。
  • R8-R15:额外的通用寄存器。

段寄存器

  • CS(代码段寄存器,Code Segment):指向当前代码段。
  • DS(数据段寄存器,Data Segment):指向数据段。
  • SS(栈段寄存器,Stack Segment):指向栈段。
  • ES(附加段寄存器,Extra Segment):额外的数据段寄存器。
  • FS(附加段寄存器,Extra Segment):用于特殊数据。
  • GS(附加段寄存器,Extra Segment):用于特殊数据。

指令指针寄存器

  • EIP(32位)/ RIP(64位):指向将要执行的下一条指令的地址。

标志寄存器

  • EFLAGS(32位)/ RFLAGS(64位):包含状态标志、控制标志和系统标志。
    • 例如:ZF(Zero Flag),CF(Carry Flag),SF(Sign Flag),OF(Overflow Flag)。

控制寄存器

  • CR0, CR2, CR3, CR4:用于控制CPU的操作模式(例如,启用保护模式、分页等)。

调试寄存器

  • DR0-DR7:用于硬件断点调试。

浮点寄存器

  • ST0-ST7:用于浮点运算。
  • XMM0-XMM15(SSE指令集):用于SIMD运算。

特殊用途寄存器

  • IDTR(中断描述符表寄存器):指向中断描述符表的基地址和界限。
  • GDTR(全局描述符表寄存器):指向全局描述符表的基地址和界限。
  • LDTR(局部描述符表寄存器):指向局部描述符表的选择子。

ARM架构中的寄存器

ARM架构寄存器包括:

  • R0-R12:通用寄存器。
  • R13(SP):栈指针。
  • R14(LR):链接寄存器,保存子程序返回地址。
  • R15(PC):程序计数器。
  • CPSR(Current Program Status Register):当前程序状态寄存器。

不同的CPU架构有不同的寄存器集,但大致都分为通用寄存器、特殊用途寄存器和状态寄存器等。

问题

img

32位与64位机器有何本质区别?

  1. 地址空间大小

    • 32位机器的地址总线宽度为32位,因此可以寻址的最大内存空间为2^32字节,即4GB。
    • 64位机器的地址总线宽度为64位,可以寻址的最大内存空间为2^64字节,这是一个极大的数值,几乎可以覆盖所有可能的内存需求。
  2. 寄存器大小

    • 32位机器中,通用寄存器的宽度通常为32位。
    • 64位机器中,通用寄存器的宽度通常为64位,这使得64位机器能够在单个指令中处理更多的数据。
  3. 指令集

    • 64位机器通常支持更多的指令集扩展,包括更多的SIMD指令和更高级的指令集,以支持更复杂的计算和操作。
  4. 性能

    • 64位机器通常具有更高的性能,因为它们可以处理更多的数据和更大的内存空间,从而更有效地执行计算任务。
  5. 内存寻址

    • 64位机器使用更长的内存地址来访问内存,这意味着可以直接访问更大的内存空间,而无需进行分段或分页。

总的来说,64位机器相对于32位机器具有更大的地址空间、更大的寄存器、更丰富的指令集和更高的性能,这使得它们能够处理更复杂和更大规模的计算任务。

内存

/*dword ptr:表示操作数的大小和类型,这里指定了操作数是一个双字(32位)的数据。
ss:表示使用的段寄存器,这里表示堆栈段(Stack Segment),即栈空间。
[ebp-0x3C]:是一个内存地址引用,它表示相对于基址指针(ebp)的偏移量为0x3C的位置。在栈桢中,ebp 通常指向当前函数的栈底,因此 [ebp-0x3C] 实际上是指向当前函数的栈空间中的某个位置,偏移量为0x3C。
综合起来,dword ptr ss:[ebp-0x3C] 表示从当前函数的栈空间中读取一个32位的双字数据。*/
dword ptr ss:[ebp-0x3C]

介绍一下堆栈:它们是用于存储程序运行时的数据和临时变量的区域,但它们具有不同的特性和用途。

  1. 栈(Stack):栈是一种后进先出(LIFO)的数据结构,用于存储函数调用和局部变量。当一个函数被调用时,它的参数、局部变量和返回地址会被压入栈中,当函数执行完成后,这些数据会被弹出栈。栈的大小在程序启动时就确定了,它的内存空间由编译器或操作系统管理。栈上的数据通常具有较短的生命周期,函数调用结束后就会被自动释放。
  2. 堆(Heap):堆是一种动态分配的内存区域,用于存储程序运行时动态分配的内存块。堆上的内存块由程序员手动申请和释放,它的大小和生命周期由程序员控制。堆的大小通常比栈大得多,它可以存储任意大小的数据。堆上的数据通常具有较长的生命周期,直到程序显式释放这些内存块或程序结束时才会被释放。

指令

顺着跳转到错误弹窗je指令找到了核心判断逻辑{C615090C-5C01-4c3c-B7F1-79CD96B33D71}

00401D9A   .  66:3BFE       cmp di,si
00401D9D   .  0F84 A0000000 je Andréna.00401E43

cmp di,si:这条指令是比较 di 寄存器中的值和 si 寄存器中的值。具体来说,它计算 di - si 的结果,并根据结果设置相应的标志位。
如果 di 中的值等于 si 中的值,则零标志位(ZF)将被设置为1,否则被清零。
如果 di 中的值小于 si 中的值,则符号标志位(SF)将被设置为1,否则被清零。
如果 di 中的值与 si 中的值的最高位(符号位)相同,则溢出标志位(OF)将被设置为1,否则被清零。

跳转指令

je(Jump if Equal),当零标志位(ZF)为1时跳转

jne:Jump if Not Equal,如果ZF为0,则跳转。
js:Jump if Sign,如果SF为1,则跳转。
jns:Jump if Not Sign,如果SF为0,则跳转。
jo:Jump if Overflow,如果OF为1,则跳转。
jno:Jump if Not Overflow,如果OF为0,则跳转。
jc:Jump if Carry,如果CF为1,则跳转。
jnc:Jump if Not Carry,如果CF为0,则跳转。
jz:Jump if Zero,与je相同,如果ZF为1,则跳转。
jnz:Jump if Not Zero,与jne相同,如果ZF为0,则跳转。
jl:Jump if Less,如果SF和OF不同,则跳转。
jle:Jump if Less or Equal,如果ZF为1或SF和OF不同,则跳转。
jg:Jump if Greater,如果ZF为0且SF和OF相同,则跳转。
jge:Jump if Greater or Equal,如果SF和OF相同,则跳转。

其他指令

/*这条指令是加载有效地址(Load Effective Address)的指令,用于将 ebp-0x28 的内存地址计算出来并存放到 ecx 寄存器中。在这里,它的作用是将栈上偏移为 0x28 的内存地址加载到 ecx 中。*/
00401D81   .  8D4D D8       lea ecx,dword ptr ss:[ebp-0x28]

/*这条指令是将 edi 寄存器的值取反(negate)。即将 edi 中的值取负数。*/
00401D84   .  F7DF          neg edi                                            ;  Andréna.<ModuleEntryPoint>

/* 这条指令是将 edi 寄存器的值与自己进行借位减法(Subtract with Borrow),并将结果存放到 edi 中。由于 edi 与自身相减,所以实际上是将 edi 寄存器清零。*/
00401D86   .  1BFF          sbb edi,edi                                        ;  Andréna.<ModuleEntryPoint>

/*这条指令是将 edi 寄存器的值加一(Increment),即将 edi 中的值加上1。*/
00401D88   .  47            inc edi                                            ;  Andréna.<ModuleEntryPoint>

/*这条指令是再次将 edi 寄存器的值取反(negate),即将 edi 中的值取负数。*/
00401D89   .  F7DF          neg edi                                            ;  Andréna.<ModuleEntryPoint>

其中我们发现:

{A5B41F8F-8F26-4ada-ACBF-E17D45A9D0F1}

由Strcmp关键字我们可以轻松得出,用户输入的key同SynTaX 2oo1比较,后跳转相应逻辑处理,验证得:

{8EE71124-C931-41f0-9146-9F64A3F641E2}


其中我们发现:

[外链图片转存中…(img-6iBaVcyA-1716694304177)]

由Strcmp关键字我们可以轻松得出,用户输入的key同SynTaX 2oo1比较,后跳转相应逻辑处理,验证得:

[外链图片转存中…(img-PCWmNbbO-1716694304177)]

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值