
WangDing-2024
card_master
网鼎半决赛的一道pwn题
浅逆一下
程序模拟的是一套扑克牌,可以随机洗牌打乱。
set功能可以设置扑克牌有几个花色,每个花色有几张牌等。
case 3 是show功能,可以打印出设置的卡牌参数,
shuffle是随机打乱牌序(洗牌)。
show_card则是展示出所有手牌。
其中存储牌参数的结构体如下
1 | 00000000 struct struct_a1 // sizeof=0x28 |
漏洞点
在set功能中,我们可以设置牌的花色个数和每个花色的牌数,还可以自定义花色的输出(默认是♥♠♦♣)。
1 | if ( *a1->symble == byte_202010 ) |
但symble是默认时,程序会调用malloc分配一块内存存储我们自定义的花色。第二次修改时就是调用realloc分配内存。
下方有一处判断if ( v5 )
,但成功分配内存时,就更新结构体的symble指针,并读入数据。
回到realloc,查阅下源码,如下
1 | void * |
看起来很复杂(),主要逻辑就是如果传入的newsize不为0,就调用_int_realloc,为0就调用__libc_free,并返回0。
_int_realloc的主要逻辑就是判断oldsize和newsize的大小关系,然后进行malloc,memcpy,free。
故,我们传入的suit_size为0的话,程序相当于free(a1->symble),且因为v5为0,并不会进入到下面的*a1->symble = v5;
,会产生uaf漏洞。
构造payload
由于程序只有在symble是默认的时候才会调用malloc,所以需要malloc的时候必须先调用一次init恢复默认。
先是常规的uaf泄露地址
1 | add(0x10, 1, 1, b'\x80') # malloc |
由于在malloc一次后,使用的是realloc,所以通过修改tcache的next指针实现任意分配需要一点手法。
正常来说,uaf实现任意地址分配,首先构造A->B->A的链条,先malloc,分配到A,修改next,使链表变成B->A->C,C就是想要分配到的地址。
在本题中,如果我们使用malloc分配到A,那么后续都是realloc,比较难以继续利用。因此我们选择利用init里面的
1 | for ( i = 0; i <= 3; ++i ) |
*v0 = malloc(0xD0uLL);
,先伪造一个链表,让tcache里面有4个chunk,这样init后,剩下我们想要分配到的地址,这时候再set,malloc到的就是我们想分配到的那个地址了。
劫持show函数,写入one_gadget即可get shell
贴一个exp
1 | #!/usr/bin/env python3 |
你问我为什么没有决赛的wp?9分钟题就被秒了,这我打鸡毛(
- 标题: WangDing-2024
- 作者: InkeyP
- 创建于 : 2024-11-28 17:50:57
- 更新于 : 2025-03-14 14:13:48
- 链接: https://blog.inkey.top/202411/28/WangDing-2024/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。