zoukankan      html  css  js  c++  java
  • CSAPP:Binary Bomb

    本篇文章参考了:http://www.cnblogs.com/remlostime/archive/2011/05/21/2052708.html大神的文章,有时候没思路了会来看一下,但是保证本文的每个阶段都是自己独立思考后总结写出来的。

    Phase_1

    对于phase1,我们只要关注一下红色框两行的代码,分别是将内存0x8049678的处的字符串A和ebp+0x8处的字符串B作为参数来调用strings_not_equal子程序,那么这里的逻辑也很明了——要想知道要求我们输入的字符串,只要查看内存0x8049678处的字符串就可以了:


    读到phase_4终于想明白为啥DWORD PTR [ebp+0x8]代表的是子程序接受的参数了,子程序调用的模型如下图所示:


    ebp+0x4是跨越ebp的4个字节,再加4是跨越返回地址的4个单元,就是这样


    Phase_2

    首先我们还是关注红色的部分,phase_2将eax和[ebp+0x8]这两处的值作为参数传递给<read_six_numbers>子程序,在这里:push eax是因为phase_2在子程序调用后还要用到eax的值,而调用的子程序恰好也要用到eax的值,为了维护eax,caller选择将其压栈,这也是保存eax的一种方法;而[ebp+0x8]处的值则是程序从键盘上读取的我们的输入,作为调用phase_2的参数,而对于这个参数的安放,是整个phase_2最关键的地方!

    这两行是read_six_numbers子程序内部的两行代码,首先ebp+0x8处是传递给该子程序的参数,即phase_2的ebp+0x8,即我们键盘输入的6个数。然后该proc用sscanf从该输入中读取数据——放到哪里呢?
    没错,就是phase_2子程序的绿色一行,如果不加以严谨的测试,我们只通过看代码,黄色的一行设置esi的指定位置,以及后续的循环过程,都能帮助我们推测出read_six_numbers的sscanf函数就是将输入的字符串读取到了[ebp-0x20]这个位置

    如果最科学的做法应该是这样的:我们在绿线的那行设置断点,然后执行程序,然后对第2个函数的参数输入23 x x x x x,x是随机一个整数(不超过int范围),然后我们再观察[ebp-0x20]处的DWORD,就会发现这个值是23——这就证明了我们上面的猜测~


     Phase_3

    首先看刚开始的红色部分,都是作为调用sscanf函数的参数来压栈的,首先第一个红框不难看出是用来存储参数,那么那个内存地址里面是啥呢?观察一下就可以明了:

    没错,就是传递sscanf函数所需要的字符串格式的参数,然后我们从[ebp+0x8]所指向的内存中来读取我们所需要的内容到相应的位置即可
    还有一点需要注意,就是绿色框的switch选择语句,我们可以通过相应的指令显示出该内存地址后面的所有16进制内容:

    那么到底该选择哪一个呢,我们再看下面的黄色语句,他告诉我们其中一个参数的值是必须要小于等于5的,也就是eax*4<=20,即我们最多可以选择到0x8048bcc这条内存地址,然后从第一个地址到底6个地址任选一条来运算,求得的答案都可以通过phase_3,后面的算数过程没什么难度,就不细说了。


    Phase_4:

    同phase_3查看内存0x804996b处的值,可以看到是“%d”,可见sscanf是input读取一个数字的,这点通过后面的返回值eax也可以看出来。
    黄色框说明我们输入的这个数一定是个正数。
    绿色的框告诉我们func4(input)的返回值是144D(0x90),思路也很显而易见,我们关注func4函数的返回值即可

    这是func4函数的disassembly-code,首先棕色的框可以看出每次调用子程序用ebx来保存参数的值
    然后就是判断参数的值,如果大于1,就调转到偏移地址为20的地方,反之则跳转到50偏移地址处,中间具体的运算过程在下面给出:
    func(1):1
    return 1
     
    func(2):2
    esi = 0
    esi += func(1) = 0+1 = 1
    ebx = 2-2 = 0    NO
    return esi+1 = 1+1 = 2
     
    func(3):3
    esi = 0
    esi += func(2) = 0+2 = 2
    ebx = 3-2 = 1    NO
    return esi+1 = 2+1 = 3
     
    func(4):5
    esi = 0
    esi += func(3) = 0+3 = 3
    ebx = 4-2 = 2    OK
    esi += func(2-1) = 3+1 = 4
    ebx = 2-2 = 0    NO
    return esi+1 = 4+1 = 5
     
    func(5):8
    esi = 0
    esi += func(4) = 0+5 = 5
    ebx = 5-2 = 3    OK
    esi += func(3-1) = 5+2 = 7
    ebx = 3-2 = 1    NO
    return esi+1 = 7+1 = 8
     
    func(6):13
    esi = 0
    esi += func(5) = 0+8 = 8
    ebx = 6-2 = 4    OK
    esi += func(4-1) = 8+3 = 11
    ebx = 4-2 = 2    OK
    esi += func(2-1) = 11+1 = 12
    ebx = 2-2 = 0    NO
    return esi+1 = 12+1 = 13
     
    func(7):21
    esi = 0
    esi += func(6) = 0+13 = 13
    ebx = 7-2 = 5    OK
    esi += func(5-1) = 13+5 = 18
    ebx = 5-2 = 3    OK
    esi += func(3-1) = 18+2 = 20
    ebx = 3-2 = 1    NO
    return esi+1 = 20+1 = 21
     
    func(8):34
    esi = 0
    esi += func(7) = 0+21 = 21
    ebx = 8-2 = 6    OK
    esi += func(6-1) = 21+8 = 29
    ebx = 6-2 = 4    OK
    esi += func(4-1) = 29+3 = 32
    ebx = 4-2 = 2    OK
    esi += func(2-1) = 32+1 = 33
    ebx = 2-2 = 0    NO
    return esi+1 = 33+1 = 34
     
    func(9):55
    esi = 0
    esi += func(8) = 0+34 = 34
    ebx = 9-2 = 7    OK
    esi += func(7-1) = 34+13 = 47
    ebx = 7-2 = 5    OK
    esi += func(5-1) = 47+5 = 52
    ebx = 5-2 = 3    OK
    esi += func(3-1) = 52+2 = 54
    ebx = 3-2 = 1    NO
    return esi+1 = 54+1 = 55
     
    func(10):11
    esi = 0
    esi += func(9) = 0+55 = 55
    ebx = 10-2 = 8    OK
    esi += func(8-1) = 55+21 = 76
    ebx = 8-2 = 6    OK
    esi += func(6-1) = 76+8 = 84
    ebx = 6-2 = 4    OK
    esi += func(4-1) = 84+3 = 87
    ebx = 4-2 = 2    OK
    esi += func(2-1) = 87+1 = 88
    ebx = 2-2 = 0    NO
    return esi+1 = 88+1 = 89
     
    func(11):
    esi = 0
    esi += func(10) = 0+89 = 89
    ebx = 11-2 = 9    OK
    esi += func(9-1) = 89+34 = 123
    ebx = 9-2 = 7    OK
    esi += func(7-1) = 123+13 = 136
    ebx = 7-2 = 5    OK
    esi += func(5-1) = 136+5 = 141
    ebx = 5-2 = 3    OK
    esi += func(3-1) = 141+2 = 143
    ebx = 3-2 = 1    NO
    return esi+1 = 143+1 = 144
     
    一定要注意每次调用结束后esi的值都还要变回调用前的,也就是一直是0,这儿被坑了好久。。

    Phase_5:

    前面没什么好说的,绿色部分是循环体,作用是把phase_5的参数经过变换后转移到ecx所指向的地址中,edx作为循环变量从1到6

    很容易得知题目给我们的提示是转换后的字符串等于内存0x80496c2起始的内容,我们查看这个内容

    在这里转换后的字符没什么用,转换后的ASCII码是我们破解这层炸弹的关键,而每个ASCII码的获得如图一红色方框所示:
    先将原操作数的ASCII码存到eax中,然后保留其后四位,再将后四位当成偏移地址来寻找相应的新的ASCII码
    根据0x80496c2中的6个数字,我们可以反过来分别推出原来6个char的ASCII码的后四位,然后我们可以测出abcdef的ASCII码的后四位,发现是从0001开始增长的,这样可以列出a-z的后四位ASCII码,然后将相应的字符带入即可(此题有4种答案都是正确的)
     
    转换后        al           转换前
    116/t        1101        m        
    105/i        0000        p                
    116/t        1101        m        
    97/a        0101        e/u    
    110/n        1011        k        
    115/s        0001        a/q
    Phase_6:
    这题是对我智商的侮辱,我拒绝贴出来。
    secrete_phase:
    这个炸弹折腾了能有一个周,今天下午把第6个拆出来了,感觉对汇编的兴趣并不是太大,就没再做这个,不过我参考的文章里有对secrete_phase的详解释,大家可以去看。
     
     
     
  • 相关阅读:
    hdu 5366 简单递推
    hdu 5365 判断正方形
    hdu 3635 并查集
    hdu 4497 数论
    hdu5419 Victor and Toys
    hdu5426 Rikka with Game
    poj2074 Line of Sight
    hdu5425 Rikka with Tree II
    hdu5424 Rikka with Graph II
    poj1009 Edge Detection
  • 原文地址:https://www.cnblogs.com/immortal-worm/p/5499298.html
Copyright © 2011-2022 走看看