Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 二进制炸弹第2阶段-解码汇编代码_Assembly_X86_Reverse Engineering - Fatal编程技术网

Assembly 二进制炸弹第2阶段-解码汇编代码

Assembly 二进制炸弹第2阶段-解码汇编代码,assembly,x86,reverse-engineering,Assembly,X86,Reverse Engineering,我刚刚开始学习汇编代码,我偶然发现了这个二进制炸弹实验室,觉得这将是一个很好的练习 这是二进制炸弹的第二阶段,为了进入下一阶段,我需要从这个汇编代码中找出一个6位数的密码 我已经看了好一阵子了,但我似乎不明白 任何关于如何解决这一问题的意见或解释都将不胜感激。我想对这一点有一个很好的了解,以便进入更复杂的阶段 Dump of assembler code for function phase_2: 0x0000000000400f49 <+0>: push %rbp

我刚刚开始学习汇编代码,我偶然发现了这个二进制炸弹实验室,觉得这将是一个很好的练习

这是二进制炸弹的第二阶段,为了进入下一阶段,我需要从这个汇编代码中找出一个6位数的密码

我已经看了好一阵子了,但我似乎不明白

任何关于如何解决这一问题的意见或解释都将不胜感激。我想对这一点有一个很好的了解,以便进入更复杂的阶段

    Dump of assembler code for function phase_2:
   0x0000000000400f49 <+0>: push   %rbp
   0x0000000000400f4a <+1>: push   %rbx
   0x0000000000400f4b <+2>: sub    $0x28,%rsp
   0x0000000000400f4f <+6>: mov    %fs:0x28,%rax
   0x0000000000400f58 <+15>:    mov    %rax,0x18(%rsp)
   0x0000000000400f5d <+20>:    xor    %eax,%eax
   0x0000000000400f5f <+22>:    mov    %rsp,%rsi
   0x0000000000400f62 <+25>:    callq  0x401682 <read_six_numbers>
   0x0000000000400f67 <+30>:    cmpl   $0x1,(%rsp) //first password number = 1?
   0x0000000000400f6b <+34>:    je     0x400f72 <phase_2+41>
   0x0000000000400f6d <+36>:    callq  0x40164c <explode_bomb>
   0x0000000000400f72 <+41>:    mov    %rsp,%rbx
   0x0000000000400f75 <+44>:    lea    0x14(%rsp),%rbp
   0x0000000000400f7a <+49>:    mov    (%rbx),%eax
=> 0x0000000000400f7c <+51>:    add    %eax,%eax 
   0x0000000000400f7e <+53>:    cmp    %eax,0x4(%rbx)
   0x0000000000400f81 <+56>:    je     0x400f88 <phase_2+63>
   0x0000000000400f83 <+58>:    callq  0x40164c <explode_bomb>
   0x0000000000400f88 <+63>:    add    $0x4,%rbx
   0x0000000000400f8c <+67>:    cmp    %rbp,%rbx
   0x0000000000400f8f <+70>:    jne    0x400f7a <phase_2+49> // loop? What is it doing?
   0x0000000000400f91 <+72>:    mov    0x18(%rsp),%rax
---Type <return> to continue, or q <return> to quit---return
   0x0000000000400f96 <+77>:    xor    %fs:0x28,%rax
   0x0000000000400f9f <+86>:    je     0x400fa6 <phase_2+93>
   0x0000000000400fa1 <+88>:    callq  0x400b90 <__stack_chk_fail@plt>
   0x0000000000400fa6 <+93>:    add    $0x28,%rsp
   0x0000000000400faa <+97>:    pop    %rbx
   0x0000000000400fab <+98>:    pop    %rbp
   0x0000000000400fac <+99>:    retq   
