BCTF_海报探秘(300)

19 篇文章 0 订阅

这个题目来自上周的BCTF比赛,题目是海报探秘(300),一张png图片中隐藏了KEY,解出KEY,具体报告,

请下载:http://download.csdn.net/detail/l0g1n/7042787

我对217战队的这个题目报告进行了学习,对他的代码进行注释,理解。

我至少学习到了三点:png文件的解压,文件对齐的处理,还有这优雅的代码。分享给大家:


#include <bits/stdc++.h>
#include <zlib.h>

typedef unsigned char Byte;
//把二进制的大小转换为长度
inline unsigned convert_uint(Byte *b)
{
    unsigned ret = 0;
    for(int i = 0;i < 4; i++)
        ret = ret << 8 | b[i];
    return ret;
}

Byte chunk_len_buf[4];
Byte chunk_name[4];
Byte chunk_data[8 << 10];
Byte raw_data[8 << 20];


int main(int argc, char *argv[])
{
    //原始文件路径
    FILE *fin = fopen(argv[1], "r");
    //要输出的文件路径
    FILE *fout = fopen(argv[2], "w");
    //跳过png文件头部分
    fseek(fin, 8 + 4 + 4 + 13 + 4, SEEK_CUR);
    //zlib中用来解压的模块
    z_stream zs;
    //清0
    memset(&zs, 0, sizeof(zs));
    //初始化zs
    inflateInit(&zs);
    //设置用来保存解压后数据的路径
    zs.next_out = raw_data;
    //大小
    zs.avail_out = sizeof(raw_data);
    //读取节的长度
    while(fread(chunk_len_buf, 1, 4, fin) == 4)
    {
        //转换为unsigned
        unsigned chunk_len = convert_uint(chunk_len_buf);
        //读取每个节的名称
        fread(chunk_name, 1, 4, fin);
        //读取每一节的数据
        fread(chunk_data, 1, chunk_len, fin);
        //跳过CRC校验部分
        fseek(fin, 4, SEEK_CUR);
        //节的名称比较,只解压IDAT节
        if(memcmp(chunk_name, "IDAT", 4) == 0)
        {
            //输入的数据
            zs.next_in = chunk_data;
            //输入的长度
            zs.avail_in = chunk_len;
            //执行解压
            inflate(&zs, Z_SYNC_FLUSH);
        }
    }
    //解压结束
    inflateEnd(&zs);
    //这里看了很长时间,查了资料才明白,1003×654是像素点的个数乘以4,转换为bits,最后加654,是因为1003除以4不整除,这里是字节对齐的处理。
    unsigned raw_png_len = 1003 * 654 * 4 + 654;
    //out_len要生成新文件(被隐藏的数据)的长度,申请的内存空间-剩余可用的内存空间-图片应有的长度
    unsigned out_len = sizeof(raw_data) - zs.avail_out - raw_png_len;
    //生成数据。
    fwrite(raw_data + raw_png_len, 1, out_len, fout);

    fclose(fin);
    fclose(fout);

    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值