BUUMisc通关2

真的很杂

知识点:APK反编译

参考这篇文章学习关于APK的知识

Android逆向基础----APK文件结构

APK文件结构:

apk文件实际是一个zip压缩包,可以通过解压缩工具解开。

META-INF目录 存放的是签名信息,用来保证apk包的完整性和系统的安全。
res目录 res是resource的缩写,这个目录存放资源文件
AndroidManifest.xml 是Android应用程序的配置文件,是一个用来描述Android应用“整体资讯”的设定文件, Android系统可以根据这个“自我介绍”完整地了解APK应用程序的资讯,每个Android应用程序都必须包含一个AndroidManifest.xml文件,且它的名字是固定的,不能修改。
classes.dex 传统的Java程序,首先先把Java文件编译成class文件,字节码都保存在了class文件中,Java虚拟机可以通过解释执行这些class文件。
resources.arsc 用来记录资源文件和资源ID之间的映射关系,用来根据资源ID寻找资源。

APK反编译工具

APK改之理(ApkIDE)v3.5.0 少月增强版

题目分析

题目给了一张 真的很杂.jpg

使用 binwalk -e 真的很杂.jpg ,解析文件得到一份文件包,得到了下面这些文件:

1
2
3
4
5
6
# resources.arsc
# classes.dex
# AndroidManifest.xml
# res目录
# META-INF目录
# 1438.zip

这里的 1438.zip 文件可以解压缩打开,和当前目录的文件是一样的。由apk文件实际是一个zip压缩包,可以通过解压缩工具解开。我们可以知道 1438.zip 应该为apk文件,改后缀为 .apk 用 APK IDE打开进行反编译。

image-20210703133351874

找到 flag{25f991b27fcdc2f7a82a2b34386e81c4}

image-20210703133506747

【QCTF2018】X-man-A face

知识点:二维码定位点缺失

二维码有三个定位点,通常出题人会让二维码定位点缺失或者反色。

定位点:左上,左下,右上

题目分析

直接用截屏软件截取定位点,然后补全空缺的,用微信扫二维码拿到 base32 编码,解码得到 flag:

Snipaste_2021-07-05_20-35-30

QCTF{Pretty_Sister_Who_Buys_Me_Lobster}

【MRCTF2020】pyFlag

知识点:zip文件,python解码base编码

题目分析

将三张图片用010editor打开,发现每张 jpg 的后面都有隐藏的 ZIP 信息:

1
2
Furan.jpg 
[Secret File Part 2:]

image-20210705210406506

1
2
Setsuna.jpg 
[Secret File Part 1:]

image-20210705210641030

1
2
Furan.jpg 
[Secret File Part 2:]

image-20210705210713501

将三张图的 zip 信息提取出来,按顺序排好,保存为 zip文件。

打开后发现是加密的 ,用 Ziperello 爆破密码,弱密码:1234

