IR0NBYTE/Karukatta

GitHub: IR0NBYTE/Karukatta

一款内置混淆的原生机器码编译型语言,探索底层编译原理并生成难以逆向的小型可执行文件。

Stars: 6 | Forks: 0

# Karukatta
Karukatta Logo
一种生成原生机器码并内置混淆功能的编译型语言。不需要汇编器,也不需要链接器——直接将原始字节输出为可执行文件。 同时支持 **x86-64 Linux** 和 **ARM64 macOS**(Apple Silicon)。 ## 这是什么? Karukatta 是一个小型语言,我编写它是为了探索编译器是如何在底层工作的——从解析到最终对每条机器指令进行编码。特点是:它生成的每个二进制文件都可以在出厂时进行混淆。控制流平坦化、死代码注入、指令替换等功能都内置于编译器流水线中。 编译器全权负责所有流程。在 Linux 上,它直接写入 ELF 二进制文件(无需 NASM、无需 LD、没有任何中间工具)。在 macOS 上,它生成原始 ARM64 机器码并交给系统链接器进行代码签名。 ## 快速开始 ``` git clone https://github.com/IR0NBYTE/Karukatta.git cd Karukatta ./runner.sh ``` 编写程序: ``` let a = 5; let b = 3; let result = a * 2 + b; exit(result); // exits with 13 ``` 编译并运行: ``` ./build/karukatta program.kar -o program ./program echo $? # 13 ``` 启用混淆编译: ``` # level 1: instruction substitution ./build/karukatta program.kar -o program --obf=1 # level 2: control flow flattening + dead code injection ./build/karukatta program.kar -o program --obf=2 # different seed = different binary, same behavior ./build/karukatta program.kar -o program --obf=2 --seed=1337 ``` ## 语言特性 目前功能较为基础——支持整数、变量、比较、分支和循环。 ``` let score = 75; if (score >= 90) { exit(1); // A } else { if (score >= 70) { exit(2); // B } else { exit(3); // C } } ``` ``` // all the comparison operators work let a = 10; let b = 20; let eq = a == b; // 0 let ne = a != b; // 1 let lt = a < b; // 1 let sum = eq + ne + lt; exit(sum); // 2 ``` ``` // while loops let flag = 1; while (flag) { exit(42); } ``` **当前支持:** - `let` 绑定(不可变) - `+` `-` `*` `/` 算术运算 - `==` `!=` `<` `<=` `>` `>=` 比较运算 - `if` / `else` - `while` 循环 - `{ }` 作用域块(支持变量遮蔽) - `//` 注释 - `exit(n)` 设置进程退出码 **尚未支持:** - 函数 - 字符串 - 数组 - 可变变量 - 标准库 ## 编译器工作原理 ``` source.kar | v [Lexer] tokenizes the source | v [Parser] builds an AST (Pratt parsing for expressions) | v [IR] lowers to three-address code with virtual registers | v [Passes] optimization + obfuscation (if enabled) | v [Backend] encodes to real machine instructions | (x86-64: REX + opcode + ModR/M + SIB) | (ARM64: fixed 32-bit instruction encoding) v [Emitter] wraps in ELF (Linux) or Mach-O (macOS) | v executable ``` 在 Linux 平台上,编译器完全不依赖外部工具——它直接将 ELF 头、程序头表以及机器码字节写入文件,最终生成可执行文件。 ## 混淆功能 这是最有趣的部分。编译器包含一个 IR 传递系统,其中部分传递专门用于使输出更难以逆向工程。 **`--obf=1`** - 指令替换。简单操作会被替换为等价但更复杂的序列。例如 `ADD a, b` 可能变为 `SUB a, NEG(b)` 或 `a + b + noise - noise`。每次使用不同的 `--seed` 都会产生不同的替换策略。 **`--obf=2`** - 在 Level 1 基础上,增加控制流平坦化和死代码注入。CFF 将所有基本块重写为一个状态机调度器——每个块转移都通过一个对随机化状态变量的中央 `switch` 完成。死代码插入会在不影响输出的情况下,随处散布虚假计算。 结果:相同的源代码,每次编译都会生成截然不同的二进制文件。试试看: ``` ./build/karukatta example.kar -o bin1 --obf=2 --seed=111 ./build/karukatta example.kar -o bin2 --obf=2 --seed=222 # both produce the same exit code, but: diff <(xxd bin1) <(xxd bin2) # completely different binaries ``` ## 跨平台编译 编译器会自动检测当前平台,但你也可以手动指定目标: ``` # compile for x86-64 Linux (produces a standalone ELF, no dependencies) ./build/karukatta program.kar -o program --target=x86_64-linux # compile for ARM64 macOS ./build/karukatta program.kar -o program --target=arm64-macos # dump the IR to see what the compiler is doing ./build/karukatta program.kar -o program --dump-ir ``` ## 构建 你只需要一个 C++17 编译器。仅此而已。 ``` ./runner.sh ``` 或者手动构建: ``` g++ -std=c++17 main.cpp -o build/karukatta ``` 在 macOS 上测试 Linux 二进制文件,请使用 Docker: ``` ./build/karukatta program.kar -o build/program --target=x86_64-linux docker run --rm -v $(pwd)/build:/app ubuntu:22.04 sh -c '/app/program; echo $?' ``` ## 项目结构 ``` Karukatta/ ├── main.cpp # compiler driver + CLI ├── pkg/ │ ├── lexer.hpp # tokenizer │ ├── parser.hpp # recursive descent + Pratt parsing │ ├── arena.hpp # bump allocator for AST nodes │ ├── ir.hpp # intermediate representation │ ├── ir_builder.hpp # AST -> IR lowering │ ├── target/ │ │ ├── x86_64.hpp # x86-64 instruction encoder │ │ └── arm64.hpp # ARM64 instruction encoder │ ├── emit/ │ │ ├── elf.hpp # ELF64 binary writer │ │ └── macho.hpp # Mach-O binary writer │ └── passes/ │ ├── pass.hpp # pass interface + seeded RNG │ ├── cff.hpp # control flow flattening │ ├── insn_sub.hpp # instruction substitution │ └── dead_insert.hpp # dead code insertion ├── example/ # test programs ├── docs/ # language spec + architecture docs └── runner.sh # build script ``` ## 语法定义 ``` program ::= statement* statement ::= exit_stmt | let_stmt | scope | if_stmt | while_stmt exit_stmt ::= "exit" "(" expression ")" ";" let_stmt ::= "let" identifier "=" expression ";" scope ::= "{" statement* "}" if_stmt ::= "if" "(" expression ")" scope ("else" scope)? while_stmt ::= "while" "(" expression ")" scope expression ::= term (operator term)* operator ::= "+" | "-" | "*" | "/" | "==" | "!=" | "<" | "<=" | ">" | ">=" term ::= integer_literal | identifier | "(" expression ")" ``` ## 许可证 MIT
标签:Apple Silicon, ARM64, ARM64 macOS, compiled language, native code, obfuscation, x86-64, x86-64 Linux, 二进制混淆, 代码混淆, 原生机器码, 可执行文件, 可执行混淆, 底层编码, 指令替换, 指令混淆, 控制流平坦化, 无汇编器, 无链接器, 机器码生成, 死代码注入, 直接编码, 种子随机化, 程序混淆, 编译器内置混淆, 编译器探索, 编译语言, 自编译