二元弹阶段4汇编

问题描述:

我有一个非常类似的问题:Binary Bomb - Phase 4但它仍然不同,我不完全确定该怎么做。二元弹阶段4汇编

这里是我的phase_4代码:

08048d3e <phase_4>: 
8048d3e:  83 ec 2c    sub $0x2c,%esp 
8048d41:  8d 44 24 18    lea 0x18(%esp),%eax 
8048d45:  89 44 24 0c    mov %eax,0xc(%esp) 
8048d49:  8d 44 24 1c    lea 0x1c(%esp),%eax 
8048d4d:  89 44 24 08    mov %eax,0x8(%esp) 
8048d51:  c7 44 24 04 75 a7 04 movl $0x804a775,0x4(%esp) 
8048d58:  08 
8048d59:  8b 44 24 30    mov 0x30(%esp),%eax 
8048d5d:  89 04 24    mov %eax,(%esp) 
8048d60:  e8 6b fb ff ff   call 80488d0 <[email protected]> 
8048d65:  83 f8 02    cmp $0x2,%eax //making sure I have 2 inputs 
8048d68:  75 0e     jne 8048d78 <phase_4+0x3a> //if not explodes bomb 
8048d6a:  8b 44 24 18    mov 0x18(%esp),%eax 
8048d6e:  83 f8 01    cmp $0x1,%eax //has to be greater than 1 
8048d71:  7e 05     jle 8048d78 <phase_4+0x3a> //otherwise jumps to bomb 
8048d73:  83 f8 04    cmp $0x4,%eax 
8048d76:  7e 05     jle 8048d7d <phase_4+0x3f> //has to be less than 4 or jumps to bomb 
8048d78:  e8 af 05 00 00   call 804932c <explode_bomb> 
8048d7d:  8b 44 24 18    mov 0x18(%esp),%eax 
8048d81:  89 44 24 04    mov %eax,0x4(%esp) 
8048d85:  c7 04 24 09 00 00 00 movl $0x9,(%esp) 
8048d8c:  e8 50 ff ff ff   call 8048ce1 <func4> //calls function 4 
8048d91:  3b 44 24 1c    cmp 0x1c(%esp),%eax 
8048d95:  74 05     je  8048d9c <phase_4+0x5e> //compares two values and explodes bomb if not equal 
8048d97:  e8 90 05 00 00   call 804932c <explode_bomb> 
8048d9c:  83 c4 2c    add $0x2c,%esp 
8048d9f:  90      nop 
8048da0:  c3      ret 

这里是func_4代码:

08048ce1 <func4>: //not entirely sure what's happening here but it might be a binary search? 
8048ce1:  83 ec 1c    sub $0x1c,%esp 
8048ce4:  89 5c 24 10    mov %ebx,0x10(%esp) 
8048ce8:  89 74 24 14    mov %esi,0x14(%esp) 
8048cec:  89 7c 24 18    mov %edi,0x18(%esp) 
8048cf0:  8b 74 24 20    mov 0x20(%esp),%esi 
8048cf4:  8b 5c 24 24    mov 0x24(%esp),%ebx 
8048cf8:  85 f6     test %esi,%esi 
8048cfa:  7e 2b     jle 8048d27 <func4+0x46> 
8048cfc:  83 fe 01    cmp $0x1,%esi 
8048cff:  74 2b     je  8048d2c <func4+0x4b> 
8048d01:  89 5c 24 04    mov %ebx,0x4(%esp) 
8048d05:  8d 46 ff    lea -0x1(%esi),%eax 
8048d08:  89 04 24    mov %eax,(%esp) 
8048d0b:  e8 d1 ff ff ff   call 8048ce1 <func4> 
8048d10:  8d 3c 18    lea (%eax,%ebx,1),%edi 
8048d13:  89 5c 24 04    mov %ebx,0x4(%esp) 
8048d17:  83 ee 02    sub $0x2,%esi 
8048d1a:  89 34 24    mov %esi,(%esp) 
8048d1d:  e8 bf ff ff ff   call 8048ce1 <func4> 
8048d22:  8d 1c 07    lea (%edi,%eax,1),%ebx 
8048d25:  eb 05     jmp 8048d2c <func4+0x4b> 
8048d27:  bb 00 00 00 00   mov $0x0,%ebx 
8048d2c:  89 d8     mov %ebx,%eax 
8048d2e:  8b 5c 24 10    mov 0x10(%esp),%ebx 
8048d32:  8b 74 24 14    mov 0x14(%esp),%esi 
8048d36:  8b 7c 24 18    mov 0x18(%esp),%edi 
8048d3a:  83 c4 1c    add $0x1c,%esp 
8048d3d:  c3      ret 

