M/o/Vfuscator PoC 详解:把 BrainF\*@k 源程序编译成只含 mov 指令的可执行文件
编译器【免费下载链接】movfuscatorThe single instruction C compiler项目地址https://gitcode.com/gh_mirrors/mo/movfuscator点击查看免费下载本篇围绕仓库 poc/README.md 展开系统讲解 M/o/Vfuscator 1.0PoC 版本如何把 BrainF*k下称 BF源程序翻译成纯mov指令的 32 位 x86 程序并逐条对照 poc/movfuscator.c 源码解析-mmio、-nojmp、-cell16、-O各编译开关的底层实现。读完本篇你可以独立完成编译 BF → 生成 NASM 汇编 → 汇编链接为 mov-only 可执行文件的完整流程并理解只用一条指令实现图灵完备计算在寄存器、数据表与控制流层面的具体落地方式。1. 背景PoC 目录与 M/o/Vfuscator 1.0/2.0 的分工整个 movfuscator 仓库包含两代实现M/o/Vfuscator 1.0PoC位于 poc/ 目录是一个把 BF 程序编译成 mov 指令的编译器原作者说明其最适合与 Jeffry Johnston 的 BFBASICBASIC → BF 编译器配合使用构成一条 BASIC → BF → mov 的完整工具链M/o/Vfuscator 2.0仓库主体根 README.md 所述是完整的单指令 C 编译器movcc以 LCC 为前端。根 README 的 History 一节明确指出The original M/o/Vfuscator (M/o/Vfuscator 1.0) compiles programs from the esoteric language BrainF*!... It is still available as a proof of concept in the poc directory。其理论灵感来自 Stephen Dolan 的论文《mov is Turing-complete》该论文证明了 x86 的mov指令集合具备图灵完备性PoC 则是对这一定理的工程化验证。PoC 目录内容如下路径内容poc/movfuscator.c1.0 编译器本体单文件 C 程序poc/examples/四个已编译好的示例可执行文件32 位 ELFpoc/examples/README示例说明各自的编译来源与使用的开关poc/examples/demo.sh实时观察 MMIO 输出的小脚本poc/crackme/两个找密钥挑战程序用 2.0 编译2. 总体架构一个读标准输入、写标准输出的汇编生成器poc/README.md 给出的核心用法只有两行命令gcc movfuscator.c -o movfuscator # 编译编译器本体 ./movfuscator example.bf example.asm # 把 BF 翻译成 mov 汇编也就是说poc/movfuscator.c 本身就是一个 C 程序它从标准输入逐字符读取 BF 源码向标准输出打印 NASM 格式汇编。从源码结构看其处理流程分为三段main函数poc/movfuscator.c#L60-L643发射固定数据段.data/.bssBF 内存模型所需的全部数据表发射前导代码_start按开关决定是否插入 MMIO 映射或 SIGILL 信号处理的前置调用主翻译循环while (!feof(stdin))逐字符扫描 BF 源码对 - . , [ ]分别生成对应的 mov 序列poc/movfuscator.c#L337-L633最后补上程序回边。三个关键容量常量定义在文件头部#define ID_STACK_SIZE 8192 // BF 循环嵌套深度上限 #define BF_DATA_SIZE (128*1024) // BF 数据指针可寻址的内存单元数 #define MMIO_SIZE (128*1024) // MMIO 映射区大小必须 BF_DATA_SIZE数据段中BF 的单元格由宏c_s声明——每个单元格附带两个索引表条目d_前缀存单元格地址s_前缀是标志 → 目标地址的跳板表这是后续所有 mov 序列做条件寻址的基础poc/movfuscator.c#L107-L111%macro c_s 1 %1: dd 0 d_%1: dd 0 s_%1: dd d_%1, %1 %endmacro.bss段则放置三块128K的 BF 内存m/s/z和一块256*256的比较表epoc/movfuscator.c#L245-L249。3. 只用 mov 实现算术与逻辑查找表 内存比较这是整个 PoC 最核心的机制。加法不是add而是查表。编译器在数据段生成四张 256 项/65536 项的查找表poc/movfuscator.c#L145-L171incb: ; 8 位加一表: incb[i] (i1) 0xff %assign y 1 %rep 256 db y0xff %assign y y1 %endrep incw: ; 16 位加一表: incw[i] (i1) 0xffff %assign y 1 %rep 256*256 dw y0xffff %assign y y1 %endrep ; decb / decw 类似生成减一表于是 BF 的指令被翻译成读出单元值 → 用值作索引取incb→ 写回全程只有 movpoc/movfuscator.c#L433-L461mov eax, [on] mov ebx, [s_mseax] mov edx, [dp] mov eax, 0 mov al, [ebxedx] mov al, [incbeax] ; “加法” 查表 mov [ebxedx], al/移动数据指针dp同理只是改用incw/decw对 16 位指针值做查表增/减poc/movfuscator.c#L493-L535。比较运算使用e表64K 字节。生成的eq宏把取两个数比较变成在内存的同一张表里分别写入 0 和 4再读回其中一个字节——两地址相同则读到 4真不同则读到 0假poc/movfuscator.c#L173-L191%macro eq 3 mov eax, 0 mov edx, 0 mov ax, [%2] mov byte [eeax], 0 mov byte [e%3], 4 mov dl, [eeax] mov [%1], edx %endmacro ; neq 宏把 0/4 对调逻辑运算or/and/not则直接走三张小常数表o、a、no_0: dd 0,4、a_0: dd 0,0、n: dd 4,0poc/movfuscator.c#L129-L140以左操作数、右操作数为下标各查一次表即可。可以看到布尔值编码为4 真0 假初始标志on: dd 4。BF 的[]循环在没有跳转指令的前提下是这样翻译的编译器在 C 端维护一个 ID 栈上限 8192对应 BF 嵌套循环深度为每个[分配一个自增编号id发射的代码不跳过循环体而是更新一组线程状态——on执行开关、id当前循环号、otother tag——使[处根据单元值为 0 与否改写这些标志]处再按对称逻辑复位[见 poc/movfuscator.c#L545-L587]见 poc/movfuscator.c#L589-L629。从源码结构看整个 BF 程序因此被拉直成一个单一直线无限循环所有分支都退化为对标志位与单元格的 mov 读写[ ]语义靠标志状态维持而不再有任何控制转移指令。4. I/O 的两种实现int 0x80 与 MMIO 映射4.1 默认模式保留一条 int 0x80不传开关时.输出与,输入使用 32 位系统调用poc/movfuscator.c#L370-L383mov eax, 4 ; sys_write mov ebx, 1 ; stdout mov ecx, c mov edx, 1 int 0x80此时程序含int 0x80与末尾一条jmp严格意义已不是纯 mov——poc/examples/factor 就是按这种方式编译的。4.2 -mmio用内存映射文件替代系统调用加-mmio后编译器在_start处发射一段前导代码poc/movfuscator.c#L257-L313用常规调用建立两幅内存映射 I/O 区open(/dev/stdin, O_RDONLY)与open(/dev/stdout, O_RDWR)fd 分别存入fdi/fdo对输出文件lseek(fdout, MMIO_SIZE-1, SEEK_SET)再write一个字节——把文件撑到 128K对两个 fd 各做一次mmap(0, MMIO_SIZE, PROT_READ/PROT_WRITE, MAP_SHARED, fd, 0)得到只读映射src与可写映射dst。之后 BF 的,就是mov cl, [srcsri]从映射区读一字节.就是mov [dstdsi], cl写映射区配合incw表推进读写下标sri/dsipoc/movfuscator.c#L354-L408。这就是 README 中-mmio 允许用 mov 替代 int 0x80的含义。关键限制mmap只映射真实文件管道/终端不可用所以 I/O 流必须由文件承载——运行-mmio程序时必须写成./example sample_in sample_out而不能直接连终端详见第 7 节。5. 程序回边一条 jmp 还是故障 movBF 是一个无限循环的虚拟机程序末尾必须回到loop:标号。poc/README.md 给出的两条路默认发射jmp looppoc/movfuscator.c#L638-L640-nojmp改为发射一条会触发 SIGILL 的 movmov cs, ax ; ax 恒为 0写段寄存器立即触发非法指令异常编译器会先通过sigaction注册 SIGILL 处理器处理器指向loop本身poc/movfuscator.c#L315-L322extern sigaction mov dword [esp], 4 ; sigill mov dword [esp4], sa mov dword [esp8], 0 call sigaction并且每轮循环开头会先执行mov esp, [dsp]恢复栈指针抵消信号处理帧对esp的扰动poc/movfuscator.c#L329-L335。从源码结构看指令流因异常被打断、由信号处理函数把控制权送回循环起点用异常机制替代了控制转移这正是--no-mov-loop思路在 1.0 中的前身。-mov开关等价于同时打开-mmio -nojmppoc/movfuscator.c#L86-L89得到真正只有 mov 指令的程序体。6. 使用方法从 BF 到 mov-only 可执行文件的完整流程以下内容完整继承自 poc/README.md 的 Usage 一节并补充依赖前提第一步编译编译器本体gcc movfuscator.c -o movfuscator第二步把 BF 翻译成 mov 汇编./movfuscator example.bf example.asm第三步用 NASM 32 位链接器生成可执行文件nasm -felf example.asm -o example.o ld -melf_i386 example.o -o example完整流水线从 BASIC 到 mov-only 可执行文件./bfbasic.sh example.bas example.bf # BFBASIC: BASIC - BF ./movfuscator example.bf example.asm nasm -felf example.asm -o example.o ld -melf_i386 example.o -o example ./example适用前提与限制目标平台必须是 32 位 Linuxld -melf_i386生成 i386 ELF需要自备 NASM 与 binutils完整流水线中的bfbasic.shBFBASIC 包装脚本不在本仓库内需按原文档 References 提及的 BFBASIC 项目自行准备仓库未附带 BF 源码样例README 引用了外部 BF 程序集作为练习来源此处按规范不附链接若希望得到-mov级别的纯 mov 程序第三步运行前请确保 I/O 由文件承载。7. 编译开关详解文档说明 源码行为poc/README.md 列出的 Flags 全表如下并逐条对照源码开关文档说明源码行为-mmioUse memory mapped I/O. 用 mov 替代 int 0x80 做 I/O但要求 I/O 流由文件承载发射src/dst/sri/dsi等数据L216-L232与第 4.2 节的open/lseek/write/mmap前导-nojmp用一条故障 mov 替代唯一的 jmp 来实现程序循环注册 SIGILL 信号处理L315-L322程序尾部发射mov cs, axL635-L637循环开头恢复esp-mov只用 mov 指令等价于-mmio -nojmp同时置位两个开关L86-L89-cell16使用 16 位内存单元格所有读/写单元格的指令从al/cl/dl升级为ax/cx/dx加法查表改用incw/decw见第 3 节-O启用优化扫描 BF 源码中连续的 - 把重复次数记入repL343-L351生成时共享同一段取址设置、仅重复查表 mov如 L441-L446避免为同一指令重复发射完整序列关于-O值得说明它的优化不是把 100 个折叠成一次乘法而是去冗余——对...这样的连续序列只发射一次指针/标志取址代码随后重复发射查表 mov使输出显著变短、变快。8. 示例程序集examples/ 与 demo.shpoc/examples/ 提供了四个已编译的 32 位 ELF 示例均为ELF 32-bit LSB executable其 README 说明了各自的编译路径与开关组合恰好覆盖了第 7 节全部开关场景示例编译来源使用的开关结果nibblesC 经 M/o/Vfuscator2.0编译—非 1.0 产物贪吃蛇游戏w a s d控制移动末尾的 jmp 与外部调用尚未 mov 化factorBF 经 M/o/Vfuscator1.0无保留int 0x80与末尾唯一一条jmp的基线示例primesBF 经 M/o/Vfuscator1.0-nojmp移除末尾 jmp 的示例99_bottlesBASIC 经 BFBASIC → BF → M/o/Vfuscator1.0-mmio-nojmp只含 mov 指令的完整流水线成果输出走 MMIO要求文件承载的 I/O 流运行方式摘自 poc/examples/README./example # 普通示例直接运行 # -mmio 编译的程序必须由文件承载 I/O ./example sample_in sample_out # 或用仓库自带脚本边跑边看输出 ./demo.sh exampledemo.sh 的实现很简短touch出sample_in/sample_out两个空文件把示例进程在文件重定向下放到后台运行然后watch -t -n .1 tail -20 sample_out | sed ...每 0.1 秒刷新一次输出文件尾部最后pkill结束示例。它本质上是给 MMIO 程序提供了终端实时查看的体验补偿——因为-mmio程序无法直接写终端。9. 附带挑战poc/crackmepoc/crackme/ 还包含两个挑战程序目标都是找出密钥crackme1一个约 15 行的 C 语言 crackme使用 M/o/Vfuscator 2.0 编译crackme2与 crackme1 结构相同但换了密钥并将strcmp改为常数时间比较用于防止针对 crackme1 的某些最简求解思路。这两个程序虽然由 2.0 编译但与 PoC 目录放在一起为读者提供了一个动手逆向mov-only 程序的真实靶子由于汇编体只有 mov传统基于控制流与运算指令模式的静态分析手段基本失效。10. 小结与延伸阅读poc/movfuscator.c 用不到 700 行 C 代码完整演示了mov 图灵完备的工程化路径查表做算术、内存写入-读回做比较、标志位拉直控制流、MMIO 映射做 I/O、故障 mov 信号处理做回边与仓库主体的 2.0movccLCC 前端的完整 C 编译器相比1.0 的价值在于概念验证与最小实现——根 README.md 的 History 一节即以此定位 poc 目录1.0 的 BF 数据区上限为 128KBBF_DATA_SIZE、循环嵌套上限 8192ID_STACK_SIZE使用时需自行确保 BF 程序规模在范围内参考资料原作者为 chris domasxoreaxeaxeax理论依据为 Stephen Dolan 的论文《mov is Turing-complete》BASIC → BF 前端建议使用 Jeffry Johnston 的 BFBASIC原文档 References 一节列出按输出规范此处不附外部链接。赞分享编译器【免费下载链接】movfuscatorThe single instruction C compiler项目地址https://gitcode.com/gh_mirrors/mo/movfuscator点击查看免费下载相关推荐如何快速本地部署Wan2.1-Fun-1.3B-InPAI视频生成环境配置与权重下载一步到位指南 如何快速本地部署Wan2.1 Fun 1.3B InPAI视频生成环境配置与权重下载一步到位指南 想要在本地电脑上体验强大的AI视频生成功能吗Wan2M/o/Vfuscator 完全实战指南一个只输出 mov 指令的单指令 C 编译器如何工作M/o/Vfuscator 完全实战指南一个只输出 mov 指令的单指令 C 编译器如何工作 本篇以 README https://link.gitcode.编译器Skidfuscator核心功能深度解析第三代控制流混淆技术揭秘Skidfuscator核心功能深度解析第三代控制流混淆技术揭秘 你是否正在寻找一款真正能保护Java代码安全的生产级混淆工具Skidfuscator作为基应用安全开发工具上一篇Lap数据库迁移机制详解v0.1到v0.2如何无痛自动升级下一篇RT-Thread 在珠海泰为 TAE32F5300_EVAL_BOARD 开发板上的 BSP 移植与快速上手指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

