尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
CTF隐写题入门:Base64隐写、LSB图片隐写与文件分离实战
1. 隐写题的共性套路拿到文件先别急着“看”CTF里的Misc杂项题目说白了就是考“找藏起来的东西”。这个方向不像PWN和逆向那样门槛极高但特别考验信息收集的完整度和对各种编码格式的敏感度。很多时候题目本身不难难的是你以为自己已经找遍了所有线索其实漏了最关键的一步。拿最近在某公开靶场刷到的三道隐写题来说——base64隐写、一张马里奥主题图片、一个黑客帝国风格的字符雨文件——它们放在一起做非常有意思几乎把Misc入门阶段最核心的几类考点串了一遍。我先说一个个人经验拿到任何题目附件第一反应不要是“用某个神器跑一下”而是先把文件当成一个“未知物体”做基础信息收集。这个过程叫“体检”。file查看文件类型strings查看明文串hexdump或者010 Editor查看文件头binwalk扫描有没有内嵌文件这四步走完再决定下一步用什么工具。很多新手拿到一张图片就开始上StegSolve结果眼都快看瞎了也没发现异常就是因为漏了strings这一步。如果图片后面直接接了一个zip文件头binwalk一扫描就出来了根本不需要去分析像素。再比如某些题目故意把flag写在图片的EXIF信息或者PNG的tEXt块里strings直接就能打印出来。所以“体检”这个环节不是浪费时间它决定了你后续用什么思路解题是整套做题流程的地基。我在这次的三道题里也踩了这个过程的坑尤其是第二道马里奥图片前面体检步骤做全了后面才顺利很多。下面我把这三道题拆开细讲每个考点都附上可以直接复用的脚本和命令最后再整理一份常见坑位速查表希望能帮你省下一些走弯路的时间。2. Base64隐写藏在填充位里的秘密第一道题给了一个文本文件打开一看里面全是标准的base64字符串大概几十行每行末尾都带着一个或两个。看到这种格式大多数人第一反应是解码于是一顿操作base64 -d结果解出来一堆乱码或者中文字符怎么看都不像flag。到这里就卡住了。此时需要冷静下来想一个问题如果题目只是想让你解码为什么每个串的末尾数量不一致有些一行一个有些一行两个有些干脆没有。这在正常的base64输出里是存在的但几十行规律分布就显得刻意了。这就是base64隐写最核心的信号——填充位被人为塞了数据。2.1 base64编码的填充机制到底哪里能藏base64编码的原理并不复杂它把每3个字节24bit拆成4组6bit数据每组6bit对应一个字符字符表就是A-Za-z0-9/这64个。如果原始数据长度不是3的倍数编码时会在末尾补零并用记录补充的字节数缺一个字节补一个缺两个字节补两个。问题就出在这个“补零”上。正常解码器在读取填充位时并不会去校验那些补的0是不是真的0它直接忽略掉就用。这就意味着在凑不满6bit的最后一个有效字符里有一部分二进制位是完全自由的。具体来说剩余2个字节16bit时编码成4个字符最后一个字符实际只用了4bit另外2bit可以随便塞数据。剩余1个字节8bit时最后一个字符实际只用了2bit另外4bit可以随便塞数据。所以一个含一个的base64串能藏4bit含两个的能藏2bit。单独一个串藏的数据太少但几十个串拼在一起这几十个bit拼起来重新按8bit切分就能还原出完整的flag。这就是隐写题里特别常见的“每个载体都贡献一点点最后拼出完整消息”的套路。2.2 提取脚本逐行扫描把隐藏bit抠出来思路清楚了脚本就很好写。核心逻辑是遍历文件中每一段base64串检查末尾数量取出最后一个有效字符在base64字符表中的索引值按规则截取它的低位bit累积成完整的二进制流最后每8bit转成一个字符。参考脚本如下import re b64chars ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/ def extract_hidden_bits(b64_str): pad b64_str.count() if pad 0: return # 去掉末尾“”后取最后一个有效字符 last_char b64_str.rstrip()[-1] idx b64chars.index(last_char) # 一个“”时最后一个字符只有2bit有效可抠出低4位 # 两个“”时最后一个字符只有4bit有效可抠出低2位 if pad 1: return bin(idx)[2:].zfill(6)[-4:] elif pad 2: return bin(idx)[2:].zfill(6)[-2:] return bits with open(base64_hidden.txt, r) as f: for line in f: line line.strip() for chunk in re.findall(r[A-Za-z0-9/]{0,2}, line): bits extract_hidden_bits(chunk) flag for i in range(0, len(bits), 8): byte bits[i:i8] if len(byte) 8: char chr(int(byte, 2)) if 32 ord(char) 126: # 只保留可打印字符过滤干扰 flag char print(flag)跑完这段脚本flag就会以可打印字符串的形式被拼出来。如果flag前面有一堆乱码也不用慌那是隐藏的起始bit没有对齐可以用bits bits[1:]或者bits bits[:-1]微调一下直到输出中出现flag{为止。这个“对齐”是个常见小坑因为隐藏位可能有前置的空白padding并不一定从第一个bit就是有意义数据。2.3 边界情况的处理心得这种题有两个容易翻车的地方。一个是base64串里如果出现了标准编码没有的字符比如换行的处理、带\r\n的Windows换行读取时要先strip()否则会把空格也算进字符表检索里导致报错。另一个是有些题目会把base64串放在一行里连续拼接line.strip()以后可能是好几串连在一起所以脚本里用re.findall去匹配所有合规的base64格式片段而不是简单把整行当一个串处理。我做这道题的时候还犯过一个低级错误直接用base64.b64decode去解每一行的内容发现全解出乱码后怀疑是编码表被改过绕了好大一圈。实际上真正需要做的只是统计末尾和提取低位bit根本不关心每行能不能正常解出明文。这也是隐写题和编码题的思维差异——编码题指望你能解码隐写题则暗示信息根本不在“正常的读取路径”上。3. 马里奥主题图片LSB隐写与文件分离实战第二题的附件是一张PNG图片内容是一个经典的马里奥角色像素图红帽子、蓝背带裤那种看起来人畜无害。这种“知名游戏角色图片”在Misc里出现频率极高原因很简单制作题目的师傅们喜欢用承载度高、不引起怀疑的载体像素风格的游戏角色图天然适合做LSB隐写因为像素变化不仔细看根本感知不到。3.1 先体检binwalk、strings、宽高校验都不能少处理这类图片我推荐的顺序是file xxx.png确认文件类型顺便看颜色类型、位深这些参数。binwalk xxx.png扫描里面是否附着其他文件。strings xxx.png | head -50快速浏览明文串有些flag直接裸奔在EXIF信息里。python3用PIL打开图片检查宽高是否正常有没有被改过宽高导致内容被裁掉。这张马里奥图在binwalk阶段就发现了异常图片末尾紧跟着一个ZIP压缩包的魔数PK504B0304。这里有个细节binwalk的默认扫描有时候会因为文件系统的“几何位置”判断不准确漏报某些后附文件所以我习惯再用010 Editor直接跳转到图片末尾看一眼。更严谨的办法是直接看十六进制搜索50 4B 03 04这个zip头特征找到后手动把从该位置到文件末尾的内容dump出来。手动分离的姿势也不难Linux下可以用dd加skip参数配合if和of比如已知zip数据从偏移量0x1234开始就执行dd ifxxx.png ofhidden.zip bs1 skip$((0x1234))dd的bs1在文件较小的时候没问题如果图片很大建议把bs设成大块再配合skip的块数计算否则速度会慢到你怀疑人生。解压出来是一个加密的zip需要密码。围绕密码的线索通常在图片本身可以继续用zsteg扫描LSB层用StegSolve逐通道看低位平面或者检查PNG的文件头信息里有没有自定义的注释字段。这时候我立刻想到刚才strings扫出来的一串疑似密码的字符串。拿过来一试zip解压成功里面是一个文本文件flag就在其中。3.2 LSB隐写检查的完整操作路径如果binwalk没查出问题第二步就要怀疑LSB隐写了。所谓LSB全称是Least Significant Bit即每个像素颜色值的最低1bit。图像的高位bit决定了人眼看到的大致颜色而最低位只有0和1的区别肉眼根本分辨不出来所以这里成了最经典的隐藏位置。检查LSB最直观的工具是StegSolve打开图片后选择Analyse - Data Extract把Red、Green、Blue三个通道的勾选都调整到LSB firstBit order选LSBPreview后如果能看到明显的字符串或图形轮廓基本就实锤了。命令行选手则强烈推荐zsteg一条命令能扫描大部分常见组合zsteg xxx.pngzsteg内置了PNG和BMP的多种通道、多种位级别的隐写检测算法跑完一遍如果没有任何输出那说明大概率不是LSB套路。我之前遇到过一张图zsteg什么都没扫出来但用StegSolve手动查看Blue通道0号平面时隐约看到了一个二维码轮廓。所以工具的结果只能当参考不能当结论尤其是暗通道的隐写自动扫描未必能识别人眼经验反而更可靠。3.3 关于改宽高这个经典陷阱还有一种非常常见的图片隐写方式不是藏数据而是“切画面”——把PNG的IHDR块里的宽或高改小导致图片只显示一部分而flag就写在被裁掉的那部分区域。判断方法很简单用Python读取IHDR的宽高然后用zlib去解图像数据流如果解出来的原始数据长度和当前宽高计算出的理论值对不上就说明宽高被改过。其中有一种只改高度的做法原始数据长度不变但CRC32校验会报错。遇到这种情况直接用pngcheck跑一下pngcheck -v xxx.png它会告诉你CRC校验错误发生在哪个chunk以及理论上的IHDR校验值。修正宽高的方式是把高度逐字节枚举直到zlib流能正常解压且CRC匹配。网上有很多现成的脚本自己写也不复杂核心就是用PIL逐高度尝试读取看能否成功load。这个知识点属于Misc图片题必考范围虽然这道马里奥图没用到但同场题目里经常和LSB混合出题我习惯写在这里做个备忘。4. 黑客帝国里的字符雨文本载体隐写的变体思路第三题的附件是一个纯文本文件打开以后屏幕上全是“黑客帝国”风格的绿色字符雨——满屏随机的小写字母、数字和符号一行一行往下滚猛一看毫无规律。很多选手看到这种文件会先入为主地认为“这就是个障眼法信息得靠图片分析”于是拿着它当图片工具折腾半天其实方向就错了。字符雨文本这类题目说白了还是在考“从噪声里提取信息”但载体从图片变成了纯文本那么手段也从像素分析变成了文本模式分析。4.1 先看格式是否有规律性的列结构我拿到这个文本文件后第一步是用编辑器查看发现每一行的长度基本都是一样的大约是80字符左右这个长度恰好是传统终端的一行宽度。既然列数固定那么第一反应就是“按列去读”。具体操作是把文件读进Python按行拆分然后按列索引依次取字符看看每一列能不能拼出有意义的字符串。如果某一列拼出来是一串base64字符那就是突破口如果每一列都没有意义那再考虑行变换、列置换等隐藏规则。这道题的实际情况是每行看起来都是随机字符但把每一行的最后一个字符连起来读得到了一串base64编码。这其实不罕见在字符雨这种场景里干扰信息越多真正有用的信息就越容易被藏在相对固定的位置上。定位方法也很简单可以用Python统计每行最后一个字符打印出来看看是不是有规律的ASCII范围或者直接awk {print substr($0,length($0),1)}提取末列。4.2 绿色字符雨图片版帧对比和颜色通道有些“黑客帝国”题目给的不是文本文件而是一张GIF动画或一段视频画面就是电影里那种不断下落的绿色字符雨。动态载体相比静态图片多了一个“帧”维度最常见的隐写方式是绝大多数帧都是一样的乱码雨只有某一帧或某几帧藏着关键信息比如一个二维码一串坐标或者某几个字符明显和其他帧不同。处理手段是把所有帧拆出来逐张对比。GIF用convertImageMagick可以拆帧convert matrix.gif -coalesce frame_%03d.png拆完以后可以用Python的PIL库把所有帧叠在一起逐像素对比帧间的差异差异最小的位置往往就是藏信息的帧。更简单的方法是肉眼快速浏览一遍缩略图如果图片有几十帧一眼能扫完那个“长得不一样”的孤帧很容易被揪出来。另外绿色字符雨本身还有一个经典陷阱字符的颜色值并不全是同一款绿色。有些字符的RGB是(0, 255, 0)有些是(0, 254, 0)这种微小的色差也是数据载体。把颜色值按低bit提取和LSB隐写的思路完全一致只是载体从静态图变成了动图。所以遇到绿色主题的题记得顺手做一次色值分析把出现次数最多的绿色值列出来看看有没有不止一种“绿”。4.3 文本噪声题的正确解题心态这类题真正的难点不在技术而在心态。字符雨文本动辄几百行每行七八十个字符肉眼盯久了容易眼花这时候最容易犯的错误是用“感觉”去找线索而不是用“统计”。我在做这道题时一开始也是盯着屏幕看了半天试图找出某一行里隐藏的单词结果什么也没看出来。后来调整思路把所有行长度、字符频率、每行末列都导出来统计了一遍才锁定了末列这个位置。另外一个经验是如果途中发现某一部分拼出来的字符串疑似base64但解码后是乱码不要立刻否定可以先尝试URL解码、十六进制转ASCII、反转字符串等二次编解码。隐写题经常会出现“base64编码里再套一层十六进制”的情况留意那些解码结果中出现的0x、%、\x前缀都是多层编码的信号。5. 工具选型与快速排查手册做Misc隐写题工具不在多核心那几样必须练熟。我整理了一份自己日常做题时固定使用的工具清单和适用场景你可以直接抄作业。工具/命令适用场景常用姿势file判定文件真实类型防止扩展名骗人file flag.png看输出是PNG还是JPEG还是其他strings提取文件中的可打印字符串strings -n 8 flag.png过滤太短的噪声串binwalk检测文件内嵌的其他文件binwalk flag.png关注是否出现ZIP、RAR、7z等签名zstegPNG/BMP的LSB隐写检测一行命令多通道扫描速度快StegSolve手动逐通道查看像素平面Java图形工具适合肉眼判断LSB是否有内容pngcheck校验PNG结构检查CRC错误pngcheck -v flag.png排查宽高是否被改dd手动截取文件中某段数据dd ifflag.png ofout.zip bs1 skip偏移010 Editor十六进制查看与编辑搜寻文件签名搜504B0304定位zip头convertImageMagickGIF拆帧、格式转换convert a.gif -coalesce frame_%03d.pngPython PIL /zlib自定义分析像素、文件结构适合写脚本做批量扫描和格式修正工具的使用有一个原则先用自动化的广谱扫描再用人工分析做定点确认。比如zsteg扫完没有输出再用StegSolve手动看几个关键通道binwalk扫完没有发现再用010 Editor人工找签名。反过来先上手手动工具容易在噪声里迷失方向效率反而低。关于binwalk还有一个小提醒有些情况下它会报出一堆无关的“压缩包”或“固件”签名尤其是文件中间某些随机数据恰好命中了常见魔数。这时候不要盲目分离要用十六进制确认一下签名后的数据是否真的构成了一个完整有效文件——最简单的办法是把分离出来的文件用file命令再看一次确认是否是Zip archive data而非data。6. 三道题连做的踩坑心得最后这条算是我在做这三道题时反复踩过、又最终趟平的一些经验总结对入门Misc的选手应该有参考价值。第一别把简单问题复杂化。base64隐写那道题我一开始的时间几乎都花在“分析解码后的乱码”上总觉得是不是用了自定义字母表后来才意识到真正的信息根本不在解码结果里而在编码的“废弃物”填充位。Misc题的答案通常藏得很浅只是藏的路径刁钻。如果你在一个方向上折腾了半小时没有任何进展大概率是思路错了而不是工具不行。第二体检步骤永远别省。马里奥图片如果当时直接跳过strings和binwalk直接上StegSolve那个zip可能耗掉大量时间才能被偶然翻出来。相反按顺序做完体检几分钟就能锁定后续方向。我后来养成一个习惯拿到附件先花5分钟做完file、strings、binwalk、hexdump这一套再决定用什么高级工具这个小习惯帮我避开了无数次无效分析。第三脚本能力是真·核心。base64隐写题没有现成工具必须自己写Python提取bit哪怕代码再丑能跑就行。Misc方向越往后做越能体会很多题不是“会不会工具”而是“会不会写脚本把数据批量处理成有意义的信息”。建议初学者至少掌握Python的文件读写、字符串处理、编码转换和PIL图像读取这四样能覆盖80%的隐写题场景。第四注意信息的多层编码。黑客帝国那道题里从末列提取出来的base64解码后是一段十六进制字符串那段十六进制再转ASCII才得到真正的flag。很多选手栽在最后一步解出来一眼看到666C6167这种十六进制文本就以为是自己提错了数据其实那正是flag的十六进制表示。“解码结果可能还是一层壳”这句话在Misc做题时建议贴在脑门上。对我来说这三道题的价值不在于难度而在于完整覆盖了“编码隐写—文件分离—文本噪声”三种载体形态。把它们的解题路径各自走通以后再遇到类似的题目基本上看一眼附件特征就能锁定排查方向。后面你如果也碰上了类似风格的题不妨先按这套流程跑一遍大概率能少走一些弯路。
RELATED

相关推荐

图像切割与特征提取实战:从原始图像到特征矩阵的完整流程

图像切割与特征提取实战:从原始图像到特征矩阵的完整流程

1. 图像切割:拿到一张图,先想清楚要“切谁”1.1 切割在整个预处理链路里的位置“数据预处理与特征工程”这个系列写到这里,终于轮到图像切割与特征提取这对组合。很多人容易忽略一件事:图像任务里真正的胜负手,往往不在…

📅 2026/10/17 13:34:46
传一个关键词,影刀自己上小红书搜图、翻笔记、点赞收藏发评论|AI 流程助手全链路复盘

传一个关键词,影刀自己上小红书搜图、翻笔记、点赞收藏发评论|AI 流程助手全链路复盘

目录引言研究背景与意义文献综述研究方法与设计数据收集与处理结果分析讨论与启示结论与展望参考文献附录摘要本研究聚焦于[具体研究主题],旨在探讨[核心问题或目标]。通过系统梳理相关文献,结合定量与定性相结合的研究方法,对[研究对象或数据…

📅 2026/10/17 13:34:46
前端学习底层逻辑:从解决问题出发,构建稳固技术地基

前端学习底层逻辑:从解决问题出发,构建稳固技术地基

1. 先别急着列技术清单:前端学习的底层逻辑1.1 我把问题从"学什么"改成了"解决什么"时不时有人带着一张截图来找我,上面密密麻麻列着几十项技术名词,问我说"这些是不是都得学,哪个先学哪个后学"。我…

📅 2026/10/17 13:34:46
MORE NEWS

更多资讯

📰

大模型微调全流程指南:从LoRA选型到部署实战

这几周在好几个技术社群里看到同样一个问题:为什么我用了开源大模型做垂直领域的问答,效果还是差强人意?有让它理解某个行业术语的,有想让模型学会特定文风的,也有希望模型能根据自家产品知识库说话的。问题五花八门&a…

📰

免费简历模板网站.doc:Word表格排版与PDF导出避坑指南

简介:这份免费简历模板网站.doc面向应届毕业生、求职者及需要快速整理个人履历的职场新人,提供可直接套用的中文简历表格与填写框架,解决从零排版、格式不统一、信息遗漏等常见问题。资源包共1个文件,为doc格式文档,整…

📰

大模型微调实战指南:从数据准备到部署评估

跟好几个做 NLP 应用的团队聊过之后,我发现大家对“大模型微调”这件事的态度很分裂:一边觉得它是灵丹妙药,什么坏结果都能靠微调来救;另一边觉得它是吞金兽,几万块钱的算力砸下去,模型反而变得比原来还笨。…

📰

BSDS500数据集预处理全流程:mat标注转轮廓图与分割图

做边缘检测或者图像分割的时候,BSDS500基本是一道绕不过去的门槛。很多论文里报告的准确率、召回率,都是在这500张图的标准划分上算出来的。真正走到准备数据这一步,很多人会卡住:官方给的ground truth是.mat格式,不是…

📰

爬虫数据匿名化实战:k-匿名与差分隐私技术实现指南

简介:这份PDF文档聚焦爬虫数据匿名化处理,面向具备一定Python基础、关注数据合规与隐私保护的技术开发者和数据科学学习者,系统讲解k-匿名与差分隐私两大核心技术的原理与实现路径。文档共1个PDF文件,压缩包约4.31MB,支…

📰

用Excel看懂LSTM:手把手模拟门控机制与前向传播全过程

LSTM 往往是很多人学习序列模型时第一道坎。公式不过五六行,但真要把“遗忘门、输入门、候选值、输出门、细胞状态更新”串起来讲清楚,大多数人会卡在原地。尤其是用了深度学习框架之后,调用一个现成的 LSTM 模块只要一行代码,数据…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