feat: Improve Custom Pass feature code, docs, and demos

- Improved the Custom Pass code to align with Ryujin coding standards.
- Added clear and helpful comments for better understanding of how RyujinCustomPassDemo works.
- Improved README.md for better structure and readability as user-facing documentation.
- Updated demo images for Ryujin and added more visual examples.
This commit is contained in:
keowu
2025-07-27 11:10:32 -03:00
parent 64cdfe6e71
commit d8c37b2d4c
5 changed files with 87 additions and 8 deletions

View File

@@ -48,6 +48,43 @@ For both options, you will need exclusively a PE file (Apanas, executable, for n
---
## Custom Pass Support
In addition to the standard techniques available via CLI or GUI options, Ryūjin also supports a Custom Pass feature. This allows anyone to implement a callback that is invoked during the obfuscation flow, enabling users to extend Ryūjins capabilities with custom features specific to their code.
To do this, the user must follow a specific callback model:
```c++
void RyujinCustomPassDemo(RyujinProcedure* proc);
```
Each time the callback is invoked, a ```RyujinProcedure``` instance is provided, allowing the user to modify execution scopes, basic block structures, and more. The class definition can be found in [RyujinProcedure.hh](https://github.com/keowu/Ryujin/blob/main/RyujinCore/Ryujin/Models/RyujinProcedure.hh). Additionally, a usage example is available in [RyujinConsole.cc](https://github.com/keowu/Ryujin/blob/main/RyujinConsole/RyujinConsole/RyujinConsole.cc#L10), No additional configuration file changes are required. The ```RyujinObfuscatorConfig``` class already includes all necessary settings for immediate use.
## Dependencies
To compile RyujinCore, RyujinConsole, and RyujinGUI, critical dependencies must be installed via [Microsoft VCPKG](https://github.com/microsoft/vcpkg), You can install them using the following commands:
```
vcpkg install asmjit
vcpkg install zydis
```
For a consistent development environment, consider the following versions:
```
asmjit:x64-windows - 2024-06-28
zycore:x64-windows - 1.5.0
zydis:x64-windows - 4.1.0
```
In addition to these critical dependencies, some optional ones exist, for example, ```wxWidgets```, which is required to build RyujinGUI. It can be obtained from the [wxWidgets website](https://wxwidgets.org/downloads/).
## Research Paper
If you enjoy understanding how things work technically and exploring deep concepts, consider reading the **Ryūjin paper**:
**TODO**
## Getting Started
GITHUB_WIKI_URL
For more detailed usage information and explanations of each feature intended for daily use, consider reading the [**Ryūjin Wiki**](https://github.com/keowu/Ryujin/wiki).

View File

@@ -9,9 +9,40 @@
void RyujinCustomPassDemo(RyujinProcedure* proc) {
std::printf("Ol<EFBFBD> mundinho!\n");
/*
This is a sample callback that demonstrates how Ryujin users can register callbacks during its operation/integration to be used with the RyujinCore engine.
This callback provides direct access to the RyujinProcedure class, which encapsulates all the logic of basic blocks and information about each obfuscated procedure,
allowing modifications and extensions limited only by the implementer's creativity.
In this example, the registered callback is used solely to display relevant information about each procedure to be obfuscated, as a demonstration.
std::printf("Meu custom pass foi chamado para(teste) -> %s\n", proc->name.c_str());
A sample output:
----------------------------------------------
RyujinCustomPassDemo get called for subadd
subadd has 31 bytes, resides on 0x7ff6c7fd1100, with 1 basic blocks.
Instructions:
mov [rsp+0x08], ecx
mov eax, [rsp+0x08]
add eax, 0x0A
mov [rsp+0x08], eax
mov eax, [rsp+0x08]
sub eax, 0x02
mov [rsp+0x08], eax
mov eax, [rsp+0x08]
ret
----------------------------------------------
*/
std::printf("----------------------------------------------\n");
std::printf("RyujinCustomPassDemo get called for %s\n", proc->name.c_str());
std::printf("%s has %lld bytes, resides on 0x%llx, with %llx basic blocks.\n", proc->name.c_str(), proc->size, proc->address, proc->basic_blocks.size());
std::printf("Instructions:\n");
for (auto& block : proc->basic_blocks)
for (auto& inst : block.instructions)
std::printf("%s\n", inst.instruction.text);
std::printf("----------------------------------------------\n");
}
@@ -101,6 +132,7 @@ auto main(int argc, char* argv[]) -> int {
config.m_isAntiDump = has_flag(args, "--AntiDump");
config.m_isMemoryProtection = has_flag(args, "--MemoryProtection");
// Registering a new custom pass for invocation via callback
config.RegisterCallback(RyujinCustomPassDemo);
if (has_flag(args, "--procs")) {

View File

@@ -2439,6 +2439,21 @@ BOOL RyujinObfuscationCore::Run(bool& RyujinRunOncePass) {
}
// Checking if we have any user-registered callbacks
if (m_config.m_callbacks.callbackCount > 0)
// Iterating over each registered callback
for (auto i = 0; i < m_config.m_callbacks.callbackCount; i++)
// If it's a valid address
if (m_config.m_callbacks.callbacks[i]) {
// We invoke the callback, passing the m_proc instance by reference to allow user modifications.
m_config.m_callbacks.callbacks[i](&m_proc);
// We update the Basic Blocks context to stay 1:1 with the user's modifications.
this->updateBasicBlocksContext();
}
if (RyujinRunOncePass) {
if (this->m_config.m_isMemoryProtection && (!this->m_config.m_isAntiDump || !this->m_config.m_isEncryptObfuscatedCode || !this->m_config.m_isRandomSection)) {
@@ -2455,11 +2470,6 @@ BOOL RyujinObfuscationCore::Run(bool& RyujinRunOncePass) {
}
if (m_config.m_callbacks.callbackCount > 0)
for (int i = 0; i < m_config.m_callbacks.callbackCount; i++)
if (m_config.m_callbacks.callbacks[i])
m_config.m_callbacks.callbacks[i](&m_proc);
return TRUE;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 103 KiB