从零搭建轻量级地图可视化组件lingbot-map:架构设计与核心实现

从零搭建轻量级地图可视化组件lingbot-map:架构设计与核心实现

1. 从零搭建一个轻量级地图可视化组件:lingbot-map 项目全记录前阵子在做数据看板类项目时,遇到一个挺典型的需求:需要在页面上嵌入一个可交互的地图,支持点位标注、区域高亮、点击弹窗这些基础能力,但又不希望引入动辄…

2026/10/14 8:39:11 阅读更多 →
FLUX.1 Kontext与Krea深度解析:从Transformer到Flow Matching的选型实战

FLUX.1 Kontext与Krea深度解析:从Transformer到Flow Matching的选型实战

1. 从两个名字说起:FLUX.1 Kontext 与 FLUX.1 Krea 到底在解决什么问题第一次看到 FLUX.1 Kontext 和 FLUX.1 Krea 这两个名字,很多人会下意识觉得它们只是同一个底模的两个微调版本,换汤不换药。但真正上手跑过一轮之后你会发现,…

2026/10/14 8:39:11 阅读更多 →
Litellm 实战:用统一网关终结多模型接入的工程噩梦

Litellm 实战:用统一网关终结多模型接入的工程噩梦

前阵子我在做内部服务的时候,最烦躁的事情不是业务逻辑本身,而是每天要同时维护两三套大模型接口的调用代码。每家返回的字段结构不一样、错误码含义不一样、限流策略也不一样,连超时时间都藏得很深。项目里换一个模型供应商,就要…

