├── .gitignore
├── .github
├── FUNDING.yml
└── workflows
│ └── autobuild-workflow.yaml
├── FlashPatch
├── icon.ico
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── App.xaml.cs
├── app.manifest
├── App.xaml
├── PatchWindow.xaml
├── PatchWindow.xaml.cs
├── UpdateChecker.cs
├── HexPatch.cs
├── PatchableBinary.cs
├── WinAPI.cs
├── FlashPatch.csproj
└── Patcher.cs
├── LICENSE
├── FlashPatch.sln
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs
2 | bin
3 | obj
4 |
5 | *.exe
6 | *.obj
7 | *.pdb
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: darktohka
2 | liberapay: darktohka
3 | ko_fi: disyer
4 |
--------------------------------------------------------------------------------
/FlashPatch/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darktohka/FlashPatch/HEAD/FlashPatch/icon.ico
--------------------------------------------------------------------------------
/FlashPatch/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/FlashPatch/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/FlashPatch/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Windows;
3 |
4 | namespace FlashPatch {
5 | public partial class App : Application {
6 |
7 | private void Application_Startup(object sender, StartupEventArgs e) {
8 | ServicePointManager.Expect100Continue = true;
9 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/FlashPatch/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 darktohka
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/FlashPatch/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace FlashPatch.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.github/workflows/autobuild-workflow.yaml:
--------------------------------------------------------------------------------
1 | name: Build FlashPatch
2 |
3 | on: [push, repository_dispatch, workflow_dispatch]
4 |
5 | jobs:
6 | build:
7 | runs-on: windows-2019
8 | steps:
9 | - name: Checkout repository
10 | uses: actions/checkout@v4
11 | - name: Setup Visual Studio
12 | uses: ilammy/msvc-dev-cmd@v1
13 | - name: Build executable
14 | shell: powershell
15 | working-directory: FlashPatch
16 | run: >
17 | msbuild /p:Configuration=Release /p:Platform="Any CPU" /p:OutputPath=bin FlashPatch.csproj
18 | - name: Import certificate
19 | shell: bash
20 | working-directory: FlashPatch/bin
21 | run: >
22 | echo ${{ secrets.SIGN_WIN_CERT }} | base64 --decode > cert.pfx
23 | - name: Sign executable
24 | shell: powershell
25 | working-directory: FlashPatch/bin
26 | run: >
27 | signtool sign /a /tr "${{ secrets.SIGN_WIN_TIMESTAMP }}" /td sha256 /fd sha256 /f cert.pfx FlashPatch.exe
28 | - name: Remove certificate
29 | shell: bash
30 | working-directory: FlashPatch/bin
31 | run: >
32 | rm cert.pfx
33 | - uses: actions/upload-artifact@v4
34 | with:
35 | name: FlashPatch
36 | path: FlashPatch/bin/FlashPatch.exe
37 |
--------------------------------------------------------------------------------
/FlashPatch.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.32602.291
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlashPatch", "FlashPatch\FlashPatch.csproj", "{3634FB53-38E0-4D55-B5D1-5F415C44A66D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x86 = Debug|x86
12 | Release|Any CPU = Release|Any CPU
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Debug|Any CPU.ActiveCfg = Release|Any CPU
17 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Debug|Any CPU.Build.0 = Release|Any CPU
18 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Debug|x86.ActiveCfg = Debug|x86
19 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Debug|x86.Build.0 = Debug|x86
20 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Release|x86.ActiveCfg = Release|x86
23 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}.Release|x86.Build.0 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {D948C739-0087-4EBC-9496-2062C0AC7CB3}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/FlashPatch/App.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
29 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/FlashPatch/PatchWindow.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Play Adobe Flash Player games in the browser after January 12th, 2021.
19 |
20 | Now supports Chinese Flash!
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | by darktohka - GitHub
29 |
30 |
31 | Patch File...
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/FlashPatch/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("FlashPatch")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("FlashPatch")]
15 | [assembly: AssemblyCopyright("Copyright © darktohka 2022")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/FlashPatch/PatchWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Diagnostics;
4 | using Microsoft.Win32;
5 | using System.Threading.Tasks;
6 |
7 | namespace FlashPatch {
8 | public partial class PatchWindow : Window {
9 |
10 | public PatchWindow() {
11 | InitializeComponent();
12 | }
13 |
14 | private void Window_Loaded(object sender, RoutedEventArgs e) {
15 | versionLabel.Content = UpdateChecker.GetCurrentVersion();
16 | StartUpdateChecker();
17 | }
18 |
19 | private void PatchButton_Click(object sender, RoutedEventArgs e) {
20 | Patcher.PatchAll();
21 | }
22 |
23 | private void RestoreButton_Click(object sender, RoutedEventArgs e) {
24 | Patcher.RestoreAll();
25 | }
26 |
27 | private void GithubButton_Click(object sender, RoutedEventArgs e) {
28 | Process.Start("https://github.com/darktohka/FlashPatch");
29 | }
30 |
31 | private void PatchFileButton_Click(object sender, RoutedEventArgs e) {
32 | IntPtr redirection = Patcher.DisableRedirection();
33 |
34 | OpenFileDialog dialog = new OpenFileDialog();
35 | dialog.Title = "Select Flash Player binaries to patch!";
36 | dialog.Multiselect = true;
37 | dialog.ShowDialog();
38 |
39 | string[] paths = dialog.FileNames;
40 |
41 | if (paths.Length != 0) {
42 | Patcher.PatchFiles(paths);
43 | }
44 |
45 | Patcher.EnableRedirection(redirection);
46 | }
47 |
48 | private void StartUpdateChecker() {
49 | #if !DEBUG
50 | Task.Run(UpdateChecker.GetLatestVersion).ContinueWith(result => {
51 | Version version = result.Result;
52 |
53 | if (version == null) {
54 | // We couldn't find the latest version.
55 | return;
56 | }
57 |
58 | if (version.GetVersion().Equals(UpdateChecker.GetCurrentVersion())) {
59 | // We're running the latest version!
60 | return;
61 | }
62 |
63 | string caption = "A new update is available for FlashPatch!\n\n" + version.GetName() + "\n\nWould you like to update now?";
64 |
65 | if (MessageBox.Show(caption, "FlashPatch!", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {
66 | Process.Start(version.GetUrl());
67 | }
68 | });
69 | }
70 | #endif
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/FlashPatch/UpdateChecker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 | using System.Net;
5 | using System.Runtime.Serialization.Json;
6 | using System.Xml;
7 | using System.Xml.Linq;
8 |
9 | namespace FlashPatch {
10 | public class Version {
11 | private string name;
12 | private string version;
13 | private string url;
14 |
15 | public Version(string name, string version, string url) {
16 | this.name = name;
17 | this.version = version;
18 | this.url = url;
19 | }
20 |
21 | public string GetName() {
22 | return name;
23 | }
24 |
25 | public string GetVersion() {
26 | return version;
27 | }
28 |
29 | public string GetUrl() {
30 | return url;
31 | }
32 | }
33 |
34 | public class UpdateChecker {
35 | private static readonly string VERSION = "v1.30";
36 | private static readonly string AUTHOR = "darktohka";
37 | private static readonly string REPO = "FlashPatch";
38 | private static readonly string USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36";
39 |
40 | public static string GetAPILink() {
41 | return "https://api.github.com/repos/" + AUTHOR + "/" + REPO + "/releases/latest";
42 | }
43 |
44 | public static string GetCurrentVersion() {
45 | return VERSION;
46 | }
47 |
48 | private static Version GetLatestVersionUnsafe() {
49 | using (WebClient client = new WebClient()) {
50 | client.Headers.Add("user-agent", USER_AGENT);
51 |
52 | string release = client.DownloadString(GetAPILink());
53 | XmlDictionaryReader jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(release), new XmlDictionaryReaderQuotas());
54 | XElement root = XElement.Load(jsonReader);
55 |
56 | string name = root.Descendants("name").FirstOrDefault().Value;
57 | string tag = root.Descendants("tag_name").FirstOrDefault().Value;
58 | string url = root.Descendants("html_url").FirstOrDefault().Value;
59 |
60 | if (!url.StartsWith("https://")) {
61 | // This is a suspicious URL... We shouldn't trust it.
62 | return null;
63 | }
64 |
65 | return new Version(name, tag, url);
66 | }
67 | }
68 |
69 | public static Version GetLatestVersion() {
70 | try {
71 | return GetLatestVersionUnsafe();
72 | } catch (Exception e) {
73 | Console.WriteLine(e);
74 | return null;
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/FlashPatch/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace FlashPatch.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FlashPatch.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/FlashPatch/HexPatch.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Linq;
3 |
4 | namespace FlashPatch {
5 | public class HexPatch {
6 |
7 | private int offset;
8 | private byte[] originalBytes;
9 | private byte[] patchedBytes;
10 |
11 | private int offsetFound = -1;
12 |
13 | public HexPatch(int offset, byte[] originalBytes, byte[] patchedBytes) {
14 | this.offset = offset;
15 | this.originalBytes = originalBytes;
16 | this.patchedBytes = patchedBytes;
17 | }
18 |
19 | public int GetOffset() {
20 | return offset;
21 | }
22 |
23 | public bool HasOffset() {
24 | return offset != -1;
25 | }
26 |
27 | public int GetFinalOffset() {
28 | return HasOffset() ? offset : offsetFound;
29 | }
30 |
31 | public byte[] GetOriginalBytes() {
32 | return originalBytes;
33 | }
34 |
35 | public byte[] GetPatchedBytes() {
36 | return patchedBytes;
37 | }
38 |
39 | public int GetLength() {
40 | return originalBytes.Length;
41 | }
42 |
43 | private int FindBytes(FileStream fileStream, byte[] bytes) {
44 | fileStream.Position = 0;
45 | int bufferSize = 65536;
46 | byte[] buffer = new byte[bufferSize];
47 |
48 | int len = bytes.Length;
49 | int totalBytes = 0;
50 | int bytesRead, k;
51 |
52 | while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
53 | int limit = bytesRead - len;
54 |
55 | for (int i = 0; i <= limit; ++i) {
56 | for (k = 0; k < len; k++) {
57 | if (bytes[k] != buffer[i + k]) {
58 | break;
59 | }
60 | }
61 |
62 | if (k == len) {
63 | return totalBytes + i;
64 | }
65 | }
66 |
67 | totalBytes += bytesRead;
68 | }
69 |
70 | return -1;
71 | }
72 |
73 | private byte[] ReadBytes(FileStream fileStream) {
74 | fileStream.Position = GetFinalOffset();
75 |
76 | int length = GetLength();
77 | byte[] readBytes = new byte[length];
78 |
79 | fileStream.Read(readBytes, 0, length);
80 | return readBytes;
81 | }
82 |
83 | public bool IsPatchable(byte[] readBytes) {
84 | return Enumerable.SequenceEqual(readBytes, originalBytes);
85 | }
86 |
87 | public bool IsPatched(byte[] readBytes) {
88 | return Enumerable.SequenceEqual(readBytes, patchedBytes);
89 | }
90 |
91 | public bool IsPatchable(FileStream fileStream) {
92 | if (!HasOffset()) {
93 | offsetFound = FindBytes(fileStream, originalBytes);
94 | return offsetFound != -1;
95 | }
96 |
97 | return IsPatchable(ReadBytes(fileStream));
98 | }
99 |
100 | public bool IsPatched(FileStream fileStream) {
101 | if (!HasOffset()) {
102 | return FindBytes(fileStream, patchedBytes) != -1;
103 | }
104 |
105 | return IsPatched(ReadBytes(fileStream));
106 | }
107 |
108 | public void PatchFile(FileStream fileStream) {
109 | fileStream.Position = GetFinalOffset();
110 | fileStream.Write(patchedBytes, 0, GetLength());
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/FlashPatch/PatchableBinary.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace FlashPatch {
5 | public class PatchableBinary {
6 |
7 | private string name;
8 | private string version;
9 | private bool x64;
10 | private long fileSize;
11 | private List filenames;
12 | private List patches;
13 | private List alternatePaths;
14 |
15 | public PatchableBinary(string name, string version, bool x64, long fileSize, List filenames, List patches, List alternatePaths) {
16 | this.name = name;
17 | this.version = version;
18 | this.x64 = x64;
19 | this.fileSize = fileSize;
20 | this.filenames = filenames;
21 | this.patches = patches;
22 | this.alternatePaths = alternatePaths;
23 | }
24 |
25 | public PatchableBinary(string name, string version, bool x64, long fileSize, List patches) :
26 | this(name, version, x64, fileSize, null, patches, new List()) {
27 | // Empty.
28 | }
29 |
30 | public PatchableBinary(string name, string version, bool x64, long fileSize, List filenames, List patches) :
31 | this(name, version, x64, fileSize, filenames, patches, new List()) {
32 | // Empty.
33 | }
34 |
35 | public PatchableBinary(string name, string filename, string version, bool x64, long fileSize, List patches, List alternatePaths) :
36 | this(name, version, x64, fileSize, new List() { filename }, patches, alternatePaths) {
37 | // Empty.
38 | }
39 |
40 | public PatchableBinary(string name, string filename, string version, bool x64, long fileSize, List patches) :
41 | this(name, version, x64, fileSize, new List() { filename }, patches, new List()) {
42 | // Empty.
43 | }
44 |
45 | public string GetName() {
46 | return name;
47 | }
48 |
49 | public List GetFilenames() {
50 | return filenames;
51 | }
52 |
53 | public bool HasFilenames() {
54 | return filenames != null;
55 | }
56 |
57 | public string GetVersion() {
58 | return version;
59 | }
60 |
61 | public bool HasVersion() {
62 | return !string.IsNullOrWhiteSpace(version);
63 | }
64 |
65 | public bool IsX64() {
66 | return x64;
67 | }
68 |
69 | public long GetFileSize() {
70 | return fileSize;
71 | }
72 |
73 | public bool HasFileSize() {
74 | return fileSize >= 0;
75 | }
76 |
77 | public List GetPatches() {
78 | return patches;
79 | }
80 |
81 | public List GetAlternatePaths() {
82 | return alternatePaths;
83 | }
84 |
85 | public string GetBackupFileName(string filename) {
86 | return string.Format("{0}.bak_{1}", filename, x64 ? "x64" : "x86");
87 | }
88 |
89 | public bool IsPatchable(FileStream file) {
90 | foreach (HexPatch patch in patches) {
91 | if (patch.IsPatchable(file)) {
92 | return true;
93 | }
94 | }
95 |
96 | return false;
97 | }
98 |
99 | public bool IsPatched(FileStream file) {
100 | foreach (HexPatch patch in patches) {
101 | if (patch.IsPatched(file)) {
102 | return true;
103 | }
104 | }
105 |
106 | return false;
107 | }
108 |
109 | public void PatchFile(FileStream file) {
110 | foreach (HexPatch patch in patches) {
111 | if (patch.IsPatchable(file)) {
112 | patch.PatchFile(file);
113 | }
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/FlashPatch/WinAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Principal;
5 |
6 | namespace FlashPatch {
7 | public class WinAPI {
8 |
9 | public static bool ModifyPrivilege(PrivilegeName privilege, bool enable) {
10 | LUID luid;
11 |
12 | if (!LookupPrivilegeValue(null, privilege.ToString(), out luid)) {
13 | throw new Win32Exception();
14 | }
15 |
16 | using (var identity = WindowsIdentity.GetCurrent(TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query)) {
17 | var newPriv = new TOKEN_PRIVILEGES();
18 | newPriv.Privileges = new LUID_AND_ATTRIBUTES[1];
19 | newPriv.PrivilegeCount = 1;
20 | newPriv.Privileges[0].Luid = luid;
21 | newPriv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
22 |
23 | var prevPriv = new TOKEN_PRIVILEGES();
24 | prevPriv.Privileges = new LUID_AND_ATTRIBUTES[1];
25 | prevPriv.PrivilegeCount = 1;
26 | uint returnedBytes;
27 |
28 | if (!AdjustTokenPrivileges(identity.Token, false, ref newPriv, (uint)Marshal.SizeOf(prevPriv), ref prevPriv, out returnedBytes)) {
29 | throw new Win32Exception();
30 | }
31 |
32 | return prevPriv.PrivilegeCount == 0 ? enable /* didn't make a change */ : ((prevPriv.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) != 0);
33 | }
34 | }
35 |
36 | const uint SE_PRIVILEGE_ENABLED = 2;
37 |
38 | [DllImport("advapi32.dll", SetLastError = true)]
39 | [return: MarshalAs(UnmanagedType.Bool)]
40 | static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState,
41 | UInt32 BufferLengthInBytes, ref TOKEN_PRIVILEGES PreviousState, out UInt32 ReturnLengthInBytes);
42 |
43 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
44 | [return: MarshalAs(UnmanagedType.Bool)]
45 | static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
46 |
47 | struct TOKEN_PRIVILEGES {
48 | public UInt32 PrivilegeCount;
49 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1 /*ANYSIZE_ARRAY*/)]
50 | public LUID_AND_ATTRIBUTES[] Privileges;
51 | }
52 |
53 | [StructLayout(LayoutKind.Sequential)]
54 | struct LUID_AND_ATTRIBUTES {
55 | public LUID Luid;
56 | public UInt32 Attributes;
57 | }
58 |
59 | [StructLayout(LayoutKind.Sequential)]
60 | struct LUID {
61 | public uint LowPart;
62 | public int HighPart;
63 | }
64 | }
65 |
66 | public enum PrivilegeName {
67 | SeAssignPrimaryTokenPrivilege,
68 | SeAuditPrivilege,
69 | SeBackupPrivilege,
70 | SeChangeNotifyPrivilege,
71 | SeCreateGlobalPrivilege,
72 | SeCreatePagefilePrivilege,
73 | SeCreatePermanentPrivilege,
74 | SeCreateSymbolicLinkPrivilege,
75 | SeCreateTokenPrivilege,
76 | SeDebugPrivilege,
77 | SeEnableDelegationPrivilege,
78 | SeImpersonatePrivilege,
79 | SeIncreaseBasePriorityPrivilege,
80 | SeIncreaseQuotaPrivilege,
81 | SeIncreaseWorkingSetPrivilege,
82 | SeLoadDriverPrivilege,
83 | SeLockMemoryPrivilege,
84 | SeMachineAccountPrivilege,
85 | SeManageVolumePrivilege,
86 | SeProfileSingleProcessPrivilege,
87 | SeRelabelPrivilege,
88 | SeRemoteShutdownPrivilege,
89 | SeRestorePrivilege,
90 | SeSecurityPrivilege,
91 | SeShutdownPrivilege,
92 | SeSyncAgentPrivilege,
93 | SeSystemEnvironmentPrivilege,
94 | SeSystemProfilePrivilege,
95 | SeSystemtimePrivilege,
96 | SeTakeOwnershipPrivilege,
97 | SeTcbPrivilege,
98 | SeTimeZonePrivilege,
99 | SeTrustedCredManAccessPrivilege,
100 | SeUndockPrivilege,
101 | SeUnsolicitedInputPrivilege,
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/FlashPatch/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/FlashPatch/FlashPatch.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {3634FB53-38E0-4D55-B5D1-5F415C44A66D}
8 | WinExe
9 | FlashPatch
10 | FlashPatch
11 | v4.5
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 |
20 | AnyCPU
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 | false
29 |
30 |
31 | AnyCPU
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 | false
39 |
40 |
41 | icon.ico
42 |
43 |
44 | app.manifest
45 |
46 |
47 | true
48 | bin\x86\Debug\
49 | DEBUG;TRACE
50 | full
51 | x86
52 | 7.3
53 | prompt
54 |
55 |
56 | bin\x86\Release\
57 | TRACE
58 | true
59 | pdbonly
60 | x86
61 | 7.3
62 | prompt
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | 4.0
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | MSBuild:Compile
84 | Designer
85 |
86 |
87 |
88 |
89 | MSBuild:Compile
90 | Designer
91 |
92 |
93 | App.xaml
94 | Code
95 |
96 |
97 |
98 | PatchWindow.xaml
99 | Code
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | Code
108 |
109 |
110 | True
111 | True
112 | Resources.resx
113 |
114 |
115 | True
116 | Settings.settings
117 | True
118 |
119 |
120 | ResXFileCodeGenerator
121 | Resources.Designer.cs
122 |
123 |
124 |
125 | SettingsSingleFileGenerator
126 | Settings.Designer.cs
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | False
138 | .NET Framework 3.5 SP1
139 | false
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FlashPatch!
2 |
3 | [](https://ko-fi.com/disyer) [](https://github.com/darktohka/FlashPatch/blob/master/LICENSE)
4 |
5 | 
6 |
7 | [Download latest version](https://github.com/darktohka/FlashPatch/releases/latest)
8 |
9 | **[Check out Clean Flash Player, the brand new distribution of Flash Player that keeps Flash Player alive in the browser!](https://gitlab.com/CleanFlash/installer) Clean Flash is built using the proven FlashPatch utility, and is the de-facto best and user-friendliest way to install Flash Player on Windows to date!**
10 |
11 | ## What's this?
12 |
13 | FlashPatch! is a tool that modifies the Flash Player installation on your computer, making it possible to play games in the browser again.
14 |
15 | It bypasses the January 12th, 2021 killswitch that prevents you from playing any Flash Player game or animation after January 12th.
16 |
17 | ## Compatibility
18 |
19 | | Browser | Plugin API | Version | Windows | Linux | Mac | 64-bit | 32-bit |
20 | | ----------------- | ---------------- | ---------- | ------------------------ | ------------------------ | ------------------------ | ------------------ | ------------------------ |
21 | | Google Chrome | PPAPI (Pepper) | 32.0.0.465 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
22 | | Mozilla Firefox | NPAPI (Netscape) | 32.0.0.465 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
23 | | Safari | NPAPI (Netscape) | 32.0.0.465 | :heavy_multiplication_x: | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_multiplication_x: |
24 | | Internet Explorer | ActiveX (OCX) | 32.0.0.465 | :heavy_check_mark: | :heavy_multiplication_x: | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_check_mark: |
25 |
26 | ✔️ means that the plugin is officially supported.
27 |
28 | ✖️ means that the plugin is unavailable on the platform (for example, Safari plugins are unavailable on Windows).
29 |
30 | ❌ means that a specific patch does not exist for that plugin on that platform. These plugins may still be patched using the `Patch File...` button.
31 |
32 | **A generic patch is also available that is version independent. To try this patch, use the `Patch File...` button and manually choose the Flash binary you wish to patch.**
33 |
34 | ## China-specific Flash
35 |
36 | | Browser | Plugin API | Version | Windows | Linux | Mac | 64-bit | 32-bit |
37 | | ----------------- | ---------------- | ---------- | ------------------------ | ------------------------ | ------------------------ | ------------------ | ------------------------ |
38 | | Google Chrome | PPAPI (Pepper) | 34.0.0.330 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
39 | | Mozilla Firefox | NPAPI (Netscape) | 34.0.0.330 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
40 | | Safari | NPAPI (Netscape) | 34.0.0.330 | :heavy_multiplication_x: | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_multiplication_x: |
41 | | Internet Explorer | ActiveX (OCX) | 34.0.0.330 | :heavy_check_mark: | :heavy_multiplication_x: | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_check_mark: |
42 |
43 | Old Chinese Flash versions supported:
44 |
45 | - Version 34.0.0.325
46 | - Version 34.0.0.323
47 | - Version 34.0.0.321
48 | - Version 34.0.0.317
49 | - Version 34.0.0.315
50 | - Version 34.0.0.308
51 | - Version 34.0.0.301
52 | - Version 34.0.0.289
53 | - Version 34.0.0.282
54 | - Version 34.0.0.277
55 | - Version 34.0.0.267
56 | - Version 34.0.0.251
57 | - Version 34.0.0.242
58 | - Version 34.0.0.231
59 | - Version 34.0.0.211
60 | - Version 34.0.0.209
61 | - Version 34.0.0.201
62 | - Version 34.0.0.192
63 | - Version 34.0.0.184
64 | - Version 34.0.0.175
65 | - Version 34.0.0.164
66 | - Version 34.0.0.155
67 | - Version 34.0.0.137
68 | - Version 34.0.0.118
69 |
70 | While Adobe has completely stopped updating the global version of Adobe Flash Player, they are still maintaining a special version of Adobe Flash for Mainland China only. This version is completely compatible with the global version of Flash, but contains a non-closable process, known as the "Flash Helper Service", that collects private information and pops up advertisement window contents.
71 |
72 | This version of Flash normally only works within Mainland China. Furthermore, in order to let business users to purchase a China-specific enterprise edition of Adobe Flash, if it detects an enterprise environment (an Active Directory environment) it refuses to start. It also contains a dormant killswitch.
73 |
74 | FlashPatch fully supports the latest version of the Chinese Flash Player browser plugin: 34.0.0.325.
75 |
76 | FlashPatch provides the following patches for this version:
77 |
78 | - Patch Chinese region lock on runtime (geo2.adobe.com)
79 | - Remove dependence on adware "Flash Helper Service"
80 | - Deactivate dormant OOD Macromedia XML killswitch
81 | - Patch Chinese Enterprise phone-home service
82 | - Patch activation check
83 |
84 | Download clean builds of Flash 34.0.0.330:
85 |
86 | - [For Windows - Chrome/Firefox/IE](https://github.com/darktohka/clean-flash-builds/releases/tag/v1.52)
87 | - [For Linux - Chrome/Firefox](https://github.com/darktohka/clean-flash-builds/releases/tag/v1.7)
88 | - [For Mac - Chrome/Firefox](https://github.com/darktohka/clean-flash-builds/releases/tag/v1.51)
89 |
90 | ## Flash Player
91 |
92 | **But I want to play games using the standalone Flash Player!**
93 |
94 | Adobe ships a current version of the Flash Player projector without the killswitch built-in [on their debug downloads page](https://adobe.com/support/flashplayer/debug_downloads.html).
95 |
96 | **I do not have Adobe Flash Player installed, where can I get it?**
97 |
98 | You can download Adobe Flash Player 32.0.0.465 from [this archived link](https://web.archive.org/web/20210112063313/http://fpdownload.adobe.com/get/flashplayer/pdc/32.0.0.465/install_flash_player.exe). You might need to turn back your system clock to January 11th, 2021 or earlier to install it.
99 |
100 | ## Linux
101 |
102 | **I would like to use Flash Player on Linux!**
103 |
104 | Unfortunately, the tool only works on Windows right now, but if you have a Windows machine, feel free to manually patch version 32.0.0.465 of `libpepflashplayer.so` or `libflashplayer.so`. You can then use these binaries on your Linux machine.
105 |
106 | Notice: Starting with Adobe Flash Player version 34, video playing function on Linux has dropped. If you need this feature please use version 32.0.0.465 instead.
107 |
108 | ## Windows XP
109 |
110 | **I need to use Flash Player on Windows XP!**
111 |
112 | FlashPatch is not compatible with Windows XP. FlashPatch relies on .NET Framework 4.5, but the last supported version of .NET Framework on Windows XP is [4.0.3](https://docs.microsoft.com/en-us/dotnet/framework/install/on-windows-xp#net-framework-403). Regardless, there is a way to keep using Flash on Windows XP. [Please check out the following instructions on GitHub.](https://github.com/darktohka/FlashPatch/issues/7#issuecomment-785096536)
113 |
114 | Notice: Starting with Adobe Flash Player version 34, video playing function on Windows XP has dropped. If you need this feature please use version 32.0.0.465 instead.
115 |
116 | ## Usage
117 |
118 | - Extract `FlashPatch.exe` into a new folder.
119 | - Run `FlashPatch.exe` and allow it to run as administrator (necessary to change system Flash Player files)
120 | - Press the "Patch" button and agree to the warning message
121 | - Your Flash Player is now usable once again!
122 |
123 | To restore the old, unpatched binaries:
124 |
125 | - The unpatched binaries are saved into a `Backup` folder when you patch Flash Player
126 | - Run `FlashPatch.exe` and allow it to run as administrator (necessary to change system Flash Player files)
127 | - Press the "Restore" button and agree
128 | - Your Flash Player is now back to its factory defaults.
129 |
--------------------------------------------------------------------------------
/FlashPatch/Patcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.IO;
5 | using System.Security.AccessControl;
6 | using System.Security.Principal;
7 | using System.Diagnostics;
8 | using System.Windows;
9 | using System.Runtime.InteropServices;
10 | using Microsoft.Win32;
11 | using System.Management;
12 | using System.ServiceProcess;
13 | using System.Linq;
14 |
15 | namespace FlashPatch {
16 | public class Patcher {
17 |
18 | private static string executionOptionsPath = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\";
19 | private static List telemetryApps = new List() { "FlashCenterService.exe", "FlashHelperService.exe" };
20 | private static List telemetryServices = new List() { "FlashCenterService", "Flash Helper Service" };
21 |
22 | [DllImport("kernel32.dll", SetLastError = true)]
23 | static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
24 |
25 | [DllImport("kernel32.dll", SetLastError = true)]
26 | static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
27 |
28 | static Patcher() {
29 | WinAPI.ModifyPrivilege(PrivilegeName.SeRestorePrivilege, true);
30 | WinAPI.ModifyPrivilege(PrivilegeName.SeTakeOwnershipPrivilege, true);
31 | }
32 |
33 | private static string GetWindowsDir() {
34 | return Environment.GetFolderPath(Environment.SpecialFolder.Windows);
35 | }
36 |
37 | private static string GetFlashDir32() {
38 | if (Environment.Is64BitOperatingSystem) {
39 | return Path.Combine(GetWindowsDir(), "SysWOW64", "Macromed", "Flash");
40 | } else {
41 | return Path.Combine(GetWindowsDir(), "System32", "Macromed", "Flash");
42 | }
43 | }
44 |
45 | private static string GetFlashDir64() {
46 | if (Environment.Is64BitOperatingSystem) {
47 | return Path.Combine(GetWindowsDir(), "System32", "Macromed", "Flash");
48 | } else {
49 | return null;
50 | }
51 | }
52 |
53 | private static string GetVersion(string filename) {
54 | return FileVersionInfo.GetVersionInfo(filename).FileVersion;
55 | }
56 |
57 | private static bool IsSharingViolation(Exception e) {
58 | return ((uint)e.HResult) == 0x80070020;
59 | }
60 |
61 | private static void ShowError(string message) {
62 | MessageBox.Show(message, "FlashPatch!", MessageBoxButton.OK, MessageBoxImage.Error);
63 | }
64 |
65 | private static void AppendItems(StringBuilder builder, string message, List items) {
66 | if (items.Count <= 0) {
67 | return;
68 | }
69 |
70 | builder.AppendLine(message);
71 |
72 | foreach (string item in items) {
73 | builder.AppendLine(item);
74 | }
75 |
76 | builder.AppendLine();
77 | }
78 |
79 | private static void StopService(string serviceName) {
80 | ServiceController service = new ServiceController(serviceName);
81 |
82 | service.Stop();
83 | }
84 |
85 | private static void ChangeServiceStartMode(string serviceName, string startMode) {
86 | using (ManagementObject obj = new ManagementObject(string.Format("Win32_Service.Name=\"{0}\"", serviceName))) {
87 | obj.InvokeMethod("ChangeStartMode", new object[] { startMode });
88 | }
89 | }
90 |
91 | private static void PreventExecution(string filename) {
92 | RegistryKey key = Registry.LocalMachine.CreateSubKey(executionOptionsPath + filename);
93 |
94 | key.SetValue("Debugger", Guid.NewGuid().ToString() + ".exe");
95 | }
96 |
97 | private static void RestoreExecution(string filename) {
98 | Registry.LocalMachine.DeleteSubKeyTree(executionOptionsPath + filename);
99 | }
100 |
101 | private static void TakeOwnership(string filename) {
102 | // Remove read-only attribute
103 | File.SetAttributes(filename, File.GetAttributes(filename) & ~FileAttributes.ReadOnly);
104 |
105 | FileSecurity security = new FileSecurity();
106 |
107 | SecurityIdentifier sid = WindowsIdentity.GetCurrent().User;
108 | security.SetOwner(sid);
109 | security.SetAccessRule(new FileSystemAccessRule(sid, FileSystemRights.FullControl, AccessControlType.Allow));
110 |
111 | File.SetAccessControl(filename, security);
112 | }
113 |
114 | public static void PatchAll() {
115 | if (MessageBox.Show("Are you sure you want to patch your system-wide Flash plugins to allow Flash games to be played in your browser?", "FlashPatch!", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) {
116 | return;
117 | }
118 |
119 | if (MessageBox.Show("Have you closed ALL your browser windows yet?\n\nIf not, please close them right now!", "FlashPatch!", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) {
120 | return;
121 | }
122 |
123 | if (MessageBox.Show("WARNING!\n\nThe developers of this program do not assume any responsibility for the usage of this tool.\n\nEven though the developers have tried their best to ensure the quality of this tool, it may introduce instability, or even crash your computer.\n\nAll changes made by the program may be reverted using the \"Restore\" button, but even this option is provided on a best-effort basis.\n\nAll responsibility falls upon your shoulders.\n\nEven so, are you sure you want to continue?", "FlashPatch!", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes) {
124 | return;
125 | }
126 |
127 | IntPtr redirection = DisableRedirection();
128 |
129 | string flashDir32 = GetFlashDir32();
130 |
131 | if (!Directory.Exists(flashDir32)) {
132 | ShowError(string.Format("Could not find 32-bit Flash directory!\n\n{0} does not exist.", flashDir32));
133 | return;
134 | }
135 |
136 | bool x64 = Environment.Is64BitOperatingSystem;
137 | string flashDir64 = null;
138 |
139 | if (x64) {
140 | flashDir64 = GetFlashDir64();
141 |
142 | if (!Directory.Exists(flashDir64)) {
143 | ShowError(string.Format("Could not find 64-bit Flash directory!\n\n{0} does not exist.", flashDir64));
144 | return;
145 | }
146 | }
147 |
148 | foreach (string service in telemetryServices) {
149 | try {
150 | ChangeServiceStartMode(service, "Disabled");
151 | } catch (Exception) {
152 | // It's fine if this doesn't work
153 | }
154 |
155 | try {
156 | StopService(service);
157 | } catch (Exception) {
158 | // It's fine if this doesn't work
159 | }
160 | }
161 |
162 | try {
163 | foreach (string telemetryApp in telemetryApps) {
164 | PreventExecution(telemetryApp);
165 | }
166 | } catch (Exception e) {
167 | ShowError(string.Format("Could not disable Flash Player telemetry! Are you running this application as administrator?\n\n{0}", e.Message));
168 | }
169 |
170 | List patched = new List();
171 | List alreadyPatched = new List();
172 | List notFound = new List();
173 | List incompatibleVersion = new List();
174 | List ownershipFailed = new List();
175 | List locked = new List();
176 | List errors = new List();
177 |
178 | string backupFolder = Path.Combine(Environment.CurrentDirectory, "Backup");
179 | bool madeBackupFolder = false;
180 |
181 | foreach (PatchableBinary binary in Patches.GetBinaries()) {
182 | if (!binary.HasFilenames()) {
183 | // This is a special binary, as we do not specifically look for it.
184 | // This binary can only be patched using the "Patch File..." option
185 | continue;
186 | }
187 |
188 | bool binaryX64 = binary.IsX64();
189 |
190 | if (binaryX64 && !x64) {
191 | // This is a 64-bit binary, but we are not on a 64-bit system.
192 | continue;
193 | }
194 |
195 | string name = binary.GetName();
196 | bool found = false;
197 |
198 | foreach (string filename in binary.GetFilenames()) {
199 | List paths = new List();
200 |
201 | paths.Add(Path.Combine(binaryX64 ? flashDir64 : flashDir32, filename));
202 | paths.AddRange(binary.GetAlternatePaths());
203 |
204 | foreach (string path in paths) {
205 | if (!File.Exists(path)) {
206 | continue;
207 | }
208 |
209 | string version = GetVersion(path);
210 |
211 | if (binary.HasVersion() && !binary.GetVersion().Equals(version)) {
212 | // We've encountered an incompatible version.
213 | found = true;
214 | incompatibleVersion.Add(string.Format("{0} ({1})", name, version));
215 | continue;
216 | }
217 |
218 | long size = new FileInfo(path).Length;
219 |
220 | if (binary.HasFileSize() && binary.GetFileSize() != size) {
221 | // This file's size does not match the expected file size.
222 | continue;
223 | }
224 |
225 | found = true;
226 |
227 | try {
228 | TakeOwnership(path);
229 | } catch {
230 | // We failed to get ownership of the file...
231 | // No continue here, we still want to try to patch the file
232 | ownershipFailed.Add(name);
233 | }
234 |
235 | try {
236 | using (FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.Read)) {
237 | if (!binary.IsPatchable(fileStream)) {
238 | // This binary has already been patched.
239 | alreadyPatched.Add(name);
240 | continue;
241 | }
242 | }
243 |
244 | if (!madeBackupFolder && !Directory.Exists(backupFolder)) {
245 | Directory.CreateDirectory(backupFolder);
246 | madeBackupFolder = true;
247 | }
248 |
249 | // Back up the current plugin to our backup folder
250 | File.Copy(path, Path.Combine(backupFolder, binary.GetBackupFileName(filename)), true);
251 |
252 | using (FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.ReadWrite)) {
253 | // Apply all pending binary patches!
254 | binary.PatchFile(fileStream);
255 | }
256 |
257 | if (!patched.Contains(name)) {
258 | patched.Add(name);
259 | }
260 | } catch (Exception e) {
261 | if (IsSharingViolation(e)) {
262 | // This is a sharing violation; i.e. the file is currently being used.
263 | locked.Add(name);
264 | } else {
265 | errors.Add(e.Message);
266 | }
267 | }
268 | }
269 | }
270 |
271 | if (!found && !notFound.Contains(name)) {
272 | // Add this binary to the not found list.
273 | notFound.Add(name);
274 | }
275 | }
276 |
277 | EnableRedirection(redirection);
278 |
279 | StringBuilder report = new StringBuilder();
280 | MessageBoxImage icon = MessageBoxImage.Information;
281 |
282 | alreadyPatched = alreadyPatched.Except(patched).ToList();
283 | notFound = notFound.Except(patched).Except(alreadyPatched).ToList();
284 | incompatibleVersion = incompatibleVersion.Except(patched).Except(alreadyPatched).ToList();
285 |
286 | AppendItems(report, "Successfully patched these plugins:", patched);
287 | AppendItems(report, "These plugins have already been patched:", alreadyPatched);
288 | AppendItems(report, "These plugins have not been found on your system:", notFound);
289 | AppendItems(report, "These plugins are incompatible with the patch because their version is outdated:", incompatibleVersion);
290 | AppendItems(report, "These plugins could not be patched because their respective browser is currently open:", locked);
291 | AppendItems(report, "Caught exceptions:", errors);
292 |
293 | if (incompatibleVersion.Count > 0 || locked.Count > 0 || errors.Count > 0) {
294 | icon = MessageBoxImage.Warning;
295 | report.AppendLine("Errors have been encountered during the patching process.\nPlease try again after reading the message above carefully.\nIf the browser you're using has been patched successfully, then no more action is required.");
296 | } else if (patched.Count > 0) {
297 | report.AppendLine("CONGRATULATIONS! The patching process has completed as expected. Enjoy your Flash games!");
298 | } else if (alreadyPatched.Count > 0) {
299 | report.AppendLine("Flash Player has already been patched on this system.\n\nNo more action is required! Enjoy your games!");
300 | } else {
301 | report.AppendLine("No action has been taken.");
302 | }
303 |
304 | MessageBox.Show(report.ToString(), "FlashPatch!", MessageBoxButton.OK, icon);
305 | }
306 |
307 | public static void PatchFiles(string[] paths) {
308 | List patched = new List();
309 | List alreadyPatched = new List();
310 | List notPatched = new List();
311 | List ownershipFailed = new List();
312 | List locked = new List();
313 | List errors = new List();
314 |
315 | foreach (string path in paths) {
316 | string filename = Path.GetFileName(path);
317 | long size = new FileInfo(path).Length;
318 |
319 | try {
320 | TakeOwnership(path);
321 | } catch {
322 | // We failed to get ownership of the file...
323 | // No continue here, we still want to try to patch the file
324 | ownershipFailed.Add(filename);
325 | }
326 |
327 | bool complete = false;
328 | string version = GetVersion(path);
329 |
330 | foreach (PatchableBinary binary in Patches.GetBinaries()) {
331 | if (binary.HasFileSize() && binary.GetFileSize() != size) {
332 | continue;
333 | }
334 |
335 | if (binary.HasVersion() && !binary.GetVersion().Equals(version)) {
336 | // We've encountered an incompatible version.
337 | continue;
338 | }
339 |
340 | try {
341 | using (FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.Read)) {
342 | if (!binary.IsPatchable(fileStream)) {
343 | if (binary.IsPatched(fileStream)) {
344 | // This binary has already been patched.
345 | alreadyPatched.Add(filename);
346 | complete = true;
347 | break;
348 | }
349 |
350 | // This binary hasn't been patched, but it's not patchable either.
351 | // This means that the current patch does not match this file.
352 | continue;
353 | }
354 | }
355 |
356 | // Back up the plugin to the same folder with a ".bak" extension
357 | File.Copy(path, Path.Combine(Path.GetDirectoryName(path), filename + ".bak"), true);
358 |
359 | using (FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.ReadWrite)) {
360 | // Apply all pending binary patches!
361 | binary.PatchFile(fileStream);
362 | }
363 |
364 | patched.Add(string.Format("{0} (patch used: {1})", filename, binary.GetName()));
365 | complete = true;
366 | break;
367 | } catch (Exception e) {
368 | if (IsSharingViolation(e)) {
369 | // This is a sharing violation; i.e. the file is currently being used.
370 | locked.Add(filename);
371 | } else {
372 | errors.Add(e.Message);
373 | }
374 | }
375 | }
376 |
377 | if (!complete) {
378 | notPatched.Add(filename);
379 | }
380 | }
381 |
382 | StringBuilder report = new StringBuilder();
383 | MessageBoxImage icon = MessageBoxImage.Information;
384 |
385 | AppendItems(report, "Successfully patched these binaries:", patched);
386 | AppendItems(report, "These binaries have already been patched:", alreadyPatched);
387 | AppendItems(report, "These binaries have not been patched, as compatible patches do not exist:", notPatched);
388 | AppendItems(report, "These binaries could not be patched because their respective browser is currently open:", locked);
389 | AppendItems(report, "Failed to take ownership of the following binaries:", ownershipFailed);
390 | AppendItems(report, "Caught exceptions:", errors);
391 |
392 | if (locked.Count > 0 || errors.Count > 0) {
393 | icon = MessageBoxImage.Warning;
394 | report.AppendLine("Errors have been encountered during the patching process.\nPlease try again after reading the message above carefully.");
395 | } else if (notPatched.Count > 0) {
396 | icon = MessageBoxImage.Warning;
397 | report.AppendLine("Sorry, but we couldn't patch some of your binaries.");
398 | } else if (patched.Count > 0) {
399 | report.AppendLine("Great work! All binaries have been successfully patched.");
400 | } else if (alreadyPatched.Count > 0) {
401 | report.AppendLine("Looks like all of your binaries have already been patched!");
402 | } else {
403 | report.AppendLine("No action has been taken.");
404 | }
405 |
406 | MessageBox.Show(report.ToString(), "FlashPatch!", MessageBoxButton.OK, icon);
407 | }
408 |
409 | public static IntPtr DisableRedirection() {
410 | IntPtr wow64Value = IntPtr.Zero;
411 |
412 | // Disable file system indirection (otherwise we can't read System32)
413 | Wow64DisableWow64FsRedirection(ref wow64Value);
414 | return wow64Value;
415 | }
416 |
417 | public static void EnableRedirection(IntPtr wow64Value) {
418 | // Enable file system indirection.
419 | Wow64RevertWow64FsRedirection(wow64Value);
420 | }
421 |
422 | public static void RestoreAll() {
423 | if (MessageBox.Show("Are you sure you want to restore your Flash Plugin backups?", "FlashPatch!", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) {
424 | return;
425 | }
426 |
427 | foreach (string service in telemetryServices) {
428 | try {
429 | ChangeServiceStartMode(service, "Automatic");
430 | } catch (Exception) {
431 | // It's fine if this doesn't work
432 | }
433 | }
434 |
435 | foreach (string telemetryApp in telemetryApps) {
436 | try {
437 | RestoreExecution(telemetryApp);
438 | } catch (Exception) {
439 | // It's fine if this doesn't work.
440 | // This means that the redirection has been removed.
441 | }
442 | }
443 |
444 | string backupFolder = Path.Combine(Environment.CurrentDirectory, "Backup");
445 |
446 | if (!Directory.Exists(backupFolder)) {
447 | ShowError("No backups are currently available.");
448 | return;
449 | }
450 |
451 | IntPtr redirection = DisableRedirection();
452 |
453 | string flashDir32 = GetFlashDir32();
454 |
455 | if (!Directory.Exists(flashDir32)) {
456 | ShowError(string.Format("Could not find 32-bit Flash directory!\n\n{0} does not exist.", flashDir32));
457 | return;
458 | }
459 |
460 | bool x64 = Environment.Is64BitOperatingSystem;
461 | string flashDir64 = null;
462 |
463 | if (x64) {
464 | flashDir64 = GetFlashDir64();
465 |
466 | if (!Directory.Exists(flashDir64)) {
467 | ShowError(string.Format("Could not find 64-bit Flash directory!\n\n{0} does not exist.", flashDir64));
468 | return;
469 | }
470 | }
471 |
472 | List restored = new List();
473 | List locked = new List();
474 | List errors = new List();
475 |
476 | foreach (PatchableBinary binary in Patches.GetBinaries()) {
477 | if (!binary.HasFilenames()) {
478 | continue;
479 | }
480 |
481 | bool binaryX64 = binary.IsX64();
482 |
483 | if (binaryX64 && !x64) {
484 | // This is a 64-bit binary, but we are not on a 64-bit system.
485 | continue;
486 | }
487 |
488 | foreach (string filename in binary.GetFilenames()) {
489 | string backupPath = Path.Combine(backupFolder, binary.GetBackupFileName(filename));
490 |
491 | if (!File.Exists(backupPath)) {
492 | continue;
493 | }
494 |
495 | string name = binary.GetName();
496 | string path = Path.Combine(binaryX64 ? flashDir64 : flashDir32, filename);
497 |
498 | try {
499 | File.Copy(backupPath, path, true);
500 | restored.Add(name);
501 | } catch (Exception e) {
502 | if (IsSharingViolation(e)) {
503 | // This is a sharing violation; i.e. the file is currently being used.
504 | locked.Add(name);
505 | } else {
506 | errors.Add(e.Message);
507 | }
508 | }
509 | }
510 | }
511 |
512 | EnableRedirection(redirection);
513 |
514 | StringBuilder report = new StringBuilder();
515 | MessageBoxImage icon = MessageBoxImage.Information;
516 |
517 | AppendItems(report, "Successfully restored these plugins to their original, unpatched version:", restored);
518 | AppendItems(report, "These plugins could not be restored because their respective browser is currently open:", locked);
519 | AppendItems(report, "Caught exceptions:", errors);
520 |
521 | if (locked.Count > 0 || errors.Count > 0) {
522 | icon = MessageBoxImage.Warning;
523 | report.AppendLine("Errors have been encountered during the restoration process. Please try again after reading the message above carefully.");
524 | } else if (restored.Count > 0) {
525 | report.AppendLine("All plugins have been restored from the previous backup!\nNo more action is necessary.");
526 | } else {
527 | ShowError("No backups are currently available.");
528 | return;
529 | }
530 |
531 | MessageBox.Show(report.ToString(), "FlashPatch!", MessageBoxButton.OK, icon);
532 | }
533 | }
534 | }
535 |
--------------------------------------------------------------------------------