{"id":24974419,"url":"https://github.com/sub1to/ctninja","last_synced_at":"2025-04-19T03:21:20.382Z","repository":{"id":275431620,"uuid":"926027992","full_name":"sub1to/ctninja","owner":"sub1to","description":"Compile-time string encryption and import obfuscation for Windows PE32(+) binaries","archived":false,"fork":false,"pushed_at":"2025-02-25T15:59:44.000Z","size":92,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"public","last_synced_at":"2025-03-29T06:45:04.198Z","etag":null,"topics":["compile","compile-time","cplusplus","encryption","imports","joaat","joaat64","ninja","obfuscation","pe32","pe32plus","peb","peb-walking","security","stealth","string","time","windows","xorstr"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sub1to.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":"CONTRIBUTING.MD","funding":null,"license":"LICENSE.MD","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-02T11:23:40.000Z","updated_at":"2025-03-16T12:32:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"0df016fe-6a17-4a41-958a-6f543d74f0f2","html_url":"https://github.com/sub1to/ctninja","commit_stats":null,"previous_names":["sub1to/ctninja"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sub1to%2Fctninja","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sub1to%2Fctninja/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sub1to%2Fctninja/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sub1to%2Fctninja/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sub1to","download_url":"https://codeload.github.com/sub1to/ctninja/tar.gz/refs/heads/public","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249598515,"owners_count":21297465,"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":["compile","compile-time","cplusplus","encryption","imports","joaat","joaat64","ninja","obfuscation","pe32","pe32plus","peb","peb-walking","security","stealth","string","time","windows","xorstr"],"created_at":"2025-02-03T20:04:03.615Z","updated_at":"2025-04-19T03:21:20.360Z","avatar_url":"https://github.com/sub1to.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CTNinja: Compile-Time Ninja  \n\n**Compile-time string encryption and import obfuscation for Windows PE32(+) binaries**  \n\n\u003cdiv align=\"center\"\u003e\n  \u003ca style=\"margin: 2px;\"\u003e\n    \u003cimg alt=\"LICENSE-MIT\" src=\"https://img.shields.io/badge/language-C%2B%2B20-blue?logo=C%2B%2B\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/sub1to/ctninja/blob/public/LICENSE.MD\" style=\"margin: 2px;\"\u003e\n    \u003cimg alt=\"LICENSE-MIT\" src=\"https://img.shields.io/badge/LICENSE-MIT-green\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n---\n\n## Features  \n- 🔒 **Compile-Time String Encryption**  \n  Obfuscate strings at compile-time using the `_X` operator to avoid plaintext exposure in binaries.  \n  ```cpp\n  auto str = \"SensitiveData\"_X; // Encrypted at compile-time\n  printf(str.c_str());\n  ```\n  \n- 🎯 **JOAAT Hashing**  \n  Generate Jenkins One-At-A-Time (JOAAT) hashes at compile-time (`_JOAAT`/`_JOAAT64`) or runtime (`joaat`/`wjoaat`/`joaat64`/`wjoaat64`).  \n  ```cpp\n  constexpr auto hash32 = \"Kernel32.dll\"_JOAAT;   // Compile-time hash\n  constexpr auto hash64 = \"Kernel32.dll\"_JOAAT64; // Compile-time hash\n  ```\n\n- 🕵️ **PEB Walking \u0026 Stealthy Imports**  \n  Resolve modules and exports without `GetProcAddress` or static imports:  \n  ```cpp\n  auto hModule = ctninja::xport::get_module(\"Kernel32.dll\"_JOAAT);\n  auto pFunc   = ctninja::xport::get_export(hModule, \"CloseHandle\"_JOAAT);\n  ```\n\n- 💻 **Operator-Driven Function Calls**  \n  Call obfuscated imports directly via the `$$` syntax:  \n  ```cpp\n  // Predefined in def.h: fpCreateThread, fpLoadLibraryA, fpCloseHandle, etc.\n  $$(Kernel32.dll, CloseHandle, m_hPipeThread); // Resolves and calls at runtime\n  ```\n  \n- 🛡️ **Secure Runtime Value Obfuscation**  \n  Protect in-memory values with XOR + bit rotation using `SecureValue32`/`SecureValue64`. Keys are re-rolled on every access. \n  Most operators are implemented, and it will implicitly cast to it's template type, allowing you to use SecureValue as if\n  it is a built-in type.\n  \n\n- **PE32+ Focus**  \n  Built for modern Windows binaries, with minimal overhead.\n\n---\n\n## Installation  \nCTNinja is built using **Premake5**. Follow these steps:  \n\n1. **Generate Project Files**  \n   Run `build.bat` (Visual Studio 2022) or `premake5 vs2022`. \n\n2. **Build the Library**  \n   Compile the generated project to produce `ctninja.lib`.  \n\n3. **Link in Your Project**  \n   Add `ctninja.lib` and include the `ctninja.h` header.  \n\n\n---\n\n## Usage  \n### 1. Obfuscate Strings  \n```cpp\n#include \u003cctninja/ctninja.h\u003e\n\nprintf(\"Hello, Malware Analyst\"_X.c_str());\n```\n\n⚠️ **Critical**:  \nDo not call `c_str()` multiple times on the same object!\n\nThe data is decrypted on the stack when you call `c_str()`. Calling it again will re-encrypt the data.\n\n- ❌\n   ```cpp\n   auto str = \"SensitiveData\"_X; // Encrypted at compile-time\n   printf(str.c_str());\n   printf(str.c_str());\n   ```\n- ✅\n   ```cpp\n   auto secstr = \"SensitiveData\"_X; // Encrypted at compile-time\n   auto str = secstr.c_str();\n   printf(str);\n   printf(str);\n   ```\n- ✅\n   ```cpp\n   printf(\"SensitiveData\"_X.c_str());\n   printf(\"SensitiveData\"_X.c_str());\n   ```\n\n### 2. Resolve Modules/Exports via PEB  \n```cpp\n#include \u003cctninja/ctninja.h\u003e\n\nHMODULE  hKernel32      = ctninja::xport::get_module(\"Kernel32.dll\"_JOAAT);\nFARPROC  pCreateFile    = ctninja::xport::get_export(hKernel32, \"CreateFileW\"_JOAAT);\n```\n\n### 3. Call Functions Stealthily  \n```cpp\n#define CTNINJA_MAGIC_IMPORT\n#define CTNINJA_MAGIC_IMPORT_THROW_ON_FAILURE\n#include \u003cctninja/ctninja.h\u003e\n\ntry{\n\tHANDLE   hFile          = $$(Kernel32.dll, CreateFileW, L\"file.txt\", GENERIC_READ, ...);\n}\ncatch(CallException const\u0026 e)\n{\n\tctninja::$printf(\"%s\\n\"_X.c_str(), e.what());\n}\n```\n\n- `CTNINJA_MAGIC_IMPORT` enables the `$` and `$$` macros\n- `CTNINJA_MAGIC_IMPORT_THROW_ON_FAILURE` enables exceptions in `$$` if the function is not found\n\n#### 3.1 Defining Function Signatures  \nFor `$$()` to work, **you must define the function signature** as `fp\u003cFunctionName\u003e` in your code.  \nPredefined signatures for common Windows APIs (e.g., `fpCreateThread`, `fpLoadLibraryA`) are in [`ctninja/include/def.h`](include/def.h).  \n\nFor custom functions, define the typedef **before using `$$()`**:  \n```cpp\n// Example for a custom function\ntypedef BOOL (WINAPI* fpSomeObscureFunction)(DWORD param1, LPCSTR param2);\n// Now call it via:\n$$(SomeDll.dll, SomeObscureFunction, 123, \"param\");\n```\n\n⚠️ **Critical**:  \n- The typedef **must** match the exact function signature.  \n- The naming convention **must** be `fp\u003cFunctionName\u003e` (case-sensitive).  \n\n\n### 4. JOAAT Hashing  \n\n#### 4.1 Compile-Time JOAAT Hashing  \n```cpp\n#include \u003cctninja/ctninja.h\u003e\n\nu32      ulHash32       = \"hash_me\"_JOAAT;     // Compile-Time JOAAT for static strings\nu64      ulHash64       = \"hash_me\"_JOAAT64;   // Compile-Time JOAAT64 for static strings\n```\n\n#### 4.2 Runtime JOAAT Hashing  \n```cpp\n#include \u003cctninja/ctninja.h\u003e\n\nu32      ulHash32       = ctninja::joaat(\"hash_me\");     // Runtime JOAAT for dynamic strings\nu64      ulHash64       = ctninja::wjoaat64(L\"hash_me\"); // Runtime JOAAT64 for dynamic strings\n```\n\n\n### 5. Protect Sensitive Values in Memory\n\n#### 5.1 float\n```cpp\n#include \u003cctninja/ctninja.h\u003e\n\ntypedef ctninja::SecureValue32\u003cfloat\u003e SV_Float;\n\nSV_Float secretFloat = 123.45f; // Stored encrypted in memory\n\n// Use like a normal value (automatically encrypts/decrypts):\nsecretFloat += 10.0f;\nprintf(\"%f\", (float)secretFloat);\n```\n\n#### 5.2 BYTE*\n```cpp\n#include \u003cctninja/ctninja.h\u003e\n\n// Architecture-agnostic definition (auto-chooses 32/64-bit)\n#ifdef _M_X64\ntypedef ctninja::SecureValue64\u003cBYTE*\u003e SVP_BYTE;\n#else\ntypedef ctninja::SecureValue32\u003cBYTE*\u003e SVP_BYTE;\n#endif\n\nSVP_BYTE pSec;\n\npSec    = pArray;\n*pSec\t= 0x1f;\npSec[1]\t= 0x2e;\n```\n\n---\n\n## Notes  \n- **Windows Only**: Designed for PE32(+) binaries (x86/x64).  \n- **C++20 Required**: Relies on `constexpr`/`consteval` for compile-time magic.  \n- **Antivirus Warnings**: Obfuscation may trigger heuristic detections. Test thoroughly.  \n\n---\n\n## Authors  \n- **sub1to** - *Initial work* - [sub1to](https://github.com/sub1to)  \n  \nSee also the list of [contributors](https://github.com/sub1to/ctninja/contributors) who participated in this project.  \n\n## License  \nMIT License. See [LICENSE.MD](LICENSE.MD)\n\n## Contributing  \nPRs and issues welcome! See [CONTRIBUTING.MD](CONTRIBUTING.MD) for guidelines.  ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsub1to%2Fctninja","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsub1to%2Fctninja","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsub1to%2Fctninja/lists"}