2026/10/14 8:38:11 阅读更多 →

最新新闻

手动部署OpenTelemetry Collector:从配置到运维的实践指南

手动部署OpenTelemetry Collector:从配置到运维的实践指南

简介:基于C#编写的winform Socket通信示例,面向需要掌握网络编程的C#初学者,演示了服务端与多个客户端同时连接与数据交互的实现过程。压缩包内包含服务端与客户端两个独立工程,可对照学习服务端监听、客户端连接以及多客户端并发…

2026/10/15 0:05:58 阅读更多 →
SpringBoot整合knife4j实战:接口文档与在线调试完整指南

SpringBoot整合knife4j实战:接口文档与在线调试完整指南

1. 为什么接口文档这件事值得单独拎出来聊做后端开发的人都有一个共识:写接口不难,难的是让前端、测试、甚至未来的自己看懂接口。早些年大家用 Swagger 那一套,ApiOperation、ApiModel注解满天飞,UI 长得像上世纪的产物&#xff…

2026/10/15 0:05:58 阅读更多 →
openrig 实战:用 tmux 与 Node.js 编排 Claude Code 和 Codex 多代理工作流

openrig 实战:用 tmux 与 Node.js 编排 Claude Code 和 Codex 多代理工作流

1. openrig 到底想解决什么问题第一次看到 openrig 这个名字,加上关联的 Claude Code、Codex、Node.js、tmux 这几个词,我脑子里冒出来的判断是:这大概率是一个把多个 AI 编码工具统一编排起来的工程化脚手架。后来实际折腾了一圈&#xff0c…

