This commit is contained in:
zeffy
2018-05-17 08:52:53 -07:00
parent 35760a2546
commit e6da8ec18b
71 changed files with 902 additions and 2536 deletions

View File

@@ -46,6 +46,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<OutDir>$(ProjectDir)bin\$(Configuration)\$(PlatformShortName)\</OutDir>
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -93,7 +95,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"</Command>
<Message>Copy release binaries to the setup staging directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>

View File

@@ -5,10 +5,7 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
<ROW Property="AI_CLEAN_RESOURCES_DISABLE_UPGRADE" Value="1"/>
<ROW Property="AI_CLEAN_RESOURCES_UNINSTALL" Value="1"/>
<ROW Property="AI_CLEAN_RESOURCES_USER_PROMPT_BASIC_UI" Value="1"/>
<ROW Property="AI_CLEAN_RESOURCES_USER_PROMPT_FULL_UI" Value="1"/>
<ROW Property="AI_ThemeStyle" Value="aero" MsiKey="AI_ThemeStyle"/>
<ROW Property="ALLUSERS" Value="1"/>
<ROW Property="ARPCOMMENTS" Value="Enables Windows Update on PCs with unsupported processors." ValueLocId="*"/>
@@ -21,10 +18,10 @@
<ROW Property="AiPreventAutoPin" Value="System.AppUserModel.ExcludeFromShowInNewInstall"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="x64Build:6#x86Build:6"/>
<ROW Property="Manufacturer" Value="zeffy"/>
<ROW Property="ProductCode" Value="1027:{84169AC2-619B-4E39-ABAC-D97D0CCE52AA} 1028:{3242799A-EABC-4846-9FB2-9157464AC6B2} 1031:{15845A1D-9531-4B6B-B56E-93E56652876D} 1033:{02D77154-1789-4037-8157-4F9B400D184E} 1035:{2AB75127-0A1D-46C3-9939-7E1BEF4101F8} 1036:{E0275036-3F2B-44F3-BCDB-78C55071F41B} 1038:{66A9F4FC-8DB1-45AE-98A5-469F14DC2867} 1040:{A037A274-187E-4231-9857-17075F270D01} 1041:{8E027F22-470D-4800-B135-3661E11F1B2D} 1042:{0C7CB276-E4EB-4D99-BC4D-E362BD4AEA46} 1043:{DDD233EB-262F-42B5-BB37-61366CCB3AB7} 1045:{1008FE13-9C80-4061-BAF1-AFEFA3C322BE} 1046:{2C6C0A74-CDEE-4495-858D-EE570F1B14F0} 1049:{D86825C0-4294-441C-B200-3C7B1314FF10} 1060:{D475BE6D-DB4D-4783-8396-F96186694C6E} 2052:{BA2561A6-D217-400D-A2B0-A0AA07222A94} 2070:{3C2F9949-F866-45C9-BE0E-0D046934E2CF} 3082:{AB82F7D2-24EF-47C9-9978-A69CE1BE56B0} " Type="16"/>
<ROW Property="ProductCode" Value="1027:{8788C792-140E-41E9-B875-685F557ACEE6} 1028:{C3A9DFE3-DBAB-47BA-ABAD-804D54F0FBF4} 1031:{85F838D1-6E19-4D99-BEE8-3A46A6D52813} 1033:{F011FFEE-01E3-495E-80CA-10A640C55031} 1035:{03787122-8FC5-4BF2-B447-372148E7E0CD} 1036:{C83296AB-0CC4-4954-A218-3F76BE31C530} 1038:{8D87BFD2-FE05-4506-A1D8-62EE821DB623} 1040:{C48A5EF8-8DB1-4D08-B468-683879C807E3} 1041:{5CCB0BE8-E87D-4D8C-BD5F-B5A6E1CDDB4A} 1042:{2AE0CA07-01C9-4B29-A880-E52CE19EB157} 1043:{28C34648-07BD-463C-A61E-AE47525AF2D2} 1045:{F7E7320E-9EBF-44C5-97E7-E8FEB7A47613} 1046:{393B1C36-514F-4722-A577-408055568261} 1049:{13DAE24C-D5C2-443E-8105-8B3FE24C9370} 1060:{836B7413-1503-4164-9D21-87C28468AD61} 2052:{880E51E8-4243-42F4-BAA3-B32785746291} 2070:{E76212D9-7C99-4C47-9004-3F32D658D6A6} 3082:{CFE6B8E7-9D52-488C-BEA6-A7EE3306B20C} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="wufuc"/>
<ROW Property="ProductVersion" Value="1.0.0.191" Type="32" TargetFile="wufuc64.dll"/>
<ROW Property="ProductVersion" Value="1.0.1.0" Type="32" TargetFile="wufuc64.dll"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{4C52972C-251E-4D1B-AD09-EAA765719DCC}"/>
<ROW Property="WindowsType9X" MultiBuildValue="x64Build:Windows 9x/ME#x86Build:Windows 9x/ME" ValueLocId="-"/>
@@ -43,36 +40,30 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
<ROW Directory="CommonAppDataFolder" Directory_Parent="TARGETDIR" DefaultDir="COMMON~1|CommonAppDataFolder" IsPseudoRoot="1"/>
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="Troubleshooting_1_Dir" Directory_Parent="APPDIR" DefaultDir="TROUBL~1|Troubleshooting"/>
<ROW Directory="Troubleshooting_Dir" Directory_Parent="SHORTCUTDIR" DefaultDir="TROUBL~1|Troubleshooting"/>
<ROW Directory="Troubleshooting_Dir" Directory_Parent="SHORTCUTDIR" DefaultDir="HELPAN~1|Help and Support"/>
<ROW Directory="X64FeatureItems_Dir" Directory_Parent="APPDIR" DefaultDir=".:X64FEA~1|X64FeatureItems"/>
<ROW Directory="X86FeatureItems_Dir" Directory_Parent="APPDIR" DefaultDir=".:X86FEA~1|X86FeatureItems"/>
<ROW Directory="wufuc_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="wufuc"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="COPYING" ComponentId="{6CA1ECA7-4C30-4BD0-A5E8-6B3E5BCBE31D}" Directory_="APPDIR" Attributes="0" KeyPath="COPYING" Type="0"/>
<ROW Component="ProductInformation" ComponentId="{75030EAB-5C17-4F84-B529-28003271CA3F}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
<ROW Component="Restore_wuauserv.reg" ComponentId="{ED9F90C5-1984-48DE-B109-4AF6F12A2E8F}" Directory_="Troubleshooting_1_Dir" Attributes="0" KeyPath="Restore_wuauserv.reg" Type="0"/>
<ROW Component="SHORTCUTDIR" ComponentId="{910396A4-AFDD-4E57-BF00-2FDD4108AC61}" Directory_="SHORTCUTDIR" Attributes="0"/>
<ROW Component="Troubleshooting" ComponentId="{D4F7163C-0FD7-4862-BF97-F1693236500C}" Directory_="Troubleshooting_Dir" Attributes="0"/>
<ROW Component="X64FeatureItems" ComponentId="{0E189A37-1F40-4756-ACB9-6511067D5B47}" Directory_="X64FeatureItems_Dir" Attributes="0"/>
<ROW Component="X86FeatureItems" ComponentId="{CBB84726-9EC3-4570-9012-37BA98719022}" Directory_="X86FeatureItems_Dir" Attributes="0"/>
<ROW Component="wufuc" ComponentId="{331CB0F5-F6E7-4712-9F97-3609A0D5AFE6}" Directory_="wufuc_Dir" Attributes="0"/>
<ROW Component="wufuc32.dll" ComponentId="{7FBEF396-DCBC-4838-A4EB-336F74A836C7}" Directory_="APPDIR" Attributes="0" KeyPath="wufuc32.dll"/>
<ROW Component="wufuc64.dll" ComponentId="{0407D471-998A-4FD3-BC2D-72EE56FBEEF4}" Directory_="APPDIR" Attributes="256" KeyPath="wufuc64.dll"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="COPYING ProductInformation Restore_wuauserv.reg SHORTCUTDIR Troubleshooting wufuc"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="COPYING ProductInformation SHORTCUTDIR Troubleshooting"/>
<ROW Feature="X64Feature" Feature_Parent="MainFeature" Title="X64Feature" Display="0" Level="1" Directory_="APPDIR" Attributes="0" Components="X64FeatureItems wufuc64.dll" Builds="x64Build"/>
<ROW Feature="X86Feature" Feature_Parent="MainFeature" Title="X86Feature" Display="0" Level="1" Directory_="APPDIR" Attributes="0" Components="X86FeatureItems wufuc32.dll" Builds="x86Build"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="COPYING" Component_="COPYING" FileName="COPYING.txt" Attributes="0" SourcePath="..\..\COPYING" SelfReg="false" NextFile="Restore_wuauserv.reg"/>
<ROW File="Restore_wuauserv.reg" Component_="Restore_wuauserv.reg" FileName="RESTOR~1.REG|Restore_wuauserv.reg" Attributes="0" SourcePath="..\wufuc_setup_bat\Troubleshooting\Restore_wuauserv.reg" SelfReg="false"/>
<ROW File="COPYING" Component_="COPYING" FileName="COPYING.txt" Attributes="0" SourcePath="..\..\COPYING" SelfReg="false"/>
<ROW File="wufuc32.dll" Component_="wufuc32.dll" FileName="wufuc32.dll" Attributes="0" SourcePath="wufuc32.dll" SelfReg="false" NextFile="wufuc64.dll"/>
<ROW File="wufuc64.dll" Component_="wufuc64.dll" FileName="wufuc64.dll" Attributes="0" SourcePath="wufuc64.dll" SelfReg="false" NextFile="COPYING"/>
</COMPONENT>
@@ -80,10 +71,6 @@
<ROW MsiShortcutProperty="Uninstallwufuc1" Shortcut_="Uninstallwufuc" PropertyKey="[AiPreventAutoPin]" PropVariantValue="1"/>
<ROW MsiShortcutProperty="License1" Shortcut_="License" PropertyKey="[AiPreventAutoPin]" PropVariantValue="1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.AiRemoveFileComponent">
<ROW RemoveFile="log" Condition="(AI_CLEAN_RESOURCES_UNINSTALL = &quot;1&quot;) AND (NOT UPGRADINGPRODUCTCODE)" Options="1"/>
<ROW RemoveFile="_" Condition="(AI_CLEAN_RESOURCES_UNINSTALL = &quot;1&quot;) AND (NOT UPGRADINGPRODUCTCODE)" Options="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent">
<ROW BootstrOptKey="GlobalOptions" DownloadFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\prerequisites" Options="2"/>
</COMPONENT>
@@ -128,11 +115,6 @@
<ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiActionTextComponent">
<ROW Action="AI_AiRemoveFilesCommit" Description="Executing file removal operations" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesCommit" Template="Executing file removal: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesCommit"/>
<ROW Action="AI_AiRemoveFilesDeferred_Permanent" Description="Preparing files for removal" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesDeferred_Permanent" Template="Preparing file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesDeferred_Permanent"/>
<ROW Action="AI_AiRemoveFilesDeferred_Undoable" Description="Preparing files for removal" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesDeferred_Undoable" Template="Preparing file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesDeferred_Undoable"/>
<ROW Action="AI_AiRemoveFilesImmediate" Description="Preparing files for removal" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesImmediate" Template="Preparing file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesImmediate"/>
<ROW Action="AI_AiRemoveFilesRollback" Description="Restoring removed files" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesRollback" Template="Restoring file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesRollback"/>
<ROW Action="AI_XmlCommit" Description="Committing XML file configurations." DescriptionLocId="ActionText.Description.AI_XmlCommit" Template="Committing XML file configurations." TemplateLocId="ActionText.Template.AI_XmlCommit"/>
<ROW Action="AI_XmlConfig" Description="Executing XML file configurations" DescriptionLocId="ActionText.Description.AI_XmlConfig" Template="Configuring XML file: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_XmlConfig"/>
<ROW Action="AI_XmlInstall" Description="Generating actions to configure XML files" DescriptionLocId="ActionText.Description.AI_XmlInstall"/>
@@ -143,7 +125,6 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
<ROW Name="AdvancedInstallerHelper.dll" SourcePath="AdvancedInstallerHelper.dll"/>
<ROW Name="Prereq.dll" SourcePath="&lt;AI_CUSTACTS&gt;Prereq.dll"/>
<ROW Name="ResourceCleaner.dll" SourcePath="&lt;AI_CUSTACTS&gt;ResourceCleaner.dll"/>
<ROW Name="ShortcutFlags.dll" SourcePath="&lt;AI_CUSTACTS&gt;ShortcutFlags.dll"/>
<ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
<ROW Name="viewer.exe" SourcePath="&lt;AI_CUSTACTS&gt;viewer.exe"/>
@@ -187,14 +168,8 @@
<ROW Directory_="X86FeatureItems_Dir" Component_="X86FeatureItems" ManualDelete="false"/>
<ROW Directory_="X64FeatureItems_Dir" Component_="X64FeatureItems" ManualDelete="false"/>
<ROW Directory_="Troubleshooting_Dir" Component_="Troubleshooting" ManualDelete="false"/>
<ROW Directory_="wufuc_Dir" Component_="wufuc" ManualDelete="true"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_AiRemoveFilesCommit" Type="11777" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesCommit" WithoutSeq="true"/>
<ROW Action="AI_AiRemoveFilesDeferred_Permanent" Type="11265" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesPermanent" WithoutSeq="true"/>
<ROW Action="AI_AiRemoveFilesDeferred_Undoable" Type="11265" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesUndoable" WithoutSeq="true"/>
<ROW Action="AI_AiRemoveFilesImmediate" Type="1" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesImmediate"/>
<ROW Action="AI_AiRemoveFilesRollback" Type="11521" Source="ResourceCleaner.dll" Target="OnAiUndoRemoveFiles"/>
<ROW Action="AI_AppSearchEx" Type="1" Source="Prereq.dll" Target="DoAppSearchEx"/>
<ROW Action="AI_ApplyShortcutFlags" Type="3073" Source="ShortcutFlags.dll" Target="UpdateShortcutFlags" WithoutSeq="true"/>
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
@@ -211,7 +186,6 @@
<ROW Action="AI_PinToStartScreen" Type="1025" Source="ShortcutFlags.dll" Target="PinToStartScreen" WithoutSeq="true"/>
<ROW Action="AI_PinToTaskbar" Type="1025" Source="ShortcutFlags.dll" Target="PinToTaskbar" WithoutSeq="true"/>
<ROW Action="AI_PrepareShortcutFlags" Type="1" Source="ShortcutFlags.dll" Target="PrepareActionData"/>
<ROW Action="AI_PromptUserBasicUI" Type="1" Source="ResourceCleaner.dll" Target="OnPromptUserBasicUI"/>
<ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
@@ -235,24 +209,26 @@
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="x64Build:[ProgramFiles64Folder]\[ProductName]#x86Build:[ProgramFilesFolder]\[ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
<ROW Action="SetRebootProperty" Type="51" Source="REBOOT" Target="Force"/>
<ROW Action="StartWindowsUpdateService" Type="3073" Source="aicustact.dll" Target="StartWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_3"/>
<ROW Action="StopWindowsUpdateService" Type="3073" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_2"/>
<ROW Action="StopWindowsUpdateService" Type="3137" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="msiexec.exe" SourcePath="..\..\..\..\..\..\..\Windows\System32\msiexec.exe" Index="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIniFileComponent">
<ROW IniFile="ServiceDll" FileName="RESTOR~1.REG|Restore_wuauserv.reg" DirProperty="APPDIR" Section="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv\Parameters" Key="&quot;ServiceDll&quot;" Value="hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,00,6f,\" Action="0" Component_="ProductInformation"/>
<ROW IniFile="URL" FileName="Donate.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/blob/master/DONATE.md" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_2" FileName="Readme.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/blob/master/README.md" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_6" FileName="LATEST~1.URL|Latest Release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/releases/latest" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_7" FileName="REPORT~1.URL|Report an Issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/issues" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_2" FileName="Readme.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_6" FileName="LATEST~1.URL|Latest release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/releases/latest" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_7" FileName="REPORT~1.URL|Report an issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/issues" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_8" FileName="FAQ.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/blob/master/FAQ.md" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory" FileName="Donate.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_2" FileName="Readme.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_6" FileName="LATEST~1.URL|Latest Release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_7" FileName="REPORT~1.URL|Report an Issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="WorkingDirectory" Value="[Troubleshooting_Dir]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_6" FileName="LATEST~1.URL|Latest release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_7" FileName="REPORT~1.URL|Report an issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="WorkingDirectory" Value="[Troubleshooting_Dir]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_8" FileName="FAQ.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="WorkingDirectory" Value="[Troubleshooting_Dir]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="c00730079007300740065006d0033003200" FileName="RESTOR~1.REG|Restore_wuauserv.reg" DirProperty="APPDIR" Section="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv\Parameters" Key="00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\" Value="00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\" Action="0" Component_="ProductInformation"/>
<ROW IniFile="e0067002e0064006c006c000000" FileName="RESTOR~1.REG|Restore_wuauserv.reg" DirProperty="APPDIR" Section="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv\Parameters" Key="77,00,75,00,61,00,75,00,65,00,6e,00,67,00,2e,00,64,00,6c,00,6c,00,00,00" Value="77,00,75,00,61,00,75,00,65,00,6e,00,67,00,2e,00,64,00,6c,00,6c,00,00,00" Action="0" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
<ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
@@ -277,12 +253,8 @@
<ROW Action="RunScheduledTask" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) )" Sequence="5827"/>
<ROW Action="RunSFCScan" Sequence="3603"/>
<ROW Action="AI_AppSearchEx" Sequence="101"/>
<ROW Action="SetRebootProperty" Condition="NONDEFAULT_SERVICEDLL" Sequence="201"/>
<ROW Action="StartWindowsUpdateService" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) )" Sequence="6402"/>
<ROW Action="AI_DATA_SETTER_3" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) )" Sequence="6401"/>
<ROW Action="AI_AiRemoveFilesImmediate" Sequence="3499"/>
<ROW Action="AI_AiRemoveFilesRollback" Sequence="3099"/>
<ROW Action="AI_PromptUserBasicUI" Condition="((REMOVE = &quot;ALL&quot;) AND (NOT UPGRADINGPRODUCTCODE))" Sequence="2501"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
@@ -307,13 +279,9 @@
<ROW Registry="Path" Root="-1" Key="Software\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
<ROW Registry="Version" Root="-1" Key="Software\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRemoveFileComponent">
<ROW FileKey="_" Component_="ProductInformation" DirProperty="wufuc_Dir" InstallMode="2"/>
<ROW FileKey="log" Component_="ProductInformation" FileName="*.log" DirProperty="wufuc_Dir" InstallMode="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="License" Directory_="SHORTCUTDIR" Name="License" Component_="COPYING" Target="[#COPYING]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="Openwufuclogfile" Directory_="Troubleshooting_Dir" Name="OPENWU~1|Open wufuc log file" Component_="SHORTCUTDIR" Target="[CommonAppDataFolder]wufuc\wufuc.log" Hotkey="0" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Openwufuclogfile" Directory_="Troubleshooting_Dir" Name="OPENWU~1|Open wufuc log file" Component_="SHORTCUTDIR" Target="[CommonAppDataFolder]wufuc\wufuc.1.log" Hotkey="0" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Uninstallwufuc" Directory_="SHORTCUTDIR" Name="UNINST~2|Uninstall [|ProductName]" Component_="ProductInformation" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="msiexec.exe" IconIndex="0" ShowCmd="1" CustomFlags="1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">

View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc/blob/master/DONATE.md
IDList=

View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc/releases/latest
IDList=

View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc
IDList=

View File

@@ -5,12 +5,6 @@ VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wufuc", "wufuc\wufuc.vcxproj", "{00F96695-CE41-4C2F-A344-6219DFB4F887}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wufuc_setup_bat", "wufuc_setup_bat", "{97E33D3C-9AA1-4B84-803A-1A6AE2C6F361}"
ProjectSection(SolutionItems) = preProject
wufuc_setup_bat\install_wufuc.bat = wufuc_setup_bat\install_wufuc.bat
wufuc_setup_bat\uninstall_wufuc.bat = wufuc_setup_bat\uninstall_wufuc.bat
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvancedInstallerHelper", "AdvancedInstallerHelper\AdvancedInstallerHelper.vcxproj", "{12498D61-02AF-4C13-925D-E130EEDE2543}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repository Items", "Repository Items", "{E7EDB493-4D31-4646-8537-C515613689A6}"

121
src/wufuc/asprintf.c Normal file
View File

@@ -0,0 +1,121 @@
#include "stdafx.h"
#include "asprintf.h"
#include <locale.h>
int asprintf(char **strp, char const *const fmt, ...)
{
va_list ap;
int result;
va_start(ap, fmt);
result = vasprintf(strp, fmt, ap);
va_end(ap);
return result;
}
int vasprintf(char **strp, char const *const fmt, va_list ap)
{
return vasprintf_l(strp, fmt, _get_current_locale(), ap);
}
int asprintf_l(char **strp, char const *const fmt, _locale_t locale, ...)
{
va_list ap;
int result;
va_start(ap, locale);
result = vasprintf_l(strp, fmt, locale, ap);
va_end(ap);
return result;
}
int vasprintf_l(char **strp, char const *const fmt, _locale_t locale, va_list ap)
{
va_list copy;
int result;
char *str;
int ret;
va_copy(copy, ap);
result = _vscprintf(fmt, copy);
va_end(copy);
if ( result == -1 )
return result;
str = calloc(result + 1, sizeof *str);
if ( !str )
return -1;
va_copy(copy, ap);
ret = _vsprintf_s_l(str, result + 1, fmt, locale, copy);
va_end(copy);
if ( ret == -1 ) {
free(str);
return -1;
}
*strp = str;
return result;
}
int aswprintf(wchar_t **strp, wchar_t const *const fmt, ...)
{
va_list ap;
int result;
va_start(ap, fmt);
result = vaswprintf(strp, fmt, ap);
va_end(ap);
return result;
}
int vaswprintf(wchar_t **strp, wchar_t const *const fmt, va_list ap)
{
return vaswprintf_l(strp, fmt, _get_current_locale(), ap);
}
int aswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, ...)
{
va_list ap;
int result;
va_start(ap, locale);
result = vaswprintf_l(strp, fmt, locale, ap);
va_end(ap);
return result;
}
int vaswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, va_list ap)
{
va_list copy;
int result;
wchar_t *str;
int ret;
va_copy(copy, ap);
result = _vscwprintf_l(fmt, locale, copy);
va_end(copy);
if ( result == -1 )
return result;
str = calloc(result + 1, sizeof *str);
if ( !str )
return -1;
va_copy(copy, ap);
ret = _vswprintf_s_l(str, result + 1, fmt, locale, copy);
va_end(copy);
if ( ret == -1 ) {
free(str);
return -1;
}
*strp = str;
return result;
}

