Assembly 如何在二进制文件中发现密码

Assembly 如何在二进制文件中发现密码,assembly,passwords,x86-64,reverse-engineering,elf,Assembly,Passwords,X86 64,Reverse Engineering,Elf,我最近收到一个拼图,它有一个二进制可执行文件,这个拼图的目的是发现隐藏在二进制文件十六进制转储中的密码。我试着跟随,但我没有办法在我达到的点上继续下去。这是代码的逻辑部分: #h begins the printf "password: " 4006dc: bf 14 08 40 00 mov $0x400814,%edi 4006e1: b8 00 00 00 00 mov $0x0,%eax #h sets %eax to NULL 400

我最近收到一个拼图,它有一个二进制可执行文件,这个拼图的目的是发现隐藏在二进制文件十六进制转储中的密码。我试着跟随,但我没有办法在我达到的点上继续下去。这是代码的逻辑部分:

#h begins the printf "password: "

4006dc: bf 14 08 40 00          mov    $0x400814,%edi
4006e1: b8 00 00 00 00          mov    $0x0,%eax
#h sets %eax to NULL

4006e6: e8 a5 fe ff ff          callq  400590 <printf@plt>
4006eb: 48 8b 15 6e 09 20 00    mov    0x20096e(%rip),%rdx        # 601060 <stdin@@GLIBC_2.2.5>
4006f2: 48 8d 45 b0             lea    -0x50(%rbp),%rax
#h probably the address of the string "password: "

4006f6: be 32 00 00 00          mov    $0x32,%esi
4006fb: 48 89 c7                mov    %rax,%rdi
4006fe: e8 ad fe ff ff          callq  4005b0 <fgets@plt>
#h calling the fgets function, so here we know which register is being used for storing the input

400703: c7 45 ac 00 00 00 00    movl   $0x0,-0x54(%rbp)
#h makes mem[rbp-84] = NULL

40070a: c7 45 a8 00 00 00 00    movl   $0x0,-0x58(%rbp)
#h makes mem[rpb-88] = NULL

400711: eb 27                   jmp    40073a <__gmon_start__@plt+0x17a>
#h jumps unconditionally to the pc address 40073a

400713: 8b 45 a8                mov    -0x58(%rbp),%eax
400716: 48 98                   cltq
400718: 0f b6 44 05 b0          movzbl -0x50(%rbp,%rax,1),%eax
40071d: 0f be d0                movsbl %al,%edx
400720: 8b 45 a8                mov    -0x58(%rbp),%eax
400723: 48 98                   cltq
400725: 0f b6 44 05 b0          movzbl -0x50(%rbp,%rax,1),%eax
40072a: 0f be c0                movsbl %al,%eax
40072d: 89 c1                   mov    %eax,%ecx
#h ecx loop counter

40072f: d3 e2                   shl    %cl,%edx
400731: 89 d0                   mov    %edx,%eax
#h moves edx to eax

400733: 31 45 ac                xor    %eax,-0x54(%rbp)
#h do a xor between eax and -0x54(rbp)

400736: 83 45 a8 01             addl   $0x1,-0x58(%rbp)

#h pc address 40073a is below here
40073a: 8b 45 a8                mov    -0x58(%rbp),%eax
40073d: 48 63 d8                movslq %eax,%rbx
400740: 48 8d 45 b0             lea    -0x50(%rbp),%rax
#h register rax receives the mem[rbp-80] (first local variable)

400744: 48 89 c7                mov    %rax,%rdi
400747: e8 24 fe ff ff          callq  400570 <strlen@plt>
40074c: 48 39 c3                cmp    %rax,%rbx
40074f: 72 c2                   jb     400713 <__gmon_start__@plt+0x153>
#h if %rax < %rdi, jump to pc = 400713

400751: 81 7d ac 62 02 49 0d    cmpl   $0xd490262,-0x54(%rbp)
#here it compares the 0xd490262 memory address with mem[rbp-84], so I guess that the -0x54(%rbp) contains the string we want, but where???

400758: 75 0c                   jne    400766 <__gmon_start__@plt+0x1a6>
#h here it does the jump if not equal, so the contents we want is on $0xd490262

#h WELL DONE!
40075a: bf 1f 08 40 00          mov    $0x40081f,%edi
40075f: e8 fc fd ff ff          callq  400560 <puts@plt>
400764: eb 0a                   jmp    400770 <__gmon_start__@plt+0x1b0>
#h wrong password
400766: bf 2b 08 40 00          mov    $0x40082b,%edi
40076b: e8 f0 fd ff ff          callq  400560 <puts@plt>
400770: 48 8b 4d e8             mov    -0x18(%rbp),%rcx
400774: 64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
40077b: 00 00

有人能给我一个提示吗?

因为这是一种破解,可能有些部分只是诱饵,或者是红鲱鱼,所以最好学习如何有效地使用调试器,比如使用断点、搜索内存地址范围等

从获取字符串并将其保存到应用程序缓冲区的部分开始跟踪,跟踪操作输入字符串的指令,找到将输入与正确密码进行比较的方法


从外观上看,密码是常量$0xd490262,因为它与[rbp-0x54]中的值相比较,所以如果[rbp-0x54]包含$0xd490262,则比较后的jne不会跳转。因此,打印“好孩子”消息。

尝试编写与汇编代码具有相同功能的C代码。@fuzzxl我已经尝试过了,但我认为二进制代码的作者使用的逻辑与我完全不同。二进制可执行文件的hextump甚至无法接近:(您为近似此代码而编写的C代码不太可能生成相同的程序集。行为应该匹配,而不是程序集。当您说“密码是常量$0xd490262”时,您的意思是字符串“$0xd490262”或者它的十进制数22288546?我的意思是,密码是一个硬编码值,十六进制值为0D49026H,因此来自用户的输入值必须以该值结束,或者具有该4字节值,以便可以传递,但这些值不能“键入”字符?,所以我猜有什么东西在操纵输入值,在反汇编中很难破译,在运行时使用调试器检查它以进一步分析发生的情况。
$./binary
$password: (fgets function in here)
$wrong password!