2026/10/15 0:04:56 阅读更多 →
AI入门避坑指南:零基础6个月可验证学习路线

AI入门避坑指南:零基础6个月可验证学习路线

1. 这不是“学AI”的路线图,而是帮你绕开99%初学者陷阱的生存指南你搜“人工智能入门”,页面刷出来全是“30天速成大模型”“零基础玩转ChatGPT”“PythonTensorFlow年薪30万”。我盯着屏幕看了三分钟,默默关掉网页——不是内容不好&#xff…

2026/10/15 0:04:56 阅读更多 →
探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

1. 探矿数据进RAG之前,为什么必须先过清洗这一关1.1 探矿领域的文档生态:比想象中更杂做探矿业务的知识库和做通用知识库完全是两码事。通用场景里的文档再乱,基本也就是网页、PDF、Word这几类,格式相对规整。探矿业务呢&#xff…

2026/10/15 0:04:56 阅读更多 →
基于bbox的PDF文档解析:多栏重排与水印过滤实战

基于bbox的PDF文档解析:多栏重排与水印过滤实战

1. 项目概述:多栏和水印为什么是 RAG 解析里的两座山先说个场景。上个月我把一批技术论文和旧版产品手册塞进自建的 RAG 知识库,原以为 PDF 解析早就不是问题,结果检索结果让我怀疑人生:同一个问题的答案碎片化,有的片…

2026/10/15 0:04:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →