diff --git a/addacl.c b/addacl.c new file mode 100644 index 0000000..22e44ed --- /dev/null +++ b/addacl.c @@ -0,0 +1,286 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "addacl.h" + +void ShowModuleError(LPSTR pszModError, LPSTR pszError); + +typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( + IN PSECURITY_DESCRIPTOR pSecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); + +typedef struct { + PSECURITY_DESCRIPTOR pFileSD; + PACL pNewACL; +} TYP_INST; + +static void FreeInst(TYP_INST *pInst); +static BOOL ShowError(TYP_INST *pInst, LPSTR pszError); + +BOOL AddAccessRights(LPSTR lpszFileName, LPVOID pUserSID, + DWORD dwAccessMask) +{ + TYP_INST Inst = {0}; + + // File SD variables. + DWORD cbFileSD = 0; + + // New SD variables. + SECURITY_DESCRIPTOR newSD; + + // ACL variables. + PACL pACL = NULL; + BOOL fDaclPresent; + BOOL fDaclDefaulted; + ACL_SIZE_INFORMATION AclInfo; + + // New ACL variables. + DWORD cbNewACL = 0; + + // Temporary ACE. + LPVOID pTempAce = NULL; + UINT CurrentAceIndex = 0; + + UINT newAceIndex = 0; + + // Assume function will fail. + BOOL fResult = FALSE; + BOOL fAPISuccess; + + SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; + + // New APIs available only in Windows 2000 and above for setting + // SD control + SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl = NULL; + + // + // STEP 2: Get security descriptor (SD) of the file specified. + // + if (fAPISuccess = GetFileSecurity(lpszFileName, + secInfo, Inst.pFileSD, 0, &cbFileSD)) + return ShowError (&Inst, "GetFileSecurity() failed."); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + Inst.pFileSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbFileSD); + if (!Inst.pFileSD) return ShowError (&Inst, "Out of memory"); + fAPISuccess = GetFileSecurity(lpszFileName, + secInfo, Inst.pFileSD, cbFileSD, &cbFileSD); + } + if (!fAPISuccess) return ShowError (&Inst, "GetFileSecurity() failed."); + + // + // STEP 3: Initialize new SD. + // + if (!InitializeSecurityDescriptor(&newSD, SECURITY_DESCRIPTOR_REVISION)) + return ShowError (&Inst, "InitializeSecurityDescriptor() failed."); + + // + // STEP 4: Get DACL from the old SD. + // + if (!GetSecurityDescriptorDacl(Inst.pFileSD, &fDaclPresent, &pACL, + &fDaclDefaulted)) return ShowError (&Inst, "GetSecurityDescriptorDacl() failed."); + + // + // STEP 5: Get size information for DACL. + // + AclInfo.AceCount = 0; // Assume NULL DACL. + AclInfo.AclBytesFree = 0; + AclInfo.AclBytesInUse = sizeof(ACL); + + if (pACL == NULL) + fDaclPresent = FALSE; + + // If not NULL DACL, gather size information from DACL. + if (fDaclPresent) { + if (!GetAclInformation(pACL, &AclInfo, + sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) + return ShowError (&Inst, "GetAclInformation() failed."); + } + + // + // STEP 6: Compute size needed for the new ACL. + // + cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + + GetLengthSid(pUserSID) - sizeof(DWORD); + + // + // STEP 7: Allocate memory for new ACL. + // + if (!(Inst.pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL))) + return ShowError (&Inst, "Out of memory."); + + // + // STEP 8: Initialize the new ACL. + // + if (!InitializeAcl(Inst.pNewACL, cbNewACL, ACL_REVISION2)) + return ShowError (&Inst, "InitializeAcl() failed"); + + // + // STEP 9 If DACL is present, copy all the ACEs from the old DACL + // to the new DACL. + // + // The following code assumes that the old DACL is + // already in Windows 2000 preferred order. To conform + // to the new Windows 2000 preferred order, first we will + // copy all non-inherited ACEs from the old DACL to the + // new DACL, irrespective of the ACE type. + // + + newAceIndex = 0; + + if (fDaclPresent && AclInfo.AceCount) { + + for (CurrentAceIndex = 0; + CurrentAceIndex < AclInfo.AceCount; + CurrentAceIndex++) { + + // + // STEP 10: Get an ACE. + // + if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) + return ShowError (&Inst, "GetAce() failed."); + + // + // STEP 11: Check if it is a non-inherited ACE. + // If it is an inherited ACE, break from the loop so + // that the new access allowed non-inherited ACE can + // be added in the correct position, immediately after + // all non-inherited ACEs. + // + if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags + & INHERITED_ACE) + break; + + // + // STEP 12: Skip adding the ACE, if the SID matches + // with the account specified, as we are going to + // add an access allowed ACE with a different access + // mask. + // + if (EqualSid(pUserSID, + &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) + continue; + + // + // STEP 13: Add the ACE to the new ACL. + // + if (!AddAce(Inst.pNewACL, ACL_REVISION, MAXDWORD, pTempAce, + ((PACE_HEADER) pTempAce)->AceSize)) + return ShowError (&Inst, "AddAce() failed."); + + newAceIndex++; + } + } + + // + // STEP 14: Add the access-allowed ACE to the new DACL. + // The new ACE added here will be in the correct position, + // immediately after all existing non-inherited ACEs. + // + if (!AddAccessAllowedAce(Inst.pNewACL, ACL_REVISION2, dwAccessMask, + pUserSID)) + return ShowError (&Inst, "AddAccessAllowedAce() failed."); + + // + // STEP 15: To conform to the new Windows 2000 preferred order, + // we will now copy the rest of inherited ACEs from the + // old DACL to the new DACL. + // + if (fDaclPresent && AclInfo.AceCount) { + + for (; + CurrentAceIndex < AclInfo.AceCount; + CurrentAceIndex++) { + + // + // STEP 16: Get an ACE. + // + if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) + return ShowError (&Inst, "GetAce() failed."); + + // + // STEP 17: Add the ACE to the new ACL. + // + if (!AddAce(Inst.pNewACL, ACL_REVISION, MAXDWORD, pTempAce, + ((PACE_HEADER) pTempAce)->AceSize)) + return ShowError (&Inst, "AddAce() failed."); + } + } + + // + // STEP 18: Set the new DACL to the new SD. + // + if (!SetSecurityDescriptorDacl(&newSD, TRUE, Inst.pNewACL, + FALSE)) return ShowError (&Inst, "SetSecurityDescriptorDacl() failed."); + + // + // STEP 19: Copy the old security descriptor control flags + // regarding DACL automatic inheritance for Windows 2000 or + // later where SetSecurityDescriptorControl() API is available + // in advapi32.dll. + // + _SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr) + GetProcAddress(GetModuleHandle("advapi32.dll"), + "SetSecurityDescriptorControl"); + if (_SetSecurityDescriptorControl) { + + SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0; + SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0; + SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0; + DWORD dwRevision = 0; + + if (!GetSecurityDescriptorControl(Inst.pFileSD, &oldControlBits, + &dwRevision)) return ShowError (&Inst, "GetSecurityDescriptorControl() failed."); + + if (oldControlBits & SE_DACL_AUTO_INHERITED) { + controlBitsOfInterest = + SE_DACL_AUTO_INHERIT_REQ | + SE_DACL_AUTO_INHERITED; + controlBitsToSet = controlBitsOfInterest; + } + else if (oldControlBits & SE_DACL_PROTECTED) { + controlBitsOfInterest = SE_DACL_PROTECTED; + controlBitsToSet = controlBitsOfInterest; + } + + if (controlBitsOfInterest) { + if (!_SetSecurityDescriptorControl(&newSD, + controlBitsOfInterest, + controlBitsToSet)) + return ShowError (&Inst, "SetSecurityDescriptorControl() failed."); + } + } + + // + // STEP 20: Set the new SD to the File. + // + if (!SetFileSecurity(lpszFileName, secInfo, + &newSD)) return ShowError (&Inst, "SetFileSecurity() failed."); + + fResult = TRUE; + FreeInst(&Inst); + + return fResult; +} + +// ============================================================= +// Private +// ============================================================= +static void FreeInst(TYP_INST *pInst) +{ + if (pInst->pFileSD) + HeapFree(GetProcessHeap(), 0, pInst->pFileSD); + + if (pInst->pNewACL) + HeapFree (GetProcessHeap(), 0, pInst->pNewACL); +} + +// -------------------------------------------------------------- + +static BOOL ShowError(TYP_INST *pInst, LPSTR pszError) +{ + ShowModuleError("Failed setting up ACL", pszError); + FreeInst(pInst); + return FALSE; +} diff --git a/addacl.h b/addacl.h new file mode 100644 index 0000000..71aec47 --- /dev/null +++ b/addacl.h @@ -0,0 +1 @@ +BOOL AddAccessRights(LPSTR lpszFileName, LPVOID pUserSID, DWORD dwAccessMask); diff --git a/flashpatch.c b/flashpatch.c new file mode 100644 index 0000000..ad67da1 --- /dev/null +++ b/flashpatch.c @@ -0,0 +1,285 @@ +/* Adobe Flash timebomb patcher + * + * leecher@dose.0wnz.at + * + * Simple C-Version without all these .NET dependencies and stuff + * Based on research by https://github.com/KuromeSan/FlashPatcher/ + * + */ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include "takeown.h" +#ifndef CSIDL_SYSTEM +#define CSIDL_LOCAL_APPDATA 0x001c +#define CSIDL_SYSTEM 0x0025 +#define CSIDL_SYSTEMX86 0x0029 +#endif + +static int LocateExes(void); +static int ScanFolder(char *pszPath); +static BYTE *Match (BYTE *lpMem, DWORD dwSize, const BYTE *lpSig, DWORD cbSig, DWORD step); +static BOOL PatchFile(char *pszFile); +static BOOL ShowError(LPSTR pszError); +static BOOL EnablePrivilege (HANDLE hProcess, LPCTSTR lpPrivilegeName); + +static int LocateExes(void) +{ + char szDir[MAX_PATH], *p; + int nFiles = 0; + + printf ("Scanning...\n"); + if (SHGetSpecialFolderPath(NULL, szDir, CSIDL_SYSTEM, FALSE)) + { + strcat(szDir, "\\Macromed\\Flash"); + nFiles += ScanFolder(szDir); + } + +#ifdef _WIN64 + if (SHGetSpecialFolderPath(NULL, szDir, CSIDL_SYSTEMX86, FALSE)) + { + strcat(szDir, "\\Macromed\\Flash"); + nFiles += ScanFolder(szDir); + } +#endif + if (SHGetSpecialFolderPath(NULL, szDir, CSIDL_LOCAL_APPDATA, FALSE)) + { + p = szDir + strlen(szDir); + strcpy(p, "\\Google\\Chrome\\User Data\\PepperFlash"); + nFiles += ScanFolder(szDir); + strcpy(p, "\\Microsoft\\Edge\\User Data\\PepperFlash"); + nFiles += ScanFolder(szDir); + } + return nFiles; +} + +static int ScanFolder(char *pszPath) +{ + WIN32_FIND_DATA fd; + HANDLE hSearch; + size_t cbFileName; + int nFiles = 0; + char *p = pszPath + strlen(pszPath); + + *p = '\\'; p++; + strcpy(p, "*.*"); + + if ((hSearch = FindFirstFile(pszPath, &fd)) != INVALID_HANDLE_VALUE) + { + do + { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (_stricmp(fd.cFileName, ".") == 0 || + _stricmp(fd.cFileName, "..") == 0) + continue; + strcpy(p, fd.cFileName); + nFiles += ScanFolder(pszPath); + } + else + { + cbFileName = strlen(fd.cFileName); + if (cbFileName > 4 && ( + _stricmp(&fd.cFileName[cbFileName-4], ".ocx") == 0 || + _stricmp(&fd.cFileName[cbFileName-4], ".dll") == 0 || + _stricmp(&fd.cFileName[cbFileName-4], ".exe") == 0)) + { + strcpy(p, fd.cFileName); + if (PatchFile(pszPath)) nFiles++; + } + } + } + while(FindNextFile(hSearch, &fd)); + FindClose(hSearch); + } + return nFiles; +} + +static BYTE *Match (BYTE *lpMem, DWORD dwSize, const BYTE *lpSig, DWORD cbSig, DWORD step) +{ + BYTE *lpOffset, *lpEnd; + DWORD i; + + for (lpOffset=lpMem, lpEnd=lpMem+dwSize-cbSig; lpOffset +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=flashpatch - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "flashpatch.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "flashpatch.mak" CFG="flashpatch - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "flashpatch - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "flashpatch - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "flashpatch - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0xc07 /d "NDEBUG" +# ADD RSC /l 0xc07 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "flashpatch - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0xc07 /d "_DEBUG" +# ADD RSC /l 0xc07 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "flashpatch - Win32 Release" +# Name "flashpatch - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\addacl.c +# End Source File +# Begin Source File + +SOURCE=.\flashpatch.c +# End Source File +# Begin Source File + +SOURCE=.\takeown.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\addacl.h +# End Source File +# Begin Source File + +SOURCE=.\takeown.h +# End Source File +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/flashpatch.dsw b/flashpatch.dsw new file mode 100644 index 0000000..0f2692b --- /dev/null +++ b/flashpatch.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "flashpatch"=.\flashpatch.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/flashpatch.mak b/flashpatch.mak new file mode 100644 index 0000000..f2645fa --- /dev/null +++ b/flashpatch.mak @@ -0,0 +1,182 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on flashpatch.dsp +!IF "$(CFG)" == "" +CFG=flashpatch - Win32 Debug +!MESSAGE Keine Konfiguration angegeben. flashpatch - Win32 Debug wird als Standard verwendet. +!ENDIF + +!IF "$(CFG)" != "flashpatch - Win32 Release" && "$(CFG)" != "flashpatch - Win32 Debug" +!MESSAGE Ungltige Konfiguration "$(CFG)" angegeben. +!MESSAGE Sie k”nnen beim Ausfhren von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "flashpatch.mak" CFG="flashpatch - Win32 Debug" +!MESSAGE +!MESSAGE Fr die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "flashpatch - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "flashpatch - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE +!ERROR Eine ungltige Konfiguration wurde angegeben. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "flashpatch - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +ALL : "$(OUTDIR)\flashpatch.exe" + + +CLEAN : + -@erase "$(INTDIR)\addacl.obj" + -@erase "$(INTDIR)\flashpatch.obj" + -@erase "$(INTDIR)\res.res" + -@erase "$(INTDIR)\takeown.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(OUTDIR)\flashpatch.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /GS- /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\flashpatch.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\res.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\flashpatch.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\flashpatch.pdb" /out:"$(OUTDIR)\flashpatch.exe" +LINK32_OBJS= \ + "$(INTDIR)\addacl.obj" \ + "$(INTDIR)\flashpatch.obj" \ + "$(INTDIR)\takeown.obj" \ + "$(INTDIR)\res.res" + +"$(OUTDIR)\flashpatch.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "flashpatch - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : "$(OUTDIR)\flashpatch.exe" + + +CLEAN : + -@erase "$(INTDIR)\addacl.obj" + -@erase "$(INTDIR)\flashpatch.obj" + -@erase "$(INTDIR)\res.res" + -@erase "$(INTDIR)\takeown.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(OUTDIR)\flashpatch.exe" + -@erase "$(OUTDIR)\flashpatch.ilk" + -@erase "$(OUTDIR)\flashpatch.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MTd /GS- /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\flashpatch.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\res.res" /d "_DEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\flashpatch.bsc" +BSC32_SBRS= \ + +LINK32=xilink6.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\flashpatch.pdb" /debug /out:"$(OUTDIR)\flashpatch.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\addacl.obj" \ + "$(INTDIR)\flashpatch.obj" \ + "$(INTDIR)\takeown.obj" \ + "$(INTDIR)\res.res" + +"$(OUTDIR)\flashpatch.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("flashpatch.dep") +!INCLUDE "flashpatch.dep" +!ELSE +!MESSAGE Warning: cannot find "flashpatch.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "flashpatch - Win32 Release" || "$(CFG)" == "flashpatch - Win32 Debug" +SOURCE=.\addacl.c + +"$(INTDIR)\addacl.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\flashpatch.c + +"$(INTDIR)\flashpatch.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\takeown.c + +"$(INTDIR)\takeown.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\res.rc + +"$(INTDIR)\res.res" : $(SOURCE) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/res.rc b/res.rc new file mode 100644 index 0000000..f006a90 --- /dev/null +++ b/res.rc @@ -0,0 +1,6 @@ +///////////////////////////////////////////////////////////////////////////// +// +// 24 +// + +1 24 DISCARDABLE "res\\manifest.xml" diff --git a/res/manifest.xml b/res/manifest.xml new file mode 100644 index 0000000..eb4abb7 --- /dev/null +++ b/res/manifest.xml @@ -0,0 +1,15 @@ + + + +elevate execution level + + + + + + + + diff --git a/takeown.c b/takeown.c new file mode 100644 index 0000000..d83a24e --- /dev/null +++ b/takeown.c @@ -0,0 +1,266 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "addacl.h" + +BOOL ShowModuleError(LPSTR pszModError, LPSTR pszError); + +static BOOL +AssertTakeOwnership( + HANDLE TokenHandle + ); +static BOOL +GetTokenHandle( + PHANDLE TokenHandle + ); +static BOOL +VariableInitialization(); +static BOOL ShowError(LPSTR pszError); + +PSID AliasAdminsSid = NULL; +PSID SeWorldSid; +static SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY; +static SID_IDENTIFIER_AUTHORITY SepWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; + +BOOL TakeOwnership(LPSTR lpFileName) +{ + BOOL Result; + SECURITY_DESCRIPTOR SecurityDescriptor; + HANDLE TokenHandle; + + Result = VariableInitialization(); + if ( !Result ) return ShowError ("SID Initialization failed"); + + Result = GetTokenHandle( &TokenHandle ); + if ( !Result ) return ShowError ("Unable to obtain the handle to our token, exiting\n"); + + // + // Attempt to put a NULL Dacl on the object + // + InitializeSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); + + Result = SetSecurityDescriptorDacl ( + &SecurityDescriptor, + TRUE, + NULL, + FALSE + ); + + if ( !Result ) return ShowError ("SetSecurityDescriptorDacl failed"); + + Result = SetFileSecurity( + lpFileName, + DACL_SECURITY_INFORMATION, + &SecurityDescriptor + ); + if ( Result ) return TRUE; + + // + // That didn't work. + // + + // + // Attempt to make Administrator the owner of the file. + // + + Result = SetSecurityDescriptorOwner ( + &SecurityDescriptor, + AliasAdminsSid, + FALSE + ); + if ( !Result ) return ShowError ("SetSecurityDescriptorOwner failed"); + + Result = SetFileSecurity( + lpFileName, + OWNER_SECURITY_INFORMATION, + &SecurityDescriptor + ); + if ( !Result ) { + + // + // That didn't work either. + // + + // + // Assert TakeOwnership privilege, then try again. Note that + // since the privilege is only enabled for the duration of + // this process, we don't have to worry about turning it off + // again. + // + Result = AssertTakeOwnership( TokenHandle ); + if ( !Result ) return ShowError("Could not enable SeTakeOwnership privilege"); + + Result = SetFileSecurity( + lpFileName, + OWNER_SECURITY_INFORMATION, + &SecurityDescriptor + ); + if ( !Result ) return ShowError ("Unable to assign Administrator as owner"); + } + // + // Try to put a benign DACL onto the file again + // + Result = SetFileSecurity( + lpFileName, + DACL_SECURITY_INFORMATION, + &SecurityDescriptor + ); + if ( !Result ) return ShowError ("SetFileSecurity unexpectedly failed"); + + return TRUE; +} + +// -------------------------------------------------------------- + +BOOL GrantAllPrivileges (LPSTR lpszFileName) +{ + VariableInitialization(); + return AddAccessRights (lpszFileName, SeWorldSid, GENERIC_ALL); +} + +// ============================================================= +// Private +// ============================================================= +static BOOL +GetTokenHandle( + PHANDLE TokenHandle + ) +// +// This routine will open the current process and return +// a handle to its token. +// +// These handles will be closed for us when the process +// exits. +// +{ + HANDLE ProcessHandle; + BOOL Result; + ProcessHandle = OpenProcess( + PROCESS_QUERY_INFORMATION, + FALSE, + GetCurrentProcessId() + ); + if ( ProcessHandle == NULL ) { + // + // This should not happen + // + return( FALSE ); + } + + Result = OpenProcessToken ( + ProcessHandle, + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + TokenHandle + ); + if ( !Result ) { + // + // This should not happen + // + return( FALSE ); + } + return( TRUE ); +} + +// -------------------------------------------------------------- + +static BOOL +AssertTakeOwnership( + HANDLE TokenHandle + ) +// +// This routine turns on SeTakeOwnershipPrivilege in the current +// token. Once that has been accomplished, we can open the file +// for WRITE_OWNER even if we are denied that access by the ACL +// on the file. +{ + LUID TakeOwnershipValue; + BOOL Result; + TOKEN_PRIVILEGES TokenPrivileges; + + // + // First, find out the value of TakeOwnershipPrivilege + // + + Result = LookupPrivilegeValue( + NULL, + "SeTakeOwnershipPrivilege", + &TakeOwnershipValue + ); + if ( !Result ) return ShowError ("Unable to obtain value of TakeOwnership privilege"); + + // + // Set up the privilege set we will need + // + TokenPrivileges.PrivilegeCount = 1; + TokenPrivileges.Privileges[0].Luid = TakeOwnershipValue; + TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + + (VOID) AdjustTokenPrivileges ( + TokenHandle, + FALSE, + &TokenPrivileges, + sizeof( TOKEN_PRIVILEGES ), + NULL, + NULL + ); + if ( GetLastError() != NO_ERROR ) { + return( FALSE ); + } else { + return( TRUE ); + } +} + +// -------------------------------------------------------------- + +static BOOL +VariableInitialization() +// +// Create some useful SIDs. +// +{ + static BOOL Result = FALSE; + + if (Result) return TRUE; + Result = AllocateAndInitializeSid( + &SepNtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, + 0, + 0, + 0, + 0, + 0, + &AliasAdminsSid + ); + if ( !Result ) { + return( FALSE ); + } + + Result = AllocateAndInitializeSid( + &SepWorldSidAuthority, + 1, + SECURITY_WORLD_RID, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + &SeWorldSid + ); + if ( !Result ) { + return( FALSE ); + } + return( TRUE ); +} + +// -------------------------------------------------------------- + +static BOOL ShowError(LPSTR pszError) +{ + return ShowModuleError("Failed taking ownership", pszError); +} diff --git a/takeown.h b/takeown.h new file mode 100644 index 0000000..3de6be9 --- /dev/null +++ b/takeown.h @@ -0,0 +1,2 @@ +BOOL TakeOwnership(LPSTR lpFileName); +BOOL GrantAllPrivileges (LPSTR lpszFileName);