feat: Improve Ryujin MiniVM to support dual arguments for better compatibility and more
- Ryujin MiniVM now supports dynamic register values, allowing it to store immediate values and registers using dual arguments: the first as the register operand (argument one) and the VM bytecode as the second (argument two). - Code improvements and bug fixes.
This commit is contained in:
@@ -162,39 +162,45 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) {
|
|||||||
//Insert minivm enter routine
|
//Insert minivm enter routine
|
||||||
if (config.m_isVirtualized) {
|
if (config.m_isVirtualized) {
|
||||||
|
|
||||||
std::vector<unsigned char> miniVmEnter{
|
// Ryujin MiniVM Routine -> TODO: MAKE THIS DYNAMIC
|
||||||
|
std::vector<unsigned char> miniVmEnter {
|
||||||
0x48, 0x89, 0x4C, 0x24, 0x08, 0x48, 0x83, 0xEC, 0x28, 0x48, 0x8B, 0x44,
|
|
||||||
0x24, 0x30, 0x48, 0xC1, 0xE8, 0x10, 0x48, 0x25, 0xFF, 0x00, 0x00, 0x00,
|
0x48, 0x89, 0x54, 0x24, 0x10, 0x48, 0x89, 0x4C, 0x24, 0x08, 0x48, 0x83,
|
||||||
0x88, 0x44, 0x24, 0x01, 0x48, 0x8B, 0x44, 0x24, 0x30, 0x48, 0xC1, 0xE8,
|
0xEC, 0x28, 0x48, 0x8B, 0x44, 0x24, 0x38, 0x48, 0xC1, 0xE8, 0x10, 0x48,
|
||||||
0x08, 0x48, 0x25, 0xFF, 0x00, 0x00, 0x00, 0x88, 0x04, 0x24, 0x48, 0x8B,
|
0x25, 0xFF, 0x00, 0x00, 0x00, 0x88, 0x44, 0x24, 0x01, 0x48, 0x8B, 0x44,
|
||||||
0x44, 0x24, 0x30, 0x48, 0x25, 0xFF, 0x00, 0x00, 0x00, 0x48, 0x89, 0x44,
|
0x24, 0x38, 0x48, 0xC1, 0xE8, 0x08, 0x48, 0x25, 0xFF, 0x00, 0x00, 0x00,
|
||||||
0x24, 0x10, 0x48, 0xC7, 0x44, 0x24, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0F,
|
0x88, 0x04, 0x24, 0x48, 0x8B, 0x44, 0x24, 0x38, 0x48, 0x25, 0xFF, 0x00,
|
||||||
0xB6, 0x04, 0x24, 0x88, 0x44, 0x24, 0x04, 0x80, 0x7C, 0x24, 0x04, 0x01,
|
0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x10, 0x48, 0x8B, 0x44, 0x24, 0x30,
|
||||||
0x74, 0x17, 0x80, 0x7C, 0x24, 0x04, 0x02, 0x74, 0x27, 0x80, 0x7C, 0x24,
|
0x48, 0x89, 0x44, 0x24, 0x08, 0x0F, 0xB6, 0x04, 0x24, 0x88, 0x44, 0x24,
|
||||||
0x04, 0x03, 0x74, 0x37, 0x80, 0x7C, 0x24, 0x04, 0x04, 0x74, 0x42, 0xEB,
|
0x04, 0x80, 0x7C, 0x24, 0x04, 0x01, 0x74, 0x17, 0x80, 0x7C, 0x24, 0x04,
|
||||||
0x53, 0x48, 0x8B, 0x44, 0x24, 0x10, 0x48, 0x8B, 0x4C, 0x24, 0x08, 0x48,
|
0x02, 0x74, 0x27, 0x80, 0x7C, 0x24, 0x04, 0x03, 0x74, 0x37, 0x80, 0x7C,
|
||||||
0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48, 0x89, 0x44, 0x24, 0x08, 0xEB, 0x45,
|
0x24, 0x04, 0x04, 0x74, 0x42, 0xEB, 0x53, 0x48, 0x8B, 0x44, 0x24, 0x10,
|
||||||
0x48, 0x8B, 0x44, 0x24, 0x10, 0x48, 0x8B, 0x4C, 0x24, 0x08, 0x48, 0x2B,
|
0x48, 0x8B, 0x4C, 0x24, 0x08, 0x48, 0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48,
|
||||||
0xC8, 0x48, 0x8B, 0xC1, 0x48, 0x89, 0x44, 0x24, 0x08, 0xEB, 0x2E, 0x48,
|
0x89, 0x44, 0x24, 0x08, 0xEB, 0x45, 0x48, 0x8B, 0x44, 0x24, 0x10, 0x48,
|
||||||
0x8B, 0x44, 0x24, 0x08, 0x48, 0x0F, 0xAF, 0x44, 0x24, 0x10, 0x48, 0x89,
|
0x8B, 0x4C, 0x24, 0x08, 0x48, 0x2B, 0xC8, 0x48, 0x8B, 0xC1, 0x48, 0x89,
|
||||||
0x44, 0x24, 0x08, 0xEB, 0x1C, 0x33, 0xD2, 0x48, 0x8B, 0x44, 0x24, 0x08,
|
0x44, 0x24, 0x08, 0xEB, 0x2E, 0x48, 0x8B, 0x44, 0x24, 0x08, 0x48, 0x0F,
|
||||||
0x48, 0xF7, 0x74, 0x24, 0x10, 0x48, 0x89, 0x44, 0x24, 0x08, 0xEB, 0x09,
|
0xAF, 0x44, 0x24, 0x10, 0x48, 0x89, 0x44, 0x24, 0x08, 0xEB, 0x1C, 0x33,
|
||||||
0x48, 0xC7, 0x44, 0x24, 0x08, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x44,
|
0xD2, 0x48, 0x8B, 0x44, 0x24, 0x08, 0x48, 0xF7, 0x74, 0x24, 0x10, 0x48,
|
||||||
0x24, 0x08, 0x48, 0x83, 0xC4, 0x28, 0xC3
|
0x89, 0x44, 0x24, 0x08, 0xEB, 0x09, 0x48, 0xC7, 0x44, 0x24, 0x08, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x48, 0x8B, 0x44, 0x24, 0x08, 0x48, 0x83, 0xC4, 0x28,
|
||||||
|
0xC3
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Inserting the Ryujin MiniVm stub at the beginning of Ryujin section
|
||||||
opcodesWithRelocsFixed.insert(opcodesWithRelocsFixed.end(), miniVmEnter.begin(), miniVmEnter.end());
|
opcodesWithRelocsFixed.insert(opcodesWithRelocsFixed.end(), miniVmEnter.begin(), miniVmEnter.end());
|
||||||
|
|
||||||
|
// Storing the MiniVm Stub Offset
|
||||||
miniVmEnterAddress = peSections.getRyujinSectionVA();
|
miniVmEnterAddress = peSections.getRyujinSectionVA();
|
||||||
|
|
||||||
|
// Calculating the size of the MiniVM Stub
|
||||||
offsetVA += miniVmEnter.size();
|
offsetVA += miniVmEnter.size();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& obc : processed_procs) {
|
for (auto& obc : processed_procs) {
|
||||||
|
|
||||||
|
// Getting new obfuscated opcodes
|
||||||
auto tempValued = obc.getProcessedProc().getUpdateOpcodes();
|
auto tempValued = obc.getProcessedProc().getUpdateOpcodes();
|
||||||
|
|
||||||
// Fix relocations
|
// Fix relocations
|
||||||
|
|||||||
@@ -408,44 +408,44 @@ void RyujinObfuscationCore::insertJunkCode() {
|
|||||||
void RyujinObfuscationCore::insertVirtualization() {
|
void RyujinObfuscationCore::insertVirtualization() {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1 - Converter instru<72><75>es do procedimento e seus basic blocks para o bytecode da VM(cada instru<72><75>o gera 8 bytes de bytecode).
|
1 - Convert the procedure's instructions and their basic blocks into the VM's bytecode (each instruction generates 8 bytes of bytecode).
|
||||||
2 - Substiuir a instru<72><75>o por uma call para a rotina de interpreta<74><61>o da VM e passar os bytecodes via RCX. (levar em considera<72><61>o o salvamento dos contextos de registradore e stack)
|
2 - Replace the instruction with a call to the VM's interpretation routine and pass the bytecodes via RCX. (Take into account saving the register and stack contexts.)
|
||||||
3 - Ser capaz de continuar a execu<EFBFBD><EFBFBD>o sem problemas integrando a rotina da VM com o c<>digo original a ser executado e n<>o ofuscado
|
3 - Be able to continue execution without issues, integrating the VM routine with the original code that is to be executed and not obfuscated.
|
||||||
|
4 - This routine should insert only the VM stub and bytecode. After that, there will be a processing step before saving and fixing relocations, so we can identify the virtualization routine pattern and insert the real address of the VM interpreter to make it work.
|
||||||
4 - Essa rotina deve inserir a stub e bytecode da vm apenas. ap<61>s isso teremos um processamento antes de salvar e corrigir reloca<63><61>es
|
|
||||||
para sermos capazes de encontrar o padr<64>o da rotina de virtualiza<7A><61>o e colocar o endere<72>o real do interpretador da VM para que a mesma funcione.
|
|
||||||
|
|
||||||
|
Basically, this is a single-VM that:
|
||||||
|
Analyzes the instruction in question, extracts its opcode and maps it to the VM's opcode, extracts its immediates and stores everything in a single set.
|
||||||
|
Example:
|
||||||
|
0x48 -> mov -> bytecode
|
||||||
|
rbx -> bytecode
|
||||||
|
10 -> value
|
||||||
|
|
||||||
Basicamente essa <20> uma single-vm que:
|
Example output:
|
||||||
Analisa a instru<72><75>o em quest<73>o. extrair seu opcode e mapear para o da vm, extrair seus immediatos e armazenala em um unico conjunto
|
0x112210
|
||||||
exemplo:
|
|
||||||
0x48 -> mov -> bytecode
|
|
||||||
rbx -> bytecode
|
|
||||||
10 -> valor
|
|
||||||
|
|
||||||
Exemplo de sa<73>da:
|
Which will be assigned to the value of RCX:
|
||||||
0x112210
|
|
||||||
|
|
||||||
Que sera atribuido ao valor de rcx:
|
push rcx
|
||||||
|
mov rcx, 112210h
|
||||||
|
call vmentry (but a symbolic value, since the immediate offset wouldn't be inserted here)
|
||||||
|
-> rax result goes to the register in question that would continue the execution flow or receive the result, in this example: rbx
|
||||||
|
pop rcx
|
||||||
|
|
||||||
push rcx
|
In this way, the code would continue.
|
||||||
mov rcx, 112210h
|
|
||||||
call vmentry(mas um valor simbolico visto que n<>o seria inserido o offset immediato aqui)
|
|
||||||
-> rax resultado vai no registrado em quest<73>o que continuaria o fluxo de execu<63><75>o ou receberia o resultado, nesse exemplo: rbx
|
|
||||||
pop rcx
|
|
||||||
|
|
||||||
Dessa forma o c<>digo continuaria
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// <20> uma instru<72><75>o candidata a ser virtualizada pela minivm ??
|
/*
|
||||||
|
Ryujin MiniVM Logic Begin
|
||||||
|
*/
|
||||||
|
// Is it a candidate instruction to be virtualized by the minivm?
|
||||||
auto isValidToSRyujinMiniVm = [&](RyujinInstruction instr) {
|
auto isValidToSRyujinMiniVm = [&](RyujinInstruction instr) {
|
||||||
|
|
||||||
return instr.instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.instruction.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
return instr.instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.instruction.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||||
//Ignorando registradores e opera<72><61>es de stack
|
// Ignoring registers and stack operations
|
||||||
(instr.instruction.operands[0].reg.value != ZYDIS_REGISTER_RSP && instr.instruction.operands[0].reg.value != ZYDIS_REGISTER_RBP);
|
(instr.instruction.operands[0].reg.value != ZYDIS_REGISTER_RSP && instr.instruction.operands[0].reg.value != ZYDIS_REGISTER_RBP);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vamos mapear o registrador do Zydis para o ASMJIT
|
// Let's map the Zydis register to ASMJIT
|
||||||
auto mapZydisToAsmjitGp = [&](ZydisRegister zydisReg) -> asmjit::x86::Gp {
|
auto mapZydisToAsmjitGp = [&](ZydisRegister zydisReg) -> asmjit::x86::Gp {
|
||||||
|
|
||||||
switch (zydisReg) {
|
switch (zydisReg) {
|
||||||
@@ -555,7 +555,7 @@ void RyujinObfuscationCore::insertVirtualization() {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vamos traduzir uma instru<72><75>o para o bytecode da MiniVm do Ryujin
|
// Let's translate an instruction to the MiniVm bytecode from Ryujin
|
||||||
auto translateToMiniVmBytecode = [&](ZydisRegister reg, ZyanU8 op, ZyanU64 value) {
|
auto translateToMiniVmBytecode = [&](ZydisRegister reg, ZyanU8 op, ZyanU64 value) {
|
||||||
|
|
||||||
ZyanU64 miniVmByteCode = 0;
|
ZyanU64 miniVmByteCode = 0;
|
||||||
@@ -727,69 +727,89 @@ void RyujinObfuscationCore::insertVirtualization() {
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return miniVmByteCode;
|
return miniVmByteCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inicializando o runtime do asmjit
|
// Initializing the asmjit runtime
|
||||||
asmjit::JitRuntime runtime;
|
asmjit::JitRuntime runtime;
|
||||||
|
|
||||||
for (auto& block : m_proc.basic_blocks) {
|
for (auto& block : m_proc.basic_blocks) {
|
||||||
|
|
||||||
for (auto& instr : block.instructions) {
|
for (auto& instr : block.instructions) {
|
||||||
|
|
||||||
// Vector para armazenarmos os opcodes da MiniVm do Ryujin
|
// Vector to store the MiniVm opcodes from Ryujin
|
||||||
std::vector<ZyanU8> minivm_enter;
|
std::vector<ZyanU8> minivm_enter;
|
||||||
|
|
||||||
// Operand type
|
// Operand type
|
||||||
ZyanU8 opType = 0;
|
ZyanU8 opType = 0;
|
||||||
|
|
||||||
// Encontrando o block info para o opcode atual
|
// Finding the block info for the current opcode
|
||||||
auto block_info = findBlockId(instr.instruction.info.opcode, instr.instruction.operands[1].imm.value.u, 2, sizeof(unsigned char));
|
auto block_info = findBlockId(instr.instruction.info.opcode, instr.instruction.operands[1].imm.value.u, 2, sizeof(unsigned char));
|
||||||
|
|
||||||
// Caso n<>o encontremos
|
// If not found
|
||||||
if (block_info.first == -1 || block_info.second == -1) continue;
|
if (block_info.first == -1 || block_info.second == -1) continue;
|
||||||
|
|
||||||
// Recuperando os opcodes originais desta instru<72><75>o ao qual trabalhamos
|
// Retrieving the original opcodes of the instruction we're working on
|
||||||
auto& data = m_proc.basic_blocks[block_info.first].opcodes[block_info.second];
|
auto& data = m_proc.basic_blocks[block_info.first].opcodes[block_info.second];
|
||||||
|
|
||||||
// Verificando por operands candidatos a serem virtualizados pela minivm
|
// Checking for operands that are candidates to be virtualized by the minivm
|
||||||
if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_ADD && isValidToSRyujinMiniVm(instr)) opType = 1;
|
if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_ADD && isValidToSRyujinMiniVm(instr)) opType = 1;
|
||||||
else if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_SUB && isValidToSRyujinMiniVm(instr)) opType = 2;
|
else if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_SUB && isValidToSRyujinMiniVm(instr)) opType = 2;
|
||||||
else if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_IMUL && isValidToSRyujinMiniVm(instr)) opType = 3;
|
else if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_IMUL && isValidToSRyujinMiniVm(instr)) opType = 3;
|
||||||
else if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_DIV && isValidToSRyujinMiniVm(instr)) opType = 4;
|
else if (instr.instruction.info.mnemonic == ZYDIS_MNEMONIC_DIV && isValidToSRyujinMiniVm(instr)) opType = 4;
|
||||||
|
|
||||||
//Existe um VM Operator novo ?
|
// Is there a new VM Operator?
|
||||||
if (opType != 0) {
|
if (opType != 0) {
|
||||||
|
|
||||||
// Inicializando para o asmjit gerar as instru<EFBFBD><EFBFBD>es de nossa minivm
|
//TODO: Implementar algoritmo para ofuscar as constantes da PEB e do Bytecode da VM para um layer extra de seguran<61>a
|
||||||
|
//TODO: Tentar fazer a MiniVm Stub din<69>micamente
|
||||||
|
|
||||||
|
// Initializing asmjit to generate our minivm instructions
|
||||||
asmjit::CodeHolder code;
|
asmjit::CodeHolder code;
|
||||||
code.init(runtime.environment());
|
code.init(runtime.environment());
|
||||||
asmjit::x86::Assembler a(&code);
|
asmjit::x86::Assembler a(&code);
|
||||||
|
|
||||||
|
// Saving the current value of RCX
|
||||||
a.push(asmjit::x86::rcx);
|
a.push(asmjit::x86::rcx);
|
||||||
a.mov(asmjit::x86::rcx, translateToMiniVmBytecode(instr.instruction.operands[0].reg.value, opType, instr.instruction.operands[1].imm.value.u)); //TODO: e se o reg ex: rax j<> tiver uma valor para um add, devemos armazenar rax tamb<6D>m ?
|
// Saving the current value of RDX
|
||||||
|
a.push(asmjit::x86::rdx);
|
||||||
|
// Storing in the first argument RCX the value of the register from the first operand of the mathematical operation
|
||||||
|
a.mov(asmjit::x86::rcx, mapZydisToAsmjitGp(instr.instruction.operands[0].reg.value));
|
||||||
|
// Storing in the second argument RDX the value of the bytecode sequence to be interpreted by the Ryujin MiniVM
|
||||||
|
a.mov(asmjit::x86::rdx, translateToMiniVmBytecode(instr.instruction.operands[0].reg.value, opType, instr.instruction.operands[1].imm.value.u));
|
||||||
|
// Using `rdgsbase rax` to store the base address of the GS segment in RAX
|
||||||
a.emit(asmjit::x86::Inst::kIdRdgsbase, asmjit::x86::rax);
|
a.emit(asmjit::x86::Inst::kIdRdgsbase, asmjit::x86::rax);
|
||||||
|
// Adding to RAX the offset value for the PEB
|
||||||
a.add(asmjit::x86::rax, 0x60);
|
a.add(asmjit::x86::rax, 0x60);
|
||||||
|
// Accessing and retrieving the PEB address to store it in RAX
|
||||||
a.mov(asmjit::x86::rax, asmjit::x86::ptr(asmjit::x86::rax));
|
a.mov(asmjit::x86::rax, asmjit::x86::ptr(asmjit::x86::rax));
|
||||||
|
// Adding to RAX the "ImageBase" field of the PEB
|
||||||
a.add(asmjit::x86::rax, 0x10);
|
a.add(asmjit::x86::rax, 0x10);
|
||||||
|
// Accessing the "ImageBase" address in the PEB to obtain the actual value
|
||||||
a.mov(asmjit::x86::rax, asmjit::x86::ptr(asmjit::x86::rax));
|
a.mov(asmjit::x86::rax, asmjit::x86::ptr(asmjit::x86::rax));
|
||||||
|
// Adding to the "ImageBase" value a "default" offset that will later be overwritten by the actual offset of the MiniVM enter
|
||||||
a.add(asmjit::x86::rax, asmjit::imm(0x88));
|
a.add(asmjit::x86::rax, asmjit::imm(0x88));
|
||||||
|
// Calling the MiniVMEnter procedure to execute
|
||||||
a.call(asmjit::x86::rax);
|
a.call(asmjit::x86::rax);
|
||||||
|
// Storing the result of the MiniVM execution stored in RAX into the correct register to continue the normal execution flow
|
||||||
a.mov(mapZydisToAsmjitGp(instr.instruction.operands[0].reg.value), asmjit::x86::rax);
|
a.mov(mapZydisToAsmjitGp(instr.instruction.operands[0].reg.value), asmjit::x86::rax);
|
||||||
|
// Restoring the original value of RDX
|
||||||
|
a.pop(asmjit::x86::rdx);
|
||||||
|
// Restoring the original value of RCX
|
||||||
a.pop(asmjit::x86::rcx);
|
a.pop(asmjit::x86::rcx);
|
||||||
|
|
||||||
|
// Retrieving from ASMJIT<49>s JIT the resulting opcodes generated by our algorithm
|
||||||
auto& opcodeBuffer = code.sectionById(0)->buffer();
|
auto& opcodeBuffer = code.sectionById(0)->buffer();
|
||||||
const auto pOpcodeBuffer = opcodeBuffer.data();
|
const auto pOpcodeBuffer = opcodeBuffer.data();
|
||||||
minivm_enter.reserve(opcodeBuffer.size());
|
minivm_enter.reserve(opcodeBuffer.size());
|
||||||
|
|
||||||
// Armazenando cada opcocde individual no nosso vector da minivm
|
// Storing each individual opcode in our minivm vector
|
||||||
for (auto i = 0; i < opcodeBuffer.size(); ++i) minivm_enter.push_back(static_cast<ZyanU8>(pOpcodeBuffer[i]));
|
for (auto i = 0; i < opcodeBuffer.size(); ++i) minivm_enter.push_back(static_cast<ZyanU8>(pOpcodeBuffer[i]));
|
||||||
|
|
||||||
// Sobrescrevendo opcodes antigos pelos novos
|
// Overwriting old opcodes with the new ones
|
||||||
data.assign(minivm_enter.begin(), minivm_enter.end());
|
data.assign(minivm_enter.begin(), minivm_enter.end());
|
||||||
|
|
||||||
std::printf("[!] Inserting a new MiniVm on %s\n", instr.instruction.text);
|
std::printf("[!] Inserting a new MiniVm ByteCode on %s\n", instr.instruction.text);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,17 +1174,23 @@ void RyujinObfuscationCore::InsertMiniVmEnterProcedureAddress(uintptr_t imageBas
|
|||||||
|
|
||||||
//Inserting Ryujin MiniVm Address on each vm entry reference
|
//Inserting Ryujin MiniVm Address on each vm entry reference
|
||||||
if (m_config.m_isVirtualized) {
|
if (m_config.m_isVirtualized) {
|
||||||
|
|
||||||
auto size = new_opcodes.size();
|
auto size = new_opcodes.size();
|
||||||
auto data = new_opcodes.data();
|
auto data = new_opcodes.data();
|
||||||
|
|
||||||
unsigned char ucSignature[]{ 0x48, 0x05, 0x88, 0x00, 0x00, 0x00 };
|
unsigned char ucSignature[]{ 0x48, 0x05, 0x88, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
for (auto i = 0; i < size; i++)
|
for (auto i = 0; i < size; i++)
|
||||||
|
|
||||||
if (std::memcmp(&*(data + i), ucSignature, 6) == 0) {
|
if (std::memcmp(&*(data + i), ucSignature, 6) == 0) {
|
||||||
std::printf("FIND!!\n");
|
|
||||||
|
std::printf("[OK] Inserting MiniVmEnter at %llx\n", imageBase + virtualAddress + i);
|
||||||
|
|
||||||
std::memset(&*(data + i + 2), 0, 4);
|
std::memset(&*(data + i + 2), 0, 4);
|
||||||
std::memcpy(&*(data + i + 2), &virtualAddress, sizeof(uint32_t));
|
std::memcpy(&*(data + i + 2), &virtualAddress, sizeof(uint32_t));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ auto main() -> int {
|
|||||||
config.m_isEncryptObfuscatedCode = FALSE;
|
config.m_isEncryptObfuscatedCode = FALSE;
|
||||||
std::vector<std::string> procsToObfuscate{
|
std::vector<std::string> procsToObfuscate{
|
||||||
"sum",
|
"sum",
|
||||||
|
"sub",
|
||||||
|
"subadd",
|
||||||
"main",
|
"main",
|
||||||
"invoke_main"
|
"invoke_main"
|
||||||
"__scrt_common_main",
|
"__scrt_common_main",
|
||||||
|
|||||||
Reference in New Issue
Block a user