{"id":13490051,"url":"https://github.com/xoreaxeaxeax/movfuscator","last_synced_at":"2025-03-28T05:31:53.936Z","repository":{"id":33806938,"uuid":"37501621","full_name":"xoreaxeaxeax/movfuscator","owner":"xoreaxeaxeax","description":"The single instruction C compiler","archived":false,"fork":true,"pushed_at":"2024-05-29T18:29:10.000Z","size":12232,"stargazers_count":9437,"open_issues_count":26,"forks_count":396,"subscribers_count":206,"default_branch":"master","last_synced_at":"2024-10-31T03:35:29.566Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Battelle/movfuscator","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xoreaxeaxeax.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-16T01:49:40.000Z","updated_at":"2024-10-30T12:57:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/xoreaxeaxeax/movfuscator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xoreaxeaxeax%2Fmovfuscator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xoreaxeaxeax%2Fmovfuscator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xoreaxeaxeax%2Fmovfuscator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xoreaxeaxeax%2Fmovfuscator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xoreaxeaxeax","download_url":"https://codeload.github.com/xoreaxeaxeax/movfuscator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245978200,"owners_count":20703675,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T19:00:39.954Z","updated_at":"2025-03-28T05:31:52.108Z","avatar_url":"https://github.com/xoreaxeaxeax.png","language":"C","funding_links":[],"categories":["C","Compiler","Tools and Frameworks","\u003ca id=\"1d9dec1320a5d774dc8e0e7604edfcd3\"\u003e\u003c/a\u003e工具-新添加的","Pentesting"],"sub_categories":["Language Agnostic","\u003ca id=\"8f1b9c5c2737493524809684b934d49a\"\u003e\u003c/a\u003e文章\u0026\u0026视频","Exploits"],"readme":"```\n       ___     ___            ___    ___     ___     ___     ___          ___     ___      \n      /\\  \\   /\\  \\    ___   /\\__\\  /\\  \\   /\\__\\   /\\__\\   /\\  \\        /\\  \\   /\\  \\    .\n     |::\\  \\ /::\\  \\  /\\  \\ /:/ _/_ \\:\\  \\ /:/ _/_ /:/  /  /::\\  \\  ___ /::\\  \\ /::\\  \\   .\n     |:::\\  \\:/\\:\\  \\ \\:\\  \\:/ /\\__\\ \\:\\  \\:/ /\\  \\:/  /  /:/\\:\\  \\/\\__\\:/\\:\\  \\:/\\:\\__\\  .\n   __|:|\\:\\  \\  \\:\\  \\ \\:\\  \\ /:/  /  \\:\\  \\ /::\\  \\  /  _:/ /::\\  \\/  //  \\:\\  \\ /:/  /   \n  /::::|_\\:\\__\\/ \\:\\__\\ \\:\\__\\:/  / \\  \\:\\__\\:/\\:\\__\\/  /\\__\\:/\\:\\__\\_//__/ \\:\\__\\:/__/___ \n  \\:\\~~\\  \\/__/\\ /:/  / |:|  |/  /\\  \\ /:/  // /:/  /\\ /:/  //  \\/__/ \\\\  \\ /:/  /::::/  / \n   \\:\\  \\  \\:\\  /:/  / \\|:|  |__/\\:\\  /:/  // /:/  /  /:/  //__/:/\\:\\  \\\\  /:/  //~~/~~~~  \n    \\:\\  \\  \\:\\/:/  /\\__|:|__|  \\ \\:\\/:/  //_/:/  /:\\/:/  /:\\  \\/__\\:\\  \\\\/:/  /:\\~~\\     .\n     \\:\\__\\  \\::/  /\\::::/__/:\\__\\ \\::/  /  /:/  / \\::/  / \\:\\__\\   \\:\\__\\:/  / \\:\\__\\    .\n      \\/__/   \\/__/  ~~~~    \\/__/  \\/__/   \\/__/   \\/__/   \\/__/    \\/__/ __/   \\/__/    2\n                                                                                           \n\n M/o/Vfuscator2\n\n github.com/xoreaxeaxeax/movfuscator :: the single instruction C compiler\n chris domas           @xoreaxeaxeax\n\n```\n\n## Overview\n\nThe M/o/Vfuscator (short 'o', sounds like \"mobfuscator\") compiles programs into\n\"mov\" instructions, and only \"mov\" instructions.  Arithmetic, comparisons,\njumps, function calls, and everything else a program needs are all performed\nthrough mov operations; there is no self-modifying code, no transport-triggered\ncalculation, and no other form of non-mov cheating.\n\nThe basic effects of the process can be seen in [overview](overview/), which\nillustates compiling a simple prime number function with gcc and the\nM/o/Vfuscator.\n\nAssembly:\n\n GCC                               | M/o/Vfuscator\n:---------------------------------:|:---------------------------------:\n ![gcc asm](overview/gcc_asm.png)  | ![mov asm](overview/mov_asm.png)\n\nControl flow graphs:\n\n GCC                               | M/o/Vfuscator\n:---------------------------------:|:---------------------------------:\n ![gcc CFG](overview/gcc_cfg.png)  | ![mov CFG](overview/mov_cfg.png)\n\nIn action:\n\n| movcc prime.c -o prime                     |\n|:------------------------------------------:|\n| ![demo_mov](overview/demo_mov.gif)         |\n\nOf course, as a complete C compiler, it is not limited to simple programs:\n\n| movcc nibbles.c -o nibbles -lncurses       |\n|:------------------------------------------:|\n| ![demo_nibbles](overview/demo_nibbles.gif) |\n\nThe compiler currently targets the C programming language and x86 processor\narchitecture, but is easily adaptable to other languages and architectures.\n\n## Building\n\nThe M/o/Vfuscator uses LCC as the compiler frontend.  The included build script\nwill automatically download LCC, configure it for the mov backend, and build the\nM/o/Vfuscator tool.\n\n_If you are building on a 64 bit system, ensure that you have a 32 bit libc\navailable_ (for example, 'apt-get install libc6-dev-i386' or 'yum install\nglibc-devel.i686').\n\n```\ngit clone https://github.com/xoreaxeaxeax/movfuscator\ncd movfuscator\n./build.sh\nsudo ./install.sh\n```\n\nIf you have trouble building LCC, you can get more details on the LCC build\nprocess at: https://drh.github.io/lcc/current/doc/install.html\n\n## Testing\n\nCheck that the build was successful with the check script.  This will\nautomatically download an open source AES implementation, compile it to mov\ninstructions, objdump the result, and run the program.\n\n```\n./check.sh\n```\n\n## Usage\n\nCompile programs as you would with any traditional C compiler:\n```\nmovcc example.c -o example\n```\n\n## Flags\n\nFlags are passed to the compiler proper via -Wfflag, e.g. -Wf--no-mov-id\n\n```\n--mov-id\n  Add reference instructions for each basic block to assist debugging.\n\n--no-mov-id\n  Do not add reference instructions.  This is the default.\n\n--mov-flow\n  Use mov instructions in implementing control flow.  This is the default.\n\n--no-mov-flow\n  Use jmp instructions in implementing control flow.  This will substantially\n  speed up execution in larger projects.  If using floating point operations\n  with this flag, link to softfloat*_cf.o instead of the fully obfuscated\n  libraries.\n\n--mov-extern\n  Use mov instructions to implement external function calls.  This is the\n  default.\n\n--no-mov-extern\n  Use jmp instructions to implement external function calls.  This is useful for\n  debugging.\n\n--mov-loop\n  Use mov instructions to implement the primary execution loop.  This is the\n  default.\n\n--no-mov-loop\n  Use jmp instructions to implement the primary execution loop.  This is useful\n  for debugging.\n\n--crt0\n  Build the M/o/Vfuscator crt0 library (_start routines).\n\n--crtf\n  Build the M/o/Vfuscator crtf library (primary execution loop routines).\n\n--crtd\n  Build the M/o/Vfuscator crtd library (data tables).\n\n--crt\n  Same as --crt0 --crtf --crtd.\n```\n\n## Floats\n\n* The M/o/Vfuscator contains a complete mov-only floating point emulator.  Since\n  it is approximately 500,000 instructions, you must explicitly link to it if\n  you need it.  Use the smaller softfloat32.o if you only use floats,\n  softfloat64.o if you need floats and doubles, and softfloatfull.o for a full\n  IEEE floating point emulator.\n\n  ```\n  movcc your_code.c movfuscator/lib/softfloat32.o\n  ```\n\n## Recommendations\n\n* Due to the lookup tables used for arithmetic, the symbol tables in the\n  compiled binary can be extremely large.  Stripping symbols with the -s flag\n  can cut the final binary size by half.\n\n  ```\n  movcc example.c -s\n  ```\n\n## Warnings\n\n* You may occassionally run into ABI conflicts when calling into libraries\n  compiled with other compilers.  These are relatively rare, but do\n  occassionally pop up.  Watch out for:\n\n  * Passing a pointer to a callback function into a library.  The M/o/Vfuscator\n\twill clobber registers the library was expecting to have preserved.\n\n  * Using the long long type.  The M/o/Vfuscator uses a 32 bit long long; your\n    library may be expecting 64 bits.\n\n  * Such ABI issues are relatively rare; they can be roughly fixed with some\n\tcoding caution, or more robustly fixed by recompiling your libraries with\n\tthe M/o/Vfuscator.\n\n* LCC is a C89 compiler.  If you try to compile C99 code, you will get errors.\n  Don't use C99 features like bool, for (int ...), etc.  Don't declare variables\n  in the middle of blocks.\n\n* To generate code correctly, the M/o/Vfuscator must be able to determine\n  when a call is being made to a shared library.  If a function is used before\n  it is declared, this determination may be incorrect.  If your executable\n  hangs, it may be because a function prototype was missing.\n\n* LCC strongly enforces type and const rules.  You may not be able to compile\n  code with unsafe type or const conversions, unless you explicitly cast for it.\n\n* These are by far the most common causes of the M/o/Vfuscator \"breaking\".  Make\n  sure you handle these before you try to compile your code.\n\n## Limitations\n\n* Calls to external functions (printf, etc) through function pointers are not\n  yet implemented.  That is,\n\n    ```\n    getchar()\n    ```\n\n  works, but\n  \n    ```\n    int (*f)(void)=getchar; f();\n    ```\n\n  does not.\n\n  If you need to do this, wrap the function internally:\n\t\n    ```\n    int g(void) { return getchar(); }\n    int (*f)(void)=g; f();\n    ```\n\n## MOV violations\n\n* When calling into libraries compiled with other compilers, an occassional\n  non-mov instruction is necessary.  This can be fixed by compiling all of your\n  libraries with the M/o/Vfuscator.  To be clear, this is not a limitation of\n  the M/o/Vfuscator, or a violation of mov Turing-completeness - non-mov\n  instructions are only necessary to accommodate non-mov calling conventions.\n  If you do not recompile your libraries, the non-mov instructions are as\n  follows:\n\n  * A single jmp instruction at the end of the program is used to dispatch\n\tthe program's external functions.  If you wish to avoid this jmp instruction\n\tto have a truly mov only program, compile with --no-mov-extern, and avoid\n\tcalling into shared libraries.  If you still need an external function,\n\trecompile the library with the M/o/Vfuscator, and statically link it to your\n\tprogram.\n\n  * An fstp instruction is used following every call to an external function\n\treturning a float or a double.  This is because there is no way to access\n\tthe x86 floating point registers with a mov instruction.  To get rid of the\n\tfstp instruction, recompile your libraries to use the M/o/Vfuscator's\n\tfloating point emulator, instead of the x86 FPU.\n\n## Post-processing\n\nThe M/o/Vfuscator post-processors take assembly from the M/o/Vfuscator and\ntranslate it for additional obfuscation, new instructions, or optimization.  At\nsome point they may be integrated into the actual compiler; for now they are\nseparate scripts.\n\nCurrent post-processing scripts include:\n\n  * Instruction shuffling and register renaming, to prevent simple decompilation\n    through pattern matching.\n\n  * Assembly translation into only: XOR, SUB, ADD, XADD, ADC, SBB, AND/OR,\n    PUSH/POP, 1-bit shifts, or CMPXCHG/XCHG instructions.\n\n  * Translation into only 32 bit register-to-memory and memory-to-register\n\ttransfers.  This may assist in translating M/o/Vfuscated code to other\n\tinstructions or architectures.\n\n  * Translation into only indexed addressing forms.\n\n  * Randomization of the above translations.\n\n## Other source languages\n\n* The M/o/Vfuscator currently uses C as the source language.  The following\n  proof of concept, provided by Adam Schwalm, illustrates how to use a variety\n  of other source languages:\n\n  ```\n  # Compile c++ to llvm bytecode\n  clang++ -S -emit-llvm -o bytecode.ll $1\n\n  # Convert bytecode to C\n  llc -march=c -o code.c bytecode.ll\n\n  # 'fix' static inline. This is a workaround for a bug\n  # in one of the parsers, I think.\n  sed -i 's/static inline.*//' code.c\n\n  # hack\n  sed -i 's/extern unsigned char \\*__dso_handle;/unsigned char \\*__dso_handle=0;/' code.c\n\n  # Compile the resulting C as usual (but with the c++ stdlib)\n  movcc code.c -lstdc++\n  ```\n\n## Other architectures\n\n* A common observation on the M/o/Vfuscator output is that it uses all available\n  forms and addressing modes for the mov instruction.  Although the point was\n  never anything different, the RISC post-processor (risc.py) illustrates\n  transforming the program into RISC-like data transfers, reducing the program\n  to 4 byte memory accesses, only indexed addressing modes, and only two\n  registers.  With this, all mov instructions become either \n  \"mov esi/edi, [BASE+esi/edi]\" or \"mov [BASE+esi/edi], esi/edi\", where BASE is\n  some constant address.  This should demonstrate the applicability of the\n  approach on non-x86 architectures, and deter complaints about the diversity of\n  the x86 mov instruction.\n\n## Notes\n\n* While Dolan's paper required a jmp instruction, the M/o/Vfuscator does not -\n  it uses a faulting mov instruction to achieve the infinite execution loop.  If\n  you're worried that this is still \"jumping\", the same effect could be achieved\n  through pages aliased to the same address, wrapping execution around the upper\n  range of memory, ring 0 exception handling, or simply repeating the mov loop\n  indefinitely.  A jmp _is_ currently used to dispatch external functions - if\n  this is a problem, avoid using external functions, or compile libraries with\n  the M/o/Vfuscator as well.\n\n## History\n\n* The original M/o/Vfuscator (M/o/Vfuscator 1.0) compiles programs from the\n  esoteric language BrainF@$!, and is best used in conjunction with the BFBASIC\n  compiler by Jeffry Johnston.  It is still available as a proof of concept in\n  the [poc](poc/) directory.\n\n* M/o/Vfuscator2 is a complete single-instruction C compiler.\n\n## F.A.Q.\n\n* Q: Why did you make this?\n  A: I thought it would be funny.\n\n## References\n\n* A presentation explaining the ideation, design, and goals of the M/o/Vfuscator\n  can be found [here](https://www.youtube.com/watch?v=R7EEoWg6Ekk).\n\n* Slides outlining the mechanisms used are [here](slides/domas_2015_the_movfuscator.pdf).\n\n* The inspiration for the compiler is the paper [\"mov is Turing-complete\", \n  by Stephen Dolan](http://stedolan.net/research/mov.pdf).\n\n## Author\n\n* chris domas, @xoreaxeaxeax\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxoreaxeaxeax%2Fmovfuscator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxoreaxeaxeax%2Fmovfuscator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxoreaxeaxeax%2Fmovfuscator/lists"}