我检查,以确保输入必须是两位小数,而且我还可以看到最后两个数字相互比较(第8048d97行,0x1c(%esp)和%eax)。在阶段4开始时,我认为代码也表明第一个数字必须在1到4之间,而在阶段4结束时,数字已被修改,它必须等于第二个数字。如果我错了,请纠正我。

我只是不确定func_4在做什么,以及如何确定输入应该是什么。我认为这可能是二分搜索,但不知道如何检查它与第一个输入的对应关系。任何帮助将不胜感激!

+0

1和4之间?为什么?我在那里看到'jle'。这会让我更容易,如果你将代码与你的评论交错,你认为这几行代码可以做什么(所以我不需要自己计算什么是'0x24(%esp)') fn4。搜索几乎每个跳转地址的整个代码,无论是导致爆炸,还是化解,添加一些标签......它还会显示更多的努力,除此之外,您是否考虑过打字这到真正的机器和看着调试?或者它被认为是作弊的炸弹实验室?然后问在SO也必须。:D – Ped7g

+0

只是在评论!对不起!我确实使用调试器,但无论如何它通过函数4跳转,它继续到爆炸炸弹的步骤,但我无法跟随,因为我不擅长解码汇编代码。 –

+0

我用'func4'的“样本”注释扩展了我的答案。通过它,让我知道它是否有帮助。“不擅长解密”=需要一些时间,但是通常只有x86 CPU的许多指令,每个指令都只是非常简单的事情,当你将自己限制在80386指令集时,它实际上比任何高级语言(就intructions/keywords而言)学习ASM要容易得多)。这是您需要做的一些有用的指令,这使得在ASM中进行编程变得困难,而不是指令本身。那些很简单。 – Ped7g

func_4正在做什么,以及如何确定输入应该是什么。

8048d81:  89 44 24 04    mov %eax,0x4(%esp) 
    ; input value loaded to [esp+4] -> [esp+0x24] inside func4 
8048d85:  c7 04 24 09 00 00 00 movl $0x9,(%esp) 
    ; 9 stored to [esp+0] -> [esp+0x20] inside func4 
8048d8c:  e8 50 ff ff ff   call 8048ce1 <func4> 
    ; something calculated 
    ; then the result is compared with other input value, they should be equal 

我不知道,哪个输入是(你知道sscanf的格式字符串和您的ABI,所以你可以告诉越好,一个存储到[ESP +为0x18]和测试要在计算中使用值2,3或4时,只是比较存储在[esp + 0x1c]中的值,我猜测计算的输入是第二个(对于+ 0x0c的sscanf,另一个是+ 0x08)?因此密码是“<func4(9,2-4)> <2-4>”?

由于func4是干净的asm递归代码,因此您可以针对所有三种可能的输入运行它,以查看它产生的结果(在调试器中,逐步执行指令,以便设法捕获if一些p参数会导致无限循环或其他一些问题,再加上你会明白它是如何工作的)。

然后找出哪个输入是哪个。

不知道什么func_4做

嘿,这就是如何组装工作。你很少看看指令流,并快速浏览一下它们的算法。更常见的情况是,需要通过指令彻底模拟头部指令中的CPU状态,注意每一个细节(比如标志根据指令改变,看起来只用于设置一个值,然后在条件中使用几条指令后保存标志跳转),并且通过保持一些计算值的时间轴,通常可以猜测实现的算法。

或者如果不是算法,那么至少要知道计算的是什么值。

我检查代码一个更多的时间,它看起来像Fibonnaci主题的变化,像func4(0,x) = 0func4(1,x) = x,并func4(y, x) = (只是猜测快,懒得去验证我猜中了)x + func4(y-1, x) + func4(y-2, x)

编辑:我现在确定公式是不正确的,它至少缺少一个常量(但也许它错了甚至更多)。


所以我想知道,你是懒得费心彻底模拟CPU,并获得正确的结果,或者你有一些特殊指令的问题,它究竟做(即。你是懒得阅读说明书参考指南)?所以它归结为“你是懒惰还是懒惰?”因为我绝对都是,所以这是我对你的问题的回答。 :)

