mimikatz/modules/kull_m_cabinet.c

214 lines
6.4 KiB
C

/* Benjamin DELPY `gentilkiwi`
https://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kull_m_cabinet.h"
int DIAMONDAPI fnFilePlaced(PCCAB pccab, IN LPSTR pszFile, long cbFile, BOOL fContinuation, void FAR *pv)
{
return 0;
}
void HUGE * FAR DIAMONDAPI fnMemAlloc(ULONG cb)
{
return LocalAlloc(LPTR, cb);
}
void FAR DIAMONDAPI fnMemFree(void HUGE *memory)
{
LocalFree(memory);
}
INT_PTR FAR DIAMONDAPI fnFileOpen(IN LPSTR pszFile, int oflag, int pmode, int FAR *err, void FAR *pv)
{
HANDLE hFile;
DWORD dwDesiredAccess;
if(oflag & _O_RDWR)
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
else if(oflag & _O_WRONLY)
dwDesiredAccess = GENERIC_WRITE;
else dwDesiredAccess = GENERIC_READ;
hFile = CreateFileA(pszFile, dwDesiredAccess, FILE_SHARE_READ, NULL, (oflag & _O_CREAT) ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
*err = GetLastError();
return (INT_PTR) hFile;
}
UINT FAR DIAMONDAPI fnFileRead(INT_PTR hf, void FAR *memory, UINT cb, int FAR *err, void FAR *pv)
{
DWORD dwBytesRead;
if(!ReadFile((HANDLE) hf, memory, cb, &dwBytesRead, NULL))
{
dwBytesRead = (DWORD) -1;
*err = GetLastError();
}
return dwBytesRead;
}
UINT FAR DIAMONDAPI fnFileWrite(INT_PTR hf, void FAR *memory, UINT cb, int FAR *err, void FAR *pv)
{
DWORD dwBytesWritten;
if(!WriteFile((HANDLE) hf, memory, cb, &dwBytesWritten, NULL))
{
dwBytesWritten = (DWORD)-1;
*err = GetLastError();
}
return dwBytesWritten;
}
int FAR DIAMONDAPI fnFileClose(INT_PTR hf, int FAR *err, void FAR *pv)
{
INT iResult = 0;
if(!CloseHandle((HANDLE) hf))
{
*err = GetLastError();
iResult = -1;
}
return iResult;
}
long FAR DIAMONDAPI fnFileSeek(INT_PTR hf, long dist, int seektype, int FAR *err, void FAR *pv)
{
INT iResult = 0;
iResult = SetFilePointer((HANDLE) hf, dist, NULL, seektype);
if(iResult == INVALID_SET_FILE_POINTER)
*err = GetLastError();
return iResult;
}
int FAR DIAMONDAPI fnFileDelete(IN LPSTR pszFile, int FAR *err, void FAR *pv)
{
INT iResult = 0;
if(!DeleteFileA(pszFile))
{
*err = GetLastError();
iResult = -1;
}
return iResult;
}
BOOL DIAMONDAPI fnGetTempFileName(OUT char *pszTempName, IN int cbTempName, void FAR *pv)
{
BOOL bSucceeded = FALSE;
CHAR pszTempPath[MAX_PATH], pszTempFile[MAX_PATH];
if(GetTempPathA(MAX_PATH, pszTempPath))
{
if(GetTempFileNameA(pszTempPath, "CABINET", 0, pszTempFile) != 0)
{
DeleteFileA(pszTempFile);
bSucceeded = SUCCEEDED(StringCbCopyA(pszTempName, cbTempName, pszTempFile));
}
}
return bSucceeded;
}
BOOL DIAMONDAPI fnGetNextCabinet(PCCAB pccab, ULONG cbPrevCab, void FAR *pv)
{
return SUCCEEDED(StringCchPrintfA(pccab->szCab, ARRAYSIZE(pccab->szCab), "%s_%02d.cab", pv, pccab->iCab));
}
long DIAMONDAPI fnStatus(UINT typeStatus, ULONG cb1, ULONG cb2, void FAR *pv)
{
return 0;
}
INT_PTR DIAMONDAPI fnGetOpenInfo(IN LPSTR pszName, USHORT *pdate, USHORT *ptime, USHORT *pattribs, int FAR *err, void FAR *pv)
{
HANDLE hFile;
FILETIME fileTime;
BY_HANDLE_FILE_INFORMATION fileInfo;
hFile = (HANDLE) fnFileOpen(pszName, _O_RDONLY, 0, err, pv);
if (hFile != INVALID_HANDLE_VALUE)
{
if(GetFileInformationByHandle(hFile, &fileInfo) && FileTimeToLocalFileTime(&fileInfo.ftCreationTime, &fileTime) && FileTimeToDosDateTime(&fileTime, pdate, ptime))
{
*pattribs = (USHORT) fileInfo.dwFileAttributes;
*pattribs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
}
else
{
fnFileClose((INT_PTR) hFile, err, pv);
hFile = INVALID_HANDLE_VALUE;
}
}
return (INT_PTR) hFile;
}
LPCSTR FCIErrorToString(FCIERROR err)
{
switch (err)
{
case FCIERR_NONE:
return "No error";
case FCIERR_OPEN_SRC:
return "Failure opening file to be stored in cabinet";
case FCIERR_READ_SRC:
return "Failure reading file to be stored in cabinet";
case FCIERR_ALLOC_FAIL:
return "Insufficient memory in FCI";
case FCIERR_TEMP_FILE:
return "Could not create a temporary file";
case FCIERR_BAD_COMPR_TYPE:
return "Unknown compression type";
case FCIERR_CAB_FILE:
return "Could not create cabinet file";
case FCIERR_USER_ABORT:
return "Client requested abort";
case FCIERR_MCI_FAIL:
return "Failure compressing data";
default:
return "Unknown error";
}
}
PKIWI_CABINET kull_m_cabinet_create(LPSTR cabinetName)
{
PKIWI_CABINET cab = NULL;
if(cab = (PKIWI_CABINET) LocalAlloc(LPTR, sizeof(KIWI_CABINET)))
{
cab->ccab.cb = 0x4000000;
cab->ccab.cbFolderThresh = 0x4000000;
cab->ccab.setID = 42;
cab->ccab.iCab = 0;
cab->ccab.iDisk = 0;
if(fnGetNextCabinet(&cab->ccab, 0, cabinetName))
{
if(GetCurrentDirectoryA(ARRAYSIZE(cab->ccab.szCabPath), cab->ccab.szCabPath))
if(SUCCEEDED(StringCchCatA(cab->ccab.szCabPath, ARRAYSIZE(cab->ccab.szCabPath), "\\")))
if(!(cab->hfci = FCICreate(&cab->erf, fnFilePlaced, fnMemAlloc, fnMemFree, fnFileOpen, fnFileRead, fnFileWrite, fnFileClose, fnFileSeek, fnFileDelete, fnGetTempFileName, &cab->ccab, cabinetName)))
PRINT_ERROR(L"FCICreate failed with error code %d: %S\n", cab->erf.erfOper, FCIErrorToString((FCIERROR) cab->erf.erfOper));
}
else PRINT_ERROR(L"Failed to initialize the cabinet information structure.\n");
if(!cab->hfci)
cab = (PKIWI_CABINET) LocalFree(cab);
}
return cab;
}
BOOL kull_m_cabinet_add(PKIWI_CABINET cab, LPSTR sourceFile, OPTIONAL LPSTR destFile)
{
BOOL status = FALSE;
if(!destFile)
{
destFile = strrchr(sourceFile, '\\');
if(destFile)
destFile++;
else destFile = sourceFile;
}
if(!(status = FCIAddFile(cab->hfci, sourceFile, destFile, FALSE, fnGetNextCabinet, fnStatus, fnGetOpenInfo, TCOMPfromLZXWindow(21))))
PRINT_ERROR(L"FCIAddFile failed with error code %d: %S (%S -> %S)\n", cab->erf.erfOper, FCIErrorToString((FCIERROR) cab->erf.erfOper), sourceFile, destFile);
return status;
}
BOOL kull_m_cabinet_close(PKIWI_CABINET cab)
{
BOOL status = FALSE;
if(!(status = FCIFlushCabinet(cab->hfci, FALSE, fnGetNextCabinet, fnStatus)))
PRINT_ERROR(L"FCIFlushCabinet failed with error code %d: %S\n", cab->erf.erfOper, FCIErrorToString((FCIERROR) cab->erf.erfOper));
if(!FCIDestroy(cab->hfci))
PRINT_ERROR(L"FCIDestroy failed with error code %d: %S\n", cab->erf.erfOper, FCIErrorToString((FCIERROR) cab->erf.erfOper));
LocalFree(cab);
return status;
}