亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

CSAPP Lab2: Binary Bomb

2024-06-28 13:20:37
字體:
來源:轉載
供稿:網友
CSAPP Lab2: Binary Bomb

著名的CSAPP實驗:二進制炸彈

就是通過gdb和反匯編猜測程序意圖,共有6關和一個隱藏關卡

只有輸入正確的字符串才能過關,否則會程序會bomb終止運行

隱藏關卡需要輸入特定字符串方會開啟

實驗材料下載地址:http://csapp.cs.cmu.edu/2e/labs.html

下面通關解法:

反匯編:

objdump -d bomb > bomb_assembly_32.S

Phase 1:

打開bomb_assembly_32.S,定位到<phase_1>函數,可以看到以下代碼:

 1     8048b26:    8b 45 08                 mov    0x8(%ebp),%eax 2  3     8048b29:    83 c4 f8                 add    $0xfffffff8,%esp 4  5     8048b2c:    68 c0 97 04 08           push   $0x80497c0 6  7     8048b31:    50                       push   %eax 8  9     8048b32:    e8 f9 04 00 00           call   8049030 <strings_not_equal>10 11     8048b37:    83 c4 10                 add    $0x10,%esp12 13     8048b3a:    85 c0                    test   %eax,%eax14 15     8048b3c:    74 05                    je     8048b43 <phase_1+0x23>16 17     8048b3e:    e8 b9 09 00 00           call   80494fc <explode_bomb>

可以看出,用戶輸入字串指針保存在0x8(%ebp), <phase_1>把此指針放入eax,

然后把$0x80497c0壓棧,再把eax也就是用戶字串指針壓棧,

然后調用<strings_not_equal>

待<strings_not_equal>返回后,測試返回值,

若equal則進入下一phase,否則<explode_bomb>

從<strings_not_equal>可知該函數用于比較兩函數的值,因此需要兩個字串作為輸入,

上面代碼中,push %eax用于傳遞用戶字串指針,

則push $0x80497c0自然是傳遞比較字串的指針了.

打開gdb,x/s 0x80497c0, 可以直接查看到該指針指向的子符串:

Public speaking is very easy.

Phase 2:

打開bomb_assembly_32.S,定位到<phase_2>函數,留意以下幾行:

 1     8048b50:    8b 55 08                 mov    0x8(%ebp),%edx 2  3     8048b53:    83 c4 f8                 add    $0xfffffff8,%esp 4  5     8048b56:    8d 45 e8                 lea    -0x18(%ebp),%eax 6  7     8048b59:    50                       push   %eax 8  9     8048b5a:    52                       push   %edx10 11     8048b5b:    e8 78 04 00 00           call   8048fd8 <read_six_numbers>

mov 0x8(%ebp),%edx 將用戶字串指針存入edx,

lea -0x18(%ebp),%eax 把ebp-0x18這個地址存入eax,

則最后三句

push %eax

push %edx

call 8048fd8 <read_six_numbers>

相當于read_six_numbers( 用戶字串指針地址, ebp-0x18 )

現在我們切換到<read_six_numbers>,看看這個函數是干什么的:

先來看下面2行:

1     8048fde:    8b 4d 08                 mov    0x8(%ebp),%ecx2 3     8048fe1:    8b 55 0c                 mov    0xc(%ebp),%edx

把用戶字串指針存入ecx, ebp-0x18存入edx

往下看:

1     8048fe4:    8d 42 14                 lea    0x14(%edx),%eax

eax存入了 edx+0x14 這個值

再往下:

 1     8048fe7:    50                       push   %eax 2  3     8048fe8:    8d 42 10                 lea    0x10(%edx),%eax 4  5     8048feb:    50                       push   %eax 6  7     8048fec:    8d 42 0c                 lea    0xc(%edx),%eax 8  9     8048fef:    50                       push   %eax10 11     8048ff0:    8d 42 08                 lea    0x8(%edx),%eax12 13     8048ff3:    50                       push   %eax14 15     8048ff4:    8d 42 04                 lea    0x4(%edx),%eax16 17     8048ff7:    50                       push   %eax18 19     8048ff8:    52                       push   %edx

上面幾行依次把 edx+0x14, edx+0x10, edx+0xc, edx+0x8, edx+4, edx 這6個地址值壓棧

注意edx是<phase_2>的stack frame的 ebp-0x18 這個地址值

1     8048ff9:    68 1b 9b 04 08           push   $0x8049b1b2 3     8048ffe:    51                       push   %ecx4 5     8048fff:    e8 5c f8 ff ff           call   8048860 <sscanf@plt>

前2行把 $0x8049b1b 和 ecx(用戶字串指針) 壓棧, 然后調用sscanf

sscanf的原型是int sscanf(const char *str, const char *format, ...);

按format的格式解釋str,然后把得到的值放入后面省略號所代表的變量中

因此, 按剛才壓棧的順序, str是用戶輸入字串, $0x8049b1b 是format的地址,

edx, edx+4,...,edx+0x14是對應的變量.

先用gdb查看format, x/s $0x8049b1b, "%d %d %d %d %d %d".

可知,需要從用戶字串中提取6個整數,存入(edx)--(edx+0x14)中.

綜上, <read_six_numbers> 作用就是從用戶字串中提取6個數字, 存入<phase_2>stack frame中的(ebp-0x18)中

回到<phase_2>接著看:

1     8048b63:    83 7d e8 01              cmpl   $0x1,-0x18(%ebp)2 3     8048b67:    74 05                    je     8048b6e <phase_2+0x26>4 5     8048b69:    e8 8e 09 00 00           call   80494fc <explode_bomb>

測試(ebp-0x18)是否等于1, 不等則bomb, 因此用戶輸入的第一個數字應為1.

1     8048b6e:    bb 01 00 00 00           mov    $0x1,%ebx2 3     8048b73:    8d 75 e8                 lea    -0x18(%ebp),%esi

令ebx=1, esi = ebp-18

 1     8048b76:    8d 43 01                 lea    0x1(%ebx),%eax 2  3     8048b79:    0f af 44 9e fc           imul   -0x4(%esi,%ebx,4),%eax 4  5     8048b7e:    39 04 9e                 cmp    %eax,(%esi,%ebx,4) 6  7     8048b81:    74 05                    je     8048b88 <phase_2+0x40> 8  9     8048b83:    e8 74 09 00 00           call   80494fc <explode_bomb>10 11     8048b88:    43                       inc    %ebx12 13     8048b89:    83 fb 05                 cmp    $0x5,%ebx14 15     8048b8c:    7e e8                    jle    8048b76 <phase_2+0x2e>

注意, esi是存放6個數字中第1數字的地址,

因此 -0x4(%esi,%ebx,4) 表示第ebx個數字,

(%esi,ebx,4)表示第ebx+1個數字

因此上面第3-6行代碼檢查 a[ebx]*(ebx+1) == a[ebx+1], 其中a[n]表示第n個數字

若不等則bomb,否則ebx增1并循環

因此<phase_2>需要輸入一個數列, a[1]=1, a[n+1] = a[n]*(n+1), n<=6

1, 2, 6, 24, 120, 720

Phase 3:

打開bomb_assembly_32.S,定位到<phase_3>函數,可以看到以下代碼:

 1     ;; edx stores pointer of user input 2  3     8048b9f:    8b 55 08                 mov    0x8(%ebp),%edx 4  5     8048ba2:    83 c4 f4                 add    $0xfffffff4,%esp 6  7     ;; push ebp-4 onto stack 8  9     8048ba5:    8d 45 fc                 lea    -0x4(%ebp),%eax10 11     8048ba8:    50                       push   %eax12 13     ;; push ebp-5 onto stack14 15     8048ba9:    8d 45 fb                 lea    -0x5(%ebp),%eax16 17     8048bac:    50                       push   %eax18 19     ;; push ebp-12 onto stack20 21     8048bad:    8d 45 f4                 lea    -0xc(%ebp),%eax22 23     8048bb0:    50                       push   %eax24 25     ;; push $0x80497de onto stack26 27     ;; gdb x/s 0x80497de: "%d %c %d"28 29     8048bb1:    68 de 97 04 08           push   $0x80497de30 31     ;; push pointer of user input onto stack32 33     8048bb6:    52                       push   %edx34 35     8048bb7:    e8 a4 fc ff ff           call   8048860 <sscanf@plt>

具體代碼請看注釋,一開始主要是sscanf(用戶字串指針, "%d %c %d", ebp-12, ebp-5, ebp-4)

繼續看下去:

 1     ;; (ebp-12) stores the first int, compare to 7 2  3     ;; cmpl takes (ebp-12) as unsigned int 4  5     8048bc9:    83 7d f4 07              cmpl   $0x7,-0xc(%ebp) 6  7     ;; (unsigned)(ebp-12) > 7, jump to 0x8048c88, which will bomb 8  9     8048bcd:    0f 87 b5 00 00 00        ja     8048c88 <phase_3+0xf0>10 11     ;; jump to *( 0x80497e8 + 4*(the first int) )12 13     8048bd3:    8b 45 f4                 mov    -0xc(%ebp),%eax14 15     8048bd6:    ff 24 85 e8 97 04 08     jmp    *0x80497e8(,%eax,4)

關鍵在于最后的跳轉,根據輸入的第一個整數確定跳轉地址,

地址存儲在(0x80497e8 + 4*(the first int)).

容易聯想到(0x80497e8)存儲著一個跳轉表,用gdb查看之,x/10wx 0x80497e8:

    0x80497e8:    0x08048be0    0x08048c00    0x08048c16    0x08048c28    0x80497f8:    0x08048c40    0x08048c52    0x08048c64    0x08048c76    0x8049808:    0x67006425    0x746e6169

可以看到表中有很多個地址,先來看第一個地址指向的語句(對應的輸入整數為0):

 1     ;; bl = 0x71 2  3     8048be0:    b3 71                    mov    $0x71,%bl 4  5     ;; if 0x309==777==the last int, 6  7     ;; jump to 0x8048c8f, which will compare the char 8  9     8048be2:    81 7d fc 09 03 00 00     cmpl   $0x309,-0x4(%ebp)10 11     8048be9:    0f 84 a0 00 00 00        je     8048c8f <phase_3+0xf7>12 13     8048bef:    e8 08 09 00 00           call   80494fc <explode_bomb>

可以看出,先把0x71存入bl,

然后若輸入的最后一個整數==777的話,則跳轉到0x8048c8f

 1     ;; after compare the last int, jump here 2  3     ;; bl = 0x71 = 'q', compare to the char 4  5     ;; if ==, jump to 0x8048c99, and leave this function 6  7     8048c8f:    3a 5d fb                 cmp    -0x5(%ebp),%bl 8  9     8048c92:    74 05                    je     8048c99 <phase_3+0x101>10 11     8048c94:    e8 63 08 00 00           call   80494fc <explode_bomb>

比較輸入的字符是否等于'q',若等于則defuse成功

因此,輸入應為: "0 q 777"

當然此題應該有不止一個答案,選擇跳轉表中不同的地址會導致不同的輸入.

Phase 4:

打開bomb_assembly_32.S,定位到<phase_4>函數,可以看到以下代碼:

 1     ;; edx = pointer of input string 2  3     8048ce6:    8b 55 08                 mov    0x8(%ebp),%edx 4  5     8048ce9:    83 c4 fc                 add    $0xfffffffc,%esp 6  7     ;; eax = ebp-4 8  9     8048cec:    8d 45 fc                 lea    -0x4(%ebp),%eax10 11     ;; push ebp-412 13     8048cef:    50                       push   %eax14 15     ;; push $0x804980816 17     ;; x/s 0x804980: "%d"18 19     8048cf0:    68 08 98 04 08           push   $0x804980820 21     ;; push pointer of input string22 23     8048cf5:    52                       push   %edx24 25     8048cf6:    e8 65 fb ff ff           call   8048860 <sscanf@plt>

就是讀入一個整數,存入ebp-4

 1  ;; func4( input_number ) 2  3     8048d11:    8b 45 fc                 mov    -0x4(%ebp),%eax 4  5     8048d14:    50                       push   %eax 6  7     8048d15:    e8 86 ff ff ff           call   8048ca0 <func4> 8  9 10 11     8048d1a:    83 c4 10                 add    $0x10,%esp12 13     ;; eax should contain the return value of <func4>14 15     ;; if eax == 0x37 == 55, defused16 17     8048d1d:    83 f8 37                 cmp    $0x37,%eax18 19     8048d20:    74 05                    je     8048d27 <phase_4+0x47>20 21     8048d22:    e8 d5 07 00 00           call   80494fc <explode_bomb>

然后比較 func4( input_number )==55, 若等于則成功defuse.

接下來看看<func4>:

 1     ;; ebx = input_number 2  3     8048ca8:    8b 5d 08                 mov    0x8(%ebp),%ebx 4  5     ;; if input_number<=1, <func4> return 1 6  7     8048cab:    83 fb 01                 cmp    $0x1,%ebx 8  9     8048cae:    7e 20                    jle    8048cd0 <func4+0x30>10 11 12 13     8048cb0:    83 c4 f4                 add    $0xfffffff4,%esp14 15     ;; esi == func4( input_number-1 )16 17     8048cb3:    8d 43 ff                 lea    -0x1(%ebx),%eax18 19     8048cb6:    50                       push   %eax20 21     8048cb7:    e8 e4 ff ff ff           call   8048ca0 <func4>22 23     8048cbc:    89 c6                    mov    %eax,%esi24 25 26 27     8048cbe:    83 c4 f4                 add    $0xfffffff4,%esp28 29 30 31     ;; esi += func4( input_number-2 )32 33     8048cc1:    8d 43 fe                 lea    -0x2(%ebx),%eax34 35     8048cc4:    50                       push   %eax36 37     8048cc5:    e8 d6 ff ff ff           call   8048ca0 <func4>38 39     8048cca:    01 f0                    add    %esi,%eax

很明顯是Fibonacci數列, func4(n) = func4(n-1) + func4(n-2)

注意f(0)=f(1)=1, 通過簡單計算知f(9)=55

因此輸入應為55

Phase 5:

打開bomb_assembly_32.S,定位到<phase_5>函數,可以看到以下代碼:

 1     ;; ebx = pointer of input 2  3     ;; push ebx onto stack 4  5     ;; call string_length 6  7     8048d34:    8b 5d 08                 mov    0x8(%ebp),%ebx 8  9     8048d37:    83 c4 f4                 add    $0xfffffff4,%esp10 11     8048d3a:    53                       push   %ebx12 13     8048d3b:    e8 d8 02 00 00           call   8049018 <string_length>14 15 16 17     8048d40:    83 c4 10                 add    $0x10,%esp18 19     ;; eax stores the return value of string_length20 21     ;; if eax == 6, jump to 0x8048d4d 22 23     8048d43:    83 f8 06                 cmp    $0x6,%eax24 25     8048d46:    74 05                    je     8048d4d <phase_5+0x21>26 27     8048d48:    e8 af 07 00 00           call   80494fc <explode_bomb>

從上面代碼可知,輸入需要6個字符.

 1     ;; edx = 0 2  3     8048d4d:    31 d2                    xor    %edx,%edx 4  5     ;; ecx = ebp-8 6  7     8048d4f:    8d 4d f8                 lea    -0x8(%ebp),%ecx 8  9     ;; esi = 0x804b22010 11     8048d52:    be 20 b2 04 08           mov    $0x804b220,%esi12 13     ;; edx is a counter from 0 to 514 15     ;; al = (edx + ebx), then al reads a char each time16 17     8048d57:    8a 04 1a                 mov    (%edx,%ebx,1),%al18 19     ;; extract the low 4 bit of al20 21     8048d5a:    24 0f                    and    $0xf,%al22 23     ;; sign-extend al to eax24 25     8048d5c:    0f be c0                 movsbl %al,%eax26 27     ;; al = ( eax + 0x804b220 )28 29     ;; x/16c 0x804b220:30 31     ;; 0x804b220:    105 'i'    115 's'    114 'r'    118 'v'    101 'e'    97 'a'    119 'w'    104 'h'32 33     ;; 0x804b228:    111 'o'    98 'b'    112 'p'    110 'n'    117 'u'    116 't'    102 'f'    103 'g'34 35     8048d5f:    8a 04 30                 mov    (%eax,%esi,1),%al36 37     ;; edx + ecx = al,38 39     ;; notice that, ecx = ebp-840 41     ;; and edx is a counter from 0 to 542 43     8048d62:    88 04 0a                 mov    %al,(%edx,%ecx,1)44 45     8048d65:    42                       inc    %edx46 47     ;; loop48 49     8048d66:    83 fa 05                 cmp    $0x5,%edx50 51     8048d69:    7e ec                    jle    8048d57 <phase_5+0x2b>52 53 54 55     ;; ebp-2 = 0, a terminal of string started from ebp-856 57     8048d6b:    c6 45 fe 00              movb   $0x0,-0x2(%ebp)58 59     8048d6f:    83 c4 f8                 add    $0xfffffff8,%esp

上面代碼的作用是循環讀取6個輸入字符中的每一字符input[k],

提取input[k]的低四位,把這四位構成的整數index當作索引,

查找0x804b220開始16個字節中存儲的字符.

用gdb查看, x/16c 0x804b220:

1     0x804b220:    105 'i'    115 's'    114 'r'    118 'v'    101 'e'    97 'a'    119 'w'    104 'h'2 3     0x804b228:    111 'o'    98 'b'    112 'p'    110 'n'    117 'u'    116 't'    102 'f'    103 'g'

獲取0x804b220[ input[k] & 0xf ]后,將之copy至 (ebp-8)[k]

繼續看:

 1     ;; x/s 0x804980b: "giants" 2  3     ;; push "giants" 4  5     8048d72:    68 0b 98 04 08           push   $0x804980b 6  7     ;; push ebp-8 8  9     8048d77:    8d 45 f8                 lea    -0x8(%ebp),%eax10 11     8048d7a:    50                       push   %eax12 13     ;; compare "giants" and the string started from ebp-814 15     8048d7b:    e8 b0 02 00 00           call   8049030 <strings_not_equal>16 17     8048d80:    83 c4 10                 add    $0x10,%esp18 19     8048d83:    85 c0                    test   %eax,%eax20 21     ;; if two strings equal to each other, defused22 23     8048d85:    74 05                    je     8048d8c <phase_5+0x60>24 25     8048d87:    e8 70 07 00 00           call   80494fc <explode_bomb>

上面代碼便是將ebp-18開始的字串和"giants"比較,若相等,則defused.

注意到 (ebp-18)[k] = 0x804b220[ input[k] & 0xf ]

1     0x804b220:    105 'i'    115 's'    114 'r'    118 'v'    101 'e'    97 'a'    119 'w'    104 'h'2 3     0x804b228:    111 'o'    98 'b'    112 'p'    110 'n'    117 'u'    116 't'    102 'f'    103 'g'

因此,

1     input[0]&0xf = 0xf, input[1]&0xf = 0x0,2 3     input[2]&0xf = 0x5, input[3]&0xf = 0xb,4 5     input[4]&0xf = 0xd, input[5]&0xf = 0x1,

只要輸入的各個字符的低四位符合上面就好,我個人選取了"opekma"

Phase 6:

寫得太復雜了,各種內外循環,各種跳轉,看得頭暈,日后有閑再看.

現在先把能看懂的部份寫出來:

 1     ;; edx = pointer of input 2  3     8048da1:    8b 55 08                 mov    0x8(%ebp),%edx 4  5     ;; (ebp-0x34) = $0x804b26c 6  7     8048da4:    c7 45 cc 6c b2 04 08     movl   $0x804b26c,-0x34(%ebp) 8  9     8048dab:    83 c4 f8                 add    $0xfffffff8,%esp10 11     ;; read six numbers from input,12 13     ;; and storse in the area started from ebp-1814 15     8048dae:    8d 45 e8                 lea    -0x18(%ebp),%eax16 17     8048db1:    50                       push   %eax18 19     8048db2:    52                       push   %edx20 21     8048db3:    e8 20 02 00 00           call   8048fd8 <read_six_numbers>

上面代碼就是從輸入讀入6個整數,存入ebp-0x18,

初步懷疑0x804b26c地址存放著一個鏈表.

 1     ;; edi = 0 2  3     8048db8:    31 ff                    xor    %edi,%edi 4  5     8048dba:    83 c4 10                 add    $0x10,%esp 6  7     8048dbd:    8d 76 00                 lea    0x0(%esi),%esi 8  9     ;; eax = (ebp-0x18 + 4*edi) = six-number[edi]10 11     ;; ebp-0x18 = the beginning address of the six numbers12 13     ;; edi is a counter from 0 to 514 15     8048dc0:    8d 45 e8                 lea    -0x18(%ebp),%eax16 17     8048dc3:    8b 04 b8                 mov    (%eax,%edi,4),%eax18 19     ;; eax = six-number[edi]-120 21     8048dc6:    48                       dec    %eax22 23     ;; if eax <= 5 , continue24 25     8048dc7:    83 f8 05                 cmp    $0x5,%eax26 27     8048dca:    76 05                    jbe    8048dd1 <phase_6+0x39>28 29     8048dcc:    e8 2b 07 00 00           call   80494fc <explode_bomb>30 31 32 33     ;; if edi+1 > 5, finish edi loop34 35     8048dd1:    8d 5f 01                 lea    0x1(%edi),%ebx36 37     8048dd4:    83 fb 05                 cmp    $0x5,%ebx38 39     8048dd7:    7f 23                    jg     8048dfc <phase_6+0x64>40 41 42 43     ;; (ebp-0x38) = edi*444 45     8048dd9:    8d 04 bd 00 00 00 00     lea    0x0(,%edi,4),%eax46 47     8048de0:    89 45 c8                 mov    %eax,-0x38(%ebp)48 49 50 51     ;; esi = ebp-18 = the beginning address of the six numbers52 53     8048de3:    8d 75 e8                 lea    -0x18(%ebp),%esi54 55     ;; edx = (ebp-0x38) = edi*456 57     ;; inner loops,58 59     ;; ebx is the counter from edi+1 to 560 61     8048de6:    8b 55 c8                 mov    -0x38(%ebp),%edx62 63     ;; eax = edx + esi = six-number[edi]64 65     8048de9:    8b 04 32                 mov    (%edx,%esi,1),%eax66 67     ;; compare six-number[edi] and six-number[edi+ebx]68 69     8048dec:    3b 04 9e                 cmp    (%esi,%ebx,4),%eax70 71     ;; if six-number[edi] != six-number[edi+1], continue72 73     8048def:    75 05                    jne    8048df6 <phase_6+0x5e>74 75     8048df1:    e8 06 07 00 00           call   80494fc <explode_bomb>76 77     ;; ebx++78 79     ;; if ebx<=5, jump to 0x8048de6, ebx loops80 81     ;; else , finish ebx loop82 83     8048df6:    43                       inc    %ebx84 85     8048df7:    83 fb 05                 cmp    $0x5,%ebx86 87     8048dfa:    7e ea                    jle    8048de6 <phase_6+0x4e>

內外兩層循環,外層用edi計數,確保輸入的6個整數不大于6,

內層用ebx計數,保證所有數字兩兩不相等.

再往后的代碼異?;靵y,各種鏈表離歷,沒空看....

先從網上獲得答案:4 2 6 3 1 5

Secret Phase:

首先要找到<secret_phase>的入口,經搜索發現入口是在<phase_defused>里面.

先來看看<phase_defused>:

1     ;; every time call read_line, ( 0x804b480 )++2 3     ;; only with 6 correct answer given ,will the secret phase appear4 5     8049533:    83 3d 80 b4 04 08 06     cmpl   $0x6,0x804b4806 7     804953a:    75 63                    jne    804959f <phase_defused+0x73>

(0x804b480)是一個計數器,每當調用一次<read_line>每自增1,因此只有6關全通才能打開隱藏關卡.

 1     ;; push ebp-0x50 2  3     804953c:    8d 5d b0                 lea    -0x50(%ebp),%ebx 4  5     804953f:    53                       push   %ebx 6  7     ;; push ebp-0x54 8  9     8049540:    8d 45 ac                 lea    -0x54(%ebp),%eax10 11     8049543:    50                       push   %eax12 13     ;; (gdb) x/s 0x8049d0314 15     ;; 0x8049d03:    "%d %s"16 17     8049544:    68 03 9d 04 08           push   $0x8049d0318 19     ;; push the string stores in 0x804b77020 21     ;; the address of input of phase 422 23     8049549:    68 70 b7 04 08           push   $0x804b77024 25     804954e:    e8 0d f3 ff ff           call   8048860 <sscanf@plt>26 27 28 29     ....30 31     32 33     ;; (gdb) x/s 0x8049d0934 35     ;; 0x8049d09:    "austinpowers"36 37     804955e:    68 09 9d 04 08           push   $0x8049d0938 39     ;; push the %s40 41     8049563:    53                       push   %ebx42 43     8049564:    e8 c7 fa ff ff           call   8049030 <strings_not_equal>

省略號上方的代碼調用sscanf( (char *)0x804b770, "%d %s", (int *)(ebp-0x54), (char *)ebp-0x50 )

即從0x804b770讀入一個整數和字串.

再看省略號下方的代碼,比較讀入的字串和"austinpowers", 若相等,則打開<secret_phase>

好了,現在問題是,如何把一個整數和"austinpowers"寫入地址0x804b770?

回想前幾關,寫入字串都是通過read_line,所以猜想可能是在某一關的輸入中多輸入些內容以寫入地址0x804b770.

用gdb查看前幾關輸入字串的指針,發現第4關的輸入剛好是在地址0x804b770,而Phase 4只需輸入一個數字,因此只需

在第4關的輸入中多輸入一個"austinpowers"即可進入<secret_phase>.

現在看看<secret_phase>:

 1     8048eef:    e8 08 03 00 00           call   80491fc <read_line> 2  3  4  5     8048ef4:    6a 00                    push   $0x0 6  7  8  9     ;; strtol( user input string, 0, 10)10 11     ;; long int strtol(const char *nptr, char **endptr, int base);12 13     ;; converts the initial part of the string in nptr to a long integer value according to the given base14 15     8048ef6:    6a 0a                    push   $0xa16 17     8048ef8:    6a 00                    push   $0x018 19     8048efa:    50                       push   %eax20 21     8048efb:    e8 f0 f8 ff ff           call   80487f0 <__strtol_internal@plt>

首先,讀入一個字串,并用strtol將之轉換為long int.

 1     ;; if fun7( 0x804b320, the input long int ) 2  3     ;; x/d 0x804b320: (0x804b320) = 36 4  5     8048f17:    53                       push   %ebx 6  7     8048f18:    68 20 b3 04 08           push   $0x804b320 8  9     8048f1d:    e8 72 ff ff ff           call   8048e94 <fun7>10 11 12 13     8048f22:    83 c4 10                 add    $0x10,%esp14 15     ;; if fun7(0x804b320, the input long int) == 7, defused16 17     8048f25:    83 f8 07                 cmp    $0x7,%eax18 19     8048f28:    74 05                    je     8048f2f <secret_phase+0x47>20 21     8048f2a:    e8 cd 05 00 00           call   80494fc <explode_bomb>

代碼很簡單,調用fun7( (void *)0x804b320, 輸入的整數 ),若返回值==7, 則成功defused.

現在看看<fun7>:

  1     ;; edx = the first parameter, an address  2   3     8048e9a:    8b 55 08                 mov    0x8(%ebp),%edx  4   5     ;; eax = the input long int  6   7     8048e9d:    8b 45 0c                 mov    0xc(%ebp),%eax  8   9  10  11     ;; if edx != 0 12  13     8048ea0:    85 d2                    test   %edx,%edx 14  15     8048ea2:    75 0c                    jne    8048eb0 <fun7+0x1c> 16  17  18  19     8048ea4:    b8 ff ff ff ff           mov    $0xffffffff,%eax 20  21     8048ea9:    eb 37                    jmp    8048ee2 <fun7+0x4e> 22  23     8048eab:    90                       nop 24  25     8048eac:    8d 74 26 00              lea    0x0(%esi,%eiz,1),%esi 26  27  28  29     ;; if the input number >= (edx), jump to 0x8048ec5  30  31     8048eb0:    3b 02                    cmp    (%edx),%eax 32  33     8048eb2:    7d 11                    jge    8048ec5 <fun7+0x31> 34  35  36  37     ;; eax > (edx) 38  39     8048eb4:    83 c4 f8                 add    $0xfffffff8,%esp 40  41     ;; <func7>( (edx+4) ,the input long int ) 42  43     8048eb7:    50                       push   %eax 44  45     8048eb8:    8b 42 04                 mov    0x4(%edx),%eax 46  47     8048ebb:    50                       push   %eax 48  49     8048ebc:    e8 d3 ff ff ff           call   8048e94 <fun7> 50  51  52  53     ;; return eax *= 2, exit 54  55     8048ec1:    01 c0                    add    %eax,%eax 56  57     8048ec3:    eb 1d                    jmp    8048ee2 <fun7+0x4e> 58  59  60  61     ;; the input number >= (edx) 62  63     ;; if eax == (edx), return eax=0 64  65     8048ec5:    3b 02                    cmp    (%edx),%eax 66  67     8048ec7:    74 17                    je     8048ee0 <fun7+0x4c> 68  69  70  71     ;; the input number > (edx) 72  73     8048ec9:    83 c4 f8                 add    $0xfffffff8,%esp 74  75     ;; <fun7>( (edx+8) ,the input long int ) 76  77     8048ecc:    50                       push   %eax 78  79     8048ecd:    8b 42 08                 mov    0x8(%edx),%eax 80  81     8048ed0:    50                       push   %eax 82  83     8048ed1:    e8 be ff ff ff           call   8048e94 <fun7> 84  85  86  87     ;; fun7 return 2*eax + 1 88  89     8048ed6:    01 c0                    add    %eax,%eax 90  91     8048ed8:    40                       inc    %eax 92  93     8048ed9:    eb 07                    jmp    8048ee2 <fun7+0x4e> 94  95  96  97     8048edb:    90                       nop 98  99     8048edc:    8d 74 26 00              lea    0x0(%esi,%eiz,1),%esi100 101 102 103     8048ee0:    31 c0                    xor    %eax,%eax

從上面代碼可看出函數原型是:fun7( void *address, long int number ).

    當 number == *(int*)address, fun7( address, number) = 0    當 number > *(int*)address, fun7( address, number) = 2*fun7( address+8, number ) + 1    當 number < *(int*)address, fun7( address, number) = 2*fun7( address+4, number )

從上面可以看出, 上面的address表示的是棵二叉樹(左子樹的值<父節點的值, 右子樹的值>父節點的值):

 1     struct BST 2  3     { 4  5         int num; 6  7         struct BST *left; 8  9         struct BST *right;10 11     } *bst;

則上面的遞推式可表示為:

    當 number == bst->num, fun7( bst, number ) = 0;    當 number > bst->num, fun7( bst, number ) = 2*fun7( bst->right, number ) + 1;    當 number < bst->num, fun7( bst, number ) = 2*fun7( bst->left, number );

鑒于<secret_phase>需要fun7( (struct BST *)0x804b320, number )返回7,一個奇數,所以第一步應該執行第二鐘情況,

又經觀察發現以下遞推規律:

        fun7( (struct BST *)0x804b320, number )    =   2 * fun7( (struct BST *)0x804b320->right, number ) + 1    =   2 * (2 * fun7( (struct BST *)0x804b320->right->right, number ) + 1) + 1    =   4 * fun7( (struct BST *)0x804b320->right->right, number ) + 3    =   4 * (2 * fun7( (struct BST *)0x804b320->right->right->right, number ) + 1) + 3    =   8 * fun7( (struct BST *)0x804b320->right->right->right, number ) + 7

因此當 number == (struct BST *)0x804b320->right->right->right->num, fun7便可返回7

用gdb查看,

    x/wx 0x804b320+8  ==>  0x0804b308     x/wx 0x804b308+8  ==>  0x0804b2d8    x/wx 0x804b2d8+8  ==>  0x0804b278    x/d  0x0804b278   ==>  1001

因此應輸入1001


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国内精品视频久久| 久久久999国产精品| 国产99久久久欧美黑人| 国产精品日韩电影| 国产日本欧美一区二区三区| 亚洲精品中文字幕有码专区| 欧美超级乱淫片喷水| 国产精品网站入口| 亚洲成人免费网站| 高清欧美性猛交xxxx| 国产精品私拍pans大尺度在线| 中文字幕亚洲欧美在线| 色狠狠久久aa北条麻妃| 欧亚精品中文字幕| 亚洲免费中文字幕| 亚洲国产成人久久| 欧美一级bbbbb性bbbb喷潮片| 国产精品中文字幕久久久| 国产精品久久久久久久7电影| 国产精品久久久久久久久久久久久久| 亚洲级视频在线观看免费1级| 亚洲欧洲日产国码av系列天堂| 亚洲福利在线播放| 亚洲欧美国产一区二区三区| 在线视频精品一| 成人精品在线视频| 91亚洲精品久久久久久久久久久久| 4438全国亚洲精品在线观看视频| 北条麻妃一区二区三区中文字幕| 日韩精品欧美激情| 日本精品久久久久影院| 亚洲欧美第一页| 精品国产福利在线| 国产精品久久久久999| 精品久久久久久久久久国产| 日韩极品精品视频免费观看| 97国产suv精品一区二区62| 欧洲精品毛片网站| 欧美性视频精品| 国产热re99久久6国产精品| 欧美大尺度在线观看| 亚洲欧美日韩天堂一区二区| 在线观看免费高清视频97| 精品国产一区二区三区四区在线观看| 精品日韩视频在线观看| 日韩av电影在线播放| 国内精品免费午夜毛片| 久久手机精品视频| 91精品国产91久久久久久| 精品国模在线视频| 国产欧美精品日韩精品| 亚洲乱亚洲乱妇无码| 亚洲欧美日韩国产精品| 亚洲欧美日韩一区二区在线| 日韩中文字幕精品视频| 国产久一一精品| 久久精视频免费在线久久完整在线看| 国产精品私拍pans大尺度在线| 国产成人精品视频| 91网站在线看| 精品国模在线视频| 国产免费一区视频观看免费| 精品久久久久久| 国产精品欧美一区二区三区奶水| 伊人久久大香线蕉av一区二区| 亚洲开心激情网| 欧美精品免费在线观看| 九九久久久久99精品| 日韩av中文字幕在线免费观看| 亚洲人成网在线播放| 国产成人一区二区| 欧美日韩黄色大片| 成人网在线视频| 欧美视频在线观看免费| 日韩综合中文字幕| 91免费视频网站| 国产精品久久久亚洲| 欧美激情中文字幕在线| 亚洲国产福利在线| 日韩电视剧在线观看免费网站| 国产亚洲精品高潮| 久久久久久久一区二区三区| 国产日韩欧美一二三区| 久久久久久久久久久成人| 97精品视频在线播放| 日韩风俗一区 二区| 久久午夜a级毛片| 亚洲欧美日韩天堂| 中文字幕最新精品| 色999日韩欧美国产| 亚洲欧美精品suv| 最好看的2019年中文视频| 亚洲精品中文字幕有码专区| 国产成人av网址| 久久久久久这里只有精品| 日韩欧美精品网址| 欧美国产欧美亚洲国产日韩mv天天看完整| 奇米4444一区二区三区| 欧美肥老太性生活视频| 97视频在线观看视频免费视频| 成人97在线观看视频| 91亚洲精品久久久久久久久久久久| 91精品在线影院| 91精品久久久久久久久久久| 久久九九精品99国产精品| 性欧美长视频免费观看不卡| 亚洲欧美国产高清va在线播| 久久久精品视频成人| 久久好看免费视频| 久久九九有精品国产23| 欧美激情区在线播放| 欧美第一淫aaasss性| 少妇激情综合网| 欧美一级高清免费播放| 91成人免费观看网站| 黑人巨大精品欧美一区二区一视频| 亚洲精品久久久久中文字幕二区| 亚洲欧美在线免费观看| 亚洲在线www| 国产精品海角社区在线观看| 亚洲精品永久免费精品| 久久网福利资源网站| 亚洲福利视频专区| 亚洲性日韩精品一区二区| 国产91精品久| 国产成人91久久精品| 国产91在线高潮白浆在线观看| 黑人巨大精品欧美一区二区免费| 久久91亚洲精品中文字幕奶水| 2019亚洲男人天堂| 欧洲永久精品大片ww免费漫画| 富二代精品短视频| 2023亚洲男人天堂| 国产va免费精品高清在线| 亚洲色图五月天| 国产婷婷97碰碰久久人人蜜臀| 久久手机精品视频| 91精品久久久久久久久久| 91夜夜揉人人捏人人添红杏| 高潮白浆女日韩av免费看| 欧美成人自拍视频| 国产欧美精品日韩精品| 亚洲色图25p| 国产999精品久久久| 91福利视频网| 欧美视频免费在线| 亚洲色图第一页| 亚洲男人的天堂网站| 成人免费视频在线观看超级碰| 日韩美女在线看| 丝袜一区二区三区| 日韩一区二区在线视频| 456国产精品| 91av在线视频观看| 欧美激情喷水视频| 国产精品第8页| 综合激情国产一区| 日韩电影中文字幕| 最新国产成人av网站网址麻豆| 国内精品久久久久久久久| 国产乱人伦真实精品视频| 色噜噜狠狠狠综合曰曰曰| 91精品啪在线观看麻豆免费| 国产精品一香蕉国产线看观看|