小游戏: crack trycrackme

2022-09-03 21:10:24 +08:00
 hxndg

trycrackme 的下载地址为 https://crackmes.one/crackme/61c8deff33c5d413767ca0ea ,直接从汇编就能看出来到底在做什么

     Dump of assembler code for function main:
        # 标准开局,保存堆栈
        0x00005555555551af <+0>:        push   %rbp
        0x00005555555551b0 <+1>:        mov    %rsp,%rbp
        0x00005555555551b3 <+4>:        sub    $0xe0,%rsp
        #存储 argc & argv ,不过这里没用到
        0x00005555555551ba <+11>:       mov    %edi,-0xd4(%rbp)
        0x00005555555551c0 <+17>:       mov    %rsi,-0xe0(%rbp)
        0x00005555555551c7 <+24>:       mov    %fs:0x28,%rax
        0x00005555555551d0 <+33>:       mov    %rax,-0x8(%rbp)
        0x00005555555551d4 <+37>:       xor    %eax,%eax
        # 注意这个常量,是我们比较的关键
        0x00005555555551d6 <+39>:       movabs $0x3534323773734034,%rax
        # 存储到了-0xbb(%rbp)的位置
        0x00005555555551e0 <+49>:       mov    %rax,-0xbb(%rbp)
        # 给上面的常量补充了两个字节的数字,拼接到最后面,拼接完以后看一下具体的内容
        # (gdb) x/16xb 140737488347509
        # 0x7fffffffe175: 0x34    0x40    0x73    0x73    0x37    0x32    0x34    0x35
        # 0x7fffffffe17d: 0x33    0x36    0x00    0x00    0x00    0x00    0x00    0x00
        0x00005555555551e7 <+56>:       movw   $0x3633,-0xb3(%rbp)
        0x00005555555551f0 <+65>:       movb   $0x0,-0xb1(%rbp)
        0x00005555555551f7 <+72>:       lea    -0xbb(%rbp),%rax
        0x00005555555551fe <+79>:       mov    %rax,%rdi
        0x0000555555555201 <+82>:       callq  0x555555555050 <strlen@plt>
        # 存储我们刚才拼接出来的字符串长度,明确地看出来是 10
        0x0000555555555206 <+87>:       mov    %eax,-0xc0(%rbp)
        0x000055555555520c <+93>:       mov    $0x0,%eax
        # 调用 banner 打印一些 flag ,没有啥用,不用管
        0x0000555555555211 <+98>:       callq  0x555555555199 <banner>
        # 准备调用 printf 提示用户输入数据,格式化字符串为 Put the key:
        0x0000555555555216 <+103>:      lea    0xef9(%rip),%rax        # 0x555555556116
        0x000055555555521d <+110>:      mov    %rax,%rdi
        0x0000555555555220 <+113>:      mov    $0x0,%eax
        0x0000555555555225 <+118>:      callq  0x555555555070 <printf@plt>
        # 记住这个-0xb0(%rbp)的地址,这个是存储 scanf 输入进来的地址
        0x000055555555522a <+123>:      lea    -0xb0(%rbp),%rax
        0x0000555555555231 <+130>:      mov    %rax,%rsi
        0x0000555555555234 <+133>:      lea    0xee9(%rip),%rax        # 0x555555556124
        0x000055555555523b <+140>:      mov    %rax,%rdi
        0x000055555555523e <+143>:      mov    $0x0,%eax
        0x0000555555555243 <+148>:      callq  0x555555555080 <__isoc99_scanf@plt>
        # 初始化两个变量,分别存储上面-0xbb(%rbp)字符串处理过的字符个数
        # 和要算出来作为正确的 code 所处理过的字符个数
        0x0000555555555248 <+153>:      movl   $0x0,-0xc8(%rbp)
        0x0000555555555252 <+163>:      movl   $0x0,-0xc4(%rbp)
   |--- 0x000055555555525c <+173>:      jmp    0x5555555552ab <main+252>
   |    # -0xc8(%rbp)是刚才那个常量字符串处理过的 byte 数,所以 cltq 下面那句就很明显了
|-----> 0x000055555555525e <+175>:      mov    -0xc8(%rbp),%eax
|  |    0x0000555555555264 <+181>:      cltq
|  |    # 这里的意思是把刚才-0xbb(%rbp)字符串的字符,hex 形式丢到 eax
|  |    0x0000555555555266 <+183>:      movzbl -0xbb(%rbp,%rax,1),%eax
|  |    # 先做有符号数拓展,再做无符号数拓展,不过都小于 0x80 ,所以无所谓了
|  |    0x000055555555526e <+191>:      movsbl %al,%eax
|  |    0x0000555555555271 <+194>:      movzbl %al,%eax
|  |    0x0000555555555274 <+197>:      mov    -0xc4(%rbp),%edx
|  |    0x000055555555527a <+203>:      movslq %edx,%rdx
|  |    # rcx 存储了计算结果的首地址, -0x70(%rbp)是我们最后比较的参照物的地址
|  |    0x000055555555527d <+206>:      lea    -0x70(%rbp),%rcx
|  |    # 加上已经结算过的结果,实际上就是挪动指针,存储下面 sprintf 的结果
|  |    0x0000555555555281 <+210>:      add    %rdx,%rcx
|  |    0x0000555555555284 <+213>:      mov    %eax,%edx
|  |    # 这个字符是 %02x
|  |    0x0000555555555286 <+215>:      lea    0xe9a(%rip),%rax        # 0x555555556127
|  |    0x000055555555528d <+222>:      mov    %rax,%rsi
|  |    0x0000555555555290 <+225>:      mov    %rcx,%rdi
|  |    0x0000555555555293 <+228>:      mov    $0x0,%eax
|  |    # 这里调用 sprintf 的含义就非常清楚了,从 hex 编码转换为字符串
|  |    # 原先是 hex 0x34 ,那么转换为字符串"34"
|  |    0x0000555555555298 <+233>:      callq  0x555555555090 <sprintf@plt>
|  |    # hex 字符串处理过一 byte 后挪一
|  |    # 而 sprintf 处理的结果是 2byte (两个 char 字符)
|  |    0x000055555555529d <+238>:      addl   $0x1,-0xc8(%rbp)
|  |    0x00005555555552a4 <+245>:      addl   $0x2,-0xc4(%rbp)
|  |    #开始处理,先找到第一个字符,看看和上面的字符串长度 10 的大小,判断有没有处理完
|  ---> 0x00005555555552ab <+252>:      mov    -0xc8(%rbp),%eax
|       0x00005555555552b1 <+258>:      cmp    -0xc0(%rbp),%eax
|------ 0x00005555555552b7 <+264>:      jl     0x55555555525e <main+175>
        0x00005555555552b9 <+266>:      lea    -0x70(%rbp),%rax
        0x00005555555552bd <+270>:      mov    %rax,%rdi
        0x00005555555552c0 <+273>:      callq  0x555555555050 <strlen@plt>
        0x00005555555552c5 <+278>:      mov    %rax,%rdx
        # 算出来的正确的 code
        0x00005555555552c8 <+281>:      lea    -0x70(%rbp),%rcx
        # 输入的 code
        0x00005555555552cc <+285>:      lea    -0xb0(%rbp),%rax
        0x00005555555552d3 <+292>:      mov    %rcx,%rsi
        0x00005555555552d6 <+295>:      mov    %rax,%rdi
        # 比较
        0x00005555555552d9 <+298>:      callq  0x555555555030 <strncmp@plt>
        0x00005555555552de <+303>:      test   %eax,%eax
   |----0x00005555555552e0 <+305>:      je     0x5555555552fd <main+334>
   |    0x00005555555552e2 <+307>:      lea    0xe43(%rip),%rax        # 0x55555555612c
   |    0x00005555555552e9 <+314>:      mov    %rax,%rdi
   |    0x00005555555552ec <+317>:      mov    $0x0,%eax
   |    0x00005555555552f1 <+322>:      callq  0x555555555070 <printf@plt>
   |    0x00005555555552f6 <+327>:      mov    $0xffffffff,%eax
   |    0x00005555555552fb <+332>:      jmp    0x555555555316 <main+359>
   |    # 这里就是正确的结果,所以我们只需要输入一个字符串和上面常量字符串从 hex 到字符串转换的结果即可
   |--->0x00005555555552fd <+334>:      lea    0xe3b(%rip),%rax        # 0x55555555613f
        0x0000555555555304 <+341>:      mov    %rax,%rdi
        0x0000555555555307 <+344>:      mov    $0x0,%eax
        0x000055555555530c <+349>:      callq  0x555555555070 <printf@plt>
        0x0000555555555311 <+354>:      mov    $0x0,%eax
        0x0000555555555316 <+359>:      mov    -0x8(%rbp),%rdx
        0x000055555555531a <+363>:      sub    %fs:0x28,%rdx
        0x0000555555555323 <+372>:      je     0x55555555532a <main+379>
        0x0000555555555325 <+374>:      callq  0x555555555060 <__stack_chk_fail@plt>
        0x000055555555532a <+379>:      leaveq
        0x000055555555532b <+380>:      retq
     End of assembler dump.        









































































































简单说一下过程

1300 次点击
所在节点    信息安全
3 条回复
qfdk
2022-09-04 23:10:32 +08:00
然而我直接实战了 哈哈哈
hxndg
2022-09-05 11:22:46 +08:00
@qfdk 直接实战肯定更好,小游戏嘛,休闲娱乐
qfdk
2022-09-05 14:01:50 +08:00
@hxndg #2 想起来 以前看的加密与解密 那时候还看不懂

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/877517

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX