X86 二元炸弹拆除。解码转储-第2阶段 0x08048b94:推送%esi 0x08048b95:推送%ebx 0x08048b96:子$0x34,%esp 0x08048b99:lea 0x18(%esp),%eax 0x08048b9d:mov%eax,0x4(%esp) 0x08048ba1:mov 0x40(%esp),%eax 0x08048ba5:mov%eax,(%esp) 0x08048ba8:调用0x804920a 0x08048bad:cmpl$0x0,0x18(%esp) 0x08048bb2:jne 0x8048bbb 0x08048bb4:cmpl$0x1,0x1c(%esp) 0x08048bb9:je 0x8048bda 0x08048bbb:调用0x80490d7 0x08048bc0:jmp 0x8048bda 0x08048bc2:mov-0x8(%ebx),%eax 0x08048bc5:添加-0x4(%ebx),%eax 0x08048bc8:cmp%eax,(%ebx) 0x08048bca:je 0x8048bd1 0x08048bcc:调用0x80490d7 0x08048bd1:添加$0x4,%ebx 0x08048bd4:cmp%esi,%ebx 0x08048bd6:jne 0x8048bc2 ---键入以继续,或键入q以退出--- 0x08048bd8:jmp 0x8048be4 0x08048bda:lea 0x20(%esp),%ebx 0x08048bde:lea 0x30(%esp),%esi 0x08048be2:jmp 0x8048bc2 0x08048be4:添加$0x34,%esp 0x08048be7:弹出%ebx 0x08048be8:弹出%esi 0x08048be9:ret
这是我的汇编程序转储,用于二进制炸弹拆除实验室的特定阶段。我必须输入六个数字来破解代码并进入下一阶段。我一直在理解这一点,特别是在以下部分:X86 二元炸弹拆除。解码转储-第2阶段 0x08048b94:推送%esi 0x08048b95:推送%ebx 0x08048b96:子$0x34,%esp 0x08048b99:lea 0x18(%esp),%eax 0x08048b9d:mov%eax,0x4(%esp) 0x08048ba1:mov 0x40(%esp),%eax 0x08048ba5:mov%eax,(%esp) 0x08048ba8:调用0x804920a 0x08048bad:cmpl$0x0,0x18(%esp) 0x08048bb2:jne 0x8048bbb 0x08048bb4:cmpl$0x1,0x1c(%esp) 0x08048bb9:je 0x8048bda 0x08048bbb:调用0x80490d7 0x08048bc0:jmp 0x8048bda 0x08048bc2:mov-0x8(%ebx),%eax 0x08048bc5:添加-0x4(%ebx),%eax 0x08048bc8:cmp%eax,(%ebx) 0x08048bca:je 0x8048bd1 0x08048bcc:调用0x80490d7 0x08048bd1:添加$0x4,%ebx 0x08048bd4:cmp%esi,%ebx 0x08048bd6:jne 0x8048bc2 ---键入以继续,或键入q以退出--- 0x08048bd8:jmp 0x8048be4 0x08048bda:lea 0x20(%esp),%ebx 0x08048bde:lea 0x30(%esp),%esi 0x08048be2:jmp 0x8048bc2 0x08048be4:添加$0x34,%esp 0x08048be7:弹出%ebx 0x08048be8:弹出%esi 0x08048be9:ret,x86,reverse-engineering,X86,Reverse Engineering,这是我的汇编程序转储,用于二进制炸弹拆除实验室的特定阶段。我必须输入六个数字来破解代码并进入下一阶段。我一直在理解这一点,特别是在以下部分: 0x08048b94 <+0>:push %esi 0x08048b95 <+1>: push %ebx 0x08048b96 <+2>: sub $0x34,%esp 0x08048b99 <+5>: lea 0x18(%esp),%eax 0x08048b9d <
0x08048b94 <+0>:push %esi
0x08048b95 <+1>: push %ebx
0x08048b96 <+2>: sub $0x34,%esp
0x08048b99 <+5>: lea 0x18(%esp),%eax
0x08048b9d <+9>: mov %eax,0x4(%esp)
0x08048ba1 <+13>: mov 0x40(%esp),%eax
0x08048ba5 <+17>: mov %eax,(%esp)
0x08048ba8 <+20>: call 0x804920a <read_six_numbers>
0x08048bad <+25>: cmpl $0x0,0x18(%esp)
0x08048bb2 <+30>: jne 0x8048bbb <phase_2+39>
0x08048bb4 <+32>: cmpl $0x1,0x1c(%esp)
0x08048bb9 <+37>: je 0x8048bda <phase_2+70>
0x08048bbb <+39>: call 0x80490d7 <explode_bomb>
0x08048bc0 <+44>: jmp 0x8048bda <phase_2+70>
0x08048bc2 <+46>: mov -0x8(%ebx),%eax
0x08048bc5 <+49>: add -0x4(%ebx),%eax
0x08048bc8 <+52>: cmp %eax,(%ebx)
0x08048bca <+54>: je 0x8048bd1 <phase_2+61>
0x08048bcc <+56>: call 0x80490d7 <explode_bomb>
0x08048bd1 <+61>: add $0x4,%ebx
0x08048bd4 <+64>: cmp %esi,%ebx
0x08048bd6 <+66>: jne 0x8048bc2 <phase_2+46>
---Type <return> to continue, or q <return> to quit---<return>
0x08048bd8 <+68>: jmp 0x8048be4 <phase_2+80>
0x08048bda <+70>: lea 0x20(%esp),%ebx
0x08048bde <+74>: lea 0x30(%esp),%esi
0x08048be2 <+78>: jmp 0x8048bc2 <phase_2+46>
0x08048be4 <+80>: add $0x34,%esp
0x08048be7 <+83>: pop %ebx
0x08048be8 <+84>: pop %esi
0x08048be9 <+85>: ret
0x08048bc2:mov-0x8(%ebx),%eax
0x08048bc5:添加-0x4(%ebx),%eax
如果有人能帮我执行这个汇编代码,那就太好了。谢谢 好的,这将是一个很长的答案,但你可以这样回答: 让我从你关于+46/+49行的具体问题开始。他们所做的是:
- 将地址[ebx-8]处的内存值写入eax
- 将地址[ebx-4]处的内存值添加到eax
- 因此,它有效地设置了
,其中eax=[ebx-8]+[ebx-4]
表示解除引用/内存访问[]
- AT&T将源代码放在末尾,目标代码放在开头,而Intel则相反。例如,AT&T中的
将是英特尔中的mov%ebx,%eax
mov-eax,ebx
- 英特尔没有大多数前缀,如
、%
等*
- 对于内存访问(或使用
进行有效地址计算),AT&T使用lea
,而Intel使用offset(base)
(我个人认为这更容易阅读),因此[base+offset]
从您的示例中变成英特尔语法中的mov-0x8(%ebx),%eax
mov-eax[ebx-8]
- 它不是像
这样的命令后缀,而是在需要时使用l
等语法指定操作数大小(例如dword ptr
变成cmpl
)cmp dword ptr
0x08048bc2 <+46>: mov -0x8(%ebx),%eax
0x08048bc5 <+49>: add -0x4(%ebx),%eax
然后我实际编译了代码,然后将其加载到IDA(一个很好的反汇编程序)中。我为变量设置了一些标签,并创建了一个结构SIX\u NUMBERS\u STRUCT
,它基本上是一个由6个DWORD数字组成的数组。对我来说,它看起来像是phase_2
函数接受一个参数,可能是您输入的数字的某种字符串。然后,它调用read_six_numbers
,并将上述输入指针与指向6个DWORD值结构的指针一起传递(该结构保持在[esp+3C-24]=[esp+18],因此可以使用[esp+18]、[esp+1C]、[esp+20]、[esp+24]、[esp+28]和[esp+2C]访问6个数字)。然后,对该数据进行几次检查和计算
对以下部分的一点解释:通常,在带有局部变量的函数中使用一个基指针(ebp
),以使指针始终引用堆栈上的同一点,即使在推送新值时也是如此。在这里,您没有-相反,0x34在开始时从esp
中减去。此外,以前有两个push
es,这意味着堆栈指针现在比函数开始时的点低0x3C字节。这就是为什么IDA正在计算相对于esp+3C
的所有堆栈偏移量
首先,这里是可视化的汇编代码(您应该能够更容易地理解程序流):
我还对其运行了反编译器,以生成代码的类似C的表示形式,并对其进行了一些注释:
因此,我的见解如下:
- 首先,代码读取六个数字,方法是将
([esp+40],作为堆栈上参数列表的一部分保存在[esp+0]中)到参数u传递到\u phase_2
,并将指向保存数字的6*DWORD结构的指针(该结构从[esp+18]开始),指向该结构的指针存储在[esp+4]中作为堆栈上参数列表的一部分)读取六个数字
- 然后,代码验证第一个数字(
=[esp+18])是否为0,第二个数字(numbers[0]
=[esp+1C])是否为1numbers[1]
- 然后,代码循环遍历其余的数字(第三到第六个),验证每个数字
是否等于前两个numbers[n]
的总和。循环在超出数字列表末尾时终止,这是通过将指向当前要检查的数字的指针与数字之后的numbers[n-1]+numbers[n-2]
伪变量([esp+30])进行比较来完成的,该伪变量正好位于数字列表之后(类似于“第七个数字”)
phase_2:
push esi
push ebx
sub esp, 34
lea eax, [esp+18]
mov [esp+4], eax
mov eax, [esp+40]
mov [esp], eax
call read_six_numbers
cmp dword ptr [esp+18], 0
jne phase_2_39
phase_2_32:
cmp dword ptr [esp+1c], 1
je phase_2_70
phase_2_39:
call explode_bomb
jmp phase_2_70
phase_2_46:
mov eax, [ebx-8]
add eax, [ebx-4]
cmp [ebx], eax
je phase_2_61
phase_2_56:
call explode_bomb
phase_2_61:
add ebx, 4
cmp ebx, esi
jne phase_2_46
phase_2_68:
jmp phase_2_80
phase_2_70:
lea ebx, [esp+20]
lea esi, [esp+30]
jmp phase_2_46
phase_2_80:
add esp, 34
pop ebx
pop esi
retn
read_six_numbers:
int3
explode_bomb:
int3
void __cdecl phase_2(void *argument_to_phase_2)
{
int *currentNumber; // ebx@6
SIX_NUMBERS_STRUCT numbers_struct; // [sp+18h] [bp-24h]@1
int dummy_var_after_numbers; // [sp+30h] [bp-Ch]@6
read_six_numbers(argument_to_phase_2, &numbers_struct);
if ( numbers_struct.numbers[0] || numbers_struct.numbers[1] != 1 )
explode_bomb();
currentNumber = &numbers_struct.numbers[2];
do
{
if ( *currentNumber != *(currentNumber - 1) + *(currentNumber - 2) )
explode_bomb();
++currentNumber;
}
while ( currentNumber != &dummy_var_after_numbers );
}
|-------------------------------------------------------------------------------------|
| rel. to current esp | rel. to esp at start | usage |
|-------------------------------------------------------------------------------------|
| +0 | -3C | First parameter to read_six_numbers |
| +4 | -38 | Second parameter to read_six_numbers |
| +8 | -34 | (unused) |
| +C | -30 | (unused) |
| +10 | -2C | (unused) |
| +14 | -28 | (unused) |
| +18 | -24 | First number |
| +1C | -20 | Second number |
| +20 | -1C | Third number |
| +24 | -18 | Fourth number |
| +28 | -14 | Fifth number |
| +2C | -10 | Sixth number |
| +30 | -C | Dummy, compared against to end loop |
| +34 | -8 | Original esi register from "push esi" |
| +38 | -4 | Original ebx register from "push ebx" |
| +3C | 0 | Return address from function "phase_2" |
| +40 | +4 | Argument to function "phase_2" |
|-------------------------------------------------------------------------------------|