Poly Polymorphic Engine function reference & usage examples.
Poly Polymorphic Engine has only one function which both encrypts data and generates a corresponding decryption routine.
unsigned int __stdcall _poly(
void * lpDecryptor,
void * lpOutput,
void * lpInput,
unsigned int iSize,
unsigned int lpVA,
unsigned int cMaxInstr,
unsigned int cMinInstr,
unsigned int iGarbage,
unsigned int iForceSize,
unsigned int lpRelativeAddr,
struct POLY_REGS * lpPolyOutRegs,
unsigned int iOptions,
void * lpWorkMem,
unsigned int iRandomSeed
);
function _poly(
lpDecryptor : Pointer; // output buffer for polymorphic code
lpOutput : Pointer; // output data buffer (can be the same as lpInput)
lpInput : Pointer; // input data buffer
iSize : LongWord; // input data size
lpVA : Pointer; // virtual address of a data to be decrypted
cMaxInstr : LongWord; // max. number of real encryption instructions
cMinInstr : LongWord; // min. number of real encryption instructions
iGarbage : LongWord; // number of junks per instruction
iForceSize : LongWord; // force decryptor size (optional)
lpRelativeAddr : Integer; // relative output data offset (optional)
var lpPolyOutRegs : TPOLY_REGS; // output registers (optional)
iOptions : LongWord; // flags
lpWorkMem : Pointer; // work memory
iRandomSeed : Integer // random seed for the internal randomizer
): LongWord;stdcall;external 'poly.dll';
push dwRandomSeed
push offset lpWorkMem
push iOptions
push lpPolyOutRegs
push lpRelativeAddr
push iForceSize
push iGarbage
push cMinInstr
push cMaxInstr
push lpVA
push iSize
push lpInput
push lpOutput
push lpDecryptor
call _poly
POLY_ATTACH_DATA
flag is set.lpInput
. If the POLY_ATTACH_DATA
flag is set, this
parameter is ignored, because encrypted data will be stored alongside the decryption code in lpDecryptor
decryption code buffer.lpInput
.lpDecryptor
and lpWorkMem
buffers.lpDecryptor
and lpWorkMem
buffers.cMaxInstr
, cMinInstr
and iGarbage
parameters on
the fly if the generated code is too small or too big and re-generate the code
again to meet your exact criteria (please make sure the working buffers
lpDecryptor
and lpWorkMem
are bigger than this value).VA
or RVA
address) and position of the polymorphic
decryptor.Pointer to the POLY_REGS
structure with output CPU register values set after the decryption ends.
To make it work, the POLY_SET_REGS
flag has to be set as well as one or more register flags
specifying which registers you want to set, e.g. POLY_SET_EAX
.
struct POLY_REGS
{
unsigned int regEax;
unsigned int regEcx;
unsigned int regEdx;
unsigned int regEbx;
unsigned int regEsp;
unsigned int regEbp;
unsigned int regEsi;
unsigned int regEdi;
};
Additional feature flags for the polymorphic engine.
Name | Value | Description |
---|---|---|
POLY_SET_REGS | 0x00000001 |
Set output registers values defined in POLY_REGS structure, after the decryption code finishes its work. |
POLY_SET_EAX | 0x00000002 |
Set EAX register output value. |
POLY_SET_ECX | 0x00000004 |
Set ECX register output value. |
POLY_SET_EDX | 0x00000008 |
Set EDX register output value. |
POLY_SET_EBX | 0x00000010 |
Set EBX register output value. |
POLY_SET_ESP | 0x00000020 |
Set ESP register output value. |
POLY_SET_EBP | 0x00000040 |
Set EBP register output value.. |
POLY_SET_ESI | 0x00000080 |
Set ESI register output value. |
POLY_SET_EDI | 0x00000100 |
Set EDI register output value.. |
POLY_SAVE_REGS | 0x00000200 |
Save all 32 bit register values with PUSHAD instruction (except those used with POLY_SET_REGS flag) before the call and restore them with POPAD instruction after the decryption code finishes. |
POLY_SAVE_FLAGS | 0x00000400 |
Save all CPU flags with PUSHFD instruction before the call and restore them with POPFD instruction after the decryption code finishes. |
POLY_RETURN | 0x00000800 |
If this flag is set, a return instruction ( Polymorphic decryptor can be inlined between other code or some other code can be added after its body so it doesn't have to return to the caller. |
POLY_ATTACH_DATA | 0x00001000 |
Attach encrypted data to the decryptor body so the decryption code and encrypted data will be stored in a single block. The decryptor will decrypt the data and overwrite its own body so after decryption, a pointer to the decryption code will also be a pointer to the decrypted data. If this flag is not used, the encrypted data has to be located at the static |
POLY_FLAGS_ALL | 0xFFFFFFFF |
All above bit flags combined. |
lpDecryptor
buffer.If the data is successfully encrypted and a decryption routine is generated, this function returns the size of the
decryption routine (and optionally encrypted data) stored in lpDecryptor
memory buffer.
This function returns 0
on error.
This engine is very flexible and can be used in different scenarios, which is why the best way to show its features is to present an example.
In the below example, Poly Polymorphic Engine is used to encrypt the input block of data, generate the decryption code, and append the encrypted data to it. Although this is not shown, the resulting block can be saved to an external file, which can later be decrypted by loading its contents into an executable memory buffer and calling the memory buffer pointer like a regular function.
In this example, all of the available options are used, and it runs for 10000 iterations to test the validity of encryption and decryption process.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include "poly.h"
// helper macro
#define RND_RANGE(min,max) (min + (rand() % (int)(max - min + 1)))
// number of test iterations
const int POLY_TEST_ITERATIONS = 10000;
// safe memory buffer size
const int POLY_DECRYPTOR_SIZE = 1024 * 2048 * 10;
// sample input data to encrypt
unsigned char cInputBuffer[] = { 0x11, 0x22, 0x33, 0x44 } ;
// output buffer
unsigned char cOutputBuffer[sizeof(cInputBuffer)] = { 0 };
int main(int argc, char* argv[])
{
// allocate memory buffer for the encrypted block (it has to be executable)
PVOID lpDecryptor = VirtualAlloc(nullptr, POLY_DECRYPTOR_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// work memory buffer (same size, also has to be executable)
PVOID lpWorkMem = VirtualAlloc(nullptr, POLY_DECRYPTOR_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
for (int i = 0; i < POLY_TEST_ITERATIONS; i++)
{
//
// setup Poly engine parameters
//
// randomize parameters (remember, more means you need to increase
// the size of the lpDecryptor & lpWorkMem buffers)
// minimal number of encryption commands
unsigned int iMinEncryptionCommands = RND_RANGE(10, 50);
// maximal number of encryption commands
unsigned int iMaxEncryptionCommands = RND_RANGE(iMinEncryptionCommands, iMinEncryptionCommands + 10);
// number of junks per decryptor single command
unsigned int iGarbage = RND_RANGE(10, 50);
// force decryptor size - if this value is set, Poly engine will try to generate
// decryptor body that is exactly this size, it will modify other parameters on
// the fly if the generated code is too small or too big and re-generate the code
// again to meet your exact criteria (please make sure the working buffers
// lpDecryptor and lpWorkMem are bigger than this value)
unsigned int iForceDecryptorSize = 0;
// if this parameter is set, polymorphic decryption code will use it to calculate
// the address of the encrypted data in memory, this pointer is relative to the
// current position of the decryptor code in the memory (it can be positive or
// negative)
unsigned int iRelativeDataOutputOffset = 0;
// flags
unsigned int iOptions = 0;
// POLY_SAVE_REGS - save all registers before the call and restore them after the call
iOptions |= POLY_SAVE_REGS;
// POLY_SAVE_FLAGS - save all CPU flags before the call and restore them after the call
iOptions |= POLY_SAVE_FLAGS;
// POLY_ATTACH_DATA - attach data to the decryptor body, decryption will overwrite
// decryptor body and after decryption lpDecryptor will also be a pointer to the
// decrypted buffer
//
// if this flag is not used, encrypted data has to be located at the static VA address
// declared in lpVA parameter or declared via relative address in iRelativeDataOutputOffset
// parameter
iOptions |= POLY_ATTACH_DATA;
// POLY_RETURN - put a return instruction (RET) at the end of the decryption function,
// so the decryptor returns to the caller, polymorphic decryptor can be inlined
// between other code or some other code can be added after its body so it may or
// may not return to the caller
iOptions |= POLY_RETURN;
// POLY_SET_REGS - return exact values in CPU registers after decryption (it must be
// defined in POLY_REGS structure)
iOptions |= POLY_SET_REGS;
// return value in EAX register
iOptions |= POLY_SET_EAX;
// and let's say it should return some other value in EDX register after the call
iOptions |= POLY_SET_EDX;
// output registers values (fill out only those marked to be returned)
POLY_REGS prPolyRegs = { 0 };
// fill out the EAX register with a value that should be returned after
// the decryption, in this example let's set it to the size of the decrypted
// buffer (you can set it to anything)
prPolyRegs.regEax = sizeof(cInputBuffer);
// sample value to be returned in EDX register after the call (view it
// with a debugger)
prPolyRegs.regEdx = 0xDEADBEEF;
// encrypt data & generate polymorphic decryptor
unsigned int dwOutputSize = _poly(
lpDecryptor, // output buffer for polymorphic code
cOutputBuffer, // output data buffer (can be the same as lpInput) (optional)
cInputBuffer, // input data buffer
sizeof(cInputBuffer), // input data size
(unsigned int)&cOutputBuffer, // virtual address of data to be decrypted (optional)
iMaxEncryptionCommands, // max. number of real encryption instructions
iMinEncryptionCommands, // min. number of real encryption instructions
iGarbage, // number of junks per instruction
iForceDecryptorSize, // force decryptor size (optional)
iRelativeDataOutputOffset, // relative output data offset (optional)
&prPolyRegs, // output registers (optional)
iOptions, // additional options
lpWorkMem, // work memory
GetTickCount() // random seed for the internal randomizer
);
// validate output size (decryptor size in bytes)
if (dwOutputSize != 0)
{
PolyDecryptorFunction DecryptorFunction = reinterpret_cast<PolyDecryptorFunction>(lpDecryptor);
// decrypt data
unsigned int dwResult = DecryptorFunction();
// another way to invoke decryptor function (inline assembly)
/*
__asm
{
int 3
mov eax, lpDecryptor;
call eax
int 3
}
*/
// validate decrypted data (if POLY_ATTACH_DATA flag was set - lpDecryptor
// points to the decrypted data)
if (memcmp(reinterpret_cast<PVOID>(lpDecryptor), cInputBuffer, sizeof(cInputBuffer) != 0))
{
printf("Polymorphic engine failed (decrypted data is invalid)!\n");
_getch();
return 2;
}
}
else
{
printf("Polymorphic engine failed!\n");
_getch();
return 1;
}
}
printf("Polymorphic engine test success (%lu iterations)\n", POLY_TEST_ITERATIONS);
// relese the memory
VirtualFree(lpDecryptor, 0, MEM_RELEASE);
VirtualFree(lpWorkMem, 0, MEM_RELEASE);
_getch();
return 0;
}
Header | poly.h |
Library | poly.lib |
DLL | poly.dll |
program poly_test;
{$APPTYPE CONSOLE}
uses StrUtils, Classes, SysUtils, Math, Windows;
// load library from the DLL file (by default .LIB file is used)
{$DEFINE USE_POLY_DLL}
// include additional Poly constants
{$I poly.inc}
const
// number of test iterations
POLY_TEST_ITERATIONS = 10000;
// safe memory buffer size
POLY_DECRYPTOR_SIZE = 1024 * 2048 * 10;
// sample input data to encrypt
cInputBuffer : Array [1..4] of Byte = ( $11, $22, $33, $44 );
var
// output buffer
cOutputBuffer : Array [1..4] of Byte;
{$IFDEF USE_POLY_DLL}
// library handle
hDll : THandle;
// function pointer (if loaded dynamically)
fnPoly : TPolyProc;
{$ENDIF}
i : Integer;
iMinEncryptionCommands, iMaxEncryptionCommands : LongWord;
iGarbage : LongWord;
iForceDecryptorSize : LongWord;
iRelativeDataOutputOffset : Integer;
iOptions : LongWord;
dwResult : LongWord;
dwOutputSize : LongWord;
lpDecryptor : Pointer;
lpWorkMem : Pointer;
// output registers values (fill out only those marked to be returned)
prPolyRegs : TPOLY_REGS;
DecryptorFunction : TPolyDecryptorFunction;
//
// entrypoint
//
begin
// initialize random number generator
Randomize;
// clean output array
FillChar(cOutputBuffer, SizeOf(cOutputBuffer), 0);
// load Poly engine from the DLL library
{$IFDEF USE_POLY_DLL}
hDll := LoadLibrary('poly.dll');
if hDll = 0 Then
begin
WriteLn('Cannot load poly.dll library!');
ReadLn;
ExitCode := 1;
Halt;
end;
@fnPoly := GetProcAddress(hDll, '_poly');
if not Assigned(@fnPoly) Then
begin
WriteLn('Cannot find "_poly" function in poly.dll library!');
ReadLn;
ExitCode := 1;
Halt;
end;
{$ENDIF}
// allocate memory buffer for the encrypted block (it has to be executable)
lpDecryptor := VirtualAlloc(nil, POLY_DECRYPTOR_SIZE, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// work memory buffer (same size, also it has to be executable)
lpWorkMem := VirtualAlloc(nil, POLY_DECRYPTOR_SIZE, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
for i := 0 to POLY_TEST_ITERATIONS do
begin
//
// setup Poly engine parameters
//
// randomize parameters (remember, more means you need to increase
// the size of the lpDecryptor & lpWorkMem buffers)
// minimal number of encryption commands
iMinEncryptionCommands := RandomRange(10, 50);
// maximal number of encryption commands
iMaxEncryptionCommands := RandomRange(iMinEncryptionCommands, iMinEncryptionCommands + 10);
// number of junks per decryptor single command
iGarbage := RandomRange(10, 50);
// force decryptor size - if this value is set, Poly engine will try to generate
// decryptor body that is exactly this size, it will modify other parameters on
// the fly if the generated code is too small or too big and re-generate the code
// again to meet your exact criteria (please make sure the working buffers
// lpDecryptor and lpWorkMem are bigger than this value)
iForceDecryptorSize := 0;
// if this parameter is set, polymorphic decryption code will use it to calculate
// the address of the encrypted data in memory, this pointer is relative to the
// current position of the decryptor code in the memory (it can be positive or
// negative)
iRelativeDataOutputOffset := 0;
// flags
iOptions := 0;
// POLY_SAVE_REGS - save all registers before the call and restore them after the call
iOptions := iOptions or POLY_SAVE_REGS;
// POLY_SAVE_FLAGS - save all CPU flags before the call and restore them after the call
iOptions := iOptions or POLY_SAVE_FLAGS;
// POLY_ATTACH_DATA - attach data to the decryptor body, decryption will overwrite
// decryptor body and after decryption lpDecryptor will also be a pointer to the
// decrypted buffer
//
// if this flag is not used, encrypted data has to be located on static VA address
// declared in lpVA parameter or declared via relative address in iRelativeDataOutputOffset
// parameter
iOptions := iOptions or POLY_ATTACH_DATA;
// POLY_RETURN - put a return instruction (RET) at the end of the decryption function,
// so the decryptor returns to the caller, polymorphic decryptor can be inlined
// between other code or some other code can be added after its body so it may or
// may not return to the caller
iOptions := iOptions or POLY_RETURN;
// POLY_SET_REGS - return exact values in CPU registers after decryption (it must be
// defined in POLY_REGS structure)
iOptions := iOptions or POLY_SET_REGS;
// return value in EAX register
iOptions := iOptions or POLY_SET_EAX;
// and lets say it should return some other value in EDX register after the call
iOptions := iOptions or POLY_SET_EDX;
// output registers values (fill out only those marked to be returned)
// fill out the EAX register with a value that should be returned after
// the decryption, in this example lets set it to the size of the decrypted
// buffer (you can set anything)
prPolyRegs.regEax := Length(cInputBuffer);
// sample value to be returned in EDX register after the call (view it
// with a debugger)
prPolyRegs.regEdx := $DEADBEEF;
// encrypt data & generate polymorphic decryptor
{$IFDEF USE_POLY_DLL}
dwOutputSize := fnPoly(
lpDecryptor, // output buffer for polymorphic code
@cOutputBuffer, // output data buffer (can be the same as lpInput)
@cInputBuffer, // input data buffer
Length(cInputBuffer), // input data size
@cOutputBuffer, // virtual address of a data to be decrypted
iMaxEncryptionCommands, // max. number of real encryption instructions
iMinEncryptionCommands, // min. number of real encryption instructions
iGarbage, // number of junks per instruction
iForceDecryptorSize, // force decryptor size (optional)
iRelativeDataOutputOffset, // relative output data offset (optional)
prPolyRegs, // output registers (optional)
iOptions, // additional options
lpWorkMem, // work memory
Random(65536) // random seed for the internal randomizer
);
{$ELSE}
dwOutputSize := _poly(
lpDecryptor, // output buffer for polymorphic code
@cOutputBuffer, // output data buffer (can be the same as lpInput)
@cInputBuffer, // input data buffer
Length(cInputBuffer), // input data size
@cOutputBuffer, // virtual address of a data to be decrypted
iMaxEncryptionCommands, // max. number of real encryption instructions
iMinEncryptionCommands, // min. number of real encryption instructions
iGarbage, // number of junks per instruction
iForceDecryptorSize, // force decryptor size (optional)
iRelativeDataOutputOffset, // relative output data offset (optional)
prPolyRegs, // output registers (optional)
iOptions, // additional options
lpWorkMem, // work memory
Random(65536) // random seed for the internal randomizer
);
{$ENDIF}
// validate output size (decryptor size in bytes)
if dwOutputSize <> 0 then
begin
DecryptorFunction := lpDecryptor;
// decrypt data
dwResult := DecryptorFunction;
// another way to invoke decryptor function (inline assembly)
{
asm
int 3
mov eax, lpDecryptor;
call eax
int 3
end;
}
// validate decrypted data (if POLY_ATTACH_DATA flag was set - lpDecryptor
// points to the decrypted data)
if CompareMem(lpDecryptor, @cInputBuffer, Length(cInputBuffer)) <> True then
begin
WriteLn('Polymorphic engine failed (decrypted data is invalid)!');
ReadLn;
ExitCode := 2;
Halt;
end;
end
else
begin
WriteLn('Polymorphic engine failed!\n');
ReadLn;
ExitCode := 1;
Halt;
end;
end;
WriteLn(format('Polymorphic engine test success (%d iterations)', [ POLY_TEST_ITERATIONS ]));
// relese the memory
VirtualFree(lpDecryptor, 0, MEM_RELEASE);
VirtualFree(lpWorkMem, 0, MEM_RELEASE);
ReadLn;
end.
Header | poly.inc |
Library | poly.lib |
DLL | poly.dll |
An example of encrypting an arbitrary binary file and generating an output file containing a polymorphic decryptor at the beginning of the file with the encrypted section of the input file appended.
// exclude rarely-used stuff from Windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <vector>
#include "poly.h"
// load library from the DLL file (by default .LIB file is used)
#define USE_POLY_DLL
// helper macro
#define RND_RANGE(min,max) (min + (rand() % (int)(max - min + 1)))
// safe memory buffer size
const int POLY_DECRYPTOR_SIZE = 1024 * 2048 * 10;
// input file to be encrypted
#define INPUT_FILE "file.bin"
// output file with the attached x86 polymorphic decryptor and the encrypted data
#define OUTPUT_FILE "file_encrypted.bin"
int main(int argc, char* argv[])
{
// open file to encrypt its content
std::ifstream inputFile(INPUT_FILE, std::ios::binary);
if (!inputFile.is_open())
{
printf("Cannot open %s input file!\n", INPUT_FILE);
_getch();
return 1;
}
// get file size
inputFile.seekg(0, std::ios::end);
std::streamsize fileSize = inputFile.tellg();
inputFile.seekg(0, std::ios::beg);
// allocate memory for cInputBuffer based on the file size
std::vector<unsigned char> cInputBuffer(fileSize);
// read the content of the file into cInputBuffer
inputFile.read(reinterpret_cast<char*>(cInputBuffer.data()), fileSize);
inputFile.close();
// load Poly engine from the DLL library
#ifdef USE_POLY_DLL
HINSTANCE hDll = LoadLibrary("poly.dll");
if (hDll == nullptr)
{
printf("Cannot load poly.dll library!\n");
_getch();
return 1;
}
POLY_PROC _poly_proc = (POLY_PROC)GetProcAddress(hDll, "_poly");
if (hDll == nullptr)
{
printf("Cannot find '_poly' function in poly.dll library!\n");
_getch();
return 1;
}
#endif
// allocate memory buffer for the encrypted block (it has to be executable)
PVOID lpDecryptor = VirtualAlloc(nullptr, POLY_DECRYPTOR_SIZE + fileSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// work memory buffer (same size, also it has to be executable)
PVOID lpWorkMem = VirtualAlloc(nullptr, POLY_DECRYPTOR_SIZE + fileSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//
// setup Poly engine parameters
//
// randomize parameters (remember, more means you need to increase
// the size of the lpDecryptor & lpWorkMem buffers)
// minimal number of encryption commands
unsigned int iMinEncryptionCommands = RND_RANGE(10, 50);
// maximal number of encryption commands
unsigned int iMaxEncryptionCommands = RND_RANGE(iMinEncryptionCommands, iMinEncryptionCommands + 10);
// number of junks per decryptor single command
unsigned int iGarbage = 0; RND_RANGE(10, 50);
// force decryptor size - if this value is set, Poly engine will try to generate
// decryptor body that is exactly this size, it will modify other parameters on
// the fly if the generated code is too small or too big and re-generate the code
// again to meet your exact criteria (please make sure the working buffers
// lpDecryptor and lpWorkMem are bigger than this value)
unsigned int iForceDecryptorSize = 0;
// if this parameter is set, polymorphic decryption code will use it to calculate
// the address of the encrypted data in memory, this pointer is relative to the
// current position of the decryptor code in the memory (it can be positive or
// negative)
unsigned int iRelativeDataOutputOffset = 0;
// flags
unsigned int iOptions = 0;
// POLY_SAVE_REGS - save all registers before the call and restore them after the call
iOptions |= POLY_SAVE_REGS;
// POLY_SAVE_FLAGS - save all CPU flags before the call and restore them after the call
iOptions |= POLY_SAVE_FLAGS;
// POLY_ATTACH_DATA - attach data to the decryptor body, decryption will overwrite
// decryptor body and after decryption lpDecryptor will also be a pointer to the
// decrypted buffer
//
// if this flag is not used, encrypted data has to be located on static VA address
// declared in lpVA parameter or declared via relative address in iRelativeDataOutputOffset
// parameter
iOptions |= POLY_ATTACH_DATA;
// POLY_RETURN - put a return instruction (RET) at the end of the decryption function,
// so the decryptor returns to the caller, polymorphic decryptor can be inlined
// between other code or some other code can be added after its body so it may or
// may not return to the caller
iOptions |= POLY_RETURN;
// POLY_SET_REGS - return exact values in CPU registers after decryption (it must be
// defined in POLY_REGS structure)
iOptions |= POLY_SET_REGS;
// return value in EAX register
iOptions |= POLY_SET_EAX;
// and lets say it should return some other value in EDX register after the call
iOptions |= POLY_SET_EDX;
// output registers values (fill out only those marked to be returned)
POLY_REGS prPolyRegs = { 0 };
// fill out the EAX register with a value that should be returned after
// the decryption, in this example lets set it to the size of the decrypted
// buffer (you can set anything)
prPolyRegs.regEax = sizeof(cInputBuffer);
// sample value to be returned in EDX register after the call (view it
// with a debugger)
prPolyRegs.regEdx = 0xDEADBEEF;
// encrypt data & generate polymorphic decryptor
#ifdef USE_POLY_DLL
unsigned int dwOutputSize = _poly_proc(
#else
unsigned int dwOutputSize = _poly(
#endif
lpDecryptor, // output buffer for polymorphic code
cInputBuffer.data(), // output data buffer (can be the same as lpInput)
cInputBuffer.data(), // input data buffer
fileSize, // input data size
0, // virtual address of a data to be decrypted (optional)
iMaxEncryptionCommands, // max. number of real encryption instructions
iMinEncryptionCommands, // min. number of real encryption instructions
iGarbage, // number of junks per instruction
iForceDecryptorSize, // force decryptor size (optional)
iRelativeDataOutputOffset,// relative output data offset (optional)
&prPolyRegs, // output registers (optional)
iOptions, // additional options
lpWorkMem, // work memory
GetTickCount() // random seed for the internal randomizer
);
// validate output size (decryptor size in bytes)
if (dwOutputSize != 0)
{
std::ofstream outputFile(OUTPUT_FILE, std::ios::binary | std::ios::trunc);
if (!outputFile.is_open())
{
printf("Error saving polymorphic loader with encrypted data to a file %s\n", OUTPUT_FILE);
_getch();
return 1;
}
outputFile.write((const char *)lpDecryptor, dwOutputSize);
outputFile.close();
}
else
{
printf("Polymorphic engine failed!\n");
_getch();
return 1;
}
// relese the memory
VirtualFree(lpDecryptor, 0, MEM_RELEASE);
VirtualFree(lpWorkMem, 0, MEM_RELEASE);
printf("File %s successfully encrypted to %s\n", INPUT_FILE, OUTPUT_FILE);
_getch();
return 0;
}
Nagłówek | poly.h |
Biblioteka | poly.lib |
DLL | poly.dll |
If you would like to ask me about Poly Polymorphic Engine, or something's not clear, mail me. I'll be happy to answer all of your questions.