wechall.net/stegano 解题心得

  最近迷上了 www.wechall.net 网站,里面都是些与计算机相关的题目挑战。题目又分很多类型,例如:加密与解密、隐写术、网络攻防、趣味编程、数学逻辑等。题目有的简单,有的很难,需要一些知识和技巧。与其他题目挑战的网站不同的是,在其他类似性质的网站注册的用户可以绑定到 WeChall 网站,然后 WeChall 提供排名信息,而且也分得很细,什么按总分全球排名、什么在自己国家的排名、什么解答某种语言网站题目的排名等。可以从解题的人数判断题目的难易程度,有兴趣的朋友可以去注册,解题中也能学到很多知识。国内的学校和公司也有举办网络攻防大赛。与玩 ACM 解题不同的是:ACM 提供给定的输入和输出,中间的黑盒部分需要你来完成,需要提供一种更好更快的算法;这类攻防挑战题目可能需要更多的计算机知识,从一堆垃圾数据中发现有用的信息、越过不同的障碍终于发现答案等。

  注:Steganography 是隐写术,它与 Cryptography (密码术)是不同的。

题目1 stegano1 给了一张彩色的 BMP 图片,让你从中发现答案。

  不管是图片、音频文件,还是二进制文件,首先都可以尝试以文本文件打开,查看是否存在可疑的字符串。文件太大了就不要这么做了,鼠标会转圈好久的。
图片很小,才 102 bytes。将图片文件拖到文本编辑器里,就可以看到答案了。Notepad++ 是 Windows 上最好的文本编辑器,没有之一。体积小巧,功能齐全。
Linux 上用 gedit 打开,或者使用 vim 命令,输入 :%!xxd 切换到二进制模式,答案显而易见。
xxd 是另外一个命令,以十六进制现实内容。再输入 :%!xxd -r 命令执行,切换到原来的摸样(r 是 reverse )。
注意 vim 的 -b 选项,是否以二进制模式打开。图片是二进制文件,所以要加此选项,否则处理会有问题。
还有一个命令 strings,来的更快,直接输出文件中可打印的字符,通常用来显示二进制中的字符串常量。
strings 命令的选项 -n VALUE 或 --bytes=VALUE 选项控制输出连续字符的最短长度,这个的默认值 VALUE 是 4。
还有 -t RADIX 或 --radix=RADIX 选项以后也会用上的,用来显示每个字符串的偏移量。C++ 的 static 字符串变量需要这个偏移量索引字符串。

  你我都是做题的,但是怎么出题呢?破解别人的软件,写一个序列号注册机相对容易。但是如何写一个加壳、混淆的难以破解的程序就有点难度了,毕竟建房子拆房子简单。
我们需要了解一下 BMP 文件格式,BMP 图片很占空间,没有压缩,或者用 RLE (Run-Length Encoding)压缩一下,体积大所以很少在网络上传播。 BITMAPFILEHEADERBITMAPINFOHEADER

    const char* buffer = "put your message here";
    FILE *file = fopen(path, "wb");
    if (!file)
    {
        fprintf(stderr, "can‘t open %s\n", path);
        return false;
    }

    BITMAPFILEHEADER file_header;
    BITMAPINFOHEADER info_header;

    file_header.bfType = (WORD)(‘B‘|‘M‘<<8); // Windows BMP file tag
    file_header.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+len;
    file_header.bfReserved1 = 0;
    file_header.bfReserved2 = 0;
    file_header.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

    info_header.biSize = sizeof(BITMAPINFOHEADER);
    info_header.biWidth = width;
    info_header.biHeight = height;
    info_header.biPlanes = 1;
    info_header.biBitCount = 24;
    info_header.biCompression = 0; // BI_RGB, An uncompressed format.
    info_header.biSizeImage = len; // size in bytes. This may be set to zero for BI_RGB bitmaps
    info_header.biXPelsPerMeter = 0;
    info_header.biYPelsPerMeter = 0;
    info_header.biClrUsed = 0;
    info_header.biClrImportant = 0;

    fwrite(&file_header, sizeof(file_header), 1, file);
    fwrite(&info_header, sizeof(info_header), 1, file);
    fwrite(buffer, len, 1, file);
    fclose(file);

  这样写,太容易被发现了。我们可以通过对字符串先加密再隐写,或者用循环移位、异或操作增加难度。
  知道 BMP 格式支持颜色索引模式(GIF、PNG 格式也支持),图片里会有一个调色板用来存储使用的颜色值,相当于一个数组存储 RGB 值,然后图片只用数组索引值找到对应的颜色并显示出来,于是你也可以这样隐藏你的信息到图片中。我们用两种颜色作图,在白纸写黑字,存储为索引模式图,于是调色板会有两个值 #000000 和 #FFFFFF,颜色只需一位 0/1 就可以表示黑白颜色了,将数组中的 #000000 值篡改成 #FFFFFF,也就是黑色改成白色,其他数据不用动,保存后用再打开图片看发现,字消失了!写一些想说的话,然后把图片发给暗恋对象,对方会说你怎么发了一张空白图片。说了这么多,自己动手尝试一下吧。

