feat: IatObfuscation option, Section Name Randomizing, New Section Logic
- Adding a new option on obfuscator for IAT obfuscation support. - Adding a new logic to randomize section names. - Adding the initial logic to add a new section in the PE file. and writing some ideas and some things to be able to continue the logic in a correct way.
This commit is contained in:
@@ -2,8 +2,9 @@
|
|||||||
class RyujinObfuscatorConfig {
|
class RyujinObfuscatorConfig {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_isRandomSection; // Randomize the name of the new section with the processed code -> Ryujin standard
|
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_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_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_isIgnoreOriginalCodeRemove; // Do not remove the original code after processing (replace the original instructions with NOPs)
|
||||||
std::vector<std::string> m_strProceduresToObfuscate; // Names of the procedures to obfuscate
|
std::vector<std::string> m_strProceduresToObfuscate; // Names of the procedures to obfuscate
|
||||||
|
|||||||
@@ -97,7 +97,12 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
|
|||||||
|
|
||||||
if (it == config.m_strProceduresToObfuscate.end()) continue;
|
if (it == config.m_strProceduresToObfuscate.end()) continue;
|
||||||
|
|
||||||
std::printf("[WORKING ON]: %s\n", proc.name.c_str());
|
std::printf(
|
||||||
|
|
||||||
|
"[WORKING ON]: %s\n",
|
||||||
|
proc.name.c_str()
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
// Is a valid procedure ?
|
// Is a valid procedure ?
|
||||||
if (proc.size == 0) {
|
if (proc.size == 0) {
|
||||||
@@ -125,11 +130,30 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
|
|||||||
RyujinBasicBlockerBuilder rybb(ZYDIS_MACHINE_MODE_LONG_64, ZydisStackWidth_::ZYDIS_STACK_WIDTH_64);
|
RyujinBasicBlockerBuilder rybb(ZYDIS_MACHINE_MODE_LONG_64, ZydisStackWidth_::ZYDIS_STACK_WIDTH_64);
|
||||||
proc.basic_blocks = rybb.createBasicBlocks(ucOpcodes, proc.size, proc.address);
|
proc.basic_blocks = rybb.createBasicBlocks(ucOpcodes, proc.size, proc.address);
|
||||||
|
|
||||||
|
//Is time to obfuscate ?
|
||||||
|
if (config.m_isVirtualized) todoAction();
|
||||||
|
if (config.m_isIatObfuscation) todoAction();
|
||||||
|
if (config.m_isJunkCode) todoAction();
|
||||||
|
|
||||||
|
//TODO: Custom passes support
|
||||||
|
|
||||||
//Clean up opcodes
|
//Clean up opcodes
|
||||||
delete[] ucOpcodes;
|
delete[] ucOpcodes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//More obfuscation
|
||||||
|
if (config.m_isIgnoreOriginalCodeRemove) todoAction();
|
||||||
|
|
||||||
|
//Add section
|
||||||
|
char chSectionName[8]{ '.', 'R', 'y', 'u', 'j', 'i', 'n', '\0' };
|
||||||
|
if (config.m_isRandomSection) RyujinUtils::randomizeSectionName(chSectionName);
|
||||||
|
RyujinUtils::AddNewSection(m_mappedPE, m_szFile, chSectionName);
|
||||||
|
|
||||||
|
//Fix relocations
|
||||||
|
|
||||||
|
//Save output file
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ryujin::listRyujinProcedures() {
|
void Ryujin::listRyujinProcedures() {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ private:
|
|||||||
BOOL m_isInitialized;
|
BOOL m_isInitialized;
|
||||||
std::vector<RyujinProcedure> m_ryujinProcedures;
|
std::vector<RyujinProcedure> m_ryujinProcedures;
|
||||||
|
|
||||||
|
bool todoAction() { return FALSE; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath);
|
Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath);
|
||||||
bool run(const RyujinObfuscatorConfig& config);
|
bool run(const RyujinObfuscatorConfig& config);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#define ALIGN_UP(value, alignment) ((value + alignment - 1) & ~(alignment - 1))
|
||||||
|
|
||||||
namespace RyujinUtils {
|
namespace RyujinUtils {
|
||||||
|
|
||||||
inline std::pair<BOOL, uintptr_t> MapPortableExecutableFileIntoMemory(const std::string& m_strInputFilePath, std::shared_ptr<unsigned char>& mappedPE) {
|
inline std::pair<BOOL, uintptr_t> MapPortableExecutableFileIntoMemory(const std::string& m_strInputFilePath, std::shared_ptr<unsigned char>& mappedPE) {
|
||||||
@@ -121,5 +123,83 @@ namespace RyujinUtils {
|
|||||||
return std::make_pair(TRUE, szFile.QuadPart);
|
return std::make_pair(TRUE, szFile.QuadPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline BOOL AddNewSection(std::shared_ptr<unsigned char>& mappedPE, uintptr_t szFile, char chSectionName[8]) {
|
||||||
|
|
||||||
|
auto ucModifiedPeMap = new unsigned char[szFile] { 0 };
|
||||||
|
std::memcpy(
|
||||||
|
|
||||||
|
ucModifiedPeMap,
|
||||||
|
mappedPE.get(),
|
||||||
|
szFile
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(ucModifiedPeMap);
|
||||||
|
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
|
||||||
|
delete[] ucModifiedPeMap;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(ucModifiedPeMap + dosHeader->e_lfanew);
|
||||||
|
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
|
||||||
|
delete[] ucModifiedPeMap;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sectionTableSize = ntHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||||
|
if (dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sectionTableSize > ntHeaders->OptionalHeader.SizeOfHeaders) {
|
||||||
|
|
||||||
|
//No space to insert a new section on this PE FILE :(
|
||||||
|
|
||||||
|
delete[] ucModifiedPeMap;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Adding the new section
|
||||||
|
IMAGE_SECTION_HEADER newSection{ 0 };
|
||||||
|
std::memcpy(
|
||||||
|
|
||||||
|
newSection.Name,
|
||||||
|
chSectionName,
|
||||||
|
sizeof(chSectionName)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
auto imgLastSection = IMAGE_FIRST_SECTION(ntHeaders) + (ntHeaders->FileHeader.NumberOfSections - 1);
|
||||||
|
|
||||||
|
newSection.VirtualAddress = ALIGN_UP(
|
||||||
|
imgLastSection->VirtualAddress + imgLastSection->Misc.VirtualSize,
|
||||||
|
ntHeaders->OptionalHeader.SectionAlignment
|
||||||
|
);
|
||||||
|
|
||||||
|
newSection.PointerToRawData = ALIGN_UP(
|
||||||
|
imgLastSection->PointerToRawData + imgLastSection->SizeOfRawData,
|
||||||
|
ntHeaders->OptionalHeader.FileAlignment
|
||||||
|
);
|
||||||
|
|
||||||
|
newSection.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
|
||||||
|
|
||||||
|
//Return the following in order to put data and calculate relocs:
|
||||||
|
//newSection.VirtualAddress
|
||||||
|
//newSection.Misc.VirtualSize = size of new code;
|
||||||
|
//newSection.SizeOfRawData = ALIGN_UP(size of new code, ntHeaders->OptionalHeader.FileAlignment);
|
||||||
|
//Maybe is better wrap this things in a full new class ??
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void randomizeSectionName(char* chName) {
|
||||||
|
|
||||||
|
const char charset[] { "abcdefghijklmnopqrstuvwxyz" };
|
||||||
|
for (size_t i = 0; i < 8 - 1; ++i) chName[i] = charset[std::rand() % (sizeof(charset) - 1)];
|
||||||
|
chName[8 - 1] = '\0';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user