2016hctf Writeup.md

本文记录了作者首次参加XCTF联赛的经历,分享了在WEB、RE、MISC等领域的解题思路和技巧,包括RESTFUL的参数解析、JavaScript混淆代码解密、PHP伪协议学习、逆向工程等挑战,以及参赛后的反思和成长。
摘要由CSDN通过智能技术生成

  第一次和同学以战队MiRag3参加XCTF联赛,经验不足,技术较弱,以后会加倍努力~!留个爪纪念一下~~

WEB

2099年的flag

直接burpsuit截断,修改消息请求头如下:

这里写图片描述

直接得到flag

RESTFUL

这里主要考察的是RESTFUL格式

index.php/参数/值

这里写图片描述

然后根据提示只要put money 大于 12450即可

这里写图片描述

兵者多诡


这里写图片描述

题目说明为上传图片,首先上传一个图片试试。点击上传图片,发现url

http://pics.hctf.io/home.php?fp=upload
在这里猜想为 include($fp+'.php') 典型的文件包含漏洞
现在可以利用 php:filter//当下源码了
源码:
//home.php

<?php  
error_reporting(0);

@session_start();
posix_setuid(1000);

$fp = empty($_GET['fp']) ? 'fail' : $_GET['fp'];
if(preg_match('/\.\./',$fp))
{
    die('No No No!');
}
if(preg_match('/rm/i',$_SERVER["QUERY_STRING"]))
{
    die();
}
?>
<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta charset="utf-8">
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <link href="css/jumbotron-narrow.css" rel="stylesheet">
    </head>
    <body>
        <div class="container">
            <div class="header clearfix">
                <nav>
                    <ul class="nav nav-pills pull-right">
                        <li role="presentation" class="active"><a href="home.php?key=hduisa123">Home</a></li>
                    </ul>
                </nav>
                <h3 class="text-muted">pictures</h3>
            </div>

            <div class="jumbotron">
                <h1>Pictures Storage</h1>
                <p class="lead">在这里上传您的图片,我们将为您保存</p>
                <form action="?fp=upload" method="POST" id="form" enctype="multipart/form-data">
                    <input type="file" id="image" name="image" class="btn btn-lg btn-success" style="margin-left: auto; margin-right: auto;">
                    <br>
                    <input type="submit" id="submit" name="submit" class="btn btn-lg btn-success" role="button" value="上传图片">
                </form>
            </div>
           </div> 
    </body>
</html>
<?php  
if($fp !== 'fail')
{
    if(!(include($fp.'.php')))
    {
        ?>
        <div class="alert alert-danger" role="alert">没有此页面</div>
        <?php
            exit;
    }
}
?>

home.php中找到了文件包含源码现在利用它来,上传恶意文件

  1. 首先想到的是挂图片马:发现菜刀连接不行
  2. 利用zip上传解压

这里其实考察的还是phar协议,可参考(http://www.hackdig.com/09/hack-26779.htm
具体可参考此writeup

方法

(1)制作1.php

http://pics.hctf.io/home.php?fp=phar://uploads/4213d630a939bd4fbc7dff432fc0ed4b76c01d1c.png/1

(3)应用菜刀直接连

这里写图片描述

得到flag

这里写图片描述

giligili

这道题是通过这道题改的,(https://github.com/sternze/CTF_writeups/blob/master/sCTF/2016_Q1/obfuscat/readme.md#here-we-go-the-second-word-inside-our-flag-is-iz)
深刻理解这个这个大神的题解是解决这道题的先决条件。
这道题就改了几个参数,其他几乎没有变。
这是一道JavaScript代码混淆,打开之后这样的
这里写图片描述

通过在中间那个框中输入flag,失败就会弹框报错,查看源码,其中有一段JS代码

<script type="text/javascript">
            // Come on and get flag:>
            var _ = { 0x4c19cff: "random", 0x4728122: "charCodeAt", 0x2138878: "substring", 0x3ca9c7b: "toString", 0x574030a: "eval", 0x270aba9: "indexOf", 0x221201f: function(_9) {
     var _8 = []; for (var _a = 0, _b = _9.length; _a < _b; _a++) { _8.push(Number(_9.charCodeAt(_a)).toString(16)); } return "0x" + _8.join(""); }, 0x240cb06: function(_2, _3) {
     var _4 = Math.max(_2.length, _3.length); var _7 = _2 + _3; var _6 = ""; for(var _5=0; _5<_4; _5++) { _6 += _7.charAt((_2.charCodeAt(_5%_2.length) ^ _3.charCodeAt(_5%_3.length)) % _4); } return _6; }, 0x5c623d0: function(_c, _d) {
     var _e = ""; for(var _f=0; _f<_d; _f++) { _e += _c; } return _e; } };
            var $ = [ 0x4c19cff, 0x3cfbd6c, 0xb3f970, 0x4b9257a, 0x1409cc7, 0x46e990e, 0x2138878, 0x1e1049, 0x164a1f9, 0x494c61f, 0x490f545, 0x51ecfcb, 0x4c7911a, 0x29f7b65, 0x4dde0e4, 0x49f889f, 0x5ebd02c, 0x556f342, 0x3f7f3f6, 0x11544aa, 0x53ed47d, 0x697a, 0x623f21c1, 0x5c623d0, 0x32e8f8b, 0x3ca9c7b, 0x367a49b, 0x360179b, 0x5c862d6, 0x30dc1af, 0x7797d1, 0x221201f, 0x5eb4345, 0x5e9baad, 0x39b3b47, 0x32f0b8f, 0x48554de, 0x3e8b5e8, 0x5e4f31f, 0x48a53a6, 0x270aba9, 0x240cb06, 0x574030a, 0x1618f3a, 0x271259f, 0x3a306e5, 0x1d33b46, 0x17c29b5, 0x1cf02f4, 0xeb896b ];
            var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
            function check() {
    
                var answer = document.getElementById("message").value;
                var correct = (function() {
    
                    try {
                        h = new MersenneTwister(parseInt(btoa(answer[_[$[6]]](0, 4)), 32));
                        e = h[_[$[""+ +[]]]]()*(""+{})[_[0x4728122]](0xc); for(var _1=0; _1<h.mti; _1++) { e ^= h.mt[_1]; }
                        l = new MersenneTwister(e), v = true;
                        l.random(); l.random(); l.random();
                        o = answer.split("_");
                        i = l.mt[~~(h.random()*$[0x1f])%0xff];
                        s = ["0x" + i[_[$[$.length/2]]](0x10), "0x" + e[_[$[$.length/2]]](0o20).split("-")[1]];
                        e =- (this[_[$[42]]](_[$[31]](o[1])) ^ s[0]); if (-e != $[21]) return false;
                        e ^= (this[_[$[42]]](_[$[31]](o[2])) ^ s[1]); if (-e != $[22]) return false; e -= 0x352c4a9b;
                        t = new MersenneTwister(Math.sqrt(-e));
                        h.random();
                        a = l.random();
                        t.random();
                        y = [ 0xb3f970, 0x4b9257a, 0x46e990e ].map(function(i) {
     return $[_[$[40]]](i)+ +1+ -1- +1; });
                        o[0] = o[0].substring(5); o[3] = o[3].substring(0, o[3].length - 1);
                        u = ~~~~~~~~~~~~~~~~(a * i); if (o[0].length > 5) return false;
                        a = parseInt(_[$[23]]("1", Math.max(o[0].length, o[3].length)), 3) ^ eval(_[$[31]](o[0]));
                        r = (h.random() * l.random() * t.random()) / (h.random() * l.random() * t.random());
                        e ^= ~r;
                        r = (h.random() / l.random() / t.random()) / (h.random() * l.random() * t.random());
                        e ^= ~~r;
                        a += _[$[31]](o[3].substring(o[3].length - 2)).split("x")[1]; if (parseInt(a.split("84")[1], $.length/2) != 0x4439feb) return false;
                        d = parseInt(a, 16) == (Math.pow(2, 16)+ -5+ "") + o[3].charCodeAt(o[3].length - 3).toString(16) + "53846" + (new Date().getFullYear() - 1 + "");
                        i = 0xffff;
                        n = (p = (f = _[$[23]](o[3].charAt(o[3].length - 4), 3)) == o[3].substring(1, 4));
                        g = 3;
                        t = _[$[23]](o[3].charAt(3), 3) == o[3].substring(5, 8) && o[3].charCodeAt(1) * o[0].charCodeAt(0) == 0x2ef3;
                        h = ((31249*g) & i).toString(16);
                        i = _[$[31]](o[3].split(f).join("").substring(0, 2)).split("x")[1];
                        s = i == h;
                        return (p & t & s & d) === 1 || (p & t & s & d) === true;
                    } catch (e) {
                        console.log("gg");
                        return false;
                    }
                })();
                document.getElementById("message").placeholder = correct ? "correct" : "wrong";
                if (correct) {
                    alert("Congratulations! you got it!");
                } else {
                    alert("Sorry, you are wrong...");
                }
            };
        </script>

这个题目的意思就是在主站输入你构造的flag,反馈你的构造的flag是否正确,首先尝试随意提交一个flag,显然报错
这里写图片描述
这就需要回到那段JavaScript代码了,通过这段代码就可以推测出flag,现在依次分析这段代码

首先从整体分析这个check()函数,可以看到有四处return false。这个函数通过分析输入的flag来判断flag对错,这四个return false就是分别用来判断flag中四个单词对错
所以首先构造hctf{xxxx_xx_xxxx_xxxxx},其中x代表位未知字母,每个单词字母长度时未知的,之所以中间用_符号连接,是应为有这句代码o = answer.split("_")(在64行)
先看这段代码

l.random(); l.random(); l.random();
o = answer.split("_");
i = l.mt[~~(h.random()*$[0x1f])%0xff];
s = ["0x" + i[_[$[$.length/2]]](0x10), "0x" + e[_[$[$.length/2]]](0o20).split("-")[1]];
e =- (this[_[$[42]]](_[$[31]](o[1])) ^ s[0]); if (-e != $[21]) return false;

把以上代码换成正常代码大概是这样的

e =- (this.eval(_[35725343](o[1])) ^ s[0]);
if (-e != $[21]) 
    return false;

仔细看看这个_[35725343],将35725343转为16进制,就是221201f,在代码中找一找
这里写图片描述
这是个函数,直接看writeup,这个函数可以写成

function toHexString(s) {
   
    var charArray = s.sp    lit('');
    var result = "0x";
    for(i = 0; i < charArray.length; i++) {
        result += s.charCodeAt(i).toString(16)
    }
    return result;
}

这个函数就是将输入的16进制参数转化为ASCLL字符,我们将在后面多次用到这个函数,利用这个函数在此改写刚才那个代码

e = - (this.eval(toHexString(o[1])) ^ 0x381f4862); 
if(-e != 941564184) 
    return false;    

所以this.eval(toHexString(o[1])) ^ 0x381f4862==941564184
计算得到
this.eval(toHexString(o[1]))=941564184^0x381f4862=27002
将这个数转为16进制再转为字符串,得flag第二个单词为iz,这里给出从10进制转为16进制再转为ascii字符的python代码

s=raw_input("input:")
s=hex(int(s))[2:]
ch=''
string=''
for i in range(0,len(s),2):
   ch=s[i]+s[i+1]
   string+=chr(int(ch,16))
print string

接下来接着看这段代码

e ^= (this[_[$[42]]](_[$[31]](o[2])) ^ s[1]); if (-e != $[22]) return false; e -= 0x352c4a9b;

根据writeup换成正常人可以看懂的代码

e
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值