第二届校赛pwn题wp
PWN
这次校赛由我负责出pwn部分题目,也都挺简单的。
GGKING’s gift
本题是shellcode签到题,大致思路是在栈上写shellcode然后栈溢出返回到shellcode即可
来看具体wp
首先就是看保护

nx保护没开,看看是不是shellcode
首先看main函数

是GGKING把nx保护关了,感谢GGKING,我们发现程序把code设置成了可执行,所以就可以用shellcode
我们可以输入0x17的字节到code里,我们看看code是在哪里

我们在看看vuln是啥

我们发现可以输入0x100字节,所以可以溢出到返回地址,将返回地址设置到code处就可以执行shellcode了
注意这里我们只能输入0x17个字节的shellcode,所以pwntools自带的那个shellcode过大输入不进去可以百度下找找短点的shellcode
exp
1 | from pwn import * |

成功获得shell
热天text pro
上次新生赛出了这个ret2text,这里加个保护继续拿来用 大概思路是pie爆破
先看看保护

相比上次多开了pie
看看main函数

哇 是欢迎界面
点开vuln看看

哇 是最喜欢的栈溢出
发现旁边还有个func函数看看

哇 是最喜欢的system
点开shell看看是啥

哇 是最喜欢的pwn帝mowen
总体题目和上次一样 可以看到mowen是pwn帝 可以联系他的qq来获得flag 但真的重要的是后面的/bin/sh,看到/bin/sh前面有分号 这样在执行函数时前面一团乱的就不用管 真正执行的是system(/bin/sh)所以后门函数确定是这个 再看看这个后门函数地址在哪

找到了0x1294
那是不是直接栈溢出返回地址到这里就好了吗,错误的,我们前面看到了此题开了pie保护,那pie是啥呢百度一下你就知道
简单来说程序开启了 pie 保护,我们无法完全确定程序的地址 但是由于内存分页机制,程序地址最后 3个 16进制位是不会改变的 linux 下一个内存页为 0x1000 即(4KB) 所以是我们后三个16位进制是不会变的
我们动调看看返回地址

是0x555555555334
我们再看看func函数地址

是0x555555555273,后面三位是不同的,可惜了,如果只是最后两位不同那我们直接覆盖最后一个字节就行了,但是这里是三位不同那我们是要覆盖两个字节,但是倒数第4位是不确定的,所以我们不知道应该输入什么,(1273或者2273或者3273都有可能)这时候就需要爆破了,写个爆破脚本即可,注意接收
exp
1 | from pwn import * |
可能打一次没出,一次不够那就再来次
得到flag,”mowen找不到flag”

她不见了
照例看看保护

开启了Canary和NX保护。
看看第一个函数

是个输入然后用printf输出,没有溢出 可以联想到格式化字符串漏洞 由于开了canary保护,可以想到用printf泄露出来
那么canary是啥呢百度一下你就知道
简单来说就是防止缓冲区溢出 你栈溢出时候要保证canary没变,不然就会报错
那么格式化字符串漏洞又是啥呢百度一下你就知道
通过printf我们就可以利用
在程序中我们发现居然没有后门函数,这我要咋获得shell啊(可以通过ret2libc)

这里有喜欢的栈溢出
所以具体思路是利用secret()函数中的格式化字符串漏洞泄露Canary的地址,从而泄露出Canary的值;
利用SetString()函数泄露puts()函数的实际地址,进而计算libc基址、system()函数和/bin/sh字符串的地址;
构造栈结构,利用栈溢出来进行ret2libc攻击;

这里知道canary位于rbp-0x8位置 所以到时候覆盖到这里

通过打印输出的内容,从左到右数,可以知道格式化字符串的偏移量为6 这里如果不太清楚可以去百度搜索格式化字符串漏洞学习下
动调输入看看 断点断到printf

所以其实canary的偏移是39,用’%39$p’打印出来然后接收
1 | from pwn import * |
接下来,利用SetString()函数泄露puts()函数的实际地址,进而计算libc基址。
由于是64位程序,所以需要rdi寄存器
1 | ROPgadget --binary pwn --only "pop|ret" |

第一段payload
1 | from pwn import * |
但是请注意不要在本地打,因为我给你们的文件的libc和远程不一样,题目中我也提醒了以远程为主,所以我们是远程看puts的后三位
查询对应的libc库 https://libc.blukat.me/

看到是以0x6a0结尾

可以下载或者直接使用偏移
下载的话可以直接
1 | system_addr = libc_base + libc.symbols['system'] |
再和前面一样栈溢出即可
exp
1 | from pwn import * |
得到shell

想要成为原神高手
这是一个基本的堆题,有很多方法可以解,我试了下堆溢出任意地址写bss也可以,但我想考察的是unsortedbin attack,这里就讲解此方法。
一般的堆题都要先换下libc,更换为发放的2.23版本才行 具体更换方法百度一下你就知道
照例先看看保护

主页面写的很乱 将就着看

有四个选项,看着就像创建,编辑,删除,退出等功能
创建函数

编辑函数

这里发现编辑多少是由我们输入决定的 所以可以造成堆溢出
删除函数

这里发现还有个特别的选项

点开阳光青提发现是最喜欢的后门函数

哎呀,去洗了点阳光青提
所以思路就是让magic大于0x1314就行
这里就聊到了unsortedbin attack
Unsorted Bin Attack从字面上就可以看出,正合适一种针对Unsorted Bin机制的攻击手法。这种攻击手法实现的前提是能够控制挂进unsorted bin中的chunk的bk指针,在控制bk指针的情况下可以实现修改任意地址值为一个较大的数值。
1 | unsorted_chunks (av)->bk = bck; |
unsorted_chunk的bk指针指向的是它后一个被释放的chunk的块地址(bck),后一个被释放的chunk的fd指针指向的是unsorted_chunk的块地址。如果我们能够控制unsorted_chunk的bk,那么就意味着可以将unsorted_chunks (av),即unsorted_chunk的块地址写到任意可写地址内(具体知识可以百度搜索)
具体看题目讲解(我讲的每一步可以对照最下面的exp并且对应调试效果更佳)
我们首先先创建三个堆块

前两个用来溢出和构造,最后一个防止合并
接着我们释放1号堆块(注意我堆块是从0开始算,所以是第二个堆块)

1号堆块我特意搞了个0x80大小,这样释放就可以直接进入unsortedbin中,
然后我们堆溢出覆写堆块

我们将1号堆块的bk位置写入目标地址也就是magic-0x10 至于为啥是要减0x10后面解释(bk位置如果不知道的话可以先去了解堆结构)
查看下bins

我们就成功把1号堆块的bk位置写成了magic-0x10
前面浅浅介绍了unsortedbin attack 我们把位于unsortedbin的堆块(也就是1号堆块)的bk位置写成目标地址-0x10那么堆块申请之后目标地址-0x10位置的fd指针被赋值为了unsorted_chunk的块地址,相当于就是在目标地址填写了一个很大的值,满足了大于0x1314的条件

赋值成功,那么我们输入412后就可以进入阳光青提获取shell

恭喜你成为了mvp
exp
1 | from pwn import * |
题目总的来说都是比较简单的基础题,wp也特意写的比较详细,如果还有不懂的可以去问mowen师傅,不过mowen师傅很忙,基本还是得要靠大家自行理解学习。主要目的是让大家对pwn感兴趣,好好学习天天向上,(学好了然后带我躺赢)。