17
src/wufuc/asprintf.h Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
int asprintf(char **strp, char const *const fmt, ...);
int vasprintf(char **strp, char const *const fmt, va_list ap);
int asprintf_l(char **strp, char const *const fmt, _locale_t locale, ...);
int vasprintf_l(char **strp, char const *const fmt, _locale_t locale, va_list ap);
int aswprintf(wchar_t **strp, wchar_t const *const fmt, ...);
int vaswprintf(wchar_t **strp, wchar_t const *const fmt, va_list ap);
int aswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, ...);
int vaswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, va_list ap);

View File

@@ -1,165 +0,0 @@
#include "stdafx.h"
#include "callbacks.h"
#include "hooks.h"
#include "log.h"
#include "modulehelper.h"
#include "registryhelper.h"
#include "servicehelper.h"
#include "versionhelper.h"
#include "ptrlist.h"
#include "wufuc.h"
#include <VersionHelpers.h>
#include <minhook.h>
VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer)
{
switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS:
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
wufuc_inject(
pNotifyBuffer->ServiceStatus.dwProcessId,
(LPTHREAD_START_ROUTINE)thread_start_callback,
(ptrlist_t *)pNotifyBuffer->pContext);
break;
case ERROR_SERVICE_MARKED_FOR_DELETE:
SetEvent(ptrlist_at((ptrlist_t *)pNotifyBuffer->pContext, 0, NULL));
break;
}
if ( pNotifyBuffer->pszServiceNames )
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
}
DWORD WINAPI thread_start_callback(HANDLE *pParam)
{
HANDLE handles[2];
HANDLE hCrashMutex;
HANDLE hProceedEvent;
SC_HANDLE hSCM;
SC_HANDLE hService;
DWORD dwProcessId;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
DWORD dwServiceType;
const wchar_t szKernel32Dll[] = L"kernel32.dll";
const wchar_t szKernelBaseDll[] = L"kernelbase.dll";
const wchar_t *pszModule;
MH_STATUS status;
int tmp;
LPVOID pv1 = NULL;
LPVOID pv2 = NULL;
wchar_t *str;
HMODULE hModule;
if ( !pParam ) {
log_error(L"Parameter argument is null!");
goto unload;
}
handles[0] = pParam[0]; // main mutex
handles[1] = pParam[1]; // unload event
hCrashMutex = pParam[2]; // crash mutex
hProceedEvent = pParam[3]; // proceed event
if ( !VirtualFree(pParam, 0, MEM_RELEASE) )
log_warning(L"VirtualFree failed! (lpAddress=%p, GLE=%lu)", pParam, GetLastError());
// acquire child mutex, this should be immediate.
if ( WaitForSingleObject(hCrashMutex, 5000) != WAIT_OBJECT_0 ) {
log_error(L"Failed to acquire crash mutex within five seconds. (%p)", hCrashMutex);
goto close_handles;
}
SetEvent(hProceedEvent);
CloseHandle(hProceedEvent);
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
if ( !hSCM ) {
log_error(L"Failed to open SCM. (GetLastError=%lu)", GetLastError());
goto release;
}
hService = OpenServiceW(hSCM, L"wuauserv", SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
dwProcessId = svc_heuristic_process_id(hSCM, hService);
pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL);
dwServiceType = pServiceConfig->dwServiceType;
tmp = _wcsicmp(pServiceConfig->lpBinaryPathName, GetCommandLineW());
free(pServiceConfig);
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
if ( tmp || dwProcessId != GetCurrentProcessId() ) {
log_error(L"Injected into wrong process!");
goto release;
}
if ( !ver_verify_version_info(6, 1, 0) && !ver_verify_version_info(6, 3, 0) ) {
log_error(L"Unsupported operating system!");
goto release;
}
if ( dwServiceType == SERVICE_WIN32_SHARE_PROCESS ) {
// assume wuaueng.dll hasn't been loaded yet, apply
// RegQueryValueExW hook to fix incompatibility with
// UpdatePack7R2 and other patches that modify the
// Windows Update ServiceDll path in the registry.
pszModule = IsWindows8OrGreater()
? szKernelBaseDll
: szKernel32Dll;
status = MH_CreateHookApiEx(pszModule,
"RegQueryValueExW",
RegQueryValueExW_hook,
&(PVOID)g_pfnRegQueryValueExW,
&pv1);
if ( status == MH_OK ) {
status = MH_EnableHook(pv1);
if ( status == MH_OK )
log_info(L"Hooked RegQueryValueExW! (Module=%ls, Address=%p)", pszModule, pv1);
else log_error(L"Failed to enable RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status));
} else log_error(L"Failed to create RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status));
}
// query the ServiceDll path after applying our compat hook so that it
// is consistent
str = (wchar_t *)reg_query_value_alloc(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
L"ServiceDll", NULL, NULL);
if ( !str ) {
abort_hook:
if ( pv1 )
MH_RemoveHook(pv1);
goto release;
}
g_pszWUServiceDll = env_expand_strings_alloc(str, NULL);
free(str);
if ( !g_pszWUServiceDll ) goto abort_hook;
status = MH_CreateHookApiEx(szKernelBaseDll,
"LoadLibraryExW",
LoadLibraryExW_hook,
&(PVOID)g_pfnLoadLibraryExW,
&pv2);
if ( status == MH_OK ) {
status = MH_EnableHook(pv2);
if ( status == MH_OK )
log_info(L"Hooked LoadLibraryExW! (Module=%ls, Address=%p)", szKernelBaseDll, pv2);
else log_error(L"Failed to enable LoadLibraryExW hook! (Status=%hs)", MH_StatusToString(status));
} else log_error(L"Failed to create LoadLibraryExW hook! (Status=%hs)", MH_StatusToString(status));
if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule)
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
// hook IsDeviceServiceable if wuaueng.dll is already loaded
wufuc_patch(hModule);
FreeLibrary(hModule);
}
// wait for unload event or the main mutex to be released or abandoned,
// for example if the user killed rundll32.exe with task manager.
WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
log_info(L"Unload condition has been met.");
MH_DisableHook(MH_ALL_HOOKS);
free(g_pszWUServiceDll);
release:
ReleaseMutex(hCrashMutex);
close_handles:
CloseHandle(hCrashMutex);
CloseHandle(handles[0]);
CloseHandle(handles[1]);
unload:
log_info(L"Unloading wufuc and exiting thread.");
FreeLibraryAndExitThread(PIMAGEBASE, 0);
}

View File

@@ -1,4 +0,0 @@
#pragma once
VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer);
DWORD WINAPI thread_start_callback(HANDLE *pParam);

View File

@@ -1,7 +1,4 @@
#include "stdafx.h"
#include "log.h"
#include <minhook.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
@@ -9,14 +6,12 @@ BOOL APIENTRY DllMain(HMODULE hModule,
{
switch ( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
MH_Initialize();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
MH_Uninitialize();
log_close();
if ( !lpReserved )
log_close();
break;
}
return TRUE;

View File

@@ -1,23 +0,0 @@
#include "stdafx.h"
#include "eventhelper.h"
#include <sddl.h>
HANDLE event_create_with_string_security_descriptor(
bool ManualReset,
bool InitialState,
const wchar_t *Name,
const wchar_t *StringSecurityDescriptor)
{
SECURITY_ATTRIBUTES sa = { sizeof sa };
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
StringSecurityDescriptor,
SDDL_REVISION_1,
&sa.lpSecurityDescriptor,
NULL) ) {
return CreateEventW(&sa, ManualReset, InitialState, Name);
}
return NULL;
}

View File

@@ -1,7 +0,0 @@
#pragma once
HANDLE event_create_with_string_security_descriptor(
bool ManualReset,
bool InitialState,
const wchar_t *Name,
const wchar_t *StringSecurityDescriptor);

54
src/wufuc/helpers.c Normal file
View File

@@ -0,0 +1,54 @@
#include "stdafx.h"
#include "helpers.h"
#include <sddl.h>
HANDLE CreateEventWithStringSecurityDescriptor(
LPCWSTR lpStringSecurityDescriptor,
BOOL bManualReset,
BOOL bInitialState,
LPCWSTR lpName)
{
SECURITY_ATTRIBUTES sa = { sizeof sa };
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
lpStringSecurityDescriptor,
SDDL_REVISION_1,
&sa.lpSecurityDescriptor,
NULL) ) {
return CreateEventW(&sa, bManualReset, bInitialState, lpName);
}
return NULL;
}
HANDLE CreateNewMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName)
{
HANDLE result;
result = CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
if ( result ) {
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
CloseHandle(result);
return NULL;
}
return result;
}
return NULL;
}
BOOL VerifyVersionInfoHelper(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
DWORDLONG dwlConditionMask = 0;
OSVERSIONINFOEXW osvi = { sizeof osvi };
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(&osvi,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
dwlConditionMask);
}

11
src/wufuc/helpers.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
HANDLE CreateNewMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName);
HANDLE CreateEventWithStringSecurityDescriptor(
LPCWSTR lpStringSecurityDescriptor,
BOOL bManualReset,
BOOL bInitialState,
LPCWSTR lpName);
BOOL VerifyVersionInfoHelper(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);

View File

@@ -1,93 +0,0 @@
#include "stdafx.h"
#include "hooks.h"
#include "log.h"
#include "registryhelper.h"
#include "ptrlist.h"
#include "wufuc.h"
wchar_t *g_pszWUServiceDll;
LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
{
wchar_t *pBuffer;
DWORD MaximumLength = 0;
LSTATUS result;
ULONG ResultLength;
PKEY_NAME_INFORMATION pkni;
size_t NameCount;
unsigned int current;
int pos;
wchar_t *fname;
const wchar_t realpath[] = L"%systemroot%\\system32\\wuaueng.dll";
wchar_t *expandedpath;
DWORD cchLength;
// save original buffer size
if ( lpData && lpcbData )
MaximumLength = *lpcbData;
result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
if ( result != ERROR_SUCCESS
|| !MaximumLength
|| !lpValueName
|| (lpType && *lpType != REG_EXPAND_SZ)
|| _wcsicmp(lpValueName, L"ServiceDll") )
return result;
pBuffer = (wchar_t *)lpData;
// get name of registry key being queried
pkni = reg_query_key_alloc((HANDLE)hKey, KeyNameInformation, &ResultLength);
if ( !pkni )
return result;
NameCount = pkni->NameLength / sizeof *pkni->Name;
// change key name to lower-case because there is no case-insensitive version of _snwscanf_s
for ( size_t i = 0; i < NameCount; i++ )
pkni->Name[i] = towlower(pkni->Name[i]);
if ( _snwscanf_s(pkni->Name, NameCount, L"\\registry\\machine\\system\\controlset%03u\\services\\wuauserv\\parameters%n", &current, &pos) == 1
&& pos == NameCount ) {
fname = PathFindFileNameW(pBuffer);
if ( (!_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2
|| !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix
|| !_wcsicmp(fname, L"WuaCpuFix.dll")) ) {
expandedpath = env_expand_strings_alloc(realpath, &cchLength);
if ( expandedpath ) {
if ( PathFileExistsW(expandedpath)
&& SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) ) {
*lpcbData = cchLength * (sizeof *expandedpath);
log_info(L"Fixed path to Windows Update service library.");
}
free(expandedpath);
}
}
}
free(pkni);
return result;
}
HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE result;
result = g_pfnLoadLibraryExW(lpFileName, hFile, dwFlags);
if ( !result ) return result;
log_debug(L"Loaded library: %ls (%p)", lpFileName, result);
if ( dwFlags == LOAD_WITH_ALTERED_SEARCH_PATH
&& g_pszWUServiceDll
&& (!_wcsicmp(lpFileName, g_pszWUServiceDll)
|| !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) {
wufuc_patch(result);
}
return result;
}

View File

@@ -1,16 +0,0 @@
#pragma once
typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
extern wchar_t *g_pszWUServiceDll;
extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
extern PVOID g_ptRegQueryValueExW;
extern PVOID g_ptLoadLibraryExW;
LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags);

View File

