diff --git a/RyujinConsole/RyujinGUI/RyujinApp.cc b/RyujinConsole/RyujinGUI/RyujinApp.cc index fce4a0d..b78fcf3 100644 --- a/RyujinConsole/RyujinGUI/RyujinApp.cc +++ b/RyujinConsole/RyujinGUI/RyujinApp.cc @@ -1,16 +1,16 @@ #include "RyujinApp.hh" bool RyujinApp::OnInit() { - + auto* frame = new wxFrame( - + nullptr, wxID_ANY, "Ryujin Obfuscator", wxDefaultPosition, wxSize( - - 850, + + 650, 580 ), @@ -18,7 +18,7 @@ bool RyujinApp::OnInit() { ); - frame->SetBackgroundColour( + frame->SetBackgroundColour( wxColour( 25, @@ -26,7 +26,6 @@ bool RyujinApp::OnInit() { 25 )); - frame->SetFont( wxFont( @@ -34,49 +33,48 @@ bool RyujinApp::OnInit() { wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL - + )); + auto* panel = new wxPanel( + + frame, + wxID_ANY + + ); + panel->SetBackgroundColour( + + frame->GetBackgroundColour( ) + + ); + auto* topSizer = new wxBoxSizer( wxVERTICAL ); - auto* title = new wxStaticText( - - frame, - wxID_ANY, - "Ryujin Obfuscator" - - ); - title->SetFont( - wxFont( + if ( + auto* icon = LoadPngFromRes( - 18, - wxFONTFAMILY_SWISS, - wxFONTSTYLE_NORMAL, - wxFONTWEIGHT_BOLD + panel, + wxID_ANY, + IDB_PNG1 - )); - title->SetForegroundColour( + )) + topSizer->Add( + + icon, + 0, + wxALIGN_CENTER | wxTOP, + 10 - *wxWHITE - - ); + ); + topSizer->Add( - - title, - 0, - wxALIGN_CENTER | wxTOP, - 20 - - ); - topSizer->Add( - new wxStaticLine( - - frame + + panel ), 0, @@ -88,18 +86,18 @@ bool RyujinApp::OnInit() { auto* pathBox = new wxStaticBoxSizer( wxVERTICAL, - frame, + panel, "Paths" ); - pathBox->GetStaticBox()->SetForegroundColour( + pathBox->GetStaticBox( )->SetForegroundColour( *wxWHITE ); m_input = DrawnPathRow( - frame, + panel, pathBox, "Input EXE:", wxID_HIGHEST + 1 @@ -107,15 +105,15 @@ bool RyujinApp::OnInit() { ); m_pdb = DrawnPathRow( - frame, - pathBox, - "PDB File:", + panel, + pathBox, + "PDB File:", wxID_HIGHEST + 2 ); m_output = DrawnPathRow( - frame, + panel, pathBox, "Output EXE:", wxID_HIGHEST + 3 @@ -133,11 +131,11 @@ bool RyujinApp::OnInit() { auto* optionsBox = new wxStaticBoxSizer( wxVERTICAL, - frame, + panel, "Obfuscation Options" ); - optionsBox->GetStaticBox()->SetForegroundColour( + optionsBox->GetStaticBox( )->SetForegroundColour( *wxWHITE @@ -152,37 +150,37 @@ bool RyujinApp::OnInit() { ); m_virtualize = DrawnStyledCheckbox( - frame, + panel, "Virtualize" ); m_junk = DrawnStyledCheckbox( - frame, + panel, "Junk Code" ); m_encrypt = DrawnStyledCheckbox( - frame, + panel, "Encrypt" ); m_randomSection = DrawnStyledCheckbox( - frame, + panel, "Random Section" ); m_obfuscateIat = DrawnStyledCheckbox( - frame, + panel, "Obfuscate IAT" ); m_ignoreOriginalCodeRemove = DrawnStyledCheckbox( - frame, + panel, "Ignore Original Code Removal" ); @@ -217,7 +215,6 @@ bool RyujinApp::OnInit() { m_ignoreOriginalCodeRemove ); - optionsBox->Add( optionsSizer, @@ -238,18 +235,18 @@ bool RyujinApp::OnInit() { auto* procBox = new wxStaticBoxSizer( wxVERTICAL, - frame, + panel, "Procedures to Obfuscate" ); - procBox->GetStaticBox()->SetForegroundColour( + procBox->GetStaticBox( )->SetForegroundColour( *wxWHITE ); m_procList = new wxListBox( - frame, + panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, @@ -258,6 +255,14 @@ bool RyujinApp::OnInit() { wxBORDER_NONE ); + + m_procList->SetMinSize( + wxSize( + + -1, + 200 + + )); m_procList->SetBackgroundColour( wxColour( @@ -288,10 +293,10 @@ bool RyujinApp::OnInit() { procBtnRow->Add( DrawnRyujinButton( - frame, + panel, "Add", wxID_HIGHEST + 4 - + ), 0, wxRIGHT, @@ -301,10 +306,10 @@ bool RyujinApp::OnInit() { procBtnRow->Add( DrawnRyujinButton( - frame, + panel, "Remove", wxID_HIGHEST + 5 - + )); procBox->Add( @@ -324,14 +329,14 @@ bool RyujinApp::OnInit() { m_progress = new wxGauge( - frame, + panel, wxID_ANY, 100 ); m_progress->SetMinSize( wxSize( - + -1, 14 @@ -355,7 +360,7 @@ bool RyujinApp::OnInit() { auto* runBtn = DrawnRyujinButton( - frame, + panel, "Run Obfuscator", wxID_HIGHEST + 6 @@ -406,15 +411,21 @@ bool RyujinApp::OnInit() { ); - frame->CreateStatusBar(); - frame->SetSizerAndFit( + panel->SetSizer( topSizer ); - frame->Centre(); - frame->Show(); + topSizer->SetSizeHints( + + panel + + ); + frame->Fit( ); + frame->Centre( ); + frame->Show( ); + frame->CreateStatusBar( ); BindFileDialogs( frame @@ -434,6 +445,7 @@ bool RyujinApp::OnInit() { return true; } + auto RyujinApp::DrawnPathRow(wxWindow* parent, wxBoxSizer* sizer, const wxString& label, int buttonId) -> wxTextCtrl* { auto* row = new wxBoxSizer( @@ -596,7 +608,7 @@ auto RyujinApp::BindListEvents(wxFrame* frame) -> void { frame->Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { - wxTextEntryDialog dlg(frame, "Enter comma-separated procedures or a unique procedure name:"); + wxTextEntryDialog dlg(frame, "Enter comma-separated procedures or a unique procedure name:", "Procedures to obfuscate"); if (dlg.ShowModal() == wxID_OK) { wxArrayString list = wxSplit(dlg.GetValue(), ','); @@ -620,13 +632,122 @@ auto RyujinApp::BindListEvents(wxFrame* frame) -> void { auto RyujinApp::BindRunEvent(wxFrame* frame) -> void { frame->Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { - + frame->SetStatusText("Starting obfuscation..."); m_progress->Pulse(); - wxMilliSleep(1000); - m_progress->SetValue(100); - frame->SetStatusText("Obfuscation complete."); - + + std::thread([=]() { + + RyujinObfuscatorConfig core; + + // Options Configuration + core.m_isEncryptObfuscatedCode = m_encrypt->IsChecked(); + core.m_isIatObfuscation = m_obfuscateIat->IsChecked(); + core.m_isIgnoreOriginalCodeRemove = m_ignoreOriginalCodeRemove->IsChecked(); + core.m_isJunkCode = m_junk->IsChecked(); + core.m_isRandomSection = m_randomSection->IsChecked(); + core.m_isVirtualized = m_virtualize->IsChecked(); + + // Procedures to obfuscate + std::vector procsToObfuscate; + auto count = m_procList->GetCount(); + procsToObfuscate.reserve(count); + + for (auto i = 0; i < count; ++i) { + + auto item = m_procList->GetString(i); + procsToObfuscate.push_back(item.ToStdString()); + + } + core.m_strProceduresToObfuscate.assign(procsToObfuscate.begin(), procsToObfuscate.end()); + + auto bSuccess = core.RunRyujin(m_input->GetValue().ToStdString(), m_pdb->GetValue().ToStdString(), m_output->GetValue().ToStdString(), core); + + frame->CallAfter([=]() { + + if (bSuccess) { + + m_progress->SetValue(100); + frame->SetStatusText("Obfuscation complete."); + + } else { + + m_progress->SetValue(50); + frame->SetStatusText("Obfuscation error."); + + } + + }); + + }).detach(); + }, wxID_HIGHEST + 6); -} \ No newline at end of file +} + +auto RyujinApp::LoadPngFromRes(wxWindow* parent, wxWindowID id, int resId) -> wxStaticBitmap* { + + wxImage::AddHandler( + + new wxPNGHandler + + ); + + auto hInst = reinterpret_cast(GetModuleHandle( + + _In_ NULL + + )); + auto rs = FindResource( + + _In_ hInst, + _In_ MAKEINTRESOURCE(resId), + _In_ wxT("PNG") + + ); + + if (!rs) return nullptr; + + auto hGlob = LoadResource( + + _In_opt_ hInst, + _In_ rs + + ); + auto* data = LockResource( + + _In_ hGlob + + ); + auto size = SizeofResource( + + _In_opt_ hInst, + _In_ rs + + ); + wxMemoryInputStream mis( + + data, + size + + ); + + wxImage img( + + mis, + wxBITMAP_TYPE_PNG + + ); + + if (!img.IsOk( )) return nullptr; + + return new wxStaticBitmap( + + parent, + id, + wxBitmap( + + img + + )); +} diff --git a/RyujinConsole/RyujinGUI/RyujinApp.hh b/RyujinConsole/RyujinGUI/RyujinApp.hh index c12c71b..4d76074 100644 --- a/RyujinConsole/RyujinGUI/RyujinApp.hh +++ b/RyujinConsole/RyujinGUI/RyujinApp.hh @@ -3,6 +3,10 @@ #include #include #include +#include +#include +#include "resource.h" +#include "RyujinCore.hh" class RyujinApp : public wxApp { @@ -25,6 +29,7 @@ private: auto BindFileDialogs(wxFrame* frame) -> void; auto BindListEvents(wxFrame* frame) -> void; auto BindRunEvent(wxFrame* frame) -> void; + auto LoadPngFromRes(wxWindow* parent, wxWindowID id, int resId) -> wxStaticBitmap*; public: bool OnInit() override; diff --git a/RyujinConsole/RyujinGUI/RyujinCore.hh b/RyujinConsole/RyujinGUI/RyujinCore.hh new file mode 100644 index 0000000..ba70975 --- /dev/null +++ b/RyujinConsole/RyujinGUI/RyujinCore.hh @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include + +class RyujinObfuscatorConfig { + +public: + bool m_isRandomSection; // Randomize the name of the new section with the processed code -> ".Ryujin" standard + bool m_isVirtualized; // Virtualize the code [Try as much as possible] + bool m_isIatObfuscation; //Process IAT Obfuscation + bool m_isJunkCode; // Insert junk code to confuse + bool m_isIgnoreOriginalCodeRemove; // Do not remove the original code after processing (replace the original instructions with NOPs) + bool m_isEncryptObfuscatedCode; // The user wants to encrypt all obfuscated code to avoid detection + std::vector m_strProceduresToObfuscate; // Names of the procedures to obfuscate + + bool RunRyujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath, RyujinObfuscatorConfig& config) { + + using tpdRunRyujinCore = BOOL(__stdcall*)(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath, RyujinObfuscatorConfig& config); + + auto hModule = LoadLibraryW(L"RyujinCore.dll"); + + if (!hModule) return FALSE; + + auto RunRyujinCore = reinterpret_cast(GetProcAddress(hModule, "RunRyujinCore")); + + if (!RunRyujinCore) return FALSE; + + return RunRyujinCore(strInputFilePath, strPdbFilePath, strOutputFilePath, config); + } + +}; diff --git a/RyujinConsole/RyujinGUI/RyujinGUI.rc b/RyujinConsole/RyujinGUI/RyujinGUI.rc new file mode 100644 index 0000000..efc0d9b Binary files /dev/null and b/RyujinConsole/RyujinGUI/RyujinGUI.rc differ diff --git a/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj b/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj index 65276de..d412cc2 100644 --- a/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj +++ b/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj @@ -93,7 +93,8 @@ Windows true - $(WXWIN)\lib\vc_lib;%(AdditionalLibraryDirectories) + $(WXWIN)\lib\vc_lib;%(AdditionalLibraryDirectories);libwebp.lib + libwebp.lib;%(AdditionalDependencies) @@ -111,7 +112,8 @@ true true true - $(WXWIN)\lib\vc_lib;%(AdditionalLibraryDirectories) + $(WXWIN)\lib\vc_lib;%(AdditionalLibraryDirectories);libwebp.lib + libwebp.lib;%(AdditionalDependencies) @@ -125,7 +127,8 @@ Windows true - $(WXWIN)\lib\vc_x64_lib;%(AdditionalLibraryDirectories) + $(WXWIN)\lib\vc_x64_lib;%(AdditionalLibraryDirectories);libwebp.lib + libwebp.lib;%(AdditionalDependencies) @@ -143,14 +146,23 @@ true true true - $(WXWIN)\lib\vc_x64_lib;%(AdditionalLibraryDirectories) + $(WXWIN)\lib\vc_x64_lib;%(AdditionalLibraryDirectories);libwebp.lib + libwebp.lib;%(AdditionalDependencies) + + + + + + + + diff --git a/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj.filters b/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj.filters index 5c0b6b1..264ae54 100644 --- a/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj.filters +++ b/RyujinConsole/RyujinGUI/RyujinGUI.vcxproj.filters @@ -13,15 +13,37 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {38744ed6-b50a-4be0-bf17-6128092b44eb} + + + {77bfeccd-c1fb-48af-af85-98b6afe4398c} + - - Source Files - - - + + RyujinCore + + RyujinGUI + + Header Files + + + RyujinGUI + + + + + Resource Files + + + + + Resource Files + + \ No newline at end of file diff --git a/RyujinConsole/RyujinGUI/resource.h b/RyujinConsole/RyujinGUI/resource.h new file mode 100644 index 0000000..fd79549 --- /dev/null +++ b/RyujinConsole/RyujinGUI/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by RyujinGUI.rc +// +#define IDB_PNG1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/imgs/logogui.png b/imgs/logogui.png new file mode 100644 index 0000000..20297a5 Binary files /dev/null and b/imgs/logogui.png differ diff --git a/imgs/ryujin.png b/imgs/ryujin.png new file mode 100644 index 0000000..3b5a458 Binary files /dev/null and b/imgs/ryujin.png differ