如果您不明白某些指令的某些特定细节,请询问。


编辑约的评论:

“//必须是小于4或跳转到炸弹”

不,这是jle,这是记忆法“跳签署以下/等于“,所以正确的评论是”必须小于或等于4“,并且对于值[TYPE_MIN,4]是有效的。

对于“少于4”,您需要使用jl =“跳过少签名”。

对于“小于4”,无符号的有jb =“跳到下面”,覆盖值[0,3]。 jbe涵盖[0,4]值。

如果您将检查Jcc description,你会看到那些条件跳转仅基于在标志寄存器中几个标志,仅此而已(除了jcxz/jecxz,其中比较cx寄存器和不接触标志在所有)。

另外你可能会注意到有几个别名,所以你可以在你的代码中写出一个符合你的目的的语义。例如jzje是相同的指令,第一个别名代表“jump when zero(flag)”,另一个代表“跳转时相等”。所以仔细阅读并习惯这些缩写,它会使拆解的阅读更容易一些。


//调用函数4

那是没用的评论,这是由指令本身明显。您是否会添加例如参数(9,input_2),这对读者会更有好处。

下一个“比较”评论具有类似的无用性质。两个数字是什么?如果你已经记下了它们,你应该把这个结果写入注释,所以像“比较func4和input_1的结果”。


我会努力向您展示的例子中,FUNC4:

8048ce1 <func4>: 
    ; allocates 0x1c bytes on stack for local variables 
    ; (so return address is at [esp+0x1c] now, was at [esp]) 
8048ce1:  83 ec 1c    sub $0x1c,%esp 
    ; stores current ebx, esi and edi in [esp+0x10/0x14/0x18] 
8048ce4:  89 5c 24 10    mov %ebx,0x10(%esp) 
8048ce8:  89 74 24 14    mov %esi,0x14(%esp) 
8048cec:  89 7c 24 18    mov %edi,0x18(%esp) 
    ; esi = [esp+0x20] = first argument of func4(arg1, arg2) 
8048cf0:  8b 74 24 20    mov 0x20(%esp),%esi 
    ; ebx = [esp+0x24] = second argument of func4(arg1, arg2) 
8048cf4:  8b 5c 24 24    mov 0x24(%esp),%ebx 
    ; when esi(arg1) <= 0, jump to ExitWith0 
8048cf8:  85 f6     test %esi,%esi 
8048cfa:  7e 2b     jle 8048d27 ExitWith0 
    ; when esi(arg1) == 1, jump to ExitWithValueFromEbx 
8048cfc:  83 fe 01    cmp $0x1,%esi 
8048cff:  74 2b     je  8048d2c ExitWithValueFromEbx 
    ; store arg2 in [esp+4] 
8048d01:  89 5c 24 04    mov %ebx,0x4(%esp) 
    ; store (arg1-1) in [esp] (preparing args for recursive call) 
8048d05:  8d 46 ff    lea -0x1(%esi),%eax 
8048d08:  89 04 24    mov %eax,(%esp) 
    ; recursion: eax = func4(arg1-1, arg2) ; ebx/esi/edi preserved 
8048d0b:  e8 d1 ff ff ff   call 8048ce1 <func4> 
    ; edi = eax (result) + ebx*1 (arg2) 
