├── .github
├── FUNDING.yml
└── workflows
│ └── auto-update.yml
├── BulkBindex.sln
├── BulkBindex
├── BulkBindex.csproj
├── Helper.cs
├── Program.cs
├── Worker.cs
└── obj
│ └── Debug
│ └── net6.0
│ ├── .NETCoreApp,Version=v6.0.AssemblyAttributes.cs
│ ├── BulkBindex.AssemblyInfo.cs
│ ├── BulkBindex.AssemblyInfoInputs.cache
│ ├── BulkBindex.GeneratedMSBuildEditorConfig.editorconfig
│ ├── BulkBindex.GlobalUsings.g.cs
│ └── BulkBindex.csproj.AssemblyReference.cache
└── README.md
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: FuzzySecurity
4 |
--------------------------------------------------------------------------------
/.github/workflows/auto-update.yml:
--------------------------------------------------------------------------------
1 | name: Build, Run and Publish Results
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build_and_upload_artifacts:
10 | runs-on: ubuntu-latest
11 | strategy:
12 | matrix:
13 | input:
14 | - { value: ' -b 11-22H2 -d 2023-08', prefix: '11-22H2' }
15 | - { value: ' -b 22H2 -d 2023-08', prefix: '10-22H2' }
16 |
17 | steps:
18 | - name: Checkout code
19 | uses: actions/checkout@v2
20 |
21 | - name: Setup .NET
22 | uses: actions/setup-dotnet@v1
23 | with:
24 | dotnet-version: 6.0.x
25 |
26 | - name: Build the .NET 6 application
27 | run: dotnet build --configuration Release
28 |
29 | - name: Extract date from input
30 | id: extract_date
31 | run: |
32 | date=$(echo '${{ matrix.input.value }}' | grep -oP '(?<=-d\s)[\d-]+')
33 | echo "::set-output name=date::$date"
34 |
35 | - name: Run the binary with matrix input
36 | run: dotnet ./BulkBindex/bin/Release/net6.0/BulkBindex.dll ${{ matrix.input.value }}
37 |
38 | - name: Archive x86 result
39 | run: zip -j ./BulkBindex/bin/Release/net6.0/x86-${{ matrix.input.prefix }}-${{ steps.extract_date.outputs.date }}.zip ./BulkBindex/bin/Release/net6.0/Worker-Output/Download/x86/*
40 | env:
41 | OUTPUT_DIR: Worker-Output/Download
42 | PROJECT_DIR: BulkBindex/bin/Release/net6.0
43 |
44 | - name: Archive x64 result
45 | run: zip -j ./BulkBindex/bin/Release/net6.0/x64-${{ matrix.input.prefix }}-${{ steps.extract_date.outputs.date }}.zip ./BulkBindex/bin/Release/net6.0/Worker-Output/Download/x64/*
46 | env:
47 | OUTPUT_DIR: Worker-Output/Download
48 | PROJECT_DIR: BulkBindex/bin/Release/net6.0
49 |
50 | - name: Upload x86 result
51 | uses: actions/upload-artifact@v2
52 | with:
53 | name: x86-result-${{ matrix.input.prefix }}-${{ steps.extract_date.outputs.date }}
54 | path: ./BulkBindex/bin/Release/net6.0/x86-${{ matrix.input.prefix }}-${{ steps.extract_date.outputs.date }}.zip
55 |
56 | - name: Upload x64 result
57 | uses: actions/upload-artifact@v2
58 | with:
59 | name: x64-result-${{ matrix.input.prefix }}-${{ steps.extract_date.outputs.date }}
60 | path: ./BulkBindex/bin/Release/net6.0/x64-${{ matrix.input.prefix }}-${{ steps.extract_date.outputs.date }}.zip
61 |
62 | create_release:
63 | needs: build_and_upload_artifacts
64 | runs-on: ubuntu-latest
65 | permissions:
66 | contents: write
67 | steps:
68 | - name: Checkout code
69 | uses: actions/checkout@v2
70 |
71 | - name: Create release tag
72 | id: create_tag
73 | run: |
74 | TAG_NAME="release-$(date +'%Y-%m-%d')-$(git rev-parse --short HEAD)"
75 | git config user.name "github-actions"
76 | git config user.email "github-actions@users.noreply.github.com"
77 | git tag $TAG_NAME
78 | echo "::set-output name=tag::$TAG_NAME"
79 |
80 | - name: Download all artifacts
81 | uses: actions/download-artifact@v2
82 |
83 | - name: Publish release
84 | if: github.ref == 'refs/heads/main'
85 | uses: softprops/action-gh-release@v1
86 | with:
87 | tag_name: ${{ steps.create_tag.outputs.tag }}
88 | draft: false
89 | prerelease: false
90 | files: |
91 | x86-result-*/*.zip
92 | x64-result-*/*.zip
93 | env:
94 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
--------------------------------------------------------------------------------
/BulkBindex.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BulkBindex", "BulkBindex\BulkBindex.csproj", "{907D3586-BD02-4BD5-AA04-8422FDBDF215}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {907D3586-BD02-4BD5-AA04-8422FDBDF215}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {907D3586-BD02-4BD5-AA04-8422FDBDF215}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {907D3586-BD02-4BD5-AA04-8422FDBDF215}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {907D3586-BD02-4BD5-AA04-8422FDBDF215}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/BulkBindex/BulkBindex.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/BulkBindex/Helper.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 |
3 | namespace BulkBindex;
4 | using System.IO.Compression;
5 |
6 | public class Helper
7 | {
8 | internal struct FileData
9 | {
10 | public String OSVersion;
11 | public String? ReleaseDate;
12 | public String FileName;
13 | public String? FileVersion;
14 | public String? md5;
15 | public Int64 Timestamp;
16 | public Int64 VirtualSize;
17 | public String DownloadURL;
18 | public String MachineType;
19 | }
20 |
21 | internal static List ProcessGZJSON(String sFullPath, String sDate, String sBuildName)
22 | {
23 | // Result object
24 | List oResult = new List();
25 |
26 | // gz decompress the file
27 | String sJSON = String.Empty;
28 | using (FileStream fs = new FileStream(sFullPath, FileMode.Open))
29 | {
30 | using (GZipStream gz = new GZipStream(fs, CompressionMode.Decompress))
31 | {
32 | using (StreamReader sr = new StreamReader(gz))
33 | {
34 | sJSON = sr.ReadToEnd();
35 | }
36 | }
37 | }
38 |
39 | // Load the JSON into a JObject
40 | JObject oJSON = JObject.Parse(sJSON);
41 |
42 | // Loop through the json object
43 | foreach (JProperty oProperty in oJSON.Properties())
44 | {
45 | //Console.WriteLine(oProperty.Name);
46 | JObject? fileInfo = null;
47 | try
48 | {
49 | fileInfo = (JObject)oProperty.Value["fileInfo"]!;
50 | } catch {continue;}
51 |
52 | Int64 timestamp = 0;
53 | Int64 virtualSize = 0;
54 | Int64 machineType = 0;
55 | try
56 | {
57 | // Get the timestamp / virtualSize / machineType values from the fileInfo object
58 | timestamp = (Int64) (fileInfo["timestamp"] ?? 0);
59 | virtualSize = (Int64) (fileInfo["virtualSize"] ?? 0);
60 | machineType = (Int64) (fileInfo["machineType"] ?? 0);
61 | if (timestamp == 0 || virtualSize == 0 || machineType == 0)
62 | {
63 | continue;
64 | }
65 | } catch {continue;}
66 |
67 | // We only want x86 and x64 files
68 | String sMachineType = String.Empty;
69 | if (machineType != 332 && machineType != 34404)
70 | {
71 | continue;
72 | }
73 |
74 | // Set the machine type in the result object
75 | if (machineType == 332)
76 | {
77 | sMachineType = "x86";
78 | }
79 | else
80 | {
81 | sMachineType = "x64";
82 | }
83 |
84 | String? sVersion = String.Empty;
85 | String? sMD5 = String.Empty;
86 | JObject? windowsVersions = null;
87 | try
88 | {
89 | sVersion = (String) fileInfo["version"]!;
90 | sMD5 = (String) fileInfo["md5"]!;
91 | windowsVersions = (JObject) oProperty.Value["windowsVersions"]!;
92 | } catch {continue;}
93 |
94 | // Loop through each version in the windowsVersions object
95 | foreach (JProperty versionProperty in windowsVersions.Properties())
96 | {
97 | // Get the version object from the current version property
98 | JObject version = (JObject) versionProperty.Value;
99 |
100 | // Loop through the version object
101 | foreach (JProperty versionProperty2 in version.Properties())
102 | {
103 | JObject? windowsVersionInfo = null;
104 | try
105 | {
106 | windowsVersionInfo = (JObject) versionProperty2.Value["windowsVersionInfo"]!;
107 | }
108 | catch {}
109 |
110 | JArray? otherWindowsVersions = null;
111 | if (windowsVersionInfo == null)
112 | {
113 | try
114 | {
115 | windowsVersionInfo = (JObject) versionProperty2.Value["updateInfo"]!;
116 | } catch {continue;}
117 |
118 | try
119 | {
120 | // If we have updateInfo, there can be an array of otherWindowsVersions
121 | // Stop it ok, just make a sane format MSFT ffs..
122 | otherWindowsVersions = (JArray)windowsVersionInfo["otherWindowsVersions"]!;
123 | } catch {}
124 | }
125 |
126 | String? releaseDate = String.Empty;
127 | try
128 | {
129 | releaseDate = (String) windowsVersionInfo["releaseDate"]!;
130 | } catch {continue;}
131 |
132 | // Do we want this file?
133 | if (otherWindowsVersions != null)
134 | {
135 | try
136 | {
137 | if ((!otherWindowsVersions.Contains(sDate) && !versionProperty.Name.Contains(sBuildName)) || !releaseDate.Contains(sDate))
138 | {
139 | continue;
140 | }
141 | } catch {continue;}
142 |
143 | }
144 | else
145 | {
146 | try
147 | {
148 | if (!releaseDate.Contains(sDate) || !versionProperty.Name.Contains(sBuildName))
149 | {
150 | continue;
151 | }
152 | } catch {continue;}
153 | }
154 |
155 | // Get name (Win)
156 | String sFile = sFullPath.Split('\\').Last();
157 | // Get name (Lin)
158 | sFile = sFile.Split('/').Last();
159 | sFile = sFile.Remove(sFile.Length - 8);
160 |
161 | // We only want the first part of the version if there are spaces
162 | if (!String.IsNullOrEmpty(sVersion))
163 | {
164 | if (sVersion.Contains(' '))
165 | {
166 | sVersion = sVersion.Split(' ').First();
167 | }
168 | }
169 |
170 | // Add the result to the list
171 | oResult.Add(new FileData
172 | {
173 | OSVersion = versionProperty.Name,
174 | ReleaseDate = releaseDate,
175 | FileName = sFile,
176 | md5 = sMD5,
177 | FileVersion = sVersion,
178 | Timestamp = timestamp,
179 | VirtualSize = virtualSize,
180 | DownloadURL = MakeMSFTSymbolDownloadLink(sFile, timestamp, virtualSize),
181 | MachineType = sMachineType
182 | });
183 | }
184 | }
185 | }
186 |
187 | // Return the result
188 | return oResult;
189 | }
190 |
191 | public static String MakeMSFTSymbolDownloadLink(String peName, Int64 timeStamp, Int64 imageSize)
192 | {
193 | // "%s/%s/%08X%x/%s" % (serverName, peName, timeStamp, imageSize, peName)
194 | // https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/
195 |
196 | String timeStampHex = timeStamp.ToString("X").ToUpper();
197 | String paddedTimeStampHex = "0000000".Substring(0, 8 - timeStampHex.Length) + timeStampHex;
198 | String imageSizeHex = imageSize.ToString("x").ToLower();
199 |
200 | String fileId = $"{paddedTimeStampHex}{imageSizeHex}";
201 | return $"https://msdl.microsoft.com/download/symbols/{peName}/{fileId}/{peName}";
202 | }
203 |
204 | internal static void DisplayProgress(Int64 index, Int64 count)
205 | {
206 | Double progress = (Double) index / count;
207 | Int32 progressInChars = (Int32)Math.Floor(progress * 50);
208 |
209 | Console.SetCursorPosition(0, Console.CursorTop);
210 | Console.Write('[');
211 |
212 | for (Int32 i = 0; i < 50; i++)
213 | {
214 | if (i < progressInChars)
215 | {
216 | Console.Write('=');
217 | }
218 | else if (i == progressInChars)
219 | {
220 | Console.Write('>');
221 | }
222 | else
223 | {
224 | Console.Write(' ');
225 | }
226 | }
227 |
228 | Int32 progressPercentage = (Int32)Math.Floor(progress * 100);
229 | Console.Write($"] {progressPercentage}% ({index}/{count})");
230 | Console.SetCursorPosition(0, Console.CursorTop);
231 | }
232 | }
--------------------------------------------------------------------------------
/BulkBindex/Program.cs:
--------------------------------------------------------------------------------
1 | using BulkBindex;
2 | using System.Text.RegularExpressions;
3 |
4 | Int32 iBuildName = Array.FindIndex(args, s => new Regex(@"(?i)(-|--|/)(b|Build)$").Match(s).Success);
5 | Int32 iYearMonth = Array.FindIndex(args, s => new Regex(@"(?i)(-|--|/)(d|Date)$").Match(s).Success);
6 |
7 | if (iBuildName != -1 && iYearMonth != -1)
8 | {
9 | try
10 | {
11 | String BuildName = args[iBuildName + 1];
12 | String YearMonth = args[iYearMonth + 1];
13 |
14 | // Run the worker
15 | Worker.Run(BuildName, YearMonth);
16 |
17 | // DEBUG CODE
18 | //--------------
19 |
20 | //List lFiles = Helper.ProcessGZJSON(@"C:\Users\b33f\tools\Dev\BulkBindex\BulkBindex\BulkBindex\bin\Debug\net6.0\Worker-Output\Compressed\ntdll.dll.json.gz", YearMonth, BuildName);
21 | //
22 | //// Print the results
23 | //foreach (Helper.FileData file in lFiles)
24 | //{
25 | // Console.WriteLine("\n[+] File: " + file.FileName);
26 | // Console.WriteLine(" OS Version: " + file.OSVersion);
27 | // Console.WriteLine(" Release Date: " + file.ReleaseDate);
28 | // Console.WriteLine(" File Version: " + file.FileVersion);
29 | // Console.WriteLine(" MD5: " + file.md5);
30 | // Console.WriteLine(" Timestamp: " + file.Timestamp);
31 | // Console.WriteLine(" Virtual Size: " + file.VirtualSize);
32 | // Console.WriteLine(" Download URL: " + file.DownloadURL);
33 | //}
34 | } catch (Exception ex)
35 | {
36 | Console.WriteLine($"[!] Error: {ex.Message}");
37 | }
38 | }
39 | else
40 | {
41 | Console.WriteLine("[!] Missing required arguments. Please use the following format:");
42 | Console.WriteLine(" BulkBindex.exe -b -d ");
43 | Console.WriteLine(" Example: BulkBindex.exe -b 11-22H2 -d 2023-04");
44 | }
--------------------------------------------------------------------------------
/BulkBindex/Worker.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Reflection;
3 | using System.IO.Compression;
4 | using System.Text.RegularExpressions;
5 |
6 | namespace BulkBindex;
7 |
8 | public class Worker
9 | {
10 | internal static void Run(String BuildName, String YearMonth)
11 | {
12 | // Get the current directory of the executable
13 | String CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
14 |
15 | // Create the output directory
16 | String OutputDirectory = Path.Combine(CurrentDirectory, "Worker-Output");
17 |
18 | // If directory exists, delete it and all of its contents
19 | if (Directory.Exists(OutputDirectory))
20 | {
21 | Directory.Delete(OutputDirectory, true);
22 | }
23 | Directory.CreateDirectory(OutputDirectory);
24 |
25 | // Download zip to output directory
26 | // https://github.com/m417z/winbindex/archive/refs/heads/gh-pages.zip
27 | String zFile = Path.Combine(OutputDirectory, "winbindex.zip");
28 | String ZipURL = "https://github.com/m417z/winbindex/archive/refs/heads/gh-pages.zip";
29 | Console.WriteLine($"[+] Downloading winbindex from GitHub to {zFile}");
30 | using (WebClient Client = new WebClient())
31 | {
32 | Client.DownloadFile(ZipURL, zFile);
33 | }
34 |
35 | // Get file size of zip file
36 | FileInfo ZipFileInfo = new FileInfo(zFile);
37 | Console.WriteLine($"[>] Downloaded {ZipFileInfo.Length} bytes");
38 | String sCompressedPath = Path.Combine(OutputDirectory, "Compressed");
39 | Directory.CreateDirectory(sCompressedPath);
40 |
41 | // Extract zip file to output directory
42 | Console.WriteLine($"[+] Extracting compressed files to {sCompressedPath}");
43 |
44 | using (ZipArchive archive = ZipFile.OpenRead(zFile))
45 | {
46 | foreach (ZipArchiveEntry entry in archive.Entries)
47 | {
48 | if (entry.FullName.StartsWith("winbindex-gh-pages/data/by_filename_compressed/"))
49 | {
50 | String sPattern = @"\.exe|\.dll|\.sys|\.winmd|\.cpl|\.ax|\.node|\.ocx|\.efi|\.acm|\.scr|\.tsp|\.drv";
51 | if (Regex.IsMatch(entry.FullName, sPattern))
52 | {
53 | // Extract the file
54 | entry.ExtractToFile(Path.Combine(sCompressedPath, entry.Name));
55 | }
56 | }
57 | }
58 | }
59 | Console.WriteLine("[>] Extraction complete.");
60 |
61 | // Delete the zip file
62 | File.Delete(zFile);
63 |
64 | // Make output directory for downloaded files
65 | String sDownloadedPath = Path.Combine(OutputDirectory, "Download");
66 | String sDownloadedPathx86 = Path.Combine(sDownloadedPath, "x86");
67 | String sDownloadedPathx64 = Path.Combine(sDownloadedPath, "x64");
68 | Directory.CreateDirectory(sDownloadedPath);
69 | Directory.CreateDirectory(sDownloadedPathx86);
70 | Directory.CreateDirectory(sDownloadedPathx64);
71 | Console.WriteLine($"[DEBUG] Downloaded files will be saved to {sDownloadedPath}");
72 | Console.WriteLine($"[+] Downloading all binaries for {BuildName} {YearMonth}..");
73 |
74 | // Process the files
75 | // 1. Decompress
76 | // 2. Read as JSON
77 | // 3. Loop through each file
78 |
79 | // Get count of files
80 | Int64 iFileCount = Directory.GetFiles(sCompressedPath).Length;
81 | Int64 iCurrentFile = 0;
82 | List lFailedDownloads = new List();
83 | foreach (String sGZInstance in Directory.GetFiles(sCompressedPath))
84 | {
85 | // Pass the full path to the helper
86 | List fileList = Helper.ProcessGZJSON(sGZInstance, YearMonth, BuildName);
87 |
88 | // Print the results
89 | foreach (Helper.FileData file in fileList)
90 | {
91 | // Create the file name
92 | String sFileName = String.Empty;
93 | if (!String.IsNullOrEmpty(file.FileVersion))
94 | {
95 | sFileName = file.FileName + "-" + file.FileVersion + "-" + file.md5 + ".blob";
96 | }
97 | else
98 | {
99 | sFileName = file.FileName + "-" + file.md5 + ".blob";
100 | }
101 |
102 | // Download the file
103 | String sDownloadPath = String.Empty;
104 | if (file.MachineType == "x86")
105 | {
106 | sDownloadPath = Path.Combine(sDownloadedPathx86, sFileName);
107 | }
108 | else
109 | {
110 | sDownloadPath = Path.Combine(sDownloadedPathx64, sFileName);
111 | }
112 | //Console.WriteLine("[DEBUG] " + sDownloadPath);
113 |
114 | try
115 | {
116 | using (WebClient Client = new WebClient())
117 | {
118 | Client.DownloadFile(file.DownloadURL, sDownloadPath);
119 | }
120 | }
121 | catch (Exception ex)
122 | {
123 | String sError = " - " + file.DownloadURL + "\n |_ " + ex.Message;
124 | lFailedDownloads.Add(sError);
125 | }
126 | }
127 |
128 | // Delete the compressed file
129 | File.Delete(sGZInstance);
130 |
131 | // Increment and print progress
132 | iCurrentFile++;
133 | Helper.DisplayProgress(iCurrentFile, iFileCount);
134 | }
135 |
136 | Console.WriteLine("\n[>] Download complete.");
137 | // Print failed downloads
138 | if (lFailedDownloads.Count > 0)
139 | {
140 | Console.WriteLine("\n[!] Failed file downloads..");
141 | foreach (String sError in lFailedDownloads)
142 | {
143 | Console.WriteLine(sError);
144 | }
145 | }
146 | }
147 | }
--------------------------------------------------------------------------------
/BulkBindex/obj/Debug/net6.0/.NETCoreApp,Version=v6.0.AssemblyAttributes.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using System.Reflection;
4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
5 |
--------------------------------------------------------------------------------
/BulkBindex/obj/Debug/net6.0/BulkBindex.AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | using System;
11 | using System.Reflection;
12 |
13 | [assembly: System.Reflection.AssemblyCompanyAttribute("BulkBindex")]
14 | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
15 | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
16 | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
17 | [assembly: System.Reflection.AssemblyProductAttribute("BulkBindex")]
18 | [assembly: System.Reflection.AssemblyTitleAttribute("BulkBindex")]
19 | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
20 |
21 | // Generated by the MSBuild WriteCodeFragment class.
22 |
23 |
--------------------------------------------------------------------------------
/BulkBindex/obj/Debug/net6.0/BulkBindex.AssemblyInfoInputs.cache:
--------------------------------------------------------------------------------
1 | b1481bc9685728b3b79cbbd34ffbf784f5d3b7ae
2 |
--------------------------------------------------------------------------------
/BulkBindex/obj/Debug/net6.0/BulkBindex.GeneratedMSBuildEditorConfig.editorconfig:
--------------------------------------------------------------------------------
1 | is_global = true
2 | build_property.TargetFramework = net6.0
3 | build_property.TargetPlatformMinVersion =
4 | build_property.UsingMicrosoftNETSdkWeb =
5 | build_property.ProjectTypeGuids =
6 | build_property.InvariantGlobalization =
7 | build_property.PlatformNeutralAssembly =
8 | build_property._SupportedPlatformList = Linux,macOS,Windows
9 | build_property.RootNamespace = BulkBindex
10 | build_property.ProjectDir = c:\Users\b33f\tools\GitHub\BulkBindex\BulkBindex\
11 |
--------------------------------------------------------------------------------
/BulkBindex/obj/Debug/net6.0/BulkBindex.GlobalUsings.g.cs:
--------------------------------------------------------------------------------
1 | //
2 | global using global::System;
3 | global using global::System.Collections.Generic;
4 | global using global::System.IO;
5 | global using global::System.Linq;
6 | global using global::System.Net.Http;
7 | global using global::System.Threading;
8 | global using global::System.Threading.Tasks;
9 |
--------------------------------------------------------------------------------
/BulkBindex/obj/Debug/net6.0/BulkBindex.csproj.AssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FuzzySecurity/BulkBindex/cd155782916fca08e602ff24f3e7a848bb437355/BulkBindex/obj/Debug/net6.0/BulkBindex.csproj.AssemblyReference.cache
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # BulkBindex
4 |
5 | `BulkBindex` is a **very** DIY extension for [`Winbindex`](https://winbindex.m417z.com/) by [@m417z](https://twitter.com/m417z). All the great work is done there really!
6 |
7 | `BulkBindex` fetches compressed JSON files from the `Winbindex` repository and processes those to download all binaries related to a specific Windows build and month. It can just be really useful to have everything collected after `patch tuesday` for example.
8 |
9 | ## Usage
10 |
11 | `BulkBindex` is built on .NET6 so you can compile and run it anywhere. Command line usage is shown below.
12 |
13 | ```
14 | // Windows
15 | BulkBindex.exe -b 11-22H2 -d 2023-04
16 |
17 | // Nix
18 | dotnet BulkBindex.dll -b 11-22H2 -d 2023-04
19 | ```
20 |
21 | #### Where do I get build names?
22 |
23 | `BulkBindex` uses the same build identifiers as on `Winbindex`. For example, in the listing for `ntdll` below you can see the version is `11-22H2`. Note however that sometimes, other applicable versions are specified in `otherWindowsVersions` (e.g., `21H2` etc.).
24 |
25 | ```json
26 | {
27 | "fileInfo": {
28 | "description": "NT Layer DLL",
29 | "machineType": 34404,
30 | "md5": "c9b7eb6b6320deb5a9dc6ab23be3029d",
31 | "sha1": "ac9d441181e3b35d4d321002ca5b4d26aa59615d",
32 | "sha256": "abb30adf05bd71ae8283d8a44e55268de3c408421ec059c626b92b9168adc0f9",
33 | "signatureType": "Overlay",
34 | "signingDate": [
35 | "2023-03-18T02:15:00"
36 | ],
37 | "signingStatus": "Signed",
38 | "size": 2174872,
39 | "timestamp": 3085964618,
40 | "version": "10.0.22621.1485 (WinBuild.160101.0800)",
41 | "virtualSize": 2179072
42 | },
43 | "windowsVersions": {
44 | "11-22H2": {
45 | "KB5023778": {
46 | "assemblies": {
47 | "amd64_microsoft-windows-ntdll_31bf3856ad364e35_10.0.22621.1485_none_38c42af777bdcc16": {
48 | "assemblyIdentity": {
49 | "buildType": "release",
50 | "language": "neutral",
51 | "name": "Microsoft-Windows-Ntdll",
52 | "processorArchitecture": "amd64",
53 | "publicKeyToken": "31bf3856ad364e35",
54 | "version": "10.0.22621.1485",
55 | "versionScope": "nonSxS"
56 | },
57 | "attributes": [
58 | {
59 | "destinationPath": "$(runtime.system32)\\",
60 | "importPath": "$(build.nttree)\\",
61 | "name": "ntdll.dll",
62 | "sourceName": "ntdll.dll",
63 | "sourcePath": ".\\"
64 | }
65 | ]
66 | }
67 | },
68 | "updateInfo": {
69 | "heading": "March 28, 2023—KB5023778 (OS Build 22621.1485) Preview",
70 | "releaseDate": "2023-03-28",
71 | "releaseVersion": "22621.1485",
72 | "updateUrl": "https://support.microsoft.com/help/5023778"
73 | }
74 | },
75 | "KB5025239": {
76 | "assemblies": {
77 | "amd64_microsoft-windows-ntdll_31bf3856ad364e35_10.0.22621.1485_none_38c42af777bdcc16": {
78 | "assemblyIdentity": {
79 | "buildType": "release",
80 | "language": "neutral",
81 | "name": "Microsoft-Windows-Ntdll",
82 | "processorArchitecture": "amd64",
83 | "publicKeyToken": "31bf3856ad364e35",
84 | "version": "10.0.22621.1485",
85 | "versionScope": "nonSxS"
86 | },
87 | "attributes": [
88 | {
89 | "destinationPath": "$(runtime.system32)\\",
90 | "importPath": "$(build.nttree)\\",
91 | "name": "ntdll.dll",
92 | "sourceName": "ntdll.dll",
93 | "sourcePath": ".\\"
94 | }
95 | ]
96 | }
97 | },
98 | "updateInfo": {
99 | "heading": "April 11, 2023—KB5025239 (OS Build 22621.1555)",
100 | "releaseDate": "2023-04-11",
101 | "releaseVersion": "22621.1555",
102 | "updateUrl": "https://support.microsoft.com/help/5025239"
103 | }
104 | }
105 | }
106 | }
107 | }
108 | ```
109 |
110 | ## Downloads & Automation
111 |
112 | When you run `BulkBindex` you should expect about a 20 minute runtime to fetch all binaries for a single build (depending on bandwidth). In this repository I have also added `GitHub Workflow` automation which allows workers to fetch builds for various versions and add them to the same release.
113 |
114 | Further testing is needed but a release has already been uploaded for `April 2023 -> 11 22H2 & 10 22H2`. The intention is to add a schedule to the workflow so these releases are created right after `patch tuesday` starting from the next cycle.
115 |
116 | ## Halp?!
117 |
118 | The code is still quite DIY. I am more than happy to receive PR's both on `BulkBindex` and the `GitHub Workflow` automation! Additions which also fetch `PDB's` welcome!
--------------------------------------------------------------------------------