├── .gitignore
├── BasicChromeDriverDetectionPatch.sln
├── BasicChromeDriverDetectionPatch
├── BasicChromeDriverDetectionPatch.csproj
├── BinHelper.cs
└── Program.cs
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | .build/
7 |
8 | # User-specific files
9 | *.rsuser
10 | *.suo
11 | *.user
12 | *.userosscache
13 | *.sln.docstates
14 |
15 | # User-specific files (MonoDevelop/Xamarin Studio)
16 | *.userprefs
17 |
18 | # Mono auto generated files
19 | mono_crash.*
20 |
21 | # Build results
22 | [Dd]ebug/
23 | [Dd]ebugPublic/
24 | [Rr]elease/
25 | [Rr]eleases/
26 | x64/
27 | x86/
28 | [Ww][Ii][Nn]32/
29 | [Aa][Rr][Mm]/
30 | [Aa][Rr][Mm]64/
31 | bld/
32 | [Bb]in/
33 | [Oo]bj/
34 | [Ll]og/
35 | [Ll]ogs/
36 |
37 | # Visual Studio 2015/2017 cache/options directory
38 | .vs/
39 | # Uncomment if you have tasks that create the project's static files in wwwroot
40 | #wwwroot/
41 |
42 | # Visual Studio 2017 auto generated files
43 | Generated\ Files/
44 |
45 | # MSTest test Results
46 | [Tt]est[Rr]esult*/
47 | [Bb]uild[Ll]og.*
48 |
49 | # NUnit
50 | *.VisualState.xml
51 | TestResult.xml
52 | nunit-*.xml
53 |
54 | # Build Results of an ATL Project
55 | [Dd]ebugPS/
56 | [Rr]eleasePS/
57 | dlldata.c
58 |
59 | # Benchmark Results
60 | BenchmarkDotNet.Artifacts/
61 |
62 | # .NET Core
63 | project.lock.json
64 | project.fragment.lock.json
65 | artifacts/
66 |
67 | # Tye
68 | .tye/
69 |
70 | # ASP.NET Scaffolding
71 | ScaffoldingReadMe.txt
72 |
73 | # StyleCop
74 | StyleCopReport.xml
75 |
76 | # Files built by Visual Studio
77 | *_i.c
78 | *_p.c
79 | *_h.h
80 | *.ilk
81 | *.meta
82 | *.obj
83 | *.iobj
84 | *.pch
85 | *.pdb
86 | *.ipdb
87 | *.pgc
88 | *.pgd
89 | *.rsp
90 | *.sbr
91 | *.tlb
92 | *.tli
93 | *.tlh
94 | *.tmp
95 | *.tmp_proj
96 | *_wpftmp.csproj
97 | *.log
98 | *.vspscc
99 | *.vssscc
100 | .builds
101 | *.pidb
102 | *.svclog
103 | *.scc
104 |
105 | # Chutzpah Test files
106 | _Chutzpah*
107 |
108 | # Visual C++ cache files
109 | ipch/
110 | *.aps
111 | *.ncb
112 | *.opendb
113 | *.opensdf
114 | *.sdf
115 | *.cachefile
116 | *.VC.db
117 | *.VC.VC.opendb
118 |
119 | # Visual Studio profiler
120 | *.psess
121 | *.vsp
122 | *.vspx
123 | *.sap
124 |
125 | # Visual Studio Trace Files
126 | *.e2e
127 |
128 | # TFS 2012 Local Workspace
129 | $tf/
130 |
131 | # Guidance Automation Toolkit
132 | *.gpState
133 |
134 | # ReSharper is a .NET coding add-in
135 | _ReSharper*/
136 | *.[Rr]e[Ss]harper
137 | *.DotSettings.user
138 |
139 | # TeamCity is a build add-in
140 | _TeamCity*
141 |
142 | # DotCover is a Code Coverage Tool
143 | *.dotCover
144 |
145 | # AxoCover is a Code Coverage Tool
146 | .axoCover/*
147 | !.axoCover/settings.json
148 |
149 | # Coverlet is a free, cross platform Code Coverage Tool
150 | coverage*.json
151 | coverage*.xml
152 | coverage*.info
153 |
154 | # Visual Studio code coverage results
155 | *.coverage
156 | *.coveragexml
157 |
158 | # NCrunch
159 | _NCrunch_*
160 | .*crunch*.local.xml
161 | nCrunchTemp_*
162 |
163 | # MightyMoose
164 | *.mm.*
165 | AutoTest.Net/
166 |
167 | # Web workbench (sass)
168 | .sass-cache/
169 |
170 | # Installshield output folder
171 | [Ee]xpress/
172 |
173 | # DocProject is a documentation generator add-in
174 | DocProject/buildhelp/
175 | DocProject/Help/*.HxT
176 | DocProject/Help/*.HxC
177 | DocProject/Help/*.hhc
178 | DocProject/Help/*.hhk
179 | DocProject/Help/*.hhp
180 | DocProject/Help/Html2
181 | DocProject/Help/html
182 |
183 | # Click-Once directory
184 | publish/
185 |
186 | # Publish Web Output
187 | *.[Pp]ublish.xml
188 | *.azurePubxml
189 | # Note: Comment the next line if you want to checkin your web deploy settings,
190 | # but database connection strings (with potential passwords) will be unencrypted
191 | *.pubxml
192 | *.publishproj
193 |
194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
195 | # checkin your Azure Web App publish settings, but sensitive information contained
196 | # in these scripts will be unencrypted
197 | PublishScripts/
198 |
199 | # NuGet Packages
200 | *.nupkg
201 | # NuGet Symbol Packages
202 | *.snupkg
203 | # The packages folder can be ignored because of Package Restore
204 | **/[Pp]ackages/*
205 | # except build/, which is used as an MSBuild target.
206 | !**/[Pp]ackages/build/
207 | # Uncomment if necessary however generally it will be regenerated when needed
208 | #!**/[Pp]ackages/repositories.config
209 | # NuGet v3's project.json files produces more ignorable files
210 | *.nuget.props
211 | *.nuget.targets
212 |
213 | # Microsoft Azure Build Output
214 | csx/
215 | *.build.csdef
216 |
217 | # Microsoft Azure Emulator
218 | ecf/
219 | rcf/
220 |
221 | # Windows Store app package directories and files
222 | AppPackages/
223 | BundleArtifacts/
224 | Package.StoreAssociation.xml
225 | _pkginfo.txt
226 | *.appx
227 | *.appxbundle
228 | *.appxupload
229 |
230 | # Visual Studio cache files
231 | # files ending in .cache can be ignored
232 | *.[Cc]ache
233 | # but keep track of directories ending in .cache
234 | !?*.[Cc]ache/
235 |
236 | # Others
237 | ClientBin/
238 | ~$*
239 | *~
240 | *.dbmdl
241 | *.dbproj.schemaview
242 | *.jfm
243 | *.pfx
244 | *.publishsettings
245 | orleans.codegen.cs
246 |
247 | # Including strong name files can present a security risk
248 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
249 | #*.snk
250 |
251 | # Since there are multiple workflows, uncomment next line to ignore bower_components
252 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
253 | #bower_components/
254 |
255 | # RIA/Silverlight projects
256 | Generated_Code/
257 |
258 | # Backup & report files from converting an old project file
259 | # to a newer Visual Studio version. Backup files are not needed,
260 | # because we have git ;-)
261 | _UpgradeReport_Files/
262 | Backup*/
263 | UpgradeLog*.XML
264 | UpgradeLog*.htm
265 | ServiceFabricBackup/
266 | *.rptproj.bak
267 |
268 | # SQL Server files
269 | *.mdf
270 | *.ldf
271 | *.ndf
272 |
273 | # Business Intelligence projects
274 | *.rdl.data
275 | *.bim.layout
276 | *.bim_*.settings
277 | *.rptproj.rsuser
278 | *- [Bb]ackup.rdl
279 | *- [Bb]ackup ([0-9]).rdl
280 | *- [Bb]ackup ([0-9][0-9]).rdl
281 |
282 | # Microsoft Fakes
283 | FakesAssemblies/
284 |
285 | # GhostDoc plugin setting file
286 | *.GhostDoc.xml
287 |
288 | # Node.js Tools for Visual Studio
289 | .ntvs_analysis.dat
290 | node_modules/
291 |
292 | # Visual Studio 6 build log
293 | *.plg
294 |
295 | # Visual Studio 6 workspace options file
296 | *.opt
297 |
298 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
299 | *.vbw
300 |
301 | # Visual Studio LightSwitch build output
302 | **/*.HTMLClient/GeneratedArtifacts
303 | **/*.DesktopClient/GeneratedArtifacts
304 | **/*.DesktopClient/ModelManifest.xml
305 | **/*.Server/GeneratedArtifacts
306 | **/*.Server/ModelManifest.xml
307 | _Pvt_Extensions
308 |
309 | # Paket dependency manager
310 | .paket/paket.exe
311 | paket-files/
312 |
313 | # FAKE - F# Make
314 | .fake/
315 |
316 | # CodeRush personal settings
317 | .cr/personal
318 |
319 | # Python Tools for Visual Studio (PTVS)
320 | __pycache__/
321 | *.pyc
322 |
323 | # Cake - Uncomment if you are using it
324 | # tools/**
325 | # !tools/packages.config
326 |
327 | # Tabs Studio
328 | *.tss
329 |
330 | # Telerik's JustMock configuration file
331 | *.jmconfig
332 |
333 | # BizTalk build output
334 | *.btp.cs
335 | *.btm.cs
336 | *.odx.cs
337 | *.xsd.cs
338 |
339 | # OpenCover UI analysis results
340 | OpenCover/
341 |
342 | # Azure Stream Analytics local run output
343 | ASALocalRun/
344 |
345 | # MSBuild Binary and Structured Log
346 | *.binlog
347 |
348 | # NVidia Nsight GPU debugger configuration file
349 | *.nvuser
350 |
351 | # MFractors (Xamarin productivity tool) working folder
352 | .mfractor/
353 |
354 | # Local History for Visual Studio
355 | .localhistory/
356 |
357 | # BeatPulse healthcheck temp database
358 | healthchecksdb
359 |
360 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
361 | MigrationBackup/
362 |
363 | # Ionide (cross platform F# VS Code tools) working folder
364 | .ionide/
365 |
366 | # Fody - auto-generated XML schema
367 | FodyWeavers.xsd
368 |
369 | ##
370 | ## Visual studio for Mac
371 | ##
372 |
373 |
374 | # globs
375 | Makefile.in
376 | *.userprefs
377 | *.usertasks
378 | config.make
379 | config.status
380 | aclocal.m4
381 | install-sh
382 | autom4te.cache/
383 | *.tar.gz
384 | tarballs/
385 | test-results/
386 |
387 | # Mac bundle stuff
388 | *.dmg
389 | *.app
390 |
391 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
392 | # General
393 | .DS_Store
394 | .AppleDouble
395 | .LSOverride
396 |
397 | # Icon must end with two \r
398 | Icon
399 |
400 |
401 | # Thumbnails
402 | ._*
403 |
404 | # Files that might appear in the root of a volume
405 | .DocumentRevisions-V100
406 | .fseventsd
407 | .Spotlight-V100
408 | .TemporaryItems
409 | .Trashes
410 | .VolumeIcon.icns
411 | .com.apple.timemachine.donotpresent
412 |
413 | # Directories potentially created on remote AFP share
414 | .AppleDB
415 | .AppleDesktop
416 | Network Trash Folder
417 | Temporary Items
418 | .apdisk
419 |
420 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
421 | # Windows thumbnail cache files
422 | Thumbs.db
423 | ehthumbs.db
424 | ehthumbs_vista.db
425 |
426 | # Dump file
427 | *.stackdump
428 |
429 | # Folder config file
430 | [Dd]esktop.ini
431 |
432 | # Recycle Bin used on file shares
433 | $RECYCLE.BIN/
434 |
435 | # Windows Installer files
436 | *.cab
437 | *.msi
438 | *.msix
439 | *.msm
440 | *.msp
441 |
442 | # Windows shortcuts
443 | *.lnk
444 |
445 | # JetBrains Rider
446 | .idea/
447 | *.sln.iml
448 |
449 | ##
450 | ## Visual Studio Code
451 | ##
452 | .vscode/*
453 | !.vscode/settings.json
454 | !.vscode/tasks.json
455 | !.vscode/launch.json
456 | !.vscode/extensions.json
457 |
--------------------------------------------------------------------------------
/BasicChromeDriverDetectionPatch.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.32112.339
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicChromeDriverDetectionPatch", "BasicChromeDriverDetectionPatch\BasicChromeDriverDetectionPatch.csproj", "{F248F80C-4F89-4BFF-AD5B-5094E712C1BA}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F248F80C-4F89-4BFF-AD5B-5094E712C1BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {F248F80C-4F89-4BFF-AD5B-5094E712C1BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {F248F80C-4F89-4BFF-AD5B-5094E712C1BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {F248F80C-4F89-4BFF-AD5B-5094E712C1BA}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {2DAE7423-1720-4CA5-8221-DE10E977E833}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/BasicChromeDriverDetectionPatch/BasicChromeDriverDetectionPatch.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0-windows
6 | enable
7 | enable
8 | none
9 | ..\.build\bin\
10 | ..\.build\obj\
11 | none
12 | en-US
13 | BasicChromeDriverDetectionPatch.Program
14 | False
15 | Plot
16 | git
17 | A tool that patches the ChromeDriver binary to avert a "basic" bot detection method used by most anti-automation services.
18 | https://github.com/Plot1337/BasicChromeDriverDetectionPatch
19 | https://github.com/Plot1337/BasicChromeDriverDetectionPatch
20 | ..\LICENSE
21 | bot; chrome; automation; csharp; dotnet; selenium; chromedriver; patch; selenium-webdriver; undetected; undetectable
22 |
23 |
24 |
25 | True
26 |
27 |
28 |
29 | True
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/BasicChromeDriverDetectionPatch/BinHelper.cs:
--------------------------------------------------------------------------------
1 | namespace BasicChromeDriverDetectionPatch
2 | {
3 | internal class BinHelper
4 | {
5 | public static List FindOffsets(byte[]? source, byte[] find)
6 | {
7 | if (source == null)
8 | throw new ArgumentNullException(nameof(source));
9 |
10 | var result = new List();
11 | int matchIndex = 0;
12 |
13 | for (int i = 0; i < source.Length; i++)
14 | {
15 | if (source[i] == find[matchIndex])
16 | {
17 | if (matchIndex == (find.Length - 1))
18 | {
19 | result.Add(i - matchIndex);
20 | continue;
21 | }
22 |
23 | matchIndex++;
24 | }
25 | else if (source[i] == find[0]) matchIndex = 1;
26 | else matchIndex = 0;
27 | }
28 |
29 | return result;
30 | }
31 |
32 | public static byte[] Replace(byte[] source, byte[] search, byte[] replace)
33 | {
34 | byte[]? dst = null;
35 | byte[]? temp = null;
36 |
37 | var offsets = FindOffsets(source, search);
38 |
39 | foreach (var index in offsets)
40 | {
41 | temp = temp == null ? source : (dst ?? source);
42 | dst = new byte[temp.Length - search.Length + replace.Length];
43 |
44 | Buffer.BlockCopy(temp, 0, dst, 0, index);
45 | Buffer.BlockCopy(replace, 0, dst, index, replace.Length);
46 |
47 | Buffer.BlockCopy(
48 | temp,
49 | index + search.Length,
50 | dst,
51 | index + replace.Length,
52 | temp.Length - (index + search.Length));
53 | }
54 |
55 | return dst ?? source;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/BasicChromeDriverDetectionPatch/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace BasicChromeDriverDetectionPatch
4 | {
5 | internal class Program
6 | {
7 | static byte[]? Data;
8 |
9 | static void Main(string[] args)
10 | {
11 | Console.Title =
12 | "Basic ChromeDriver Detection Patch - Plot ";
13 |
14 | if (args.Length == 0)
15 | ErrorExit(
16 | "Usage: [current exe] [path to chromedriver.exe]"
17 | );
18 |
19 | string path = args[0];
20 |
21 | try
22 | {
23 | Console.WriteLine($"Attempting to load... ({path})");
24 | Data = File.ReadAllBytes(path);
25 |
26 | Console.WriteLine("Loaded EXE bin into memory!");
27 |
28 | var ids = GetCdcIds();
29 |
30 | if (ids.Count == 0)
31 | ErrorExit("No IDs found! Perhaps the EXE is already patched?");
32 |
33 | Console.WriteLine($"Found {ids.Count} IDs! Replacing with alts...");
34 |
35 | byte[] AsciiStr(string str) =>
36 | Encoding.ASCII.GetBytes(str);
37 |
38 | foreach (var id in ids)
39 | {
40 | string alt = RandomString();
41 |
42 | Data = BinHelper.Replace(
43 | Data,
44 | AsciiStr(id),
45 | AsciiStr(alt)
46 | );
47 |
48 | Console.WriteLine($"{id} -> {alt}");
49 | }
50 |
51 | string patchedFilePath = path.Replace(".exe", "_patched.exe");
52 |
53 | File.WriteAllBytes(patchedFilePath, Data);
54 | Console.WriteLine("Saved to: " + patchedFilePath);
55 | }
56 | catch (FileNotFoundException) { ErrorExit("Chromedriver EXE not found!"); }
57 | catch (Exception ex) { ErrorExit(ex.ToString()); }
58 |
59 | Exit();
60 | }
61 |
62 | static List GetCdcIds()
63 | {
64 | Console.WriteLine("Finding CDC ids...");
65 |
66 | if (Data == null)
67 | throw new ArgumentNullException(nameof(Data));
68 |
69 | int idLen = 26;
70 | var result = new List();
71 |
72 | // "cdc_" as bytes
73 | byte[] searchArr = {
74 | 0x63, 0x64, 0x63, 0x5F
75 | };
76 |
77 | var offsets = BinHelper.FindOffsets(Data, searchArr);
78 |
79 | foreach (var offset in offsets)
80 | {
81 | var idBytes = Data.Skip(offset).Take(idLen).ToArray();
82 | string id = Encoding.UTF8.GetString(idBytes);
83 |
84 | result.Add(id);
85 | Console.WriteLine($"{offset}: {id}");
86 | }
87 |
88 | return result.Distinct().ToList();
89 | }
90 |
91 | static string RandomString(int length = 26)
92 | {
93 | var random = new Random();
94 | string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
95 |
96 | return new string(
97 | Enumerable.Repeat(chars, length).Select(
98 | i => i[random.Next(i.Length)]
99 | ).ToArray()
100 | );
101 | }
102 |
103 | static void ErrorExit(string message)
104 | {
105 | Console.ForegroundColor = ConsoleColor.Red;
106 | Console.WriteLine(message);
107 | Console.ForegroundColor = ConsoleColor.White;
108 |
109 | Exit();
110 | }
111 |
112 | static void Exit()
113 | {
114 | Console.WriteLine("Press any key to exit...");
115 | Console.ReadKey(true);
116 | Environment.Exit(0);
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Plot
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Basic ChromeDriver Detection Patch
2 | 
3 | 
4 | 
5 |
6 | A tool that patches the ChromeDriver binary to avert a "basic" bot detection method used by most anti-automation services.
7 |
8 | ### Usage ([Download](https://github.com/Plot1337/BasicChromeDriverDetectionPatch/releases)):
9 | 1. Via CLI `BasicChromeDriverDetectionPatch.exe [path_to_chromedriver_exe]`
10 | 2. Or drag-and-drop `chromedriver.exe` into `BasicChromeDriverDetectionPatch.exe`
11 |
12 | The expected output would be an executable file named `chromedriver_patched.exe`.
13 | You can remove the original executable and renamed the modified one so Selenium can properly use it.
14 |
15 | ### How Does It Work?
16 | It's simple; the tool replaces the "CDC" (`_cdc[...]_[...]`) IDs with alternative names.
17 | This tool merely automates a method mentioned in this
18 | [StackOverflow answer](https://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver/41220267).
19 | Please note this tool — just like all other methods of making automation harder to detect, even ones claiming to be "undetectable" — will never actually be undetectable.
20 |
21 | ### Legal
22 | This tool is [licensed under MIT](https://github.com/Plot1337/BasicChromeDriverDetectionPatch/blob/main/LICENSE); do whatever you want with it.
23 |
24 | ### Contact:
25 | - Discord: `Plot#6969` (UID: `972420573173002310`)
26 | - Telegram: `@daddyplot`
27 |
--------------------------------------------------------------------------------