1
2
3
4
# .hint.txt
我用各种baseXX编码把flag套娃加密了你应该也有看出来
但我只用了一些常用的base编码哦毕竟我的智力水平你也知道...像什么base36base58听都没听过
提示0x10,0x20,0x30,0x55
1
2
# flag.txt
G&eOhGcq(ZG(t2*H8M3dG&wXiGcq(ZG&wXyG(j~tG&eOdGcq+aG(t5oG(j~qG&eIeGcq+aG)6Q<G(j~rG&eOdH9<5qG&eLvG(j~sG&nRdH9<8rG%++qG%__eG&eIeGc+|cG(t5oG(j~sG&eOlH9<8rH8C_qH9<8oG&eOhGc+_bG&eLvH9<8sG&eLgGcz?cG&3|sH8M3cG&eOtG%_?aG(t5oG(j~tG&wXxGcq+aH8V6sH9<8rG&eOhH9<5qG(<E-H8M3eG&wXiGcq(ZG)6Q<G(j~tG&eOtG%+<aG&wagG%__cG&eIeGcq+aG&M9uH8V6cG&eOlH9<8rG(<HrG(j~qG&eLcH9<8sG&wUwGek2)

根据提示,解码应该是 base85,base16,base32,base48,但感觉base48应该出题人写错了。最后用代码解的时候,发现应该是base64解码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import base64
s85 = 'G&eOhGcq(ZG(t2*H8M3dG&wXiGcq(ZG&wXyG(j~tG&eOdGcq+aG(t5oG(j~qG&eIeGcq+aG)6Q<G(j~rG&eOdH9<5qG&eLvG(j~sG&nRdH9<8rG%++qG%__eG&eIeGc+|cG(t5oG(j~sG&eOlH9<8rH8C_qH9<8oG&eOhGc+_bG&eLvH9<8sG&eLgGcz?cG&3|sH8M3cG&eOtG%_?aG(t5oG(j~tG&wXxGcq+aH8V6sH9<8rG&eOhH9<5qG(<E-H8M3eG&wXiGcq(ZG)6Q<G(j~tG&eOtG%+<aG&wagG%__cG&eIeGcq+aG&M9uH8V6cG&eOlH9<8rG(<HrG(j~qG&eLcH9<8sG&wUwGek2)'
m = base64.b85decode(s85)
# print(m)
# 475532444B4E525549453244494E4A57475132544B514A54473432544F4E4A5547515A44474D4A5648415A54414E4257473434544B514A5647595A54514D5A5147553444474D5A5547453355434E5254475A42444B514A57494D3254534D5A5447555A444D4E5256494532444F4E4A57475A41544952425547343254454E534447595A544D524A5447415A55493D3D3D'

s16 = '475532444B4E525549453244494E4A57475132544B514A54473432544F4E4A5547515A44474D4A5648415A54414E4257473434544B514A5647595A54514D5A5147553444474D5A5547453355434E5254475A42444B514A57494D3254534D5A5447555A444D4E5256494532444F4E4A57475A41544952425547343254454E534447595A544D524A5447415A55493D3D3D'
k = base64.b16decode(s16)
# print(k)

s32 = 'GU2DKNRUIE2DINJWGQ2TKQJTG42TONJUGQZDGMJVHAZTANBWG44TKQJVGYZTQMZQGU4DGMZUGE3UCNRTGZBDKQJWIM2TSMZTGUZDMNRVIE2DONJWGZATIRBUG42TENSDGYZTMRJTGAZUI==='
w = base64.b32decode(s32)
# print(w)

s16 = '54564A4456455A3757544231583046795A5638305833417A636B5A6C593352665A47566A4D47526C636E303D'
x = base64.b16decode(s16)
#print(x)

s64 = 'TVJDVEZ7WTB1X0FyZV80X3AzckZlY3RfZGVjMGRlcn0='
flag = base64.b64decode(s64)
print(flag)

# b'MRCTF{Y0u_Are_4_p3rFect_dec0der}'

放一手出题人给的脚本和出题代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python
#解题脚本

import base64
import re

def baseDec(text,type):
    if type == 1:
        return base64.b16decode(text)
    elif type == 2:
        return base64.b32decode(text)
    elif type == 3:
        return base64.b64decode(text)
    elif type == 4:
        return base64.b85decode(text)
    else:
        pass

def detect(text):
    try:
        if re.match("^[0-9A-F=]+$",text.decode()) is not None:
            return 1
    except:
        pass

    try:
        if re.match("^[A-Z2-7=]+$",text.decode()) is not None:
            return 2
    except:
        pass

    try:
        if re.match("^[A-Za-z0-9+/=]+$",text.decode()) is not None:
            return 3
    except:
        pass

    return 4

def autoDec(text):
    while True:
        if b"MRCTF{" in text:
            print("\n"+text.decode())
            break

        code = detect(text)
        text = baseDec(text,code)

with open("flag.txt",'rb') as f:
    flag = f.read()

autoDec(flag)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env python
# 出题脚本

import base64
import re

key = "31214"
# key本来非常长。。似乎太难了改的简单了点
# key = "14332234124133132214311231"
flag = b"MRCTF{Y0u_Are_4_p3rFect_dec0der}"

def baseEnc(text,type):
    if type == 1:
        return base64.b16encode(text)
    elif type == 2:
        return base64.b32encode(text)
    elif type == 3:
        return base64.b64encode(text)
    elif type == 4:
        return base64.b85encode(text)
    else:
        pass

def baseDec(text,type):
    if type == 1:
        return base64.b16decode(text)
    elif type == 2:
        return base64.b32decode(text)
    elif type == 3:
        return base64.b64decode(text)
    elif type == 4:
        return base64.b85decode(text)
    else:
        pass

def finalEnc(text,key):
    nf = text
    count = 1
    for i in key:
        nf = baseEnc(nf,int(i,10))
        #print("第"+str(count)+"次加密: ",nf)
        count +=1

    return nf

def finalDec(text,key):
    nf = text
    key = key[::-1]
    print(key)
    count = 1
    for i in key:
        nf = baseDec(nf,int(i,10))
        #print("第"+str(count)+"次解密: ",nf)
        count +=1

    return nf

def detect(text):

    try:
        if re.match("^[0-9A-F=]+$",text.decode()) is not None:
            return 1
    except:
        pass

    try:
        if re.match("^[A-Z2-7=]+$",text.decode()) is not None:
            return 2
    except:
        pass

    try:
        if re.match("^[A-Za-z0-9+/=]+$",text.decode()) is not None:
            return 3
    except:
        pass

    return 4

def autoDec(text):
    print("dec key:",end="")
    while True:
        if b"MRCTF{" in text:
            print("\n"+text.decode())
            break
        code = detect(text)
        text = baseDec(text,code)
        print(str(code),end="")


fe = finalEnc(flag,key)
with open("flag.txt",'w') as f:
    f.write(fe.decode())
'''
ff = finalDec(fe,key)
print(ff)
'''
ff = autoDec(fe)

voip

知识点:Voip-wiki,wireshark分析voip

voip:基于IP的语音传输---------------------------------from wiki

(英语:Voice over Internet Protocol,缩写:VoIP)是一种语音通话技术,经由网际协议(IP)来达成语音通话与多媒体会议,也就是经由互联网来进行通信。其他非正式的名称有IP电话(IP telephony)、互联网电话(Internet telephony)、宽带电话(broadband telephony)以及宽带电话服务(broadband phone service)。

VoIP可用于包括VoIP电话智能手机、个人计算机在内的诸多互联网接入设备,通过蜂窝网络Wi-Fi进行通话及发送短信[1]

题目分析

用 wireshark 打开问文件后,可以直接主菜单点击 电话——>VoIP电话 ——> 播放流 就可以听到声音

image-20210705225118880

1
听到 flag seccon{9001IVR}

用 Wireshark 可以知道,改文件使用的是RIP协议,工具栏中点击电话 ==> RIP ==> RIP流 ==>播放流 就可以听到声音

Business Planning Group

知识点:BPG图像格式

放一个大师傅的总结笔记:Ga1axy

BPG-------------------wiki

image-20210705231253440

题目分析

打开图片后,在 PNG 的末尾可以发现 有 BPG 的标志,将后面的内容提取出来打包为 .bpg文件

image-20210705232918922

这里 bpg 文件用软件 Honeyview 可以正常打开

image-20210705233249807

1
2
3
4
5
# YnNpZGVzX2RlbGhpe0JQR19pNV9iM3R0M3JfN2g0bl9KUEd9Cg=

base64解码

# bsides_delhi{BPG_i5_b3tt3r_7h4n_JPG}

【ACTF新生赛2020】剑龙

知识点:AAencode、图片属性、stegosaurus隐写、steghide提取jpg隐写文件

1
# AAencode:颜文字解密
1
# stegosaurus隐写

stegosaurus(剑龙):用于在 Python 字节码中嵌入 Payload(有效载荷)的隐写术工具。

  • 工具下载网站

  • 用法:

    1
    
    ./stegosaurus -x x.pyc
    

    Stegosaurus 是一种隐写术工具 ,允许在 Python 字节码(pyc 或 pyo)文件中嵌入任意有效负载。嵌入过程不会改变载体文件的运行时行为或文件大小,通常会导致低编码密度。有效载荷分散在整个字节码中,因此类似的工具 strings 不会显示实际的有效载荷。Python 的dis模块将在使用 Stegosaurus 嵌入有效载荷之前和之后返回相同的字节码结果。目前,对于这种类型的有效载荷传递,尚无已知的工作或检测方法。

    剑龙需要 Python 3.6 或更高版本。

    Stegosaurus 的基本用法如下:

    $ python3 -m stegosaurus -h
    usage: stegosaurus.py [-h] [-p PAYLOAD] [-r] [-s] [-v] [-x] carrier
    
    positional arguments:
      carrier               Carrier py, pyc or pyo file
    
    optional arguments:
      -h, --help            show this help message and exit
      -p PAYLOAD, --payload PAYLOAD
                            Embed payload in carrier file
      -r, --report          Report max available payload size carrier supports
      -s, --side-by-side    Do not overwrite carrier file, install side by side
                            instead.
      -v, --verbose         Increase verbosity once per use
      -x, --extract         Extract payload from carrier file
    
1
2
3
# steghide提取jpg隐写文件

针对jpg格式图片的隐写

安装:

kali: apt-get install steghide

用法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#隐藏文件
steghide embed -cf [图片或wav文件载体] -ef [待隐藏文件]

steghide embed -cf 1.jpg -ef 1.txt

#查看图片中嵌入的文件信息
steghide info 1.jpg

#提取图片中隐藏的文件
steghide extract -sf 1.jpg

题目分析

将所有文件解压后得到:

hh.jpg , O_O , pwd.txt 这三个文件

非预期解:

1
2
3
用linux 命令 file 查看 O_O 文件得到
O_O: python 3.6 byte-compiled
google可以知道是 pyc文件

题目有提示过剑龙,说明题目进行了 stegosaurus 隐写

1
2
3
4
5
# kali调用stegosaurus -x 命令从载体中提取payload:

./stegosaurus -x O_O.pyc

==> flag{3teg0Sauru3_!1}

预期解:

1、查看 pwd.txt

1
2
# pwd.txt 打开后知道是颜文字加密,用在线网站解密得到:
welcom3!

2、 查看 hh.jpg 图片

1
2
# 在图片的属性中提示有密钥
@#$%^&%%$)

3、用 steghide 提取 jpg 图片中隐写的文件

1
steghide extract -sf hh.jpg

得到 secret.txt 文件:

想要flag吗?解出我的密文吧~

U2FsdGVkX1/7KeHVl5984OsGUVSanPfPednHpK9lKvp0kdrxO4Tj/Q==

经过尝试,是 DES加密,这里找一个好点的 解密网站

image-20210711160647984

剩下的操作就是用 stegosaurus 隐写

【watevrCTF 2019】Evil Cuteness

知识点:jpg中隐写了zip文件

就普通的在jpg中隐写了zip文件,用binwalk 分离 或者手动分离

题目分析

用 010 editor 打开,在jpg文件尾可以看到明显的 zip 文件头 50 4B 03 04,然后手动分离出 zip文件

解压缩拿到 flag{7h475_4c7u4lly_r34lly_cu73_7h0u6h}

【UTCTF2020】File Carving

知识点:Linux下执行ELF文件

在Linux中,可执行文件的格式是ELF格式。

1、file 命令查看文件的类型

2、./ 命令在当前目录下直接执行程序

3、strings命令在对象文件或二进制文件中查找可打印的字符串。

题目分析

将图片用binwalk -e 命令提取隐藏文件,发现有 hidden_binary 文件,

用 file hidden_binary 命令查看文件类型,可知为 ELF 文件,直接 ./hidden_binary 运行拿到

flag{2fbe9adc2ad89c71da48cabe90a121c0}

image-20210711170007051

还可以使用 strings 命令,来查看文件中的所有ASCLL可打印字符

image-20210711170823355

【GUET-CTF2019】soul sipse

知识点:steghide提取音频隐写文件、Unicode编码

Unicode编码有以下四种编码方式:

源文本: The

&#x [Hex]: &#x0054;&#x0068;&#x0065;

&# [Decimal]: &#00084;&#00104;&#00101;

\U [Hex]: \U0054\U0068\U0065

\U+ [Hex]: \U+0054\U+0068\U+0065

unicode在线解码

站长工具

Steghide文件隐写:

用法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#隐藏文件
steghide embed -cf [图片或wav文件载体] -ef [待隐藏文件]

steghide embed -cf 1.jpg -ef 1.txt

#查看图片中嵌入的文件信息
steghide info 1.jpg

#提取图片中隐藏的文件
steghide extract -sf 1.jpg

题目分析

打开 out.wav 音频文件,从音频分析未果。用 steghide 命令查看是否有隐写的文件

steghide extract -sf out.wav 命令分离出 download.txt 文件

image-20210711202406897

下载图片后,打不开。用010editor查看图片信息,发现文件头错误 应该为 89 50 4E 47。

打开后得到下面:

1
\u0034\u0030\u0037\u0030\u000d\u000a\u0031\u0032\u0033\u0034\u000d\u000a

用在线工具解码unicode在线解码

得到:flag{5304}

【GWCTF2019】huyao

知识点:频域盲水印

相比传统水印添加的方法,频域盲水印的隐匿性与鲁棒性(抗攻击性)都更高,能抵挡大部分常见的攻击。

学习文章:

频域盲水印攻击性测试

盲水印和图片隐写术

Misc常用工具

Blind WaterMark盲水印:

  • 普通的盲水印

    GitHub 页面见 chishaxie/BlindWaterMark

    1
    2
    
    python3 bwm.py encode [原图] [水印图片] [加了水印的图片]  #给图片加上水印
    python3 bwm.py decode [原图] [加了水印的图片] [水印图片]  #分离出图片的水印
    
  • 频域盲水印

    GitHub 页面见 linyacool/blind-watermark

    1
    2
    
    python2 encode.py --image [原图] --watermark [水印图片] --result [加了水印的图片]  #给图片加上水印
    python2 decode.py --original [原图] --image [加了水印的图片] --result [水印图片]  #分离出图片的水印
    

题目分析

得到两张图片 huyao.png 、stillhuyao.png,看别人写的题解说是频域盲水印,没接触过...

huyao stillhuyao

直接用下面的python脚本跑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import cv2
import numpy as np
import random
import os
from argparse import ArgumentParser

ALPHA = 5

def build_parser():
    parser = ArgumentParser()
    parser.add_argument('--original', dest='ori', required=True)
    parser.add_argument('--image', dest='img', required=True)
    parser.add_argument('--result', dest='res', required=True)
    parser.add_argument('--alpha', dest='alpha', default=ALPHA)
    return parser

def main():
    parser = build_parser()
    options = parser.parse_args()
    ori = options.ori
    img = options.img
    res = options.res
    alpha = options.alpha
    if not os.path.isfile(ori):
        parser.error("original image %s does not exist." % ori)
    if not os.path.isfile(img):
        parser.error("image %s does not exist." % img)
    decode(ori, img, res, alpha)

def decode(ori_path, img_path, res_path, alpha):
    ori = cv2.imread(ori_path)
    img = cv2.imread(img_path)
    ori_f = np.fft.fft2(ori)
    img_f = np.fft.fft2(img)
    height, width = ori.shape[0], ori.shape[1]
    watermark = (ori_f - img_f) / alpha
    watermark = np.real(watermark)
    res = np.zeros(watermark.shape)
    random.seed(height + width)
    x = range(height / 2)
    y = range(width)
    random.shuffle(x)
    random.shuffle(y)
    for i in range(height / 2):
        for j in range(width):
            res[x[i]][y[j]] = watermark[i][j]
    cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100])

if __name__ == '__main__':
    main()

使用方法:

1
python2 blidwatermark.py --original huyao.png --image stillhuyao.png --result out.png

image-20210712150649228

得到:flag{BWM_1s_c00l}

注意: 上面的脚本中缺失 cv2 库的话,使用下列命令安装

1
pip2 install opencv-python==4.2.0.32

原因: Opencv 最新版不再支持 Python 2.7,而 pip install opencv-python 命令会下载最新版本Opencv。

因此需要安装时指定opencv的老版本,最后一个支持 Python 2.7 的 Opencv 版本是 4.2.0.32。

updatedupdated2022-06-032022-06-03