End of assembler dump.
功能阶段2的汇编程序代码转储: 0x0000000000400f49:推送%rbp 0x0000000000400f4a:推送%rbx 0x0000000000400f4b:子$0x28,%rsp 0x0000000000400f4f:mov%fs:0x28,%rax 0x0000000000400f58:mov%rax,0x18(%rsp) 0x0000000000400f5d:异或%eax,%eax 0x0000000000400f5f:mov%rsp,%rsi 0x0000000000400f62:callq 0x401682 0x0000000000400f67:cmpl$0x1,(%rsp)//第一个密码号=1? 0x0000000000400f6b:je 0x400f72 0x0000000000400f6d:callq 0x40164c 0x0000000000400f72:mov%rsp,%rbx 0x0000000000400f75:lea 0x14(%rsp),%rbp 0x0000000000400f7a:mov(%rbx),%eax =>0x0000000000400f7c:添加%eax,%eax 0x0000000000400f7e:cmp%eax,0x4(%rbx) 0x0000000000400f81:je 0x400f88 0x0000000000400f83:callq 0x40164c 0x0000000000400f88:添加$0x4,%rbx 0x0000000000400f8c:cmp%rbp,%rbx 0x0000000000400f8f:jne 0x400f7a//循环?它在干什么? 0x0000000000400f91:mov 0x18(%rsp),%rax ---键入以继续,或键入q以退出---return 0x0000000000400f96:xor%fs:0x28,%rax 0x0000000000400f9f:je 0x400fa6 0x0000000000400fa1:callq 0x400b90 0x0000000000400fa6:添加$0x28,%rsp 0x0000000000400faa:弹出%rbx 0x0000000000400fab:pop%rbp 0x0000000000400fac:retq 汇编程序转储结束。
你应该一步一步地解决这个问题

首先,让我们从转储中删除无用的内容开始(额外的地址只会增加冗长);我还希望我的汇编采用英特尔语法,内存访问和比较/减法读取方式更为完美

通过快速浏览,我们可以立即观察到:

:推送rbp;保存被删除的寄存器
:按rbx键
:子rsp,0x28;40字节的局部变量
:mov-rax,dword-ptr-fs:0x28;从fs引用的内容通常是
; 某种类型的线程局部变量
:mov qword ptr[rsp+0x18],rax;在偏移量0x18处有一个长的本地
:xor eax,eax
:移动相对标准差,相对标准差;rsi在系统V ABI中是第一个参数;
; 这是我们当地人作为一个整体的开始
; 指针
:呼叫;我们可以想象读六个数字需要多少时间
; 由6个int值组成的数组,可能是
; rsp和rsp+0x18(0x18)之间的局部变量=
;24=6*sizeof(int))
:cmp dword ptr[rsp],0x1;这是第一个读取值
:日本脑炎--\
:call;|第一次炸弹爆炸

:移动rbx,rsp<代码>第一个密码号码=1?
是。至于循环在做什么,将
+41
+70
之间的每条指令逐一转换为伪代码或C。制造这个炸弹的人应该真的使用
-fno-stack-protector
编译,所以
mov%fs:0x28,%rax
/
\u stack\u chk\u fail
堆栈金丝雀的东西不是二进制文件的一部分。这对初学者来说太让人困惑了。我完全同意你的看法。作为一名初学者,我花了太多的时间试图解读内容,结果我一直试图实现的解决方案并不需要这些内容,结果只是引导我远离我应该关注的内容。非常感谢你花时间如此彻底地完成所有这些步骤!通过阅读你的答案,我对组装的理解翻了一番。我一定会在本实验室的剩余阶段继续讨论。再次感谢@19921127:很高兴它有帮助,逆向工程对我来说通常都很有趣;这不是我第一次看到这些关于堆栈溢出的“二进制炸弹”问题,我认为它们是对这些技术的一个很好的介绍。我希望我的回答,除了提供这个特定问题的解决方案外,还可以作为解决类似问题的“入门模式”,对您有所帮助。Matteo我想让您知道,我已经成功地完成了第4阶段。我之所以能在第二阶段之后的两个阶段中取得成功,很大程度上是因为你在这里给出了答案,再次感谢你。目前,我发现自己被困在第五阶段,我想知道(如果我要求太多,我很抱歉)你是否允许我在你身边运行一些东西,看看我是否能解决这个问题。@19921127:很高兴这有帮助!对于问题的新部分,请在这里发布一个关于堆栈溢出的适当问题,我很乐意看一看。谢谢!然而,在接下来的几天里,我似乎不被允许在这里发布另一个问题。。。
void phase_2() {
    int numbers[6];
    read_six_numbers(numbers);
    if(numbers[0] == 1) goto l_41;
    explode_bomb();
l_41:
    int *rbx = &numbers[0];
    int *rbp = &numbers[5];
l_49:
    int eax = *rbx;
    eax += eax;
    if(eax == rbx[1]) goto l_63;
    explode_bomb();
l_63:
    rbx++;
    if(rbx != rbp) goto l_49;
}