bool mod_mimikatz_efs::toraw(vector<wstring> * arguments)
{
	if(arguments->size() == 2)
	{
		PVOID pvContext = NULL;
		wcout << L"Opening : " << arguments->front() << endl;
		if(OpenEncryptedFileRaw(arguments->front().c_str(), 0, &pvContext) == ERROR_SUCCESS)
		{
			wcout << L"To         : " << arguments->back() << endl;
			HANDLE hFile = CreateFile(arguments->back().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
			if(ReadEncryptedFileRaw(ExportToFileCallback, &hFile, pvContext) == ERROR_SUCCESS)
			{
				wcout << L" * Export OK" << endl;
			}
			else wcout << L"* Error ReadEncryptedFileRaw : " << mod_system::getWinError() << endl;
			CloseHandle(hFile);
			CloseEncryptedFileRaw(pvContext);
		}
		else wcout << L"Error OpenEncryptedFileRaw : " << mod_system::getWinError() << endl;
	}
	return true;
}
Example #2
0
int send_whole_filel(struct asfd *asfd,
#ifdef HAVE_WIN32
	enum cmd cmd,
#endif
	const char *datapth,
	int quick_read, uint64_t *bytes, struct cntr *cntr,
	struct BFILE *bfd, const char *extrameta, size_t elen)
{
	int ret=0;
	size_t s=0;
	MD5_CTX md5;
	char buf[4096]="";
	struct iobuf wbuf;

	if(!bfd)
	{
		logp("No bfd in %s()\n", __func__);
		return -1;
	}

	if(!MD5_Init(&md5))
	{
		logp("MD5_Init() failed\n");
		return -1;
	}

	if(extrameta)
	{
		size_t metalen=0;
		const char *metadata=NULL;

		metadata=extrameta;
		metalen=elen;

		// Send metadata in chunks, rather than all at once.
		while(metalen>0)
		{
			if(metalen>ZCHUNK) s=ZCHUNK;
			else s=metalen;

			if(!MD5_Update(&md5, metadata, s))
			{
				logp("MD5_Update() failed\n");
				ret=-1;
			}
			iobuf_set(&wbuf, CMD_APPEND, (char *)metadata, s);
			if(asfd->write(asfd, &wbuf))
			{
				ret=-1;
			}

			metadata+=s;
			metalen-=s;

			*bytes+=s;
		}
	}
	else
	{
#ifdef HAVE_WIN32
		if(!ret && cmd==CMD_EFS_FILE)
		{
			struct winbuf mybuf;
			mybuf.md5=&md5;
			mybuf.quick_read=quick_read;
			mybuf.datapth=datapth;
			mybuf.cntr=cntr;
			mybuf.bytes=bytes;
			mybuf.asfd=asfd;
			// The EFS read function, ReadEncryptedFileRaw(),
			// works in an annoying way. You have to give it a
			// function that it calls repeatedly every time the
			// read buffer is called.
			// So ReadEncryptedFileRaw() will not return until
			// it has read the whole file. I have no idea why
			// they do not have a plain 'read()' function for it.

			ReadEncryptedFileRaw((PFE_EXPORT_FUNC)write_efs,
				&mybuf, bfd->pvContext);
		}
		else
#endif

		if(!ret)
		{
#ifdef HAVE_WIN32
		  int do_known_byte_count=0;
		  size_t datalen=bfd->datalen;
		  if(datalen>0) do_known_byte_count=1;
#endif
		  while(1)
		  {
#ifdef HAVE_WIN32
			if(do_known_byte_count)
			{
				s=(uint32_t)bfd->read(bfd,
					buf, min((size_t)4096, datalen));
				datalen-=s;
			}
			else
			{
#endif
				s=(uint32_t)bfd->read(bfd, buf, 4096);
#ifdef HAVE_WIN32
			}
#endif
			if(s<=0) break;

			*bytes+=s;
			if(!MD5_Update(&md5, buf, s))
			{
				logp("MD5_Update() failed\n");
				ret=-1;
				break;
			}
			iobuf_set(&wbuf, CMD_APPEND, buf, s);
			if(asfd->write(asfd, &wbuf))
			{
				ret=-1;
				break;
			}
			if(quick_read)
			{
				int qr;
				if((qr=do_quick_read(asfd, datapth, cntr))<0)
				{
					ret=-1;
					break;
				}
				if(qr)
				{
					// client wants to interrupt
					break;
				}
			}
#ifdef HAVE_WIN32
			// Windows VSS headers tell us how many bytes to
			// expect.
			if(do_known_byte_count && datalen<=0) break;
#endif
		  }
		}
	}
	if(!ret)
	{
		uint8_t checksum[MD5_DIGEST_LENGTH];
		if(!MD5_Final(checksum, &md5))
		{
			logp("MD5_Final() failed\n");
			return -1;
		}
		return write_endfile(asfd, *bytes, checksum);
	}
	return ret;
}
bool mod_mimikatz_efs::full(vector<wstring> * arguments)
{
	if(!arguments->empty())
	{
		PVOID pvContext = NULL;
		if(OpenEncryptedFileRaw(arguments->front().c_str(), 0, &pvContext) == ERROR_SUCCESS)
		{
			SIMPLE_BYTE_ARRAY sba = {0, reinterpret_cast<BYTE *>(malloc(0))};
			if(ReadEncryptedFileRaw(ExportToArrayCallback, &sba, pvContext) == ERROR_SUCCESS)
			{
				PEFS_FEK Fek = NULL;
				PEFS_STREAM_DATA_SEGMENT monDataSegment = NULL;
				for(
					PEFS_MARSHALED_STREAM monMarshaledStream = reinterpret_cast<PEFS_MARSHALED_STREAM>(sba.tableau + sizeof(EFS_RAW));
					reinterpret_cast<PBYTE>(monMarshaledStream) < (sba.tableau + sba.nbElements);
				monMarshaledStream = reinterpret_cast<PEFS_MARSHALED_STREAM>(monDataSegment)
					)
				{

					bool isEFSMetaData = (monMarshaledStream->NameLenght == 2) && (monMarshaledStream->StreamName[0] == 0x1910);

					wcout << endl <<
						L"Marshaled Stream :" << endl <<
						L" * Length : " << monMarshaledStream->Length << endl <<
						L" * Flag   : " << monMarshaledStream->Flag << endl <<
						L" * Name    : " << (isEFSMetaData ? wstring(L"(EFS Metadata stream)") : wstring(monMarshaledStream->StreamName, monMarshaledStream->NameLenght / sizeof(wchar_t))) << endl <<
						L" * Type   : " << (isEFSMetaData ? L"EFS Metadata" : L"DATA") << endl <<
						endl;

					for(
						monDataSegment = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT>(reinterpret_cast<PBYTE>(monMarshaledStream) + monMarshaledStream->Length);
						(reinterpret_cast<PBYTE>(monDataSegment) < (sba.tableau + sba.nbElements)) && (monDataSegment->GURE0 == 0x00550047) && (monDataSegment->GURE1 == 0x00450052);
					monDataSegment = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT>(reinterpret_cast<PBYTE>(monDataSegment) + monDataSegment->Length)
						)

					{
						wcout << L"DataSegment : " << endl;
						PBYTE StreamData = reinterpret_cast<PBYTE>(monDataSegment) + sizeof(EFS_STREAM_DATA_SEGMENT);

						if(isEFSMetaData)
						{
							wcout << L"  EFS Metadata :" << endl;

							PEFS_METADATA_1 mesAttr = reinterpret_cast<PEFS_METADATA_1>(StreamData);
							wcout << L"   * Version EFS : " << mesAttr->EFS_Version << endl;
							if(mesAttr->DDF_Offset)
							{
								wcout << L"   * User(s) reported :" << endl;
								fullInfosFromEFS_KEY_LIST(mesAttr, mesAttr->DDF_Offset, &Fek);
							}
							if(mesAttr->DRF_Offset)
							{
								wcout << L"   * Agent(s) covering  :" << endl;
								fullInfosFromEFS_KEY_LIST(mesAttr, mesAttr->DRF_Offset, &Fek);
							}
						}
						else
						{
							wcout << L"  DATA :" << endl;
							if(!monMarshaledStream->Flag)
							{
								wcout << L"  DATA Segment Encryption Header :" << endl;
								PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER monSegEncHead = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER>(StreamData);
								wcout <<
									L"   * Length                : " << monSegEncHead->Length << endl <<
									L"   * StartingFile_Offset   : " << monSegEncHead->StartingFile_Offset << endl <<
									L"   * BytesWithinStreamSize : " << monSegEncHead->BytesWithinStreamSize << endl <<
									L"   * BytesWithinVDL        : " << monSegEncHead->BytesWithinVDL << endl <<
									L"   * DataUnitShift         : " << monSegEncHead->DataUnitShift << endl <<
									L"   * ChunkShift            : " << monSegEncHead->ChunkShift << endl <<
									L"   * ClusterShift          : " << monSegEncHead->ClusterShift << endl <<
									L"   * NumberOfDataBlocks    : " << monSegEncHead->NumberOfDataBlocks << endl <<
									endl;

								PEFS_EXTENDED_HEADER monExtHeader = reinterpret_cast<PEFS_EXTENDED_HEADER>(reinterpret_cast<PBYTE>(monSegEncHead) + FIELD_OFFSET(EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER, DataBlockSizes) + (sizeof(DWORD) * monSegEncHead->NumberOfDataBlocks));
								if(monExtHeader->EXTD_Number == 'DTXE')
								{
									wcout << L"   * Extended Header Flag  : " << monExtHeader->Flags << endl;
								}

								for(DWORD block = 0; block < monSegEncHead->NumberOfDataBlocks; block++)
								{
									wcout << L"    -> Block " << block+1 << L" ; taille : " << monSegEncHead->DataBlockSizes[block] << endl;

									PBYTE mesDatas = reinterpret_cast<PBYTE>(StreamData) + monSegEncHead->Length;
									wcout << mod_text::stringOfHex(mesDatas, monSegEncHead->DataBlockSizes[block], 16) << endl;

									if(Fek);
								}
							}
							else
							{
								wcout << L"TODO Data" << endl;
							}
						}
					}
				}
			}
			else wcout << L"Error ReadEncryptedFileRaw : " << mod_system::getWinError() << endl;

			free(sba.tableau);
			CloseEncryptedFileRaw(pvContext);
		}
		else wcout << L"Error OpenEncryptedFileRaw : " << mod_system::getWinError() << endl;
	}
	return true;
}
Example #4
0
File: handy.c Project: goneri/burp
int send_whole_file(char cmd, const char *fname, const char *datapth, int quick_read, unsigned long long *bytes, struct cntr *cntr, BFILE *bfd, FILE *fp, const char *extrameta, size_t elen)
{
	int ret=0;
	size_t s=0;
	MD5_CTX md5;
	char buf[4096]="";

	if(!MD5_Init(&md5))
	{
		logp("MD5_Init() failed\n");
		return -1;
	}

	if(extrameta)
	{
		size_t metalen=0;
		const char *metadata=NULL;

		metadata=extrameta;
		metalen=elen;

		// Send metadata in chunks, rather than all at once.
		while(metalen>0)
		{
			if(metalen>ZCHUNK) s=ZCHUNK;
			else s=metalen;

			if(!MD5_Update(&md5, metadata, s))
			{
				logp("MD5_Update() failed\n");
				ret=-1;
			}
			if(async_write(CMD_APPEND, metadata, s))
			{
				ret=-1;
			}

			metadata+=s;
			metalen-=s;

			*bytes+=s;
		}
	}
	else
	{
#ifdef HAVE_WIN32
		if(!ret && cmd==CMD_EFS_FILE)
		{
			struct winbuf mybuf;
			mybuf.md5=&md5;
			mybuf.quick_read=quick_read;
			mybuf.datapth=datapth;
			mybuf.cntr=cntr;
			mybuf.bytes=bytes;
			// The EFS read function, ReadEncryptedFileRaw(),
			// works in an annoying way. You have to give it a
			// function that it calls repeatedly every time the
			// read buffer is called.
			// So ReadEncryptedFileRaw() will not return until
			// it has read the whole file. I have no idea why
			// they do not have a plain 'read()' function for it.

			ReadEncryptedFileRaw((PFE_EXPORT_FUNC)write_efs,
				&mybuf, bfd->pvContext);
		}

		if(!ret && cmd!=CMD_EFS_FILE)
		{
		  while((s=(uint32_t)bread(bfd, buf, 4096))>0)
		  {
			*bytes+=s;
			if(!MD5_Update(&md5, buf, s))
			{
				logp("MD5_Update() failed\n");
				ret=-1;
				break;
			}
			if(async_write(CMD_APPEND, buf, s))
			{
				ret=-1;
				break;
			}
			if(quick_read)
			{
				int qr;
				if((qr=do_quick_read(datapth, cntr))<0)
				{
					ret=-1;
					break;
				}
				if(qr)
				{
					// client wants to interrupt
					break;
				}
			}
		  }
		}
#else
	//printf("send_whole_file: %s\n", fname);
		if(!ret) while((s=fread(buf, 1, 4096, fp))>0)
		{
			*bytes+=s;
			if(!MD5_Update(&md5, buf, s))
			{
				logp("MD5_Update() failed\n");
				ret=-1;
				break;
			}
			if(async_write(CMD_APPEND, buf, s))
			{
				ret=-1;
				break;
			}
			if(quick_read)
			{
				int qr;
				if((qr=do_quick_read(datapth, cntr))<0)
				{
					ret=-1;
					break;
				}
				if(qr)
				{
					// client wants to interrupt
					break;
				}
			}
		}
#endif
	}
	if(!ret)
	{
		unsigned char checksum[MD5_DIGEST_LENGTH+1];
		if(!MD5_Final(checksum, &md5))
		{
			logp("MD5_Final() failed\n");
			return -1;
		}
		return write_endfile(*bytes, checksum);
	}
	return ret;
}