movfuscator, 单指令C 编译器

分享于 

12分钟阅读

GitHub

  繁體 雙語
The single instruction C compiler
  • 源代码名称:movfuscator
  • 源代码网址:http://www.github.com/xoreaxeaxeax/movfuscator
  • movfuscator源代码文档
  • movfuscator源代码下载
  • Git URL:
    git://www.github.com/xoreaxeaxeax/movfuscator.git
    Git Clone代码到本地:
    git clone http://www.github.com/xoreaxeaxeax/movfuscator
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/xoreaxeaxeax/movfuscator
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    
     ___ ___ ___ ___ ___ ___ ___ ___ ___ 
    
    
    //___/__//__/__///. 
    
    
     |::/:://:/_/_ :/:/_/_/:///:: ___/::/::. 
    
    
     |::: :/: : ://__ : ://:///:/:/__:/: :/:__. 
    
    
     __|:|: : :/://:/::/_://::///:/://
    
    
    /::::|_:__/:__ :__://:__:/:__//__:/:___//__/:__:/__/___ 
    
    
     :~~/__//://|:| |///:////:///:////__//://:::://
    
    
     : :/://|:| |__/:/:////:///:///__/:/: /:///~~/~~~~ 
    
    
     : :/://__|:|__| :/:///_/://:/://:/__: /://:~~. 
    
    
     :__ :://::::/__/:__ ::///://:://:__ :__://:__. 
    
    
    /__//__/~~~~/__//__//__//__//__//__/__//__/2
    
    
    
     M/o/Vfuscator2
    
    
    
     github.com/xoreaxeaxeax/movfuscator :: the single instruction C compiler
    
    
     chris domas @xoreaxeaxeax
    
    
    
    
    

    概述

    M/o/Vfuscator ( 短''听起来像"mobfuscator") 将程序编译为"mov"指令,只有"mov"指令。 算术,比较,跳转,函数调用以及它的他程序都是通过of运行,没有自修改码。

    概述中可以看到这个过程的基本效果,它使用gcc和编译一个简单的素数函数,并将它的转换为

    程序集:

    GCC M/o/Vfuscator
    gcc asmmov asm

    控制流图:

    GCC M/o/Vfuscator
    gcc CFGmov CFG

    实际操作:

    movcc prime.c -o素数
    demo_mov

    当然,作为完整的C 编译器,它不仅限于简单程序:

    movcc nibbles.c -o贪食蛇 -lncurses
    demo_nibbles

    编译器目前面向C 编程语言和x86处理器架构,但很容易适应其他语言和架构。

    建筑

    M/o/Vfuscator 使用LCC作为编译器前端。 包含的构建脚本将自动下载 LCC,为mov后端配置它,并构建 M/o/Vfuscator 工具。

    如果你正在构建一个 64位系统,请确保你拥有一个 32位libc可用安装 libc6-dev-i386'或者或或者'yum安装 glibc-devel。i686')。

    
    git clone https://github.com/xoreaxeaxeax/movfuscator
    
    
    cd movfuscator
    
    
    ./build.sh
    
    
    sudo./install.sh
    
    
    
    

    在生成LCC时,你可以在以下位置获得有关LCC生成过程的更多详细信息: http://drh.github.io/lcc/current/doc/install.html

    测试

    检查生成脚本是否成功。 这将自动下载一个开源的AES实现,编译它到mov指令,结果,并运行程序。

     
    ./check.sh
    
    
    
     

    用法

    像使用任何传统的C 编译器一样编译程序:

    
    movcc example.c -o example
    
    
    
    

    标志

    标志通过 -Wfflag。比如 -Wf--no-mov-id传递给编译器

    
    --mov-id
    
    
     Add reference instructions for each basic block to assist debugging.
    
    
    
    --no-mov-id
    
    
     Do not add reference instructions. This is the default.
    
    
    
    --mov-flow
    
    
     Use mov instructions in implementing control flow. This is the default.
    
    
    
    --no-mov-flow
    
    
     Use jmp instructions in implementing control flow. This will substantially
    
    
     speed up execution in larger projects.
    
    
    
    --mov-extern
    
    
     Use mov instructions to implement external function calls. This is the
    
    
     default.
    
    
    
    --no-mov-extern
    
    
     Use jmp instructions to implement external function calls. This is useful for
    
    
     debugging.
    
    
    
    --mov-loop
    
    
     Use mov instructions to implement the primary execution loop. This is the
    
    
     default.
    
    
    
    --no-mov-loop
    
    
     Use jmp instructions to implement the primary execution loop. This is useful
    
    
     for debugging.
    
    
    
    --crt0
    
    
     Build the M/o/Vfuscator crt0 library (_start routines).
    
    
    
    --crtf
    
    
     Build the M/o/Vfuscator crtf library (primary execution loop routines).
    
    
    
    --crtd
    
    
     Build the M/o/Vfuscator crtd library (data tables).
    
    
    
    --crt
    
    
     Same as --crt0 --crtf --crtd.
    
    
    
    

    浮点数

    • M/o/Vfuscator 包含一个完整的活动浮点 模拟器。 由于它是大约 500,000条指令,如果需要,你必须显式地链接。 如果你只使用浮点。softfloat64.o,如果需要浮点和双精度,则使用较小的softfloat32.o,而对于完整的IEEE浮点。

      
      movcc your_code.c movfuscator/lib/softfloat32.o
      
      
      
      

    推荐

    • 由于用于算术的查找表,编译后的二进制中的符号表可能非常大。 使用-s标志删除符号可以将最终的二进制大小减少一半。

      
      movcc example.c -s
      
      
      
      

    警告

    • 当调用用其他编译器编译的库时,你可能偶尔遇到ABI冲突。 这些比较少见,但偶尔会出现。 注意:

      • 将指向回调函数的指针传递到库。 M/o/Vfuscator 将对库预期保留的寄存器进行攻击。

      • 使用长长类型。 在 M/o/Vfuscator 中使用 32位 long long; 你的库可能需要 64位。

      • 此类ABI问题比较少见;它们可以通过一些编码警告来解决,或者通过使用 M/o/Vfuscator. 代码重新编译库来更加可靠地修复。

    • LCC是一个C89编译器。 如果尝试编译C99代码,则会得到错误。 不要使用( int。) 之类的特性,对于,等等 不会在块的中间声明变量。

    • 若要正确生成代码,M/o/Vfuscator 必须能够确定调用什么时候对共享库进行调用。 如果函数在声明前使用,则这里确定可能不正确。 如果可执行文件挂起,可能是由于缺少函数 Prototype。

    • LCC强实施类型和常数规则。 除非显式转换,否则可能无法编译具有不安全类型或者const转换的代码。

    • 这些是 M/o/Vfuscator"断开"最常见的原因。 在尝试编译代码之前,请确保处理这些代码。

    限制

    • 通过函数指针调用外部函数( printf等) 还未实现。 也就是

       
      getchar()
      
      
      
       

      但是,

      
      int (*f)(void)=getchar; f();
      
      
      
      

      不。

      如果需要这样做,请在内部包装函数:

      
      int g(void) { return getchar(); }
      
      
      int (*f)(void)=g; f();
      
      
      
      

    MOV违例

    • 当调用与其他编译器编译的库时,需要使用occassional非mov指令。 这可以通过编译所有的库来确定,这不是 M/o/Vfuscator,的限制,也不是 M/o/Vfuscator.的完整性。 如果不重新编译库,则非mov指令如下所示:

      • 程序末尾的一个jmp指令用于调度程序函数的外部。 如果希望避免这种jmp指令拥有真正的mov程序,使用--no-mov-extern编译,并避免调用共享库。 如果仍需要外部函数,请使用 M/o/Vfuscator, 和静态链接该程序来重新编译库。

      • 在对返回float或者double的外部函数每次调用之后都使用fstp指令。 这是因为没有办法使用mov指令访问x86浮点寄存器。 为了消除fstp指令,重新编译库以使用 M/o/Vfuscator's 浮点 模拟器,而不是 x86 FPU。

    后处理

    M/o/Vfuscator post处理器从 M/o/Vfuscator 获取程序集并将它的转换为额外的混淆。新指令或者优化。 在某些时候,它们可以集成到实际的编译器中;现在它们是独立的脚本。

    当前的后处理脚本包括:

    • 指令洗牌和 register 重命名,通过 Pattern 匹配防止简单的反编译。

    • 程序集翻译只有:异步。子。添加。XADD ,和/或者,。1-bit 移位或者 cmpxchg/xchg指令。

    • 转换为 32位register-to-memory和memory-to-register传输。 这可能有助于将 M/o/Vfuscated 代码转换为其他指令或者体系结构。

    • 仅转换为索引寻址表单。

    • 上面 翻译的随机化。

    其他源语言

    • M/o/Vfuscator 当前使用C 作为源语言。 Adam Schwalm提供的下列概念证明了如何使用各种它的他源语言:

      
      # Compile c++ to llvm bytecode
      
      
      clang++ -S -emit-llvm -o bytecode.ll $1
      
      
      
      # Convert bytecode to C
      
      
      llc -march=c -o code.c bytecode.ll
      
      
      
      # 'fix' static inline. This is a workaround for a bug
      
      
      # in one of the parsers, I think.
      
      
      sed -i 's/static inline.*//' code.c
      
      
      
      # hack
      
      
      sed -i 's/extern unsigned char *__dso_handle;/unsigned char *__dso_handle=0;/' code.c
      
      
      
      # Compile the resulting C as usual (but with the c++ stdlib)
      
      
      movcc code.c -lstdc++
      
      
      
      

    其他体系结构

    • 对 M/o/Vfuscator 输出的一个常见观察是它使用了所有可用的格式和mov指令的寻址模式。 这个问题是,RISC后置处理器( risc.py ) 将程序转换为RISC字节内存访问,减少程序到 4字节内存访问,只有索引寻址模式和两个寄存器。 这样,所有mov指令都变成"。[BASE+esi/edi] esi/edi,"或者"mov [BASE+esi/edi],esi/edi",其中基是一些常量地址。 这应该演示对non-x86架构的适用性,并阻止对x86指令的集成的抱怨。

    注释

    • to需要一个rtc指令,M/o/Vfuscator 不会使用一个错误的ipqos指令来实现无限执行循环。 如果担心这种情况仍然存在,可以通过页面别名相同的地址来实现相同的效果,绕上内存的上限,或者仅仅重复运行mov循环。 如果这个问题是一个问题,目前用来分派外部函数- 如果这是一个问题,请避免使用外部函数,或者使用 M/o/Vfuscator 编译库。

    历史

    • 最初的M/o/Vfuscator (M/o/Vfuscator 1.0编译程序来自古典语言 BrainF@$,并且最好与BFBASIC编译器一起使用 Jeffry by。 它仍然可以作为 poc目录中的概念证明。

    • M/o/Vfuscator2 是一个完整的指令C 编译器。

    F.A. Q。

    • 问:你为什么要这样做? A: 我觉得这很有趣。

    引用

    作者

    • chris domas,@xoreaxeaxeax

    COM  SIN  compiler  
    相关文章