Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions deadlock/aimbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class AimbotSettings:
headshot_on_acquire: bool = True
#: force headshots for 0.4s when locking on after a 2s gap

glow_override: bool = False
#: if ``True`` NOP the in-game glow check


class Aimbot:
"""Basic aimbot controller."""
Expand Down
19 changes: 19 additions & 0 deletions deadlock/aimbot_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ def _build_settings_frame(self, parent: ttk.Frame) -> None:
ttk.Entry(hero_frame, textvariable=self.paradox_e_key, width=3).grid(row=hero_row, column=2, sticky="w")
hero_row += 1
row += 1
self.glow_override_var = tk.BooleanVar(value=self.settings.glow_override)
ttk.Checkbutton(
frame,
text="Bypass glow check",
variable=self.glow_override_var,
).grid(row=row, column=0, columnspan=2, sticky="w")
row += 1
control_frame = ttk.Frame(frame)
control_frame.grid(row=row, column=0, columnspan=2, pady=10, sticky="ew")
self.start_button = ttk.Button(control_frame, text="Start", command=self.start)
Expand Down Expand Up @@ -278,6 +285,8 @@ def _apply_widget_values(self) -> None:
if self.paradox_e_key.get():
self.settings.paradox_e_key = ord(self.paradox_e_key.get().upper()[0])

self.settings.glow_override = self.glow_override_var.get()

def start(self) -> None:
"""Start the aimbot."""
if self.is_running:
Expand Down Expand Up @@ -321,6 +330,11 @@ def _initialise_and_run(self) -> None:
"""Initialise memory and run the aimbot."""
try:
mem = DeadlockMemory()
if self.settings.glow_override:
try:
mem.toggle_glow_override(True)
except Exception as exc:
self.log_queue.put(f"Glow override failed: {exc}")
self.bot = Aimbot(mem, self.settings)
self.log_queue.put("Aimbot started successfully.")
self.root.after(0, lambda: (
Expand Down Expand Up @@ -380,6 +394,11 @@ def stop(self) -> None:
return

if self.bot:
if self.settings.glow_override:
try:
self.bot.mem.toggle_glow_override(False)
except Exception as e:
self.log_queue.put(f"Error disabling glow override: {str(e)}")
self.bot.stop()

self.is_running = False
Expand Down
41 changes: 40 additions & 1 deletion deadlock/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""Thin wrapper over :mod:`pymem` for reading Deadlock game memory."""

from dataclasses import dataclass
from typing import Dict, Tuple
from typing import Dict, Tuple, Optional

import pymem

Expand All @@ -12,6 +12,14 @@
from . import mem_offsets as mo
import offset_finder

# Pattern to locate the glow check conditional in client.dll
GLOW_PATTERN = bytes.fromhex(
"0F 85 70 02 00 00 44 0F 11 54 24 58 C7 44 24 68 FF FF 7F FF "
"48 8B CB C7 44 24 6C FF FF 7F FF 48"
)
GLOW_PATCH = b"\x90" * 6
GLOW_ORIGINAL = bytes.fromhex("0F 85 70 02 00 00")


@dataclass
class Offsets:
Expand All @@ -34,6 +42,8 @@ def __init__(self, process: str = "deadlock.exe") -> None:
self.pm.process_handle, "client.dll"
).lpBaseOfDll
self.offsets = self._read_offsets()
self._glow_addr: Optional[int] = None
self._glow_original: bytes | None = None

def _read_offsets(self) -> Offsets:
"""Read offsets via :mod:`offset_finder`."""
Expand Down Expand Up @@ -144,3 +154,32 @@ def read_entity(self, index: int) -> Dict:
"hero": hero_id,
"aim_angle": aim_angle,
}

# Glow override -----------------------------------------------------
def _find_glow_address(self) -> Optional[int]:
module = pymem.process.module_from_name(
self.pm.process_handle, "client.dll"
)
data = self.pm.read_bytes(module.lpBaseOfDll, module.SizeOfImage)
idx = data.find(GLOW_PATTERN)
if idx == -1:
return None
return module.lpBaseOfDll + idx

def toggle_glow_override(self, enable: bool) -> bool:
"""Enable or disable the glow check NOP patch."""

if self._glow_addr is None:
self._glow_addr = self._find_glow_address()
if self._glow_addr is None:
return False

if self._glow_original is None:
try:
self._glow_original = self.pm.read_bytes(self._glow_addr, len(GLOW_PATCH))
except pymem.exception.MemoryReadError as e:
print(f"Failed to read glow bytes: {e}")
self._glow_original = None
patch = GLOW_PATCH if enable else self._glow_original
self.pm.write_bytes(self._glow_addr, patch, len(patch))
return True