题目2 Stegano Attachment 
答案在图片中吗?不,答案在附件(attachment)里。等你做出了这道题,就明白前面一句话的意思。有时候,题目会给出提示容易忽视的信息,而这个可能就是解题的关键。
稍微留心一下图片 http://www.wechall.net/challenge/training/stegano/attachment/attachment.php ,是不是很坏?后缀被人改成 PHP 网页后缀。用文本编辑软件打开,发现一堆乱码。不同文件会有不同的文件头,即不同的 Magic Number,如上面的 BMP 格式图片的 “BM” 标志,PNG 图片有八字节头 “\211PNG\r\n\032\n”,用 Visual Studio 调式 C++ 代码出现很多的“烫烫烫烫”,其实是编译期初始化栈空间为 “\xCC\xCC\xCC\xCC”(0xCC 对应 x86 的 INT 3 中断指令,你应该知道为什么这么做),编译 Java 文件生成的 .class 文件的文件头有 “CAFEBABE”。从 attachment.php 里我们看到了字符 "JFIF",应该就是 JPG 图片了。更好的方法是用 linux 上的 file 命令查看文件类型,文件名后缀随你怎么该。改成 .jpg 后缀后,打开图片后,是电影 Ghostbusters (1984) 的海报,我们追到了这里,电影我没看过,看介绍好像很不错的样子。一边下载一边解题吧~

[email protected]:~/Desktop$ file attachment.php
attachment.php: JPEG image data, JFIF standard 1.01

我们稍微了解一下 JPEG 格式规范。JPEG 文件以 “\xFF\xD8” 打头,以 “\xFF\xD9” 结尾。JPEG/JFIF 文件会出现 “JFIF” 字符,JPEG/Exif 文件会出现 "Exif" 字符。

jpg 图片采用有损压缩,不支持 alpha 通道。编码时,颜色从 RGB 色彩空间转到 YUV 色彩空间,根据颜色分量的重要性和人眼的感知剔除不重要的信息,缩减采样 4:4:4 4:2:2 4:2:0,接着 分割图片成 8x8 子区域进行离散余弦变换,量化编码,支流系数用差分编码,交流系数用 RLE 编码。

我们发现图片是以 "\xFF\xD9" 开头的,但是结尾却不是 "\xFF\xD9",好像明白了什么。
我们用题目1学到的 strings 命令搜到了可疑字符串 solution.txt 和 solution.txtPK,恰恰是放文件最后的。
PK 字眼熟悉不?最常用的 ZIP 格式压缩文件头的 magic number 是 “PK\x03\x04”,而且文件中确实存在这四个字节。而且这四个字节的前面也恰好是 "\xFF\xD9"。想想之前的题目 attachment。看来,是谁把一个 ZIP 压缩文件追加到一个 JEPG 图像文件的后面了。我们需要提取出 ZIP 文件,答案离我们不远了。。

ZIP 文件的偏移量用题目1学到的 vim :%!xxd 搜索定位查看并计算,或者用 grep 命令搜索下。
我们需要复制从 0004f06 到最后 0004f8d (长度 0x88=136)到新的文件里去。

复制粘贴文件或者段落用 Ctrl+C、Ctrl+V,可是复制二进制文件流呢,也可以这么做吗?好像不行。
Notepad++ 不愧是最好用最实用的文本编辑器,选择菜单 Edit -> Paste Special,二级菜单中出现了 Copy Binary Cotent | Cut Binary Content。
或者使用 linux 的 dd 命令。

[email protected]:~/Desktop$ printf "%d\n" 0x0004f06
20230
[email protected]:~/Desktop$ dd if=attachment.jpg of=solution.zip skip=20230 bs=1 count=136
136+0 records in
136+0 records out
136 bytes (136 B) copied, 0.0021692 s, 62.7 kB/s

[email protected]:~/Desktop$ unzip solution.zip
Archive: solution.zip
inflating: solution.txt

打开 solution.txt 文件,就是最终的答案了。

从中,我们学习了另外一种隐藏文件的方法,将一个文件附属到另外一个文件末尾,打开的时候只解析第一个文件,附属文件被忽略了。
Windows 控制台下,将信息 message.txt 隐藏到图片 carrier.jpg 中:copy carrier.jpg /b + message.txt /a mixed.jpg
/A /B 分别代表文本文件和二进制文件。

题3 LSB - The least significant bit

to be continued...

 

时间: 2024-10-15 05:37:54

wechall.net/stegano 解题心得的相关文章

第四章学习小结 串的模式匹配 解题心得体会

串的模式匹配 解题心得体会 关于串,模式匹配是其一个很重要的问题.针对这个问题,书上讲了两种模式匹配的算法,即BF算法和KMP算法,下面针对这两种算法的实现谈谈我的心得. 一.BF算法的探索 [错误代码1] #include<iostream> #include<string.h> using namespace std; typedef struct{ char ch[1000002]; int length; }SString; void Index_BF(SString S,

括号配对问题——解题心得

Description You are given a string consisting of parentheses () and []. A string of this type is said to be correct: (a)if it is the empty string (b)if A and B are correct, AB is correct, (c)if A is correct, (A ) and [A ] is correct. Write a program

【WeChall 】Stegano Challenges:Training: LSB

Topic request: This is a very simple, yet spectacular trick. Can you see the hidden solution? Note: The solution is bound to your session ID and consists of twelve letters. Hidden Hint: http://wechall.blogspot.com/2007/11/steganabara-explained.html T

【WeChall 】Stegano Challenges:Training: Stegano I

Topic request: This is the most basic image stegano I can think of 题目提示这是最基础的图片隐藏术,那么一般来说在隐写术中最基础的应该属于在图片中插入信息了. 首先我们需要下载一个winhex,然后我们将隐写了的图片加载到工具中就可以看到 passwd:steganoI

Ducci Sequence 解题心得

原题贴上 A Ducci sequence is a sequence of n-tuples of integers. Given an n-tuple of integers (a1, a2, ... , an), the next n-tuple in the sequence is formed by taking the absolute differences of neighboring integers: ( a1, a2, ... , an)  (| a1 - a2|,| a2

HDU 4627 The Unsolvable Problem 解题心得

原题: Description There are many unsolvable problem in the world.It could be about one or about zero.But this time it is about bigger number. Given an integer n(2 <= n <= 10 9).We should find a pair of positive integer a, b so that a + b = n and [a, b

USACO Greedy Gift Givers 解题心得

本题算法不难想出,但是中间还是出现了一些问题. 开始的时候是#11:Execution error,后来把普通的数组改成动态数组后问题消失. 后来又出现了Execution error: Your program had this runtime error: Illegal file open (/dev/tty). 随后google解决方案,多数都是数组开小了.遂开大数组,无效. 突然意识到很有可能是低级错误,于是检查代码. 发现写了个 for(int i = 0; i < n2 ; i++

UVa 1647 - Computer Transformation 解题心得

这个题目.... 想上题意 10935 Throwing cards away I Given is an ordered deck of n cards numbered 1 to n with card 1 at the top and card n at the bottom. The following operation is performed as long as there are at least two cards in the deck: Throw away the to

Codeforces Round #315 (Div. 2) A. Music 解题心得

原题: Description Little Lesha loves listening to music via his smartphone. But the smartphone doesn't have much memory, so Lesha listens to his favorite songs in a well-known social network InTalk. Unfortunately, internet is not that fast in the city