# ciscn2022_syscall
程序的漏洞点在于 free 后不会清空 size 数组对应的数据,而且在同一个该位置再次申请一个 chunk 的时候,
1 | else if ( choice == 17 ) // malloc |
// 如果是就会跳转,而下面则是记录这次我们申请的 size,这里一旦跳转,size 数组不会被更改,可能存在溢出。如上一次我们在这个位置放的堆块,申请的 size 是 0x28, 下一次我们申请的是 0x10,数据为 DEADBEEF,这里的 size 依旧是 0x28,造成溢出。
思路
1 | add(0x28,'A'*0x28) #0 |
申请出来四个 chunk,size 数组都是为 0x28
然后申请 4 个 0x10,数据为 DEADBEEF
1 | def new_add(): |
这里就会造成溢出。先后释放 2,1,两个 chunk 进入 tcache,并且 1 对应的 chunk 的 fd 指针指向 2,chunk0 只有 0x20。我们输出 chunk0,一共输出 0x28 字节,将 chunk1 的 fd 指针泄露出来,就完成了堆地址的泄露。
1 | free(2) |
接下来,我们修改 chunk3 的头部,将其 size 从 0x21 改为 largebin 的大小范围,free (3) 令其进入 unsortedbins,我们在申请时,不要覆盖掉原本的 bk 指针就可以泄露出 libc 的地址。
这里 free (3) 要绕过检查,所以我们将伪造他的下一个 chunk 的 size。先后释放 2,1, 使 chunk1 的 fd 指向 chunk2,利用 chunk0 的溢出,修改 chnnk1 的 fd,使其指向我们的目标地址。将伪造的 chunk3 的下一个堆的头写为合法的大小。同时这个伪造的 chunk 的下一堆的 size 也要合法,但是我们只能写 0x28 字节,所以我们将第一个伪造成 0x11,
1 | new_add() #1 0x370 |
现在 chunk3 就可以正常 free,绕过检查。我们从 unsortedbins 上申请一个 chunk,完成 libc 的泄露
1 | free(3) |
后面就是我们修改__free_hook 数据为 system 地址,触发 getshell
同样的手法。chunk0 修改 chunk1 的 fd,只不过这次是先后释放 3,1,chunk1 原本指向 chunk3
1 | system = libcbase+ libc.sym['system'] |
getflag
完整 exp
1 | from pwn import * |