@@ -1,162 +0,0 @@
#include "stdafx.h"
#include "log.h"
#include <ShlObj.h>
static HANDLE m_hFile = INVALID_HANDLE_VALUE;
static DWORD m_dwProcessId;
static wchar_t m_szExeFilePath[MAX_PATH];
static wchar_t *m_pszExeName;
BOOL CALLBACK init_once_callback(
PINIT_ONCE InitOnce,
PVOID *Parameter,
PVOID *lpContext)
{
BOOL result;
HRESULT hr;
wchar_t *pszPath;
wchar_t szFilePath[MAX_PATH];
int ret;
m_dwProcessId = GetCurrentProcessId();
if ( !GetModuleFileNameW(NULL, m_szExeFilePath, _countof(m_szExeFilePath)) ) {
log_debug(L"GetModuleFileNameW failed! (GLE=%lu)", GetLastError());
return FALSE;
}
m_pszExeName = PathFindFileNameW(m_szExeFilePath);
hr = SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pszPath);
if ( hr != S_OK ) {
log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr);
return FALSE;
}
ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath);
CoTaskMemFree(pszPath);
if ( ret ) {
log_debug(L"wcscpy_s failed! (Return value=%d)", ret);
return FALSE;
}
if ( !PathAppendW(szFilePath, L"wufuc") ) {
append_fail:
log_debug(L"PathAppendW failed!");
return FALSE;
}
if ( !CreateDirectoryW(szFilePath, NULL)
&& GetLastError() != ERROR_ALREADY_EXISTS ) {
log_debug(L"CreateDirectoryW failed! (GLE=%lu)", GetLastError());
return FALSE;
}
if ( !PathAppendW(szFilePath, L"wufuc.1.log") )
goto append_fail;
m_hFile = CreateFileW(szFilePath,
FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
result = m_hFile != INVALID_HANDLE_VALUE;
if ( !result )
log_debug(L"CreateFileW failed! (GLE=%lu)", GetLastError());
return result;
}
void log_debug_(const wchar_t *const format, ...)
{
va_list ap;
wchar_t *buf;
int ret;
int count;
va_start(ap, format);
count = _vscwprintf(format, ap);
va_end(ap);
if ( count == -1 ) return;
buf = calloc(count + 1, sizeof *buf);
if ( !buf ) return;
va_start(ap, format);
ret = vswprintf_s(buf, count + 1, format, ap);
va_end(ap);
if ( ret != -1 )
OutputDebugStringW(buf);
free(buf);
}
void log_trace_(const wchar_t *const format, ...)
{
static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
BOOL bStatus;
wchar_t datebuf[9];
wchar_t timebuf[9];
va_list ap;
const wchar_t fmt[] = L"%ls %ls [%ls:%lu] %ls";
int count;
wchar_t *buf1;
int ret;
wchar_t *buf2;
int size;
char *buf3;
DWORD written;
bStatus = InitOnceExecuteOnce(&InitOnce, init_once_callback, NULL, NULL);
if ( _wstrdate_s(datebuf, _countof(datebuf))
|| _wstrtime_s(timebuf, _countof(timebuf)) )
return;
va_start(ap, format);
ret = _vscwprintf(format, ap);
va_end(ap);
if ( ret == -1 ) return;
count = ret + 1;
buf1 = calloc(count, sizeof *buf1);
if ( !buf1 ) return;
va_start(ap, format);
ret = vswprintf_s(buf1, count, format, ap);
va_end(ap);
if ( ret == -1 ) goto free_buf1;
ret = _scwprintf(fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
if ( ret == -1 ) goto free_buf1;
count = ret + 1;
buf2 = calloc(count, sizeof *buf2);
if ( !buf2 ) goto free_buf1;
ret = swprintf_s(buf2, count, fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
if ( ret == -1 ) goto free_buf2;
if ( bStatus ) {
size = WideCharToMultiByte(CP_UTF8, 0, buf2, ret, NULL, 0, NULL, NULL);
if ( !size ) goto fallback;
buf3 = malloc(size);
if ( !buf3 ) goto fallback;
ret = WideCharToMultiByte(CP_UTF8, 0, buf2, ret, buf3, size, NULL, NULL)
&& WriteFile(m_hFile, buf3, size, &written, NULL);
free(buf3);
if ( !ret ) goto fallback;
} else {
fallback:
OutputDebugStringW(buf2);
}
free_buf2:
free(buf2);
free_buf1:
free(buf1);
}
void log_close(void)
{
if ( m_hFile != INVALID_HANDLE_VALUE )
CloseHandle(m_hFile);
}

View File

@@ -1,10 +0,0 @@
#pragma once
void log_debug_(const wchar_t *const format, ...);
void log_trace_(const wchar_t *const format, ...);
void log_close(void);
#define log_debug(format, ...) log_debug_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [DEBUG] " format L"\r\n", ##__VA_ARGS__)
#define log_info(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [INFO] " format L"\r\n", ##__VA_ARGS__)
#define log_warning(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [WARNING] " format L"\r\n", ##__VA_ARGS__)
#define log_error(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [ERROR] " format L"\r\n", ##__VA_ARGS__)

99
src/wufuc/logger.c Normal file
View File

@@ -0,0 +1,99 @@
#include "stdafx.h"
#include "logger.h"
#include "utf8.h"
#include <ShlObj.h>
static WCHAR s_szExeFilePath[MAX_PATH];
static LPWSTR s_pszExeFileName;
static HANDLE s_hFile = INVALID_HANDLE_VALUE;
static BOOL CALLBACK init_once_callback(
PINIT_ONCE InitOnce,
PVOID *Parameter,
PVOID *lpContext)
{
PWSTR pszPath;
LPWSTR folder;
int count;
LPWSTR file;
if ( !GetModuleFileNameW(NULL, s_szExeFilePath, _countof(s_szExeFilePath)) )
return FALSE;
s_pszExeFileName = PathFindFileNameW(s_szExeFilePath);
if ( FAILED(SHGetKnownFolderPath(&FOLDERID_ProgramData, KF_FLAG_DEFAULT, NULL, &pszPath)) )
return FALSE;
count = aswprintf(&folder, L"%ls\\wufuc", pszPath);
CoTaskMemFree(pszPath);
if ( count == -1 )
return FALSE;
if ( (CreateDirectoryW(folder, NULL) || GetLastError() == ERROR_ALREADY_EXISTS)
&& aswprintf(&file, L"%ls\\wufuc.1.log", folder) != -1 ) {
s_hFile = CreateFileW(file,
FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
free(file);
}
free(folder);
return s_hFile != INVALID_HANDLE_VALUE;
}
void log_debug_(const wchar_t *const format, ...)
{
va_list ap;
int count;
wchar_t *buffer;
va_start(ap, format);
count = vaswprintf(&buffer, format, ap);
va_end(ap);
if ( count != -1 )
OutputDebugStringW(buffer);
free(buffer);
}
void log_trace_(const wchar_t *const format, ...)
{
static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
BOOL status;
wchar_t datebuf[9];
wchar_t timebuf[9];
va_list ap;
int count;
wchar_t *buf1;
wchar_t *buf2;
status = InitOnceExecuteOnce(&InitOnce, init_once_callback, NULL, NULL);
if ( _wstrdate_s(datebuf, _countof(datebuf))
|| _wstrtime_s(timebuf, _countof(timebuf)) )
return;
va_start(ap, format);
count = vaswprintf(&buf1, format, ap);
va_end(ap);
if ( count == -1 ) return;
count = aswprintf(&buf2, L"%ls %ls [%ls:%lu] %ls", datebuf, timebuf, s_pszExeFileName, GetCurrentProcessId(), buf1);
free(buf1);
if ( count == -1 ) return;
if ( !status || !UTF8WriteFile(s_hFile, buf2) )
OutputDebugStringW(buf2);
free(buf2);
}
void log_close(void)
{
if ( s_hFile != INVALID_HANDLE_VALUE )
CloseHandle(s_hFile);
}

11
src/wufuc/logger.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
void log_debug_(const wchar_t *const format, ...);
void log_trace_(const wchar_t *const format, ...);
void log_close(void);
#define log_debug(format, ...) log_debug_(L"[DEBUG] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
#define log_info(format, ...) log_trace_(L"[INFO] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
#define log_warning(format, ...) log_trace_(L"[WARNING] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
#define log_error(format, ...) log_trace_(L"[ERROR] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
#define log_gle(format, ...) log_trace_(L"[ERROR] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L" (LastError=%lu)\r\n", ##__VA_ARGS__, GetLastError())

8
src/wufuc/memory.c Normal file
View File

@@ -0,0 +1,8 @@
#include "stdafx.h"
#include "stdafx.h"
#include "memory.h"
BOOL WriteProcessMemoryBOOL(HANDLE hProcess, LPBOOL lpBaseAddress, BOOL bValue)
{
return WriteProcessMemory(hProcess, lpBaseAddress, &bValue, sizeof bValue, NULL);
}

3
src/wufuc/memory.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
BOOL WriteProcessMemoryBOOL(HANDLE hProcess, LPBOOL lpBaseAddress, BOOL bValue);

View File

@@ -1,157 +0,0 @@
#include "stdafx.h"
#include "modulehelper.h"
#include "log.h"
HMODULE mod_get_from_th32_snapshot(HANDLE hSnapshot, const wchar_t *pLibFileName)
{
MODULEENTRY32W me = { sizeof me };
if ( !Module32FirstW(hSnapshot, &me) )
return NULL;
do {
if ( !_wcsicmp(me.szExePath, pLibFileName) )
return me.hModule;
} while ( Module32NextW(hSnapshot, &me) );
return NULL;
}
bool mod_inject_and_begin_thread(
HANDLE hProcess,
HMODULE hModule,
LPTHREAD_START_ROUTINE pStartAddress,
const void *pParam,
size_t cbParam)
{
bool result = false;
NTSTATUS Status;
LPVOID pBaseAddress = NULL;
SIZE_T cb;
HMODULE hRemoteModule = NULL;
uintptr_t offset;
HANDLE hThread;
Status = NtSuspendProcess(hProcess);
if ( !NT_SUCCESS(Status) ) return result;
if ( pParam ) {
// this will be VirtualFree()'d by the function at pStartAddress
pBaseAddress = VirtualAllocEx(hProcess,
NULL,
cbParam,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
if ( !pBaseAddress ) goto resume_process;
if ( !WriteProcessMemory(hProcess, pBaseAddress, pParam, cbParam, &cb) )
goto virt_free;
}
if ( mod_inject_by_hmodule(hProcess, hModule, &hRemoteModule) ) {
offset = (uintptr_t)pStartAddress - (uintptr_t)hModule;
hThread = CreateRemoteThread(hProcess,
NULL,
0,
OffsetToPointer(hRemoteModule, offset),
pBaseAddress,
0,
NULL);
if ( hThread ) {
CloseHandle(hThread);
result = true;
}
}
virt_free:
if ( !result && pBaseAddress )
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
resume_process:
NtResumeProcess(hProcess);
return result;
}
bool mod_inject_by_hmodule(HANDLE hProcess, HMODULE hModule, HMODULE *phRemoteModule)
{
WCHAR Filename[MAX_PATH];
DWORD nLength;
nLength = GetModuleFileNameW(hModule, Filename, _countof(Filename));
if ( nLength ) {
return mod_inject(hProcess,
Filename,
nLength,
phRemoteModule);
}
return false;
}
bool mod_inject(
HANDLE hProcess,
const wchar_t *pLibFilename,
size_t cchLibFilename,
HMODULE *phRemoteModule)
{
bool result = false;
DWORD dwProcessId;
NTSTATUS Status;
HANDLE hSnapshot;
SIZE_T nSize;
LPVOID pBaseAddress;
HANDLE hThread;
Status = NtSuspendProcess(hProcess);
if ( !NT_SUCCESS(Status) ) return result;
dwProcessId = GetProcessId(hProcess);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if ( !hSnapshot ) goto resume_process;
*phRemoteModule = mod_get_from_th32_snapshot(hSnapshot,
pLibFilename);
CloseHandle(hSnapshot);
// already injected... still sets *phRemoteModule
if ( *phRemoteModule ) goto resume_process;
nSize = (cchLibFilename + 1) * sizeof *pLibFilename;
pBaseAddress = VirtualAllocEx(hProcess,
NULL,
nSize,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
if ( !pBaseAddress ) goto resume_process;
if ( !WriteProcessMemory(hProcess, pBaseAddress, pLibFilename, nSize, NULL) )
goto virt_free;
hThread = CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)LoadLibraryW,
pBaseAddress,
0,
NULL);
if ( !hThread ) goto virt_free;
WaitForSingleObject(hThread, INFINITE);
if ( sizeof *phRemoteModule > sizeof(DWORD) ) {
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if ( hSnapshot ) {
*phRemoteModule = mod_get_from_th32_snapshot(
hSnapshot,
pLibFilename);
CloseHandle(hSnapshot);
result = *phRemoteModule != NULL;
}
} else {
result = GetExitCodeThread(hThread, (LPDWORD)phRemoteModule) != FALSE;
}
CloseHandle(hThread);
virt_free:
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
resume_process:
NtResumeProcess(hProcess);
return result;
}

View File

@@ -1,15 +0,0 @@
#pragma once
HMODULE mod_get_from_th32_snapshot(HANDLE hSnapshot, const wchar_t *pLibFileName);
bool mod_inject_and_begin_thread(
HANDLE hProcess,
HMODULE hModule,
LPTHREAD_START_ROUTINE pStartAddress,
const void *pParam,
size_t cbParam);
bool mod_inject_by_hmodule(HANDLE hProcess, HMODULE hModule, HMODULE *phRemoteModule);
bool mod_inject(
HANDLE hProcess,
const wchar_t *pLibFilename,
size_t cchLibFilename,
HMODULE *phRemoteModule);

24
src/wufuc/modules.c Normal file
View File

@@ -0,0 +1,24 @@
#include "stdafx.h"
#include "modules.h"
HMODULE Toolhelp32GetModuleHandle(DWORD th32ProcessID, LPCWSTR lpModuleName)
{
HANDLE Snapshot;
MODULEENTRY32W me = { sizeof me };
HMODULE result = NULL;
Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, th32ProcessID);
if ( !Snapshot ) return NULL;
if ( Module32FirstW(Snapshot, &me) ) {
do {
if ( !_wcsicmp(me.szExePath, lpModuleName) ) {
result = me.hModule;
break;
}
} while ( Module32NextW(Snapshot, &me) );
}
CloseHandle(Snapshot);
return result;
}

3
src/wufuc/modules.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
HMODULE Toolhelp32GetModuleHandle(DWORD th32ProcessID, LPCWSTR lpModuleName);

View File

@@ -1,41 +0,0 @@
#include "stdafx.h"
#include "mutexhelper.h"
#include <sddl.h>
HANDLE mutex_create_new(bool InitialOwner, const wchar_t *MutexName)
{
HANDLE hMutex;
hMutex = CreateMutexW(NULL, InitialOwner, MutexName);
if ( hMutex ) {
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
CloseHandle(hMutex);
return NULL;
}
return hMutex;
}
return NULL;
}
HANDLE mutex_create_new_fmt(bool InitialOwner, const wchar_t *const NameFormat, ...)
{
HANDLE result = NULL;
va_list ap;
wchar_t *buffer;
int ret;
va_start(ap, NameFormat);
ret = _vscwprintf(NameFormat, ap) + 1;
va_end(ap);
buffer = calloc(ret, sizeof *buffer);
if ( buffer ) {
va_start(ap, NameFormat);
ret = vswprintf_s(buffer, ret, NameFormat, ap);
va_end(ap);
if (ret != -1)
result = mutex_create_new(InitialOwner, buffer);
free(buffer);
}
return result;
}

View File

@@ -1,4 +0,0 @@
#pragma once
HANDLE mutex_create_new(bool InitialOwner, const wchar_t *MutexName);
HANDLE mutex_create_new_fmt(bool InitialOwner, const wchar_t *const NameFormat, ...);

View File

@@ -1,403 +0,0 @@
#include "stdafx.h"
#include "ptrlist.h"
void ptrlist_lock(ptrlist_t *list)
{
EnterCriticalSection(&list->criticalSection);
}
void ptrlist_unlock(ptrlist_t *list)
{
LeaveCriticalSection(&list->criticalSection);
}
void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag)
{
void *result;
ptrlist_lock(list);
result = list->values[index];
if ( pTag )
*pTag = list->tags[index];
ptrlist_unlock(list);
return result;
}
bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity)
{
bool result = false;
size_t c;
size_t vsize;
size_t tsize;
void *tmp;
if ( !list || capacity > maxCapacity )
return result;
c = capacity ? capacity :
(maxCapacity ? min(maxCapacity, 16) : 16);
vsize = c * (sizeof *list->values);
tsize = c * (sizeof *list->tags);
InitializeCriticalSection(&list->criticalSection);
ptrlist_lock(list);
tmp = malloc(vsize + tsize);
if ( tmp ) {
ZeroMemory(tmp, vsize + tsize);
list->values = tmp;
list->tags = OffsetToPointer(tmp, vsize);
list->capacity = c;
list->maxCapacity = maxCapacity;
list->count = 0;
result = true;
}
ptrlist_unlock(list);
if ( !result )
DeleteCriticalSection(&list->criticalSection);
return result;
}
void ptrlist_destroy(ptrlist_t *list)
{
if ( !list ) return;
ptrlist_lock(list);
free(list->values);
list->values = NULL;
list->tags = NULL;
list->count = 0;
list->capacity = 0;
list->maxCapacity = 0;
ptrlist_unlock(list);
DeleteCriticalSection(&list->criticalSection);
}
size_t ptrlist_index_of(ptrlist_t *list, void *value)
{
size_t result = -1;
if ( !list || !value )
return result;
ptrlist_lock(list);
for ( size_t i = 0; i < list->count; i++ ) {
if ( list->values[i] == value ) {
result = i;
break;
}
}
ptrlist_unlock(list);
return result;
}
bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag)
{
bool result = false;
size_t newCapacity;
size_t diff;
size_t vsize;
size_t tsize;
void **tmp1;
uint32_t *tmp2;
if ( !list || !value )
return result;
ptrlist_lock(list);
if ( list->count >= list->capacity ) {
newCapacity = list->count;
if ( list->maxCapacity ) {
diff = list->maxCapacity - list->capacity;
if ( !diff )
goto leave;
newCapacity += min(diff, 16);
} else {
newCapacity += 16;
}
vsize = newCapacity * (sizeof *list->values);
tsize = newCapacity * (sizeof *list->tags);
tmp1 = malloc(vsize + tsize);
if ( !tmp1 )
goto leave;
ZeroMemory(tmp1, vsize);
tmp2 = OffsetToPointer(tmp1, vsize);
ZeroMemory(tmp2, tsize);
if ( memmove_s(tmp1, vsize, list->values, list->count * (sizeof *list->values))
|| memmove_s(tmp2, tsize, list->tags, list->count * (sizeof *list->tags)) ) {
free(tmp1);
goto leave;
}
list->values = tmp1;
list->tags = tmp2;
list->capacity = newCapacity;
}
list->values[list->count] = value;
list->tags[list->count] = tag;
list->count++;
result = true;
leave:
ptrlist_unlock(list);
return result;
}
bool ptrlist_add_range(ptrlist_t *list, void **values, uint32_t *tags, size_t count)
{
bool result = true;
if ( !list || !values || !count )
return false;
ptrlist_lock(list);
if ( list->count + count <= list->maxCapacity ) {
for ( size_t i = 0; result && i < count; i++ )
result = ptrlist_add(list, values[i], tags ? tags[i] : 0);
} else {
result = false;
}
ptrlist_unlock(list);
return result;
}
bool ptrlist_remove_at(ptrlist_t *list, size_t index)
{
bool result = false;
if ( !list ) return result;
ptrlist_lock(list);
if ( index <= list->count - 1 ) {
for ( size_t i = index; i < list->count - 1; i++ )
list->values[i] = list->values[i + 1];
list->values[list->count--] = NULL;
result = true;
}
ptrlist_unlock(list);
return result;
}
bool ptrlist_remove(ptrlist_t *list, void *value)
{
size_t index;
bool result = false;
if ( !list || !value )
return result;
ptrlist_lock(list);
index = ptrlist_index_of(list, value);
if ( index != -1 )
result = ptrlist_remove_at(list, index);
ptrlist_unlock(list);
return result;
}
bool ptrlist_remove_range(ptrlist_t *list, size_t index, size_t count)
{
bool result = true;
if ( !list || !count )
return false;
ptrlist_lock(list);
if ( index <= list->count - 1
&& index + count <= list->count ) {
for ( size_t i = 0; result && i < count; i++ )
result = ptrlist_remove_at(list, index);
} else {
result = false;
}
ptrlist_unlock(list);
return result;
}
bool ptrlist_clear(ptrlist_t *list)
{
bool result = false;
if ( !list ) return result;
ptrlist_lock(list);
result = ptrlist_remove_range(list, 0, list->count);
ptrlist_unlock(list);
return result;
}
size_t ptrlist_get_count(ptrlist_t *list)
{
size_t result = -1;
if ( !list ) return result;
ptrlist_lock(list);
result = list->count;
ptrlist_unlock(list);
return result;
}
size_t ptrlist_get_capacity(ptrlist_t *list)
{
size_t result = -1;
if ( !list ) return result;
ptrlist_lock(list);
result = list->capacity;
ptrlist_unlock(list);
return result;
}
size_t ptrlist_get_max_capacity(ptrlist_t *list)
{
size_t result = -1;
if ( !list ) return result;
ptrlist_lock(list);
result = list->maxCapacity;
ptrlist_unlock(list);
return result;
}
bool ptrlist_contains(ptrlist_t *list, void *value)
{
return ptrlist_index_of(list, value) != -1;
}
void **ptrlist_copy_values(ptrlist_t *list, size_t *count)
{
void **result = NULL;
size_t size;
size_t c;
if ( !list || !count )
return result;
ptrlist_lock(list);
c = list->count;
if ( !c ) goto leave;
size = c * (sizeof *list->values);
result = malloc(c * (sizeof *list->values));
if ( result ) {
if ( !memcpy_s(result, size, list->values, size) ) {
*count = c;
} else {
free(result);
result = NULL;
}
}
leave:
ptrlist_unlock(list);
return result;
}
uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count)
{
uint32_t *result = NULL;
size_t size;
size_t c;
if ( !list || !count )
return result;
ptrlist_lock(list);
c = list->count;
if ( !c ) goto leave;
size = c * (sizeof *list->tags);
result = malloc(c * (sizeof *list->tags));
if ( result ) {
if ( !memcpy_s(result, size, list->tags, size) ) {
*count = c;
} else {
free(result);
result = NULL;
}
}
leave:
ptrlist_unlock(list);
return result;
}
bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count)
{
bool result = false;
void **v;
uint32_t *t;
size_t c;
if ( !values || !tags || !count )
return result;
ptrlist_lock(list);
v = ptrlist_copy_values(list, &c);
if ( !v ) goto leave;
t = ptrlist_copy_tags(list, &c);
if ( !t ) {
free(v);
goto leave;
}
*values = v;
*tags = t;
*count = c;
result = true;
leave:
ptrlist_unlock(list);
return result;
}
void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *))
{
if ( !list || !f ) return;
ptrlist_lock(list);
if ( index + count <= list->count ) {
for ( size_t i = index; i < count; i++ )
f(list->values[i]);
}
ptrlist_unlock(list);
}
void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *))
{
if ( !list || !f ) return;
ptrlist_lock(list);
ptrlist_for(list, 0, list->count, f);
ptrlist_unlock(list);
}
void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *))
{
if ( !list || !f ) return;
ptrlist_lock(list);
if ( index + count <= list->count ) {
for ( size_t i = index; i < count; i++ )
f(list->values[i]);
}
ptrlist_unlock(list);
}
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *))
{
if ( !list || !f ) return;
ptrlist_lock(list);
ptrlist_for_stdcall(list, 0, list->count, f);
ptrlist_unlock(list);
}

View File

@@ -1,37 +0,0 @@
#pragma once
#pragma pack(push, 1)
typedef struct ptrlist_t_
{
void **values;
uint32_t *tags;
size_t capacity;
size_t maxCapacity;
size_t count;
CRITICAL_SECTION criticalSection;
} ptrlist_t;
#pragma pack(pop)
void ptrlist_lock(ptrlist_t *list);
void ptrlist_unlock(ptrlist_t *list);
void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag);
bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity);
void ptrlist_destroy(ptrlist_t *list);
size_t ptrlist_index_of(ptrlist_t *list, void *value);
bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag);
bool ptrlist_add_range(ptrlist_t *list, void **values, uint32_t *tags, size_t count);
bool ptrlist_remove_at(ptrlist_t *list, size_t index);
bool ptrlist_remove(ptrlist_t *list, void *value);
bool ptrlist_remove_range(ptrlist_t *list, size_t index, size_t count);
bool ptrlist_clear(ptrlist_t *list);
size_t ptrlist_get_count(ptrlist_t *list);
size_t ptrlist_get_capacity(ptrlist_t *list);
size_t ptrlist_get_max_capacity(ptrlist_t *list);
bool ptrlist_contains(ptrlist_t *list, void *value);
void **ptrlist_copy_values(ptrlist_t *list, size_t *count);
uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count);
bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count);
void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *));
void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *));
void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *));
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *));

22
src/wufuc/registry.c Normal file
View File

@@ -0,0 +1,22 @@
#include "stdafx.h"
#include "registry.h"
DWORD RegGetValueAlloc(PVOID *ppvData, HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwFlags, LPDWORD pdwType)
{
DWORD result;
PVOID pvData;
if ( RegGetValueW(hKey, lpSubKey, lpValueName, dwFlags, pdwType, NULL, &result) != ERROR_SUCCESS )
return 0;
pvData = malloc(result);
if ( !pvData ) return 0;
if ( RegGetValueW(hKey, lpSubKey, lpValueName, dwFlags, pdwType, pvData, &result) == ERROR_SUCCESS ) {
*ppvData = pvData;
} else {
free(pvData);
return 0;
}
return result;
}

3
src/wufuc/registry.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
DWORD RegGetValueAlloc(PVOID *ppvData, HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwFlags, LPDWORD pdwType);

View File

@@ -1,118 +0,0 @@
#include "stdafx.h"
#include "registryhelper.h"
PVOID reg_get_value_alloc(
HKEY hKey,
LPCWSTR SubKey,
LPCWSTR Value,
DWORD dwFlags,
LPDWORD pdwType,
LPDWORD pcbData)
{
DWORD cbData = 0;
PVOID result = NULL;
if ( RegGetValueW(hKey, SubKey, Value, dwFlags, pdwType, NULL, &cbData) != ERROR_SUCCESS )
return result;
result = malloc(cbData);
if ( !result ) return result;
if ( RegGetValueW(hKey, SubKey, Value, dwFlags, pdwType, result, &cbData) == ERROR_SUCCESS ) {
if ( pcbData )
*pcbData = cbData;
} else {
free(result);
result = NULL;
}
return result;
}
LPBYTE reg_query_value_alloc(
HKEY hKey,
LPCWSTR SubKey,
LPCWSTR Value,
LPDWORD pdwType,
LPDWORD pcbData)
{
HKEY hSubKey;
DWORD cbData = 0;
DWORD dwType;
LPBYTE result = NULL;
if ( SubKey && *SubKey ) {
if ( RegOpenKeyW(hKey, SubKey, &hSubKey) != ERROR_SUCCESS )
return result;
} else {
hSubKey = hKey;
}
if ( RegQueryValueExW(hSubKey, Value, NULL, &dwType, result, &cbData) != ERROR_SUCCESS )
return result;
switch ( dwType ) {
case REG_SZ:
case REG_EXPAND_SZ:
cbData += sizeof UNICODE_NULL;
break;
case REG_MULTI_SZ:
cbData += (sizeof UNICODE_NULL) * 2;
break;
}
result = malloc(cbData);
if ( !result ) return result;
ZeroMemory(result, cbData);
if ( RegQueryValueExW(hSubKey, Value, NULL, pdwType, result, &cbData) == ERROR_SUCCESS ) {
if ( pcbData )
*pcbData = cbData;
} else {
free(result);
result = NULL;
}
return result;
}
PVOID reg_query_key_alloc(
HANDLE KeyHandle,
KEY_INFORMATION_CLASS KeyInformationClass,
PULONG pResultLength)
{
NTSTATUS Status;
ULONG ResultLength;
PVOID result = NULL;
Status = NtQueryKey(KeyHandle, KeyInformationClass, NULL, 0, &ResultLength);
if ( Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL )
return result;
result = malloc(ResultLength);
if ( !result ) return result;
Status = NtQueryKey(KeyHandle, KeyInformationClass, result, ResultLength, &ResultLength);
if ( NT_SUCCESS(Status) ) {
*pResultLength = ResultLength;
} else {
free(result);
result = NULL;
}
return result;
}
LPWSTR env_expand_strings_alloc(LPCWSTR Src, LPDWORD pcchLength)
{
LPWSTR result;
DWORD buffersize;
DWORD size;
buffersize = ExpandEnvironmentStringsW(Src, NULL, 0);
result = calloc(buffersize, sizeof *result);
size = ExpandEnvironmentStringsW(Src, result, buffersize);
if ( !size || size > buffersize ) {
free(result);
result = NULL;
} else if ( pcchLength ) {
*pcchLength = buffersize;
}
return result;
}

View File

@@ -1,20 +0,0 @@
#pragma once
PVOID reg_get_value_alloc(
HKEY hkey,
LPCWSTR pSubKey,
LPCWSTR pValue,
DWORD dwFlags,
LPDWORD pdwType,
LPDWORD pcbData);
LPBYTE reg_query_value_alloc(
HKEY hKey,
LPCWSTR pSubKey,
LPCWSTR pValueName,
LPDWORD pType,
LPDWORD pcbData);
PVOID reg_query_key_alloc(
HANDLE KeyHandle,
KEY_INFORMATION_CLASS KeyInformationClass,
PULONG pResultLength);
LPWSTR env_expand_strings_alloc(LPCWSTR Src, LPDWORD pcchLength);

View File

@@ -8,11 +8,11 @@
#define BUILD_VERSION_COMMA 1,0,1,0
#endif
#define S_(x) #x
#define S(x) S_(x)
#define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x)
#ifdef X64
#ifdef _WIN64
#define FILENAME "wufuc64.dll"
#elif defined(X86)
#else
#define FILENAME "wufuc32.dll"
#endif

Binary file not shown.

View File

@@ -1,84 +0,0 @@
#include "stdafx.h"
#include "resourcehelper.h"
#include "log.h"
void *res_get_version_info(HMODULE hModule)
{
HRSRC hResInfo;
DWORD dwSize;
HGLOBAL hResData;
LPVOID pRes;
void *result;
hResInfo = FindResourceW(hModule,
MAKEINTRESOURCEW(VS_VERSION_INFO),
MAKEINTRESOURCEW(RT_VERSION));
if ( !hResInfo ) return NULL;
dwSize = SizeofResource(hModule, hResInfo);
if ( !dwSize ) return NULL;
hResData = LoadResource(hModule, hResInfo);
if ( !hResData ) return NULL;
pRes = LockResource(hResData);
if ( !pRes ) return NULL;
result = malloc(dwSize);
if ( !result ) return NULL;
if ( memcpy_s(result, dwSize, pRes, dwSize) ) {
free(result);
result = NULL;
}
return result;
}
wchar_t *res_query_string_file_info(const void *pBlock,
LANGANDCODEPAGE lcp,
const wchar_t *pszStringName,
size_t *pcchLength)
{
const wchar_t fmt[] = L"\\StringFileInfo\\%04x%04x\\%ls";
int ret;
int count;
wchar_t *pszSubBlock;
wchar_t *result = NULL;
UINT uLen;
ret = _scwprintf(fmt, lcp.wLanguage, lcp.wCodePage, pszStringName);
if ( ret == -1 ) return NULL;
count = ret + 1;
pszSubBlock = calloc(count, sizeof *pszSubBlock);
if ( !pszSubBlock ) return NULL;
ret = swprintf_s(pszSubBlock, count, fmt, lcp.wLanguage, lcp.wCodePage, pszStringName);
if ( ret != -1
&& VerQueryValueW(pBlock, pszSubBlock, &(LPVOID)result, &uLen)
&& pcchLength )
*pcchLength = uLen;
free(pszSubBlock);
return result;
}
PLANGANDCODEPAGE res_query_var_file_info(const void *pBlock, size_t *pCount)
{
PLANGANDCODEPAGE result = NULL;
UINT uLen;
if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", &(LPVOID)result, &uLen) )
*pCount = uLen / (sizeof *result);
return result;
}
VS_FIXEDFILEINFO *res_query_fixed_file_info(const void *pBlock)
{
VS_FIXEDFILEINFO *result;
UINT uLen;
if ( VerQueryValueW(pBlock, L"\\", &(LPVOID)result, &uLen) )
return result;
return NULL;
}

