Skip to content

Commit

Permalink
Fix cdc_ patching. Fixes ultrafunkamsterdam#986, ultrafunkamsterdam#882
Browse files Browse the repository at this point in the history
  • Loading branch information
lukect committed Jan 27, 2023
1 parent c4cdca8 commit 69dfc11
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 43 deletions.
24 changes: 0 additions & 24 deletions undetected_chromedriver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,31 +600,7 @@ def get_wrapped(*args, **kwargs):

self.get = get_wrapped

def _get_cdc_props(self):
return self.execute_script(
"""
let objectToInspect = window,
result = [];
while(objectToInspect !== null)
{ result = result.concat(Object.getOwnPropertyNames(objectToInspect));
objectToInspect = Object.getPrototypeOf(objectToInspect); }
return result.filter(i => i.match(/^[a-z]{3}_[a-z]{22}_.*/i))
"""
)

def _hook_remove_cdc_props(self, cdc_props):
if len(cdc_props) < 1:
return
cdc_props_js_array = '[' + ', '.join('"' + p + '"' for p in cdc_props) + ']'
self.execute_cdp_cmd(
"Page.addScriptToEvaluateOnNewDocument",
{
"source": cdc_props_js_array + ".forEach(p => delete window[p] && console.log('removed', p));"
},
)

def get(self, url):
self._hook_remove_cdc_props(self._get_cdc_props())
return super().get(url)

def add_cdp_listener(self, event_name, callback):
Expand Down
50 changes: 31 additions & 19 deletions undetected_chromedriver/patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,6 @@ def force_kill_instances(exe_name):
r = os.system("taskkill /f /im %s" % exe_name)
return not r

@staticmethod
def gen_random_cdc():
cdc = random.choices(string.ascii_lowercase, k=26)
cdc[-6:-4] = map(str.upper, cdc[-6:-4])
cdc[2] = cdc[0]
cdc[3] = "_"
return "".join(cdc).encode()

def is_binary_patched(self, executable_path=None):
"""simple check if executable is patched.
Expand All @@ -220,7 +212,7 @@ def is_binary_patched(self, executable_path=None):
executable_path = executable_path or self.executable_path
with io.open(executable_path, "rb") as fh:
for line in iter(lambda: fh.readline(), b""):
if b"cdc_" in line:
if b"cdc_adoQpoasnfa76pfcZLmcfl_" in line:
return False
else:
return True
Expand All @@ -229,20 +221,40 @@ def patch_exe(self):
"""
Patches the ChromeDriver binary
:return: False on failure, binary name on success
:return: True on success
"""
logger.info("patching driver executable %s" % self.executable_path)
start = time.time()

cdc_js_replacements = [ # (old, new, end_empty_filler_byte)
[b"(function () {window.cdc_adoQpoasnfa76pfcZLmcfl_Array = window.Array;"
b"window.cdc_adoQpoasnfa76pfcZLmcfl_Promise = window.Promise;"
b"window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol = window.Symbol;}) ();", b"", b" "],

[b"window.cdc_adoQpoasnfa76pfcZLmcfl_Array ||", b"", b" "], # b" " = whitespace = does nothing in .js

[b"window.cdc_adoQpoasnfa76pfcZLmcfl_Promise ||", b"", b" "],

[b"window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol ||", b"", b" "]
] # https://github.com/search?q=repo%3Achromium%2Fchromium+%2Fcdc_adoQpoasnfa76pfcZLmcfl_%2F&type=code

# (old, new+filler_bytes) [Make replacement equal in length by appending 'filler bytes'
for i in cdc_js_replacements:
diff = len(i[0]) - len(i[1])
if diff > 0:
i[1] = i[1].join([i[2]] * diff)
del i[2]

linect = 0
replacement = self.gen_random_cdc()
with io.open(self.executable_path, "r+b") as fh:
for line in iter(lambda: fh.readline(), b""):
if b"cdc_" in line:
fh.seek(-len(line), 1)
newline = re.sub(b"cdc_.{22}", replacement, line)
fh.write(newline)
linect += 1
return linect
file_bin = fh.read()
for r in cdc_js_replacements:
file_bin = file_bin.replace(r[0], r[1])
fh.seek(0)
fh.write(file_bin)

time_taken_s = time.time() - start
logger.info(f"finished patching driver executable in {time_taken_s:.3f}s")
return True

def __repr__(self):
return "{0:s}({1:s})".format(
Expand Down

0 comments on commit 69dfc11

Please sign in to comment.