V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hxndg
V2EX  ›  信息安全

小游戏: crack licensechecker0x03

  •  
  •   hxndg · 2022-09-03 20:42:56 +08:00 · 1000 次点击
    这是一个创建于 797 天前的主题,其中的信息可能已经有所发展或是发生改变。

    每天有时候日常工作做的很烦,疲乏之余做个小 crackme 玩下,这个的难度比较简单,进入 main ,跟着流程走一遍基本就明白了.crackme 的下载路径在这里: https://crackmes.one/crackme/62072dd633c5d46c8bcbfd9b

    可以自己看下面的代码和注释来理解,不清楚的话看最底下的流程讲解

            Dump of assembler code for function main:
               0x0000555555555179 <+0>:       push   %rbp             #标准开局,保存堆栈环境
               0x000055555555517a <+1>:       mov    %rsp,%rbp
               0x000055555555517d <+4>:       sub    $0x30,%rsp
               #非常标准的对应 main 函数的两个参数 int main(int argc, char** argv),这个是 argc
               0x0000555555555181 <+8>:     mov    %edi,-0x24(%rbp)
               0x0000555555555184 <+11>:    mov    %rsi,-0x30(%rbp)  #对应 argv
               0x0000555555555188 <+15>:    mov    %fs:0x28,%rax
               0x0000555555555191 <+24>:    mov    %rax,-0x8(%rbp)
               0x0000555555555195 <+28>:    xor    %eax,%eax
               # #比较有没有参数,换言之有没有输入参数,如果有输入参数跳转到下面箭头指的地方
               0x0000555555555197 <+30>:    cmpl   $0x2,-0x24(%rbp)
    -------    0x000055555555519b <+34>:    je     0x5555555551c5 <main+76>
    |          # 没输入参数的话直接开始调用 printf 函数打印下面的格式
    |          0x000055555555519d <+36>:    mov    -0x30(%rbp),%rax
    |          0x00005555555551a1 <+40>:    mov    (%rax),%rax
    |          0x00005555555551a4 <+43>:    mov    %rax,%rsi
    |          # 格式的字符对应"Usage : %s <license pass code here [numbers only]>\n"
    |          0x00005555555551a7 <+46>:    lea    0xe5a(%rip),%rax        # 0x555555556008
    |          0x00005555555551ae <+53>:    mov    %rax,%rdi
    |          0x00005555555551b1 <+56>:    mov    $0x0,%eax
    |          0x00005555555551b6 <+61>:    callq  0x555555555050 <printf@plt>
    |          0x00005555555551bb <+66>:    mov    $0x0,%edi
    |          0x00005555555551c0 <+71>:    callq  0x555555555070 <exit@plt>
    |          #下面的两个地址存储着两个参数
    |          # 清空两个数值,这里存储着一个计算出来的和
    ------>    0x00005555555551c5 <+76>:    movl   $0x0,-0x10(%rbp)
               #这个地址存储的是处理过的字符串的字符的个数
               0x00005555555551cc <+83>:    movl   $0x0,-0xc(%rbp)
            -- 0x00005555555551d3 <+90>:    jmp    0x555555555201 <main+136>
    -------->  0x00005555555551d5 <+92>:    mov    -0x30(%rbp),%rax #还是拿到输入的数字的位置
    |       |  0x00005555555551d9 <+96>:    add    $0x8,%rax
    |       |  0x00005555555551dd <+100>:   mov    (%rax),%rdx
    |       |  0x00005555555551e0 <+103>:   mov    -0xc(%rbp),%eax     # 这个存储着处理过的字符串字符的个数,第一次是 0
    |       |  0x00005555555551e3 <+106>:   cltq
    |       |  0x00005555555551e5 <+108>:   add    %rdx,%rax           #找到当前处理的字符
    |       |  #取 rax ,实际上就是输入的数字所在的字符串的 1byte ,拓展到 eax 里
    |       |  0x00005555555551e8 <+111>:   movzbl (%rax),%eax
    |       |  0x00005555555551eb <+114>:   mov    %al,-0x11(%rbp)  #丢到栈里面,可以看到是刚才-0x10(%rbp)的低一位
    |       |  0x00005555555551ee <+117>:   lea    -0x11(%rbp),%rax
    |       |  0x00005555555551f2 <+121>:   mov    %rax,%rdi
    |       |  #转换为整数,整个过程是一个循环,就是在不断地将每一位转换为数字,然后加到-0x10(%rbp)上
    |       |  0x00005555555551f5 <+124>:   callq  0x555555555060 <atoi@plt>
    |       |  #eax 存储着从字符转换为数字的结果(返回值),存储到求和到刚才舒适的存储和的位置
    |       |  0x00005555555551fa <+129>:   add    %eax,-0x10(%rbp)
    |       |  #addl 加了一个 1 ,实际上就是诸位比较,还是继续运行,
    |       |  0x00005555555551fd <+132>:   addl   $0x1,-0xc(%rbp)
    |       |  #argv 的起始地址,
    |       --->0x0000555555555201 <+136>:  mov    -0x30(%rbp),%rax
    |          # 偏移 8 字节,实际上目的是找到第二个元素,也就是我们输入参数所对应字符串的地址
    |          0x0000555555555205 <+140>:   add    $0x8,%rax
    |          # 将元素的值赋值给 rax ,就是输入的数字的所在字符串的地址,
    |          0x0000555555555209 <+144>:   mov    (%rax),%rax
    |          0x000055555555520c <+147>:   mov    %rax,%rdi
    |          # 对字符串调用 strlen 判断长度
    |          0x000055555555520f <+150>:   callq  0x555555555040 <strlen@plt>
    |          # 返回的字符串长度放在了 eax 里面,和已经操作的字符串的字符个数比较一下,看看是不是处理完了
    |          0x0000555555555214 <+155>:   cmp    %eax,-0xc(%rbp)
    ---        0x0000555555555217 <+158>:   jl     0x5555555551d5 <main+92>
               #比较输入的参数字符串每一个转换为数字后加起来以后是不是 0x32 ,所以构造一个字符串各位求和是 0x32 的即可
               0x0000555555555219 <+160>:   cmpl   $0x32,-0x10(%rbp)
               0x000055555555521d <+164>:   jne    0x555555555238 <main+191>
               0x000055555555521f <+166>:   lea    0xe1a(%rip),%rax        # 0x555555556040
               0x0000555555555226 <+173>:   mov    %rax,%rdi
               0x0000555555555229 <+176>:   callq  0x555555555030 <puts@plt>
               0x000055555555522e <+181>:   mov    $0x0,%edi
               0x0000555555555233 <+186>:   callq  0x555555555070 <exit@plt>
               0x0000555555555238 <+191>:   lea    0xe25(%rip),%rax        # 0x555555556064
               0x000055555555523f <+198>:   mov    %rax,%rdi
               0x0000555555555242 <+201>:   callq  0x555555555030 <puts@plt>
               0x0000555555555247 <+206>:   mov    $0x0,%edi
               0x000055555555524c <+211>:   callq  0x555555555070 <exit@plt>
    
    

















































































































    • 首先检查有没有参数,argc 是不是等于 2 ,不等于 2 报错退出
    • 初始化两个变量,一个存储处理过的位数,一个存储求和的结果
    • 判断当前 处理过的字符串的字符个数和整个字符串的长度,如果没处理完开始循环
    • 找到参数对应字符串的一个 char ,然后转换为整数加到求和的结果里,循环上一步直到处理完成
    • 比较求和的结果和 0x32 是不是相等,相等即成功

    所以构造一个求和是 0x32 的数字字符串即可,999995 ,通过

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1203 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:15 · PVG 02:15 · LAX 10:15 · JFK 13:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.