View File

@@ -1,18 +0,0 @@
#pragma once
typedef struct
{
WORD wLanguage;
WORD wCodePage;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
void *res_get_version_info(HMODULE hModule);
wchar_t *res_query_string_file_info(const void *pBlock,
LANGANDCODEPAGE lcp,
const wchar_t *pszStringName,
size_t *pcchLength);
PLANGANDCODEPAGE res_query_var_file_info(const void *pBlock, size_t *pcbData);
VS_FIXEDFILEINFO *res_query_fixed_file_info(const void *pBlock);

View File

@@ -1,148 +1,261 @@
#include "stdafx.h"
#include "callbacks.h"
#include "eventhelper.h"
#include "log.h"
#include "modulehelper.h"
#include "mutexhelper.h"
#include "ptrlist.h"
#include "registryhelper.h"
#include "servicehelper.h"
#include "wufuc.h"
#include "memory.h"
#include "modules.h"
#include "patternfind.h"
#include "registry.h"
#include "helpers.h"
#include "versioninfo.h"
const wchar_t m_szUnloadEventName[] = L"Global\\wufuc_UnloadEvent";
static BOOL s_bWindowsSevenSP1;
static BOOL s_bWindowsEightPointOne;
void CALLBACK RUNDLL32_StartW(HWND hwnd,
HINSTANCE hinst,
LPWSTR lpszCmdLine,
int nCmdShow)
static LPVOID ResolveAndTranslatePtr(LPVOID lpSrcImageBase, size_t Offset, LPVOID lpDstImageBase)
{
ptrlist_t list;
HANDLE hEvent;
DWORD dwDesiredAccess;
LPVOID p = OffsetToPointer(lpSrcImageBase, Offset);
#ifdef _WIN64
return OffsetToPointer(lpDstImageBase, PointerToOffset(lpSrcImageBase, OffsetToPointer(p, sizeof(uint32_t) + *(uint32_t *)p)));
#else
return *(LPVOID *)p;
#endif
}
static VOID CALLBACK ServiceNotifyCallback(PVOID pParameter)
{
PSERVICE_NOTIFY pNotifyBuffer = pParameter;
DWORD dwProcessId = pNotifyBuffer->ServiceStatus.dwProcessId;
const DWORD dwDesiredAccess = PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE;
LPWSTR fname;
HANDLE hProcess;
NTSTATUS Status;
LPWSTR lpwstrFilename;
LPVOID lpData;
PLANGANDCODEPAGE lpTranslate;
LPWSTR lpInternalName;
VS_FIXEDFILEINFO *lpffi;
const char *pattern;
size_t off1;
size_t off2;
HMODULE hModule;
MODULEINFO modinfo;
LPVOID lpBuffer;
SIZE_T NumberOfBytesRead;
size_t offset;
LPVOID lpAddress;
BOOL bValue;
switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS:
if ( !RegGetValueAlloc(&lpwstrFilename,
HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
L"ServiceDll",
RRF_RT_REG_SZ,
NULL) ) {
log_gle(L"Failed to get wuauserv ServiceDll value!");
break;
}
if ( !GetFileVersionInfoExAlloc(FILE_VER_GET_NEUTRAL, TRUE, lpwstrFilename, &lpData) ) {
log_gle(L"Failed to get file version information: lpwstrFilename=%ls", lpwstrFilename);
goto free_lpwstrFilename;
}
if ( !VerQueryTranslations(lpData, &lpTranslate) ) {
log_gle(L"Failed to get resource translations: pBlock=%p", lpData);
goto free_lpData;
}
if ( !VerQueryString(lpData, lpTranslate[0], L"InternalName", &lpInternalName) ) {
log_gle(L"Failed to get InternalName resource string: wLanguage=%04x wCodePage=%04x pBlock=%p",
lpTranslate[0].wLanguage, lpTranslate[0].wCodePage, lpData);
goto free_lpData;
}
if ( _wcsicmp(lpInternalName, L"wuaueng.dll") ) {
log_error(L"InternalName mismatch: lpInternalName=%ls", lpInternalName);
goto free_lpData;
}
if ( !VerQueryFileInfo(lpData, &lpffi) ) {
log_gle(L"Failed to get resource file info: pBlock=%p", lpData);
goto free_lpData;
}
#ifdef _WIN64
if ( (s_bWindowsSevenSP1 && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 6, 7601, 23714) != -1)
|| (s_bWindowsEightPointOne && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 9, 9600, 18621) != -1) ) {
// all x64
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
off1 = 0xa;
off2 = 0x12;
} else goto free_lpData;
#else
if ( s_bWindowsSevenSP1 && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 6, 7601, 23714) != -1 ) {
// windows 7 x86
pattern = "833D????????00 743E E8???????? A3????????";
off1 = 0x2;
off2 = 0xf;
} else if ( s_bWindowsEightPointOne && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 9, 9600, 18621) != -1 ) {
// windows 8.1 x86
pattern = "8BFF 51 833D????????00 7507 A1????????";
off1 = 0x5;
off2 = 0xd;
} else goto free_lpData;
#endif
fname = PathFindFileNameW(lpwstrFilename);
log_info(L"Supported version of %ls: %hu.%hu.%hu.%hu",
fname,
HIWORD(lpffi->dwProductVersionMS), LOWORD(lpffi->dwProductVersionMS),
HIWORD(lpffi->dwProductVersionLS), LOWORD(lpffi->dwProductVersionLS));
hProcess = OpenProcess(dwDesiredAccess, FALSE, dwProcessId);
if ( !hProcess ) {
log_gle(L"Failed to open target process: dwProcessId=%lu", dwProcessId);
goto free_lpData;
}
Status = NtSuspendProcess(hProcess);
if ( Status != STATUS_SUCCESS ) {
log_error(L"Failed to suspend target process: hProcess=%p (Status=%ld)", hProcess, Status);
goto close_hProcess;
}
hModule = Toolhelp32GetModuleHandle(dwProcessId, lpwstrFilename);
if ( !hModule ) {
log_gle(L"Failed to find target module in Toolhelp32 snapshot: th32ProcessId=%lu lpModuleName=%ls",
dwProcessId, lpwstrFilename);
goto resume_hProcess;
}
if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) {
log_error(L"Failed to get target module information: hProcess=%p hModule=%p", hProcess, hModule);
goto resume_hProcess;
}
lpBuffer = malloc(modinfo.SizeOfImage);
if ( !lpBuffer ) {
log_error(L"Failed to allocate memory for lpBuffer!");
goto resume_hProcess;
}
if ( !ReadProcessMemory(hProcess, modinfo.lpBaseOfDll, lpBuffer, modinfo.SizeOfImage, &NumberOfBytesRead) ) {
log_gle(L"Failed to read target process memory: hProcess=%p lpBaseAddress=%p nSize=%lu",
hProcess, modinfo.lpBaseOfDll, modinfo.SizeOfImage);
goto free_lpBuffer;
}
offset = patternfind(lpBuffer, NumberOfBytesRead, pattern);
if ( offset == -1 ) {
log_error(L"Failed to find IsDeviceServiceable pattern!");
goto free_lpBuffer;
}
log_info(L"Found IsDeviceServiceable function offset: %ls+0x%Ix", fname, offset);
lpAddress = ResolveAndTranslatePtr(lpBuffer, offset + off1, modinfo.lpBaseOfDll);
bValue = FALSE;
if ( WriteProcessMemory(hProcess, lpAddress, &bValue, sizeof bValue, NULL) )
log_info(L"Successfully wrote value to target process: lpAddress=%p", lpAddress);
else
log_gle(L"Failed to write value to target process: lpAddress=%p!", lpAddress);
lpAddress = ResolveAndTranslatePtr(lpBuffer, offset + off2, modinfo.lpBaseOfDll);
bValue = TRUE;
if ( WriteProcessMemory(hProcess, lpAddress, &bValue, sizeof bValue, NULL) )
log_info(L"Successfully wrote value to target process: lpAddress=%p", lpAddress);
else
log_gle(L"Failed to patch flag in target process at address %p!", lpAddress);
free_lpBuffer:
free(lpBuffer);
resume_hProcess:
NtResumeProcess(hProcess);
close_hProcess:
CloseHandle(hProcess);
free_lpData:
free(lpData);
free_lpwstrFilename:
free(lpwstrFilename);
break;
case ERROR_SERVICE_MARKED_FOR_DELETE:
*(bool *)pNotifyBuffer->pContext = true;
break;
}
if ( pNotifyBuffer->pszServiceNames )
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
}
void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
{
HANDLE hMutex;
HANDLE hUnloadEvent;
bool Lagging;
SC_HANDLE hSCM;
SC_HANDLE hService;
DWORD dwProcessId;
SERVICE_NOTIFYW NotifyBuffer;
bool Unloading = false;
DWORD e;
void **values;
uint32_t *tags;
size_t count;
DWORD r;
size_t index;
size_t crashes = 0;
bool Suspending = false;
DWORD Error;
g_hMainMutex = mutex_create_new(true,
L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645");
if ( !g_hMainMutex ) return;
if ( !ptrlist_create(&list, 0, MAXIMUM_WAIT_OBJECTS) ) goto release_mutex;
hEvent = event_create_with_string_security_descriptor(
true, false, m_szUnloadEventName, L"D:(A;;0x001F0003;;;BA)");
if ( !hEvent ) goto destroy_list;
if ( !ptrlist_add(&list, hEvent, 0) ) goto set_event;
dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
hMutex = CreateNewMutex(NULL, TRUE, L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645");
if ( !hMutex ) {
log_error(L"Failed to create instance mutex!");
return;
}
hUnloadEvent = CreateEventWithStringSecurityDescriptor(L"D:(A;;0x001F0003;;;BA)",
TRUE, FALSE, L"Global\\wufuc_UnloadEvent");
if ( !hUnloadEvent ) {
log_gle(L"Failed to create unload event!");
goto release_mutex;
}
s_bWindowsSevenSP1 = VerifyVersionInfoHelper(6, 1, 1);
if ( !s_bWindowsSevenSP1 ) {
s_bWindowsEightPointOne = VerifyVersionInfoHelper(6, 3, 0);
if ( !s_bWindowsEightPointOne ) {
log_error(L"Unsupported operating system!");
goto close_event;
}
}
do {
Lagging = false;
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if ( !hSCM ) goto set_event;
if ( !hSCM ) break;
hService = OpenServiceW(hSCM, L"wuauserv", dwDesiredAccess);
if ( !hService ) goto close_scm;
if ( (dwDesiredAccess & SERVICE_QUERY_CONFIG) == SERVICE_QUERY_CONFIG ) {
dwDesiredAccess &= ~SERVICE_QUERY_CONFIG;
dwProcessId = svc_heuristic_process_id(hSCM, hService);
if ( dwProcessId )
wufuc_inject(dwProcessId, (LPTHREAD_START_ROUTINE)thread_start_callback, &list);
hService = OpenServiceW(hSCM, L"wuauserv", SERVICE_QUERY_STATUS);
if ( !hService ) {
CloseServiceHandle(hSCM);
break;
}
ZeroMemory(&NotifyBuffer, sizeof NotifyBuffer);
NotifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)service_notify_callback;
NotifyBuffer.pContext = (PVOID)&list;
while ( !Unloading && !Lagging ) {
e = NotifyServiceStatusChangeW(hService,
NotifyBuffer.pfnNotifyCallback = ServiceNotifyCallback;
NotifyBuffer.pContext = &Lagging;
while ( true ) {
Error = NotifyServiceStatusChangeW(hService,
SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
&NotifyBuffer);
switch ( e ) {
switch ( Error ) {
case ERROR_SUCCESS:
do {
if ( !ptrlist_copy(&list, &values, &tags, &count) ) {
Unloading = true;
break;
Error = WaitForSingleObjectEx(hUnloadEvent, INFINITE, TRUE);
switch ( Error ) {
case WAIT_OBJECT_0:
log_info(L"Unload event signaled!");
goto exit_loop;
case WAIT_FAILED:
log_error(L"WaitForSingleObjectEx failed! Error=%lu", Error);
goto exit_loop;
}
r = WaitForMultipleObjectsEx((DWORD)count,
values, FALSE, INFINITE, TRUE);
if ( r >= WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + count ) {
// object signaled
index = r - WAIT_OBJECT_0;
if ( !index ) {
// Unload event
Unloading = true;
} else {
// crash mutex was released cleanly
ptrlist_remove(&list, values[index]);
ReleaseMutex(values[index]);
CloseHandle(values[index]);
}
} else if ( r >= WAIT_ABANDONED_0 && r < WAIT_ABANDONED_0 + count ) {
// object abandoned
// crash mutex was abandoned, process has most likely crashed.
index = r - WAIT_ABANDONED_0;
ptrlist_remove(&list, values[index]);
ReleaseMutex(values[index]);
CloseHandle(values[index]);
crashes++;
log_warning(L"A process wufuc injected into has crashed %Iu time%ls! (ProcessId=%lu)",
crashes, crashes != 1 ? L"s" : L"", tags[index]);
if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
log_error(L"Crash threshold has been reached, disabling wufuc until next reboot!");
Unloading = true;
Suspending = true;
}
} else if ( r == WAIT_FAILED ) {
log_error(L"Wait function failed!");
Unloading = true;
}
free(values);
free(tags);
} while ( r != WAIT_IO_COMPLETION && !Unloading );
} while ( Error != WAIT_IO_COMPLETION );
break;
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
log_warning(L"Client lagging!");
log_warning(L"The service notification client is lagging too far behind the current state of services in the machine.");
Lagging = true;
break;
goto exit_loop;
case ERROR_SERVICE_MARKED_FOR_DELETE:
log_warning(L"The specified service has been marked for deletion.");
Lagging = true;
goto exit_loop;
default:
log_error(L"NotifyServiceStatusChange failed! (Return value=%lu)", e);
Unloading = true;
break;
log_error(L"NotifyServiceStatusChange failed! Error=%lu", Error);
goto exit_loop;
}
}
exit_loop:
CloseServiceHandle(hService);
close_scm:
CloseServiceHandle(hSCM);
} while ( Lagging );
set_event:
// signal event in case it is open in any other processes
SetEvent(hEvent);
destroy_list:
ptrlist_for_each_stdcall(&list, CloseHandle);
ptrlist_destroy(&list);
if ( Suspending )
NtSuspendProcess(NtCurrentProcess());
close_event:
CloseHandle(hUnloadEvent);
release_mutex:
ReleaseMutex(g_hMainMutex);
CloseHandle(g_hMainMutex);
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
void CALLBACK RUNDLL32_UnloadW(
@@ -153,7 +266,7 @@ void CALLBACK RUNDLL32_UnloadW(
{
HANDLE hEvent;
hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, m_szUnloadEventName);
hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent");
if ( hEvent ) {
SetEvent(hEvent);
CloseHandle(hEvent);

View File

@@ -1,209 +0,0 @@
#include "stdafx.h"
#include "servicehelper.h"
#include "registryhelper.h"
LPQUERY_SERVICE_CONFIGW svc_query_config_by_name_alloc(
SC_HANDLE hSCM,
const wchar_t *pServiceName,
LPDWORD pcbBufSize)
{
SC_HANDLE hService;
LPQUERY_SERVICE_CONFIGW result = NULL;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_CONFIG);
if ( !hService ) return result;
result = svc_query_config_alloc(hSCM, hService, pcbBufSize);
CloseServiceHandle(hService);
return result;
}
LPQUERY_SERVICE_CONFIGW svc_query_config_alloc(
SC_HANDLE hSCM,
SC_HANDLE hService,
LPDWORD pcbBufSize)
{
DWORD cbBytesNeeded;
LPQUERY_SERVICE_CONFIGW result = NULL;
if ( !QueryServiceConfigW(hService, NULL, 0, &cbBytesNeeded)
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
result = malloc(cbBytesNeeded);
if ( result ) {
if ( QueryServiceConfigW(hService, result, cbBytesNeeded, &cbBytesNeeded) ) {
if ( pcbBufSize )
*pcbBufSize = cbBytesNeeded;
} else {
free(result);
result = NULL;
}
}
}
return result;
}
bool svc_query_process_info_by_name(
SC_HANDLE hSCM,
const wchar_t *pServiceName,
LPSERVICE_STATUS_PROCESS pServiceStatus)
{
bool result = false;
SC_HANDLE hService;
DWORD cbBytesNeeded;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS);
if ( !hService )
return result;
result = !!QueryServiceStatusEx(hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)pServiceStatus,
sizeof *pServiceStatus,
&cbBytesNeeded);
CloseServiceHandle(hService);
return result;
}
bool svc_query_group_name(
const LPQUERY_SERVICE_CONFIGW pServiceConfig,
wchar_t **pGroupName,
HLOCAL *hMem)
{
bool result = false;
int NumArgs;
wchar_t **argv;
argv = CommandLineToArgvW(pServiceConfig->lpBinaryPathName, &NumArgs);
if ( argv ) {
if ( !_wcsicmp(PathFindFileNameW(argv[0]), L"svchost.exe") ) {
for ( int i = 1; (i + 1) < NumArgs; i++ ) {
if ( !_wcsicmp(argv[i], L"-k") ) {
*pGroupName = argv[++i];
*hMem = (HLOCAL)argv;
return true;
}
}
}
LocalFree((HLOCAL)argv);
}
return false;
}
DWORD svc_query_process_id(SC_HANDLE hSCM, SC_HANDLE hService)
{
DWORD result = 0;
SERVICE_STATUS_PROCESS ServiceStatus;
DWORD cbBytesNeeded;
if ( QueryServiceStatusEx(hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ServiceStatus,
sizeof ServiceStatus,
&cbBytesNeeded) ) {
result = ServiceStatus.dwProcessId;
}
return result;
}
DWORD svc_query_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName)
{
SERVICE_STATUS_PROCESS ServiceStatusProcess;
if ( svc_query_process_info_by_name(hSCM, pServiceName, &ServiceStatusProcess) )
return ServiceStatusProcess.dwProcessId;
return 0;
}
DWORD svc_heuristic_group_process_id(SC_HANDLE hSCM, const wchar_t *pGroupNameSearch)
{
wchar_t *pData;
DWORD result = 0;
DWORD dwProcessId;
DWORD cbBufSize;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
bool success = false;
wchar_t *pGroupName;
HLOCAL hMem;
pData = reg_get_value_alloc(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost",
pGroupNameSearch,
RRF_RT_REG_MULTI_SZ,
NULL,
NULL);
if ( !pData ) return result;
for ( wchar_t *pName = pData; *pName; pName += wcslen(pName) + 1 ) {
dwProcessId = svc_query_process_id_by_name(hSCM, pName);
if ( !dwProcessId ) continue;
pServiceConfig = svc_query_config_by_name_alloc(hSCM, pName, &cbBufSize);
if ( !pServiceConfig ) continue;
if ( pServiceConfig->dwServiceType == SERVICE_WIN32_SHARE_PROCESS
&& svc_query_group_name(pServiceConfig, &pGroupName, &hMem) ) {
success = !_wcsicmp(pGroupNameSearch, pGroupName);
LocalFree(hMem);
}
free(pServiceConfig);
if ( success ) {
result = dwProcessId;
break;
}
}
free(pData);
return result;
}
DWORD svc_heuristic_process_id(SC_HANDLE hSCM, SC_HANDLE hService)
{
DWORD result = 0;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
wchar_t *pGroupName;
HLOCAL hMem;
result = svc_query_process_id(hSCM, hService);
if ( result )
return result;
pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL);
if ( pServiceConfig ) {
switch ( pServiceConfig->dwServiceType ) {
case SERVICE_WIN32_OWN_PROCESS:
// if the service isn't already running there's no
// way to accurately guess the PID when it is set to
// run in its own process. returns 0
break;
case SERVICE_WIN32_SHARE_PROCESS:
// when the service is configured to run in a shared
// process, it is possible to "guess" which svchost.exe
// it will eventually be loaded into by finding other
// services in the same group that are already running.
if ( svc_query_group_name(pServiceConfig, &pGroupName, &hMem) ) {
result = svc_heuristic_group_process_id(hSCM, pGroupName);
LocalFree(hMem);
}
break;
}
free(pServiceConfig);
}
return result;
}
DWORD svc_heuristic_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName)
{
DWORD result = 0;
SC_HANDLE hService;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
result = svc_heuristic_process_id(hSCM, hService);
CloseServiceHandle(hService);
return result;
}

View File

@@ -1,23 +0,0 @@
#pragma once
LPQUERY_SERVICE_CONFIGW svc_query_config_by_name_alloc(
SC_HANDLE hSCM,
const wchar_t *pServiceName,
LPDWORD pcbBufSize);
LPQUERY_SERVICE_CONFIGW svc_query_config_alloc(
SC_HANDLE hSCM,
SC_HANDLE hService,
LPDWORD pcbBufSize);
bool svc_query_process_info_by_name(
SC_HANDLE hSCM,
const wchar_t *pServiceName,
LPSERVICE_STATUS_PROCESS pServiceStatus);
bool svc_query_group_name(
const LPQUERY_SERVICE_CONFIGW pServiceConfig,
wchar_t **pGroupName,
HLOCAL *hMem);
DWORD svc_query_process_id(SC_HANDLE hSCM, SC_HANDLE hService);
DWORD svc_query_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName);
DWORD svc_heuristic_group_process_id(SC_HANDLE hSCM, const wchar_t *pGroupName);
DWORD svc_heuristic_process_id(SC_HANDLE hSCM, SC_HANDLE hService);
DWORD svc_heuristic_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName);

View File

@@ -11,15 +11,12 @@
#include <phnt_windows.h>
#include <phnt.h>
// TODO: reference additional headers your program requires here
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <share.h>
#include <strsafe.h>
#include <shellapi.h>
@@ -27,6 +24,10 @@
#include <Psapi.h>
#include <TlHelp32.h>
#include "asprintf.h"
#include "logger.h"
extern IMAGE_DOS_HEADER __ImageBase;
#define PIMAGEBASE ((HMODULE)&__ImageBase)
#define OffsetToPointer(Base, Offset) ((void *)(((uint8_t *)(Base)) + ((ptrdiff_t)(Offset))))
#define PointerToOffset(Base, Pointer) ((ptrdiff_t)(((uint8_t *)(Pointer)) - ((uint8_t *)(Base))))

26
src/wufuc/utf8.c Normal file
View File

@@ -0,0 +1,26 @@
#include "stdafx.h"
#include "utf8.h"
DWORD UTF8WriteFile(HANDLE hFile, LPCWSTR lpWideCharStr)
{
int cchWideChar;
int size;
char *buffer;
DWORD NumberOfBytesWritten = 0;
cchWideChar = lstrlenW(lpWideCharStr);
size = WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL);
if ( !size )
return 0;
buffer = malloc(size);
if ( !buffer )
return 0;
if ( WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, cchWideChar, buffer, size, NULL, NULL) )
WriteFile(hFile, buffer, size, &NumberOfBytesWritten, NULL);
free(buffer);
return NumberOfBytesWritten;
}

3
src/wufuc/utf8.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
DWORD UTF8WriteFile(HANDLE hFile, LPCWSTR lpWideCharStr);

View File

@@ -1,33 +0,0 @@
#include "stdafx.h"
#include "versionhelper.h"
int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev)
{
if ( HIWORD(pffi->dwProductVersionMS) < wMajor ) return -1;
if ( HIWORD(pffi->dwProductVersionMS) > wMajor ) return 1;
if ( LOWORD(pffi->dwProductVersionMS) < wMinor ) return -1;
if ( LOWORD(pffi->dwProductVersionMS) > wMinor ) return 1;
if ( HIWORD(pffi->dwProductVersionLS) < wBuild ) return -1;
if ( HIWORD(pffi->dwProductVersionLS) > wBuild ) return 1;
if ( LOWORD(pffi->dwProductVersionLS) < wRev ) return -1;
if ( LOWORD(pffi->dwProductVersionLS) > wRev ) return 1;
return 0;
}
bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
DWORDLONG dwlConditionMask = 0;
OSVERSIONINFOEXW osvi = { sizeof osvi };
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(&osvi,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
dwlConditionMask) != FALSE;
}

View File

@@ -1,4 +0,0 @@
#pragma once
int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);

130
src/wufuc/versioninfo.c Normal file
View File

@@ -0,0 +1,130 @@
#include "stdafx.h"
#include "versioninfo.h"
DWORD GetModuleVersionInfo(HMODULE hModule, LPVOID *lplpData)
{
HRSRC hResInfo;
DWORD result;
HGLOBAL hResData;
LPVOID pRes;
LPVOID lpData;
hResInfo = FindResourceW(hModule,
MAKEINTRESOURCEW(VS_VERSION_INFO),
MAKEINTRESOURCEW(RT_VERSION));
if ( !hResInfo ) return 0;
result = SizeofResource(hModule, hResInfo);
if ( !result ) return 0;
hResData = LoadResource(hModule, hResInfo);
if ( !hResData ) return 0;
pRes = LockResource(hResData);
if ( !pRes ) return 0;
lpData = malloc(result);
if ( !lpData ) return 0;
if ( !memcpy_s(lpData, result, pRes, result) ) {
*lplpData = lpData;
} else {
free(lpData);
return 0;
}
return result;
}
DWORD GetFileVersionInfoExAlloc(DWORD dwFlags, BOOL bPrefetched, LPCWSTR lpwstrFilename, LPVOID *lplpData)
{
DWORD result;
DWORD dwHandle;
LPVOID lpData;
result = GetFileVersionInfoSizeExW(dwFlags,
lpwstrFilename,
&dwHandle);
if ( !result ) return 0;
lpData = malloc(result);
if ( !lpData ) return 0;
if ( GetFileVersionInfoExW(bPrefetched ? (dwFlags | FILE_VER_GET_PREFETCHED) : dwFlags,
lpwstrFilename,
dwHandle,
result,
lpData) ) {
*lplpData = lpData;
} else {
free(lpData);
return 0;
}
return result;
}
UINT VerQueryString(LPCVOID pBlock, LANGANDCODEPAGE LangCodePage, LPCWSTR lpName, LPWSTR *lplpString)
{
LPWSTR pszSubBlock;
LPVOID lpBuffer;
UINT result = 0;
if ( aswprintf(&pszSubBlock,
L"\\StringFileInfo\\%04x%04x\\%ls",
LangCodePage.wLanguage,
LangCodePage.wCodePage,
lpName) == -1 )
return 0;
if ( VerQueryValueW(pBlock, pszSubBlock, &lpBuffer, &result) )
*lplpString = (LPWSTR)lpBuffer;
free(pszSubBlock);
return result;
}
UINT VerQueryTranslations(LPCVOID pBlock, PLANGANDCODEPAGE *lplpTranslate)
{
PLANGANDCODEPAGE lpTranslate;
UINT uLen;
if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", &(LPVOID)lpTranslate, &uLen) ) {
*lplpTranslate = lpTranslate;
return uLen / (sizeof *lpTranslate);
}
return 0;
}
UINT VerQueryFileInfo(LPCVOID pBlock, VS_FIXEDFILEINFO **lplpffi)
{
VS_FIXEDFILEINFO *lpffi;
UINT result;
if ( VerQueryValueW(pBlock, L"\\", &(LPVOID)lpffi, &result) ) {
*lplpffi = lpffi;
return result;
}
return 0;
}
int vercmp(DWORD dwMS, DWORD dwLS, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev)
{
WORD w;
w = HIWORD(dwMS);
if ( w < wMajor ) return -1;
if ( w > wMajor ) return 1;
w = LOWORD(dwMS);
if ( w < wMinor ) return -1;
if ( w > wMinor ) return 1;
w = HIWORD(dwLS);
if ( w < wBuild ) return -1;
if ( w > wBuild ) return 1;
w = LOWORD(dwLS);
if ( w < wRev ) return -1;
if ( w > wRev ) return 1;
return 0;
}

