6.1.28 pwn ASISCTF2016 b00ks

下载文件

题目复现

$ file b00ks
b00ks: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=cdcd9edea919e679ace66ad54da9281d3eb09270, stripped
$ checksec -f b00ks
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FORTIFY Fortified Fortifiable  FILE
Full RELRO      No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   No      0               2       b00ks
$ strings libc-2.23.so | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu10) stable release version 2.23, by Roland McGrath et al.
Compiled by GNU CC version 5.4.0 20160609.

64 位程序,开启了 FULL RELRO、NX 和 PIE。

在 Ubuntu 16.04 上玩一下:

$ ./b00ks
Welcome to ASISCTF book library
Enter author name: AAAA

1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 1

Enter book name size: 5
Enter book name (Max 32 chars): BBBBB

Enter book description size: 5
Enter book description: CCCCC

1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 3
Enter the book id you want to edit: 1
Enter new book description: DDDDD

1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 4
ID: 1
Name: BBBBB
Description: DDDDD
Author: AAAA

1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 2
Enter the book id you want to delete: 1

1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 5
Enter author name: EEEE

1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 6
Thanks to use our library software

程序让我们先输入一个 auther name,然后进入菜单,可以新建、删除、修改和打印一个 book,还可以对 author name 进行修改。

题目解析

Enter author name

程序首先调用函数 read_9f5() 读入 author name 到 [0x00202018],即 0x00202040

函数 read_9f5() 如下:

该函数存在单字节溢出漏洞,例如在读入 author name 的时候,arg2 为 0x20,但却可以读入最多 0x21 个字节,读入完成后将最后一个字节设置为 “\x00”,即溢出了一个字节的 null byte。

Create

Create 过程是首先在堆上为 name 分配空间,然后为 description 分配空间,最后为 book 结构体分配空间。其中 name 和 description 的大小是由输入控制的,book 结构体则固定为 0x20 字节。

通过分析可以得到下面的数据结构:

其中 books 数组的起始地址为 0x00202060

漏洞利用

现在我们已经知道漏洞点是在读入 author name 的时候存在一个 off-by-one 漏洞。另外由于 author name 和 books 之间距离正好为 0x00202060 - 0x00202040 = 0x20,并且 books 是在 author name 之后创建,所以如果 author name 恰好为 0x20 个字节,那么在 Print 的时候存在信息泄露。接下来如果对 author name 进行修改,且仍然为 0x20 字节,则溢出的一个空字节将覆盖掉 books[0] 的低位字节。

思路如下:

  1. 创建两个 book,其中要使第二个 book 的 name 和 description 通过 mmap 分配(请求一块很大的空间),这是因为 mmap 分配的空间与 libc 基址存在固定关系,后续将通过泄露这些地址得到 libc 基址。

  2. 通过 Print,利用信息泄露漏洞得到 book1 在 heap 上的地址,从而计算得到 book2 的地址。

  3. 通过 Edit 在 book1->description 中创建一个 fake book,其 fake->description 指向 book2->name。

  4. 通过 Change author name 造成空字节溢出,使 books[0] 指向伪造的 fake book。

  5. 再次通过 Print 即可打印出 book2->name,这是一个通过 mmap 得到的指针,于是计算出 libc 基址。

  6. 先 Edit 操作 fake book,将 book2->description 修改为 __free_hook 的地址,然后 Edit 操作 book2,即可将 __free_hook 修改为 one_gadget。

  7. 此时 Delete book2,即可执行 one_gadget 获得 shell。

leak_heap

创建两个 book,此时内存布局如下:

可以看到 book2 通过 mmap 分配的两个指针并不是指向 heap,而是与 libc 有某种固定关系:

leak_libc

接下来先是伪造 fake book,然后通过空字节溢出,修改了 books[0] 的低位字节,此时它指向了 fake book。而 fake->description 指向了 book2->name。

通过 Print 即可打印出 book2->name,进而计算出 libc 基址。

overwrite

依次修改 fake book 和 book2,最终将 __free_hook 修改为 one_gadget:

pwn

最后 Delete book2,获得 shell。

开启 ASLR,Bingo!!!

exploit

完整的 exp 如下:

参考资料

Last updated

Was this helpful?