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