19
src/wufuc/versioninfo.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
typedef struct
{
WORD wLanguage;
WORD wCodePage;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
DWORD GetModuleVersionInfo(HMODULE hModule, LPVOID *lplpData);
DWORD GetFileVersionInfoExAlloc(DWORD dwFlags, BOOL bPrefetched, LPCWSTR lpwstrFilename, LPVOID *lplpData);
UINT VerQueryString(LPCVOID pBlock, LANGANDCODEPAGE LangCodePage, LPCWSTR lpName, LPWSTR *lplpString);
UINT VerQueryTranslations(LPCVOID pBlock, PLANGANDCODEPAGE *lplpTranslate);
UINT VerQueryFileInfo(LPCVOID pBlock, VS_FIXEDFILEINFO **lplpffi);
int vercmp(DWORD dwMS, DWORD dwLS, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);

View File

@@ -1,222 +0,0 @@
#include "stdafx.h"
#include "ptrlist.h"
#include "wufuc.h"
#include "hooks.h"
#include "log.h"
#include "modulehelper.h"
#include "mutexhelper.h"
#include "patternfind.h"
#include "resourcehelper.h"
#include "versionhelper.h"
#include <minhook.h>
HANDLE g_hMainMutex;
static bool close_remote_handle(HANDLE hProcess, HANDLE hObject)
{
bool result = false;
DWORD ExitCode;
HANDLE hThread;
hThread = CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)CloseHandle,
(LPVOID)hObject,
0,
NULL);
if ( hThread ) {
if ( WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0
&& GetExitCodeThread(hThread, &ExitCode) ) {
result = !!ExitCode;
}
CloseHandle(hThread);
}
return result;
}
bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pStartAddress,
ptrlist_t *list)
{
bool result = false;
HANDLE hCrashMutex;
HANDLE hProcess;
HANDLE h;
HANDLE hProceedEvent;
HANDLE p[4];
hCrashMutex = mutex_create_new_fmt(false, L"Global\\wufuc_CrashMutex*%08x", dwProcessId);
if ( !hCrashMutex ) return result;
if ( !ptrlist_add(list, hCrashMutex, dwProcessId) )
goto close_mutex;
hProceedEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if ( !hProceedEvent ) goto close_mutex;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if ( !hProcess ) goto close_pevent;
h = GetCurrentProcess();
if ( !DuplicateHandle(h, g_hMainMutex, hProcess, &p[0], SYNCHRONIZE, FALSE, 0) )
goto close_process;
if ( !DuplicateHandle(h, ptrlist_at(list, 0, NULL), hProcess, &p[1], SYNCHRONIZE, FALSE, 0) )
goto close_p0;
if ( !DuplicateHandle(h, hCrashMutex, hProcess, &p[2], 0, FALSE, DUPLICATE_SAME_ACCESS) )
goto close_p1;
if ( !DuplicateHandle(h, hProceedEvent, hProcess, &p[3], EVENT_MODIFY_STATE, FALSE, 0) )
goto close_p2;
result = mod_inject_and_begin_thread(hProcess, PIMAGEBASE, pStartAddress, p, sizeof p);
if ( result ) {
// wait for injected thread to signal that it has taken
// ownership of hCrashMutex before proceeding.
result = WaitForSingleObject(hProceedEvent, 5000) != WAIT_TIMEOUT;
} else {
close_remote_handle(hProcess, p[3]);
close_p2:
close_remote_handle(hProcess, p[2]);
close_p1:
close_remote_handle(hProcess, p[1]);
close_p0:
close_remote_handle(hProcess, p[0]);
}
close_process:
CloseHandle(hProcess);
close_pevent:
CloseHandle(hProceedEvent);
if ( !result ) {
close_mutex:
ptrlist_remove(list, hCrashMutex);
CloseHandle(hCrashMutex);
}
if ( result )
log_info(L"Successfully injected into process! (ProcessId=%lu)", dwProcessId);
else
log_warning(L"Failed to inject into process! (ProcessId=%lu)", dwProcessId);
return result;
}
static bool wufuc_get_patch_info(VS_FIXEDFILEINFO *pffi, PATCHINFO *ppi)
{
#ifdef _WIN64
if ( ver_verify_version_info(6, 1, 1) && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1
|| ver_verify_version_info(6, 3, 0) && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1 ) {
ppi->pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
ppi->off1 = 0xa;
ppi->off2 = 0x12;
return true;
}
#elif _WIN32
if ( ver_verify_version_info(6, 1, 1)
&& ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1 ) {
ppi->pattern = "833D????????00 743E E8???????? A3????????";
ppi->off1 = 0x2;
ppi->off2 = 0xf;
return true;
} else if ( ver_verify_version_info(6, 3, 0)
&& ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1 ) {
ppi->pattern = "8BFF 51 833D????????00 7507 A1????????";
ppi->off1 = 0x5;
ppi->off2 = 0xd;
return true;
}
#endif
return false;
}
static bool wufuc_get_patch_ptrs(const PATCHINFO *ppi, uintptr_t pfn, PBOOL *ppval1, PBOOL *ppval2)
{
#ifdef _WIN64
*ppval1 = (PBOOL)(pfn + ppi->off1 + sizeof(uint32_t) + *(uint32_t *)(pfn + ppi->off1));
*ppval2 = (PBOOL)(pfn + ppi->off2 + sizeof(uint32_t) + *(uint32_t *)(pfn + ppi->off2));
return true;
#elif _WIN32
*ppval1 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off1));
*ppval2 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off2));
return true;
#else
return false;
#endif
}
void wufuc_patch(HMODULE hModule)
{
void *pBlock;
PATCHINFO pi;
size_t count;
PLANGANDCODEPAGE plcp;
wchar_t *pInternalName;
VS_FIXEDFILEINFO *pffi;
MODULEINFO modinfo;
size_t offset;
void *pfn;
DWORD fOldProtect;
PBOOL pval1;
PBOOL pval2;
pBlock = res_get_version_info(hModule);
if ( !pBlock ) return;
plcp = res_query_var_file_info(pBlock, &count);
if ( !plcp ) goto free_pBlock;
for ( size_t i = 0; i < count; i++ ) {
pInternalName = res_query_string_file_info(pBlock, plcp[i], L"InternalName", NULL);
if ( pInternalName && !_wcsicmp(pInternalName, L"wuaueng.dll") )
goto cont_patch;
}
goto free_pBlock;
cont_patch:
pffi = res_query_fixed_file_info(pBlock);
if ( !pffi ) goto free_pBlock;
if ( !wufuc_get_patch_info(pffi, &pi) ) {
log_warning(L"Unsupported Windows Update Agent version: %hu.%hu.%hu.%hu",
HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS));
goto free_pBlock;
}
log_info(L"Supported Windows Update Agent version: %hu.%hu.%hu.%hu",
HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS));
if ( !GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof modinfo) ) {
log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)", hModule, GetLastError());
goto free_pBlock;
}
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, pi.pattern);
if ( offset == -1 ) {
log_info(L"Couldn't match IsDeviceServiceable function!");
goto free_pBlock;
}
pfn = OffsetToPointer(modinfo.lpBaseOfDll, offset);
log_info(L"Matched %ls!IsDeviceServiceable function! (Offset=%IX, Address=%p)",
PathFindFileNameW(g_pszWUServiceDll), offset, pfn);
if ( wufuc_get_patch_ptrs(&pi, (uintptr_t)pfn, &pval1, &pval2) ) {
if ( *pval1 && VirtualProtect(pval1, sizeof *pval1, PAGE_READWRITE, &fOldProtect) ) {
*pval1 = FALSE;
VirtualProtect(pval1, sizeof *pval1, fOldProtect, &fOldProtect);
log_info(L"Patched variable! (Address=%p)", pval1);
}
if ( !*pval2 && VirtualProtect(pval2, sizeof *pval2, PAGE_READWRITE, &fOldProtect) ) {
*pval2 = TRUE;
VirtualProtect(pval2, sizeof *pval2, fOldProtect, &fOldProtect);
log_info(L"Patched variable! (Address=%p)", pval2);
}
}
free_pBlock:
free(pBlock);
}

View File

@@ -1,16 +0,0 @@
#pragma once
typedef struct _PATCHINFO
{
const char *pattern;
size_t off1;
size_t off2;
} PATCHINFO;
#define SVCHOST_CRASH_THRESHOLD 3
extern HANDLE g_hMainMutex;
bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pStartAddress,
ptrlist_t *list);
void wufuc_patch(HMODULE hModule);

View File

@@ -19,36 +19,27 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="callbacks.h" />
<ClInclude Include="eventhelper.h" />
<ClInclude Include="mutexhelper.h" />
<ClInclude Include="ptrlist.h" />
<ClInclude Include="log.h" />
<ClInclude Include="modulehelper.h" />
<ClInclude Include="registryhelper.h" />
<ClInclude Include="resourcehelper.h" />
<ClInclude Include="servicehelper.h" />
<ClInclude Include="versionhelper.h" />
<ClInclude Include="hooks.h" />
<ClInclude Include="asprintf.h" />
<ClInclude Include="logger.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="modules.h" />
<ClInclude Include="registry.h" />
<ClInclude Include="helpers.h" />
<ClInclude Include="utf8.h" />
<ClInclude Include="versioninfo.h" />
<ClInclude Include="verify.h" />
<ClInclude Include="patternfind.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="wufuc.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="callbacks.c" />
<ClCompile Include="asprintf.c" />
<ClCompile Include="dllmain.c" />
<ClCompile Include="eventhelper.c" />
<ClCompile Include="ptrlist.c" />
<ClCompile Include="modulehelper.c" />
<ClCompile Include="registryhelper.c" />
<ClCompile Include="resourcehelper.c" />
<ClCompile Include="servicehelper.c" />
<ClCompile Include="mutexhelper.c" />
<ClCompile Include="versionhelper.c" />
<ClCompile Include="hooks.c" />
<ClCompile Include="log.c" />
<ClCompile Include="logger.c" />
<ClCompile Include="memory.c" />
<ClCompile Include="modules.c" />
<ClCompile Include="patternfind.c" />
<ClCompile Include="registry.c" />
<ClCompile Include="stdafx.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
@@ -56,7 +47,9 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="rundll32.c" />
<ClCompile Include="wufuc.c" />
<ClCompile Include="helpers.c" />
<ClCompile Include="utf8.c" />
<ClCompile Include="versioninfo.c" />
</ItemGroup>
<ItemGroup>
<None Include="exports.def" />
@@ -125,8 +118,8 @@
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
@@ -134,8 +127,8 @@
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -143,8 +136,8 @@
<IntDir>$(ProjectDir)obj\$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
@@ -152,8 +145,8 @@
<IntDir>$(ProjectDir)obj\$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -172,11 +165,9 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol>
</EntryPointSymbol>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x86.MTd.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -195,11 +186,9 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol>
</EntryPointSymbol>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x64.MTd.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -226,15 +215,13 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol>
</EntryPointSymbol>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x86.MT.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<SetChecksum>true</SetChecksum>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy release binaries to the setup staging directories</Message>
@@ -263,15 +250,13 @@ copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x64.MT.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<SetChecksum>true</SetChecksum>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy release binaries to the setup staging directories</Message>

View File

@@ -15,12 +15,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="callbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -30,47 +24,38 @@
<ClInclude Include="patternfind.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="versionhelper.h">
<ClInclude Include="asprintf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="servicehelper.h">
<ClInclude Include="versioninfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="registryhelper.h">
<ClInclude Include="verify.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wufuc.h">
<ClInclude Include="registry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="modulehelper.h">
<ClInclude Include="modules.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="log.h">
<ClInclude Include="logger.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ptrlist.h">
<ClInclude Include="utf8.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="eventhelper.h">
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mutexhelper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resourcehelper.h">
<ClInclude Include="helpers.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="callbacks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hooks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rundll32.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -80,34 +65,28 @@
<ClCompile Include="patternfind.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="servicehelper.c">
<ClCompile Include="asprintf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="versionhelper.c">
<ClCompile Include="versioninfo.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="registryhelper.c">
<ClCompile Include="modules.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wufuc.c">
<ClCompile Include="registry.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="log.c">
<ClCompile Include="logger.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="modulehelper.c">
<ClCompile Include="utf8.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ptrlist.c">
<ClCompile Include="memory.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mutexhelper.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="eventhelper.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="resourcehelper.c">
<ClCompile Include="helpers.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -116,7 +95,7 @@
<Filter>Source Files</Filter>
</None>
<None Include="resource.h">
<Filter>Header Files</Filter>
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>