├── README.md ├── addacl.c ├── addacl.h ├── flashpatch.c ├── flashpatch.dsp ├── flashpatch.dsw ├── flashpatch.mak ├── reinst_flash_w10.cmd ├── res.rc ├── res └── manifest.xml ├── takeown.c └── takeown.h /README.md: -------------------------------------------------------------------------------- 1 | # What is it? 2 | Patches Adobe Flash Player timebomb on Windows. 3 | In Adobe Flash Player versions newer than 32.0.0.344 they added a "Timebomb" for the EOL. the player would refuse to run any custom flash content after 12/01/2021, 4 | 5 | # Why another patcher? 6 | When looking for a solution for the problem, I found this analysis of the timebomb: 7 | https://gist.github.com/KuromeSan/56d8b724c0696b54f9f81994ae3591d1 8 | 9 | Unfortunately, I only found patchers for the timebomb that were written in .NET. 10 | Now I definitely don't want to pollute my system with .NET Framework and the patcher above didn't even work properly on Windows XP. 11 | So I decided to write my own little patcher that is just a tiny executable without any dependencies. 12 | It is based on the work mentioned above. 13 | 14 | # How to use? 15 | Depending on whether you are on x86 or x64 System, download flashpatch_x86.exe or flashpatch_x64.exe from Releases-page. 16 | If you just want to look in the default locations and patch Flash installation there, simply run the .exe 17 | If you want to scan a certain directory or patch a specifig file, specify it as a commandline parameter. 18 | 19 | # How to reinstall flash after KB4577586 removed it? 20 | On Windows 7 and below, just download and install it from the sites mentioned [here](https://gist.github.com/KuromeSan/56d8b724c0696b54f9f81994ae3591d1#finally) 21 | On Windows 10, you need to download the latest Flash player from KB4580325 and reinstall its contents. 22 | For this, download reinst_flash_w10.cmd to the same directory as the flashpatch_???.exe files and run it, it downloads mentioned updated flash version and copies it to System directory again. 23 | -------------------------------------------------------------------------------- /addacl.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include "addacl.h" 5 | 6 | void ShowModuleError(LPSTR pszModError, LPSTR pszError); 7 | 8 | typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( 9 | IN PSECURITY_DESCRIPTOR pSecurityDescriptor, 10 | IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, 11 | IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); 12 | 13 | typedef struct { 14 | PSECURITY_DESCRIPTOR pFileSD; 15 | PACL pNewACL; 16 | } TYP_INST; 17 | 18 | static void FreeInst(TYP_INST *pInst); 19 | static BOOL ShowError(TYP_INST *pInst, LPSTR pszError); 20 | 21 | BOOL AddAccessRights(LPSTR lpszFileName, LPVOID pUserSID, 22 | DWORD dwAccessMask) 23 | { 24 | TYP_INST Inst = {0}; 25 | 26 | // File SD variables. 27 | DWORD cbFileSD = 0; 28 | 29 | // New SD variables. 30 | SECURITY_DESCRIPTOR newSD; 31 | 32 | // ACL variables. 33 | PACL pACL = NULL; 34 | BOOL fDaclPresent; 35 | BOOL fDaclDefaulted; 36 | ACL_SIZE_INFORMATION AclInfo; 37 | 38 | // New ACL variables. 39 | DWORD cbNewACL = 0; 40 | 41 | // Temporary ACE. 42 | LPVOID pTempAce = NULL; 43 | UINT CurrentAceIndex = 0; 44 | 45 | UINT newAceIndex = 0; 46 | 47 | // Assume function will fail. 48 | BOOL fResult = FALSE; 49 | BOOL fAPISuccess; 50 | 51 | SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; 52 | 53 | // New APIs available only in Windows 2000 and above for setting 54 | // SD control 55 | SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl = NULL; 56 | 57 | // 58 | // STEP 2: Get security descriptor (SD) of the file specified. 59 | // 60 | if (fAPISuccess = GetFileSecurity(lpszFileName, 61 | secInfo, Inst.pFileSD, 0, &cbFileSD)) 62 | return ShowError (&Inst, "GetFileSecurity() failed."); 63 | if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 64 | { 65 | Inst.pFileSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbFileSD); 66 | if (!Inst.pFileSD) return ShowError (&Inst, "Out of memory"); 67 | fAPISuccess = GetFileSecurity(lpszFileName, 68 | secInfo, Inst.pFileSD, cbFileSD, &cbFileSD); 69 | } 70 | if (!fAPISuccess) return ShowError (&Inst, "GetFileSecurity() failed."); 71 | 72 | // 73 | // STEP 3: Initialize new SD. 74 | // 75 | if (!InitializeSecurityDescriptor(&newSD, SECURITY_DESCRIPTOR_REVISION)) 76 | return ShowError (&Inst, "InitializeSecurityDescriptor() failed."); 77 | 78 | // 79 | // STEP 4: Get DACL from the old SD. 80 | // 81 | if (!GetSecurityDescriptorDacl(Inst.pFileSD, &fDaclPresent, &pACL, 82 | &fDaclDefaulted)) return ShowError (&Inst, "GetSecurityDescriptorDacl() failed."); 83 | 84 | // 85 | // STEP 5: Get size information for DACL. 86 | // 87 | AclInfo.AceCount = 0; // Assume NULL DACL. 88 | AclInfo.AclBytesFree = 0; 89 | AclInfo.AclBytesInUse = sizeof(ACL); 90 | 91 | if (pACL == NULL) 92 | fDaclPresent = FALSE; 93 | 94 | // If not NULL DACL, gather size information from DACL. 95 | if (fDaclPresent) { 96 | if (!GetAclInformation(pACL, &AclInfo, 97 | sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) 98 | return ShowError (&Inst, "GetAclInformation() failed."); 99 | } 100 | 101 | // 102 | // STEP 6: Compute size needed for the new ACL. 103 | // 104 | cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) 105 | + GetLengthSid(pUserSID) - sizeof(DWORD); 106 | 107 | // 108 | // STEP 7: Allocate memory for new ACL. 109 | // 110 | if (!(Inst.pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL))) 111 | return ShowError (&Inst, "Out of memory."); 112 | 113 | // 114 | // STEP 8: Initialize the new ACL. 115 | // 116 | if (!InitializeAcl(Inst.pNewACL, cbNewACL, ACL_REVISION2)) 117 | return ShowError (&Inst, "InitializeAcl() failed"); 118 | 119 | // 120 | // STEP 9 If DACL is present, copy all the ACEs from the old DACL 121 | // to the new DACL. 122 | // 123 | // The following code assumes that the old DACL is 124 | // already in Windows 2000 preferred order. To conform 125 | // to the new Windows 2000 preferred order, first we will 126 | // copy all non-inherited ACEs from the old DACL to the 127 | // new DACL, irrespective of the ACE type. 128 | // 129 | 130 | newAceIndex = 0; 131 | 132 | if (fDaclPresent && AclInfo.AceCount) { 133 | 134 | for (CurrentAceIndex = 0; 135 | CurrentAceIndex < AclInfo.AceCount; 136 | CurrentAceIndex++) { 137 | 138 | // 139 | // STEP 10: Get an ACE. 140 | // 141 | if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) 142 | return ShowError (&Inst, "GetAce() failed."); 143 | 144 | // 145 | // STEP 11: Check if it is a non-inherited ACE. 146 | // If it is an inherited ACE, break from the loop so 147 | // that the new access allowed non-inherited ACE can 148 | // be added in the correct position, immediately after 149 | // all non-inherited ACEs. 150 | // 151 | if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags 152 | & INHERITED_ACE) 153 | break; 154 | 155 | // 156 | // STEP 12: Skip adding the ACE, if the SID matches 157 | // with the account specified, as we are going to 158 | // add an access allowed ACE with a different access 159 | // mask. 160 | // 161 | if (EqualSid(pUserSID, 162 | &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) 163 | continue; 164 | 165 | // 166 | // STEP 13: Add the ACE to the new ACL. 167 | // 168 | if (!AddAce(Inst.pNewACL, ACL_REVISION, MAXDWORD, pTempAce, 169 | ((PACE_HEADER) pTempAce)->AceSize)) 170 | return ShowError (&Inst, "AddAce() failed."); 171 | 172 | newAceIndex++; 173 | } 174 | } 175 | 176 | // 177 | // STEP 14: Add the access-allowed ACE to the new DACL. 178 | // The new ACE added here will be in the correct position, 179 | // immediately after all existing non-inherited ACEs. 180 | // 181 | if (!AddAccessAllowedAce(Inst.pNewACL, ACL_REVISION2, dwAccessMask, 182 | pUserSID)) 183 | return ShowError (&Inst, "AddAccessAllowedAce() failed."); 184 | 185 | // 186 | // STEP 15: To conform to the new Windows 2000 preferred order, 187 | // we will now copy the rest of inherited ACEs from the 188 | // old DACL to the new DACL. 189 | // 190 | if (fDaclPresent && AclInfo.AceCount) { 191 | 192 | for (; 193 | CurrentAceIndex < AclInfo.AceCount; 194 | CurrentAceIndex++) { 195 | 196 | // 197 | // STEP 16: Get an ACE. 198 | // 199 | if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) 200 | return ShowError (&Inst, "GetAce() failed."); 201 | 202 | // 203 | // STEP 17: Add the ACE to the new ACL. 204 | // 205 | if (!AddAce(Inst.pNewACL, ACL_REVISION, MAXDWORD, pTempAce, 206 | ((PACE_HEADER) pTempAce)->AceSize)) 207 | return ShowError (&Inst, "AddAce() failed."); 208 | } 209 | } 210 | 211 | // 212 | // STEP 18: Set the new DACL to the new SD. 213 | // 214 | if (!SetSecurityDescriptorDacl(&newSD, TRUE, Inst.pNewACL, 215 | FALSE)) return ShowError (&Inst, "SetSecurityDescriptorDacl() failed."); 216 | 217 | // 218 | // STEP 19: Copy the old security descriptor control flags 219 | // regarding DACL automatic inheritance for Windows 2000 or 220 | // later where SetSecurityDescriptorControl() API is available 221 | // in advapi32.dll. 222 | // 223 | _SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr) 224 | GetProcAddress(GetModuleHandle("advapi32.dll"), 225 | "SetSecurityDescriptorControl"); 226 | if (_SetSecurityDescriptorControl) { 227 | 228 | SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0; 229 | SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0; 230 | SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0; 231 | DWORD dwRevision = 0; 232 | 233 | if (!GetSecurityDescriptorControl(Inst.pFileSD, &oldControlBits, 234 | &dwRevision)) return ShowError (&Inst, "GetSecurityDescriptorControl() failed."); 235 | 236 | if (oldControlBits & SE_DACL_AUTO_INHERITED) { 237 | controlBitsOfInterest = 238 | SE_DACL_AUTO_INHERIT_REQ | 239 | SE_DACL_AUTO_INHERITED; 240 | controlBitsToSet = controlBitsOfInterest; 241 | } 242 | else if (oldControlBits & SE_DACL_PROTECTED) { 243 | controlBitsOfInterest = SE_DACL_PROTECTED; 244 | controlBitsToSet = controlBitsOfInterest; 245 | } 246 | 247 | if (controlBitsOfInterest) { 248 | if (!_SetSecurityDescriptorControl(&newSD, 249 | controlBitsOfInterest, 250 | controlBitsToSet)) 251 | return ShowError (&Inst, "SetSecurityDescriptorControl() failed."); 252 | } 253 | } 254 | 255 | // 256 | // STEP 20: Set the new SD to the File. 257 | // 258 | if (!SetFileSecurity(lpszFileName, secInfo, 259 | &newSD)) return ShowError (&Inst, "SetFileSecurity() failed."); 260 | 261 | fResult = TRUE; 262 | FreeInst(&Inst); 263 | 264 | return fResult; 265 | } 266 | 267 | // ============================================================= 268 | // Private 269 | // ============================================================= 270 | static void FreeInst(TYP_INST *pInst) 271 | { 272 | if (pInst->pFileSD) 273 | HeapFree(GetProcessHeap(), 0, pInst->pFileSD); 274 | 275 | if (pInst->pNewACL) 276 | HeapFree (GetProcessHeap(), 0, pInst->pNewACL); 277 | } 278 | 279 | // -------------------------------------------------------------- 280 | 281 | static BOOL ShowError(TYP_INST *pInst, LPSTR pszError) 282 | { 283 | ShowModuleError("Failed setting up ACL", pszError); 284 | FreeInst(pInst); 285 | return FALSE; 286 | } 287 | -------------------------------------------------------------------------------- /addacl.h: -------------------------------------------------------------------------------- 1 | BOOL AddAccessRights(LPSTR lpszFileName, LPVOID pUserSID, DWORD dwAccessMask); 2 | -------------------------------------------------------------------------------- /flashpatch.c: -------------------------------------------------------------------------------- 1 | /* Adobe Flash timebomb patcher 2 | * 3 | * leecher@dose.0wnz.at 4 | * 5 | * Simple C-Version without all these .NET dependencies and stuff 6 | * Based on research by https://github.com/KuromeSan/FlashPatcher/ 7 | * 8 | */ 9 | #define WIN32_LEAN_AND_MEAN 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "takeown.h" 15 | #ifndef CSIDL_SYSTEM 16 | #define CSIDL_LOCAL_APPDATA 0x001c 17 | #define CSIDL_SYSTEM 0x0025 18 | #define CSIDL_SYSTEMX86 0x0029 19 | #endif 20 | 21 | static int LocateExes(void); 22 | static int ScanFolder(char *pszPath); 23 | static BYTE *Match (BYTE *lpMem, DWORD dwSize, const BYTE *lpSig, DWORD cbSig, DWORD step); 24 | static BOOL PatchFile(char *pszFile); 25 | static BOOL ShowError(LPSTR pszError); 26 | static BOOL EnablePrivilege (HANDLE hProcess, LPCTSTR lpPrivilegeName); 27 | 28 | static int ScanFlashFolder(int nFolder) 29 | { 30 | char szDir[MAX_PATH+16], *p, *pszDir = szDir+12; 31 | int nFiles = 0; 32 | 33 | strcpy(szDir, "regsvr32 /s "); 34 | if (SHGetSpecialFolderPath(NULL, pszDir, nFolder, FALSE)) 35 | { 36 | strcat(pszDir, "\\Macromed\\Flash"); 37 | p = pszDir + strlen(pszDir); 38 | nFiles += ScanFolder(pszDir); 39 | strcpy(p, "\\flash.ocx"); 40 | if (GetFileAttributes(pszDir) != INVALID_FILE_ATTRIBUTES) 41 | { 42 | printf ("Registering %s...", pszDir); 43 | WinExec(szDir, SW_HIDE); 44 | printf ("OK\n"); 45 | } 46 | } 47 | return nFiles; 48 | } 49 | 50 | static int LocateExes(void) 51 | { 52 | char szDir[MAX_PATH], *p; 53 | int nFiles = 0; 54 | 55 | printf ("Scanning...\n"); 56 | nFiles += ScanFlashFolder(CSIDL_SYSTEM); 57 | #ifdef _WIN64 58 | nFiles += ScanFlashFolder(CSIDL_SYSTEMX86); 59 | #endif 60 | if (SHGetSpecialFolderPath(NULL, szDir, CSIDL_LOCAL_APPDATA, FALSE)) 61 | { 62 | p = szDir + strlen(szDir); 63 | strcpy(p, "\\Google\\Chrome\\User Data\\PepperFlash"); 64 | nFiles += ScanFolder(szDir); 65 | strcpy(p, "\\Microsoft\\Edge\\User Data\\PepperFlash"); 66 | nFiles += ScanFolder(szDir); 67 | } 68 | return nFiles; 69 | } 70 | 71 | static int ScanFolder(char *pszPath) 72 | { 73 | WIN32_FIND_DATA fd; 74 | HANDLE hSearch; 75 | size_t cbFileName; 76 | int nFiles = 0; 77 | char *p = pszPath + strlen(pszPath); 78 | 79 | *p = '\\'; p++; 80 | strcpy(p, "*.*"); 81 | 82 | if ((hSearch = FindFirstFile(pszPath, &fd)) != INVALID_HANDLE_VALUE) 83 | { 84 | do 85 | { 86 | if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 87 | { 88 | if (_stricmp(fd.cFileName, ".") == 0 || 89 | _stricmp(fd.cFileName, "..") == 0) 90 | continue; 91 | strcpy(p, fd.cFileName); 92 | nFiles += ScanFolder(pszPath); 93 | } 94 | else 95 | { 96 | cbFileName = strlen(fd.cFileName); 97 | if (cbFileName > 4 && ( 98 | _stricmp(&fd.cFileName[cbFileName-4], ".ocx") == 0 || 99 | _stricmp(&fd.cFileName[cbFileName-4], ".dll") == 0 || 100 | _stricmp(&fd.cFileName[cbFileName-4], ".exe") == 0)) 101 | { 102 | strcpy(p, fd.cFileName); 103 | if (PatchFile(pszPath)) nFiles++; 104 | } 105 | } 106 | } 107 | while(FindNextFile(hSearch, &fd)); 108 | FindClose(hSearch); 109 | } 110 | return nFiles; 111 | } 112 | 113 | static BYTE *Match (BYTE *lpMem, DWORD dwSize, const BYTE *lpSig, DWORD cbSig, DWORD step) 114 | { 115 | BYTE *lpOffset, *lpEnd; 116 | DWORD i; 117 | 118 | for (lpOffset=lpMem, lpEnd=lpMem+dwSize-cbSig; lpOffsetnul 6 | if errorlevel 0 echo [*] Evil update KB4577586 installed. 7 | if not exist %systemroot%\System32\Macromed\Flash\Flash.ocx goto noflash 8 | if exist %systemroot%\SysWOW64 ( 9 | if not exist %systemroot%\SysWOW64\Macromed\Flash\Flash.ocx goto noflash 10 | ) 11 | if "%1"=="/FORCE" goto noflash 12 | echo Flash is still present, are you sure that you want me to run? 13 | echo If so, start me with /FORCE parameter 14 | goto fini 15 | 16 | :noflash 17 | rem Ensure that we are run from 64bit prompt 18 | if "%ProgramFiles(x86)%" == "" goto StartExec 19 | if not exist %SystemRoot%\Sysnative\cmd.exe goto StartExec 20 | %SystemRoot%\Sysnative\cmd.exe /C "%~f0" %* 21 | exit /b 22 | :StartExec 23 | >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" 24 | if '%errorlevel%' NEQ '0' ( 25 | echo Requesting administrative privileges... 26 | goto UACPrompt 27 | ) else ( goto gotAdmin ) 28 | :UACPrompt 29 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" 30 | echo UAC.ShellExecute "%~s0", "%1", "%1", "runas", 1 >> "%temp%\getadmin.vbs" 31 | "%temp%\getadmin.vbs" 32 | exit /B 33 | :gotAdmin 34 | if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) 35 | pushd "%CD%" 36 | CD /D "%~dp0" 37 | 38 | setlocal 39 | set ARCH=amd64 40 | reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | Find /i "x86" >nul 41 | if not errorlevel 1 set ARCH=wow64 42 | 43 | if not exist KB4580325.msu ( 44 | echo [*] Downloading update... 45 | bitsadmin /transfer KB4580325.msu /download /priority normal http://download.windowsupdate.com/d/msdownload/update/software/secu/2020/10/windows10.0-kb4580325-x64_b6e8f5b34fd68a4e3c29a540000327f6d0675a7f.msu %CD%\KB4580325.msu 46 | if not exist KB4580325.msu ( 47 | echo [-] Download failed 48 | goto fini 49 | ) 50 | ) 51 | 52 | echo [*] Extracting contents... 53 | md ContentMSU 54 | expand KB4580325.msu /F:* .\ContentMSU >nul 55 | cd ContentMSU 56 | md ContentCAB 57 | expand Windows*.cab /F:* .\ContentCAB >nul 58 | cd ContentCAB 59 | 60 | echo [*] Copying Flash.. 61 | cd %ARCH%_adobe* 62 | call :copyflash System32 63 | if "%ARCH%"=="amd64" ( 64 | cd ..\wow64_adobe* 65 | call :copyflash SysWOW64 66 | copy /y flashplayercplapp.cpl %systemroot%\SysWOW64\ 67 | copy /y flashplayerapp.exe %systemroot%\SysWOW64\ 68 | set ARCH=x64 69 | ) else ( 70 | copy /y flashplayercplapp.cpl %systemroot%\System32\ 71 | copy /y flashplayerapp.exe %systemroot%\System32\ 72 | set ARCH=x86 73 | ) 74 | cd ..\..\.. 75 | rmdir /s /q ContentMSU 76 | if not exist flashpatch_%ARCH%.exe ( 77 | echo [-] flashpatch_%ARCH%.exe not found! 78 | goto fini 79 | ) 80 | flashpatch_%ARCH%.exe 81 | exit /B 82 | 83 | :copyflash 84 | md %systemroot%\%1\Macromed\Flash 85 | md %systemroot%\%1\Macromed\Temp 86 | copy /y flash.ocx %systemroot%\%1\Macromed\Flash\ 87 | copy /y flashutil_activex.dll %systemroot%\%1\Macromed\Flash\ 88 | copy /y flashutil_activex.exe %systemroot%\%1\Macromed\Flash\ 89 | copy /y activex.vch %systemroot%\%1\Macromed\Flash\ 90 | regsvr32 /s %systemroot%\%1\Macromed\Flash\flash.ocx 91 | exit /B 92 | 93 | :fini 94 | pause 95 | -------------------------------------------------------------------------------- /res.rc: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // 24 4 | // 5 | 6 | 1 24 DISCARDABLE "res\\manifest.xml" 7 | -------------------------------------------------------------------------------- /res/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | elevate execution level 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /takeown.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include "addacl.h" 5 | 6 | BOOL ShowModuleError(LPSTR pszModError, LPSTR pszError); 7 | 8 | static BOOL 9 | AssertTakeOwnership( 10 | HANDLE TokenHandle 11 | ); 12 | static BOOL 13 | GetTokenHandle( 14 | PHANDLE TokenHandle 15 | ); 16 | static BOOL 17 | VariableInitialization(); 18 | static BOOL ShowError(LPSTR pszError); 19 | 20 | PSID AliasAdminsSid = NULL; 21 | PSID SeWorldSid; 22 | static SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY; 23 | static SID_IDENTIFIER_AUTHORITY SepWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; 24 | 25 | BOOL TakeOwnership(LPSTR lpFileName) 26 | { 27 | BOOL Result; 28 | SECURITY_DESCRIPTOR SecurityDescriptor; 29 | HANDLE TokenHandle; 30 | 31 | Result = VariableInitialization(); 32 | if ( !Result ) return ShowError ("SID Initialization failed"); 33 | 34 | Result = GetTokenHandle( &TokenHandle ); 35 | if ( !Result ) return ShowError ("Unable to obtain the handle to our token, exiting\n"); 36 | 37 | // 38 | // Attempt to put a NULL Dacl on the object 39 | // 40 | InitializeSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); 41 | 42 | Result = SetSecurityDescriptorDacl ( 43 | &SecurityDescriptor, 44 | TRUE, 45 | NULL, 46 | FALSE 47 | ); 48 | 49 | if ( !Result ) return ShowError ("SetSecurityDescriptorDacl failed"); 50 | 51 | Result = SetFileSecurity( 52 | lpFileName, 53 | DACL_SECURITY_INFORMATION, 54 | &SecurityDescriptor 55 | ); 56 | if ( Result ) return TRUE; 57 | 58 | // 59 | // That didn't work. 60 | // 61 | 62 | // 63 | // Attempt to make Administrator the owner of the file. 64 | // 65 | 66 | Result = SetSecurityDescriptorOwner ( 67 | &SecurityDescriptor, 68 | AliasAdminsSid, 69 | FALSE 70 | ); 71 | if ( !Result ) return ShowError ("SetSecurityDescriptorOwner failed"); 72 | 73 | Result = SetFileSecurity( 74 | lpFileName, 75 | OWNER_SECURITY_INFORMATION, 76 | &SecurityDescriptor 77 | ); 78 | if ( !Result ) { 79 | 80 | // 81 | // That didn't work either. 82 | // 83 | 84 | // 85 | // Assert TakeOwnership privilege, then try again. Note that 86 | // since the privilege is only enabled for the duration of 87 | // this process, we don't have to worry about turning it off 88 | // again. 89 | // 90 | Result = AssertTakeOwnership( TokenHandle ); 91 | if ( !Result ) return ShowError("Could not enable SeTakeOwnership privilege"); 92 | 93 | Result = SetFileSecurity( 94 | lpFileName, 95 | OWNER_SECURITY_INFORMATION, 96 | &SecurityDescriptor 97 | ); 98 | if ( !Result ) return ShowError ("Unable to assign Administrator as owner"); 99 | } 100 | // 101 | // Try to put a benign DACL onto the file again 102 | // 103 | Result = SetFileSecurity( 104 | lpFileName, 105 | DACL_SECURITY_INFORMATION, 106 | &SecurityDescriptor 107 | ); 108 | if ( !Result ) return ShowError ("SetFileSecurity unexpectedly failed"); 109 | 110 | return TRUE; 111 | } 112 | 113 | // -------------------------------------------------------------- 114 | 115 | BOOL GrantAllPrivileges (LPSTR lpszFileName) 116 | { 117 | VariableInitialization(); 118 | return AddAccessRights (lpszFileName, SeWorldSid, GENERIC_ALL); 119 | } 120 | 121 | // ============================================================= 122 | // Private 123 | // ============================================================= 124 | static BOOL 125 | GetTokenHandle( 126 | PHANDLE TokenHandle 127 | ) 128 | // 129 | // This routine will open the current process and return 130 | // a handle to its token. 131 | // 132 | // These handles will be closed for us when the process 133 | // exits. 134 | // 135 | { 136 | HANDLE ProcessHandle; 137 | BOOL Result; 138 | ProcessHandle = OpenProcess( 139 | PROCESS_QUERY_INFORMATION, 140 | FALSE, 141 | GetCurrentProcessId() 142 | ); 143 | if ( ProcessHandle == NULL ) { 144 | // 145 | // This should not happen 146 | // 147 | return( FALSE ); 148 | } 149 | 150 | Result = OpenProcessToken ( 151 | ProcessHandle, 152 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 153 | TokenHandle 154 | ); 155 | if ( !Result ) { 156 | // 157 | // This should not happen 158 | // 159 | return( FALSE ); 160 | } 161 | return( TRUE ); 162 | } 163 | 164 | // -------------------------------------------------------------- 165 | 166 | static BOOL 167 | AssertTakeOwnership( 168 | HANDLE TokenHandle 169 | ) 170 | // 171 | // This routine turns on SeTakeOwnershipPrivilege in the current 172 | // token. Once that has been accomplished, we can open the file 173 | // for WRITE_OWNER even if we are denied that access by the ACL 174 | // on the file. 175 | { 176 | LUID TakeOwnershipValue; 177 | BOOL Result; 178 | TOKEN_PRIVILEGES TokenPrivileges; 179 | 180 | // 181 | // First, find out the value of TakeOwnershipPrivilege 182 | // 183 | 184 | Result = LookupPrivilegeValue( 185 | NULL, 186 | "SeTakeOwnershipPrivilege", 187 | &TakeOwnershipValue 188 | ); 189 | if ( !Result ) return ShowError ("Unable to obtain value of TakeOwnership privilege"); 190 | 191 | // 192 | // Set up the privilege set we will need 193 | // 194 | TokenPrivileges.PrivilegeCount = 1; 195 | TokenPrivileges.Privileges[0].Luid = TakeOwnershipValue; 196 | TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 197 | 198 | 199 | (VOID) AdjustTokenPrivileges ( 200 | TokenHandle, 201 | FALSE, 202 | &TokenPrivileges, 203 | sizeof( TOKEN_PRIVILEGES ), 204 | NULL, 205 | NULL 206 | ); 207 | if ( GetLastError() != NO_ERROR ) { 208 | return( FALSE ); 209 | } else { 210 | return( TRUE ); 211 | } 212 | } 213 | 214 | // -------------------------------------------------------------- 215 | 216 | static BOOL 217 | VariableInitialization() 218 | // 219 | // Create some useful SIDs. 220 | // 221 | { 222 | static BOOL Result = FALSE; 223 | 224 | if (Result) return TRUE; 225 | Result = AllocateAndInitializeSid( 226 | &SepNtAuthority, 227 | 2, 228 | SECURITY_BUILTIN_DOMAIN_RID, 229 | DOMAIN_ALIAS_RID_ADMINS, 230 | 0, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | &AliasAdminsSid 237 | ); 238 | if ( !Result ) { 239 | return( FALSE ); 240 | } 241 | 242 | Result = AllocateAndInitializeSid( 243 | &SepWorldSidAuthority, 244 | 1, 245 | SECURITY_WORLD_RID, 246 | 0, 247 | 0, 248 | 0, 249 | 0, 250 | 0, 251 | 0, 252 | 0, 253 | &SeWorldSid 254 | ); 255 | if ( !Result ) { 256 | return( FALSE ); 257 | } 258 | return( TRUE ); 259 | } 260 | 261 | // -------------------------------------------------------------- 262 | 263 | static BOOL ShowError(LPSTR pszError) 264 | { 265 | return ShowModuleError("Failed taking ownership", pszError); 266 | } 267 | -------------------------------------------------------------------------------- /takeown.h: -------------------------------------------------------------------------------- 1 | BOOL TakeOwnership(LPSTR lpFileName); 2 | BOOL GrantAllPrivileges (LPSTR lpszFileName); 3 | --------------------------------------------------------------------------------