8048d10:  8d 3c 18    lea (%eax,%ebx,1),%edi 
    ; [esp+4] is set to arg2 again 
    ; (it's still there, but this asm looks like debug level of C, not very efficient) 
8048d13:  89 5c 24 04    mov %ebx,0x4(%esp) 
    ; esi -= 2 (no more original arg1 in esi), and set [esp+0] 
8048d17:  83 ee 02    sub $0x2,%esi 
8048d1a:  89 34 24    mov %esi,(%esp) 
    ; second recursive call: func4(arg1-2, arg2) 
8048d1d:  e8 bf ff ff ff   call 8048ce1 <func4> 
    ; ebx = edi + eax*1 ; edi was arg2 + f4(arg1-1, arg2) 
8048d22:  8d 1c 07    lea (%edi,%eax,1),%ebx 
    ; so ebx = arg2 + f4(arg1-1, arg2) + f4(arg1-2, arg2), return that value 
8048d25:  eb 05     jmp 8048d2c ExitWithValueFromEbx 
ExitWith0: 
8048d27:  bb 00 00 00 00   mov $0x0,%ebx 
ExitWithValueFromEbx: 
8048d2c:  89 d8     mov %ebx,%eax 
    ; restore values of ebx/esi/edi (return value is in eax) 
8048d2e:  8b 5c 24 10    mov 0x10(%esp),%ebx 
8048d32:  8b 74 24 14    mov 0x14(%esp),%esi 
8048d36:  8b 7c 24 18    mov 0x18(%esp),%edi 
    ; restore esp value, so [esp] is return address, and return 
8048d3a:  83 c4 1c    add $0x1c,%esp 
8048d3d:  c3      ret 

所以我实际上在我的答案猜测正确,在LEA那些,1)搞糊涂了,我不习惯AT & T语法,所以在一个较弱的时刻,我认为结果是+1,但它是* 1到索引寄存器(我习惯于英特尔语法,它看起来像lea ebx,[edi+eax])。

但是,正如你所看到的,一旦你开始记下笔记,并专注于单指令,这次我确实设法正确解密它。

目前,确保您理解每条指令非常重要,我指的是每个细节,比如lea的工作原理以及为什么它不读取存储器值,即使参数是(...),以及什么是全部可能的寻址模式(如果你想要做f(a,b)= 1 + b + f(a-1,b)+ f(a-2,b),它看起来会如何?尝试找到一个,必须修改一个lea(这两个中的任何一个))。

我不确定你有什么样的文献,因为我使用英特尔语法所有东西(我认为AT & T语法对于C编译器是好的,但对人类来说不是那么重要......但总的来说并不是那么糟糕,如果你已经知道另一个,大部分都很烦人,如果你只知道T,那可能是相当不错的)。

在最坏的情况下请问,尽管关于指令目的的问题是“低效”,因为所有的x86手册都是免费的,但如果您不确定某些措辞的真正含义,并且在调试器中几次运行此类指令,没有帮助,你必须问。只需添加你的想法和什么词让你感到困惑。

+0

肯定是懒惰的,但我一直试图通过这个代码3天,所以我可能只是不明白的基本指导方针。而且这个项目已经给出了如果我模拟一个CPU炸弹爆炸。我会尝试输入三个不同的值,但可能是这样做的方式。谢谢。 –

+0

@SnigdaaSethuram我的意思是“模仿”在你的脑海。你有清单,所以你可以执行你的想法中的每一条指令(很可能在纸张的帮助下将“CPU”状态保持在某个地方:))。尽管为深度“9”做完整的'func4'递归将是一件很乏味的工作。如果你真的可以在gdb中运行这些代码,那么只需在'call'后面放置断点,然后进入几次迭代就可以很容易地看到它的工作方式,然后让它运行到断点并检查结果值。 – Ped7g

+0

更新:看起来第二个输入必须在2到4之间。我也测试了第二个输入的所有三个值,但是对于所有三个值,我在最后得到%esp的值为9,这是有道理的,因为有一条线将9移入该寄存器。我不明白的是,第一个输入是如何相关的,以及我们将如何特别匹配eax,因为3个输入中没有一个给出9%的结果值%esp。 –