Preface

这个比赛的时候压根没看到。。

check

先看下基本信息

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX disabled
    PIE:      No PIE

32bit,got可覆盖'

Analysis

程序分为几个步骤

  1. 通过clone调用fn函数在子进程中运行,父进程则通过waitpid等待子进程执行结束
  2. 子进程又切换到jail目录下,然后又fork了个子进程,接下去调用chroot函数,接下去才调用真正的执行主要的函数
  3. vuln_main中首先调用函数取读两个文件,作为之后调用syscall的函数表来查看,并且两个文件对应x86和x64。在后面实际上x86提供的函数后面会给我们输入来进行调用
  4. 打印操作表,接受并执行相关操作

function list

主要有5个操作

set_syscall

获取syscall调用表到804E184(标记为tmp_syscall_ptr)

add_syscall

添加syscall。

  1. 读取名字,标号,参数个数
  2. 循环读取参数个数存放到结构体当中
  3. 修改804E174(s_e_sycall)中存放的syscall列表起始和结尾指针

有一个地方有点难理解,要分析和猜到或者调试了之后,知道程序结构之后才好理解,这里实际上就是对一个list的结尾指针进行操作,

call_syscall

.rodata:0804B4E0 off_804B4E0     dd offset ___cxa_pure_virtual

利用上面的函数进行实际函数调用。下面分析的struct中第一个就是

剩下的操作很简单了,pass

struct

主要有两个结构

struct rodata_804E174     // x86 syscall table
{
    struct *start;
    struct *end;
};

上面这个结构主要指向一个列表,列表里存的也是指针(有点像函数列表),每个指针指向下面这个结构体

struct sys_code
{
    uint4 rodata_804B4E0;  // 0  cxa_pure_virtual
    uint4 rodata_804E164;  // x64 or check overflow
    char *name;         // 8
    uint4 *rax;          // 12
    uint4 *rbx;
    uint4 *rcx;
    uint4 *rdx;
    uint4 *rsi;
    uint4 *rdi;
    uint4 *r9??;           // 40+(-1)*4
    char *number;       // 40+0*4
    char *arg1;         // 40+1*4
};

分析了挺久,主要是要结合具体的程序执行来分析比较方便

Vuln

整数溢出是很明显的

这里判断v5<=6,如果输入负数实际上就能绕过,接下来再输入 < v5的负数就行了。

这里是对struct sys_code中的argv进行添加,刚刚输入的arg index就是这里标的i,而再看看sys code 结构,控制i为负数就能覆盖到结构体前面的各个变量和参数了,不过要主要不能覆盖rodata_804E164,因为程序中好像有检查。这里很明显可以覆盖rodata_804B4E0,因为程序在后面call sys的时候就是调用其指向的rodata指向的函数。(rodata不可写,这里覆盖的是指针,所以是可以的)

Leak

具体如何覆盖的话,可以先试试。。具体的整个程序中的结构如下

 0x0804E168                 -------------------          -------------------
 0 start_ptr  ---------->   |    sys_code[0]  |------> 0 |   rodata_804B4E0  |
 4 end ptr             /    -------------------          -------------------
                   ----/    |    sys_code[1]  |        4 |   rodata_804E164  |
                  /         -------------------          -------------------          --------------------
                  |         |    sys_code[2]  |        8 |     *name_ptr     |------>|    string 'df..'  |
                  |         ------------------           -------------------          --------------------
                  |         |    sys_code[3]  |        C |      *eax_ptr     | -----\
                  |         -------------------           --------------------       \      --------------
            tmp_syscall_ptr                              |    .省略几个.      |        \--> |    '???''    |
                                                          --------------------              --------------
                                                      40 |     *number       |
                                                          --------------------
                                                      44 |     *arg1          |
                                                          -------------------

当调用第一个函数的时候,tmp_syscall_ptr就如图,指向第一个syscode块的指针,如果把rodata_804B4E0覆盖为plt.puts,那么puts就会输出sys code[0]的堆地址了!

results matching ""

    No results matching ""