├── README.md ├── LICENSE └── main.py /README.md: -------------------------------------------------------------------------------- 1 | # PyHack 2 | First Python based cheat for Counter-Strike: Global Offensive. 3 | 4 | [![Video of the cheat](http://i.imgur.com/YCKWnpS.png)](https://www.youtube.com/watch?v=b89mWi6bdtY) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Bill Demirkapi 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 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright 2017 Robater - https://www.unknowncheats.me/forum/members/656078.html 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | ''' 10 | 11 | from ctypes import * 12 | from memorpy import * 13 | import time 14 | import win32api 15 | import random 16 | import thread 17 | import win32gui 18 | import math 19 | import winsound 20 | 21 | # OFFSET START # 22 | crossHairIDOffset = 0xAA70 23 | forceAttackOffset = 0x2F0917C 24 | forceJumpOffset = 0x4F5FD5C 25 | clientStateOffset = 0x5CA524 26 | clientStateViewAnglesOffset = 0x4D0C 27 | aimPunchOffset = 0x301C 28 | clientStateInGameOffset = 0x100 29 | flagsOffset = 0x100 30 | vecOriginOffset = 0x134 31 | shotsFiredOffset = 0xA2C0 32 | 33 | entityListOffset = 0x04AC91B4 34 | localPlayerIndexOffset = 0x178 35 | localPlayerOffset = 0xAA66D4 36 | glowObjectOffset = 0x4FE3A5C 37 | glowIndexOffset = 0xA320 38 | teamNumOffset = 0xF0 39 | dormantOffset = 0xE9 40 | healthOffset = 0xFC 41 | bSpottedOffset = 0x939 42 | # OFFSET END # 43 | 44 | # OPTIONS START # 45 | glowESPEnabled = True 46 | triggerBotEnabled = True 47 | autoBHOPEnabled = True 48 | soundESPEnabled = True 49 | rcsEnabled = True 50 | 51 | maxSoundESPDistance = 780 # Default: 780, decent distance tbh 52 | RCSPerfectPercent = 100 # Percent of RCS being perfect, 100% = perfect RCS 53 | triggerBotKey = 0x12 # Default: right-click 54 | triggerBotRandomMinimum = 50 # Minimum miliseconds to wait before shooting, there is a random int between 0-50 added to this in the code 55 | # OPTIONS END # 56 | 57 | foundProcess = False 58 | end = False 59 | csgoWindow = None 60 | 61 | # triggerBot: if entity in crosshair is an enemy, fire with a random delay between triggerBotRandomMinimum miliseconds to triggerBotRandomMinimum + 50 miliseconds 62 | def triggerBot(process, client, clientState): 63 | global end 64 | global csgoWindow 65 | while not end: # This function is threaded so might as well do this :> 66 | time.sleep(0.01) 67 | if not win32gui.GetForegroundWindow(): 68 | continue 69 | if win32gui.GetForegroundWindow() == csgoWindow: 70 | if Address((clientState + clientStateInGameOffset), process).read('int') == 6: # If the client is in game 71 | localPlayer = Address((client + localPlayerOffset), process).read() # Get LocalPlayer 72 | localPlayerTeam = Address((localPlayer + teamNumOffset), process).read('int') # Get the team of the LocalPlayer 73 | 74 | crossHairID = Address((localPlayer + crossHairIDOffset), process).read('int') # Get the Entity ID of the entity in crosshairs 75 | if crossHairID == 0: # If no entity in crosshair 76 | continue 77 | 78 | crossEntity = Address((client + entityListOffset + ((crossHairID - 1) * 0x10)), process).read() # Find entity based on ID defined by crossHairID 79 | 80 | crossEntityTeam = Address((crossEntity + teamNumOffset), process).read('int') # Get team of Entity in Crosshair 81 | 82 | if crossEntityTeam != 2 and crossEntityTeam != 3: # If the entity is not a terrorist or counter-terrorist 83 | continue 84 | 85 | crossEntityDormant = Address((crossEntity + dormantOffset), process).read('int') # Get boolean that states whether entity in crosshair is dormant or not 86 | 87 | if win32api.GetAsyncKeyState(triggerBotKey) and localPlayerTeam != crossEntityTeam and crossEntityDormant == 0: # if triggerBotKey is held, the localPlayers team is not equal to entity in crosshair's team, and if the entity in crosshair is not dormant 88 | time.sleep((triggerBotRandomMinimum + random.randint(0, 50)) / 1000.0) # Sleep for random delay between triggerBotRandomMinimum miliseconds to triggerBotRandomMinimum + 50 miliseconds 89 | while crossHairID != 0 and win32api.GetAsyncKeyState(triggerBotKey): # while there is an entity in my crosshairs and my triggerbot key is held down 90 | crossHairID = Address((localPlayer + crossHairIDOffset), process).read('int') # Re-get the crosshair ID to check if maybe no longer an entity in my crosshair 91 | Address((client + forceAttackOffset), process).write(5, 'int') # Shoot 92 | time.sleep(0.01) # Sleep for 10 ms 93 | Address((client + forceAttackOffset), process).write(4, 'int') # Stop shooting 94 | 95 | # normalizeAngles: Normalize a pair of angles 96 | def normalizeAngles(viewAngleX, viewAngleY): 97 | if viewAngleX < -89.0: 98 | viewAngleX = 89.0 99 | if viewAngleX > 89.0: 100 | viewAngleX = 89.0 101 | if viewAngleY < -180.0: 102 | viewAngleY += 360.0 103 | if viewAngleY > 180.0: 104 | viewAngleY -= 360.0 105 | 106 | return viewAngleX, viewAngleY 107 | 108 | # glowESP: Enables glow around each entity 109 | def glowESP(process, client): 110 | glowLocalBase = Address((client + localPlayerOffset), process).read() # Get the localPlayer 111 | glowPointer = Address((client + glowObjectOffset), process).read() # Get the glow Pointer 112 | myTeamID = Address((glowLocalBase + teamNumOffset), process).read('int') # Get the localPlayer team ID 113 | 114 | playerCount = Address((client + glowObjectOffset + 0x4), process).read('int') 115 | for i in range(1, playerCount): # For each player until the max players available 116 | glowCurrentPlayer = Address((client + entityListOffset + ((i - 1) * 0x10)), process).read() # Get current entity based on for-loop variable i 117 | 118 | if glowCurrentPlayer == 0x0: # If the entity is invalid 119 | break # Break out of the for loop, we have reached the current max players 120 | 121 | glowCurrentPlayerDormant = Address((glowCurrentPlayer + dormantOffset), process).read('int') # Get boolean that states whether glowCurrentPlayer entity is dormant or not 122 | glowCurrentPlayerGlowIndex = Address((glowCurrentPlayer + glowIndexOffset), process).read('int') # Get the glowIndex of the glowCurrentPlayer entity 123 | 124 | entityBaseTeamID = Address((glowCurrentPlayer + teamNumOffset), process).read('int') # Get the team ID of the glowCurrentPlayer entity 125 | 126 | if entityBaseTeamID == 0 or glowCurrentPlayerDormant != 0: # If the glowCurrentPlayer entity is on an irrelevant team (0) or if the glowCurrentPlayer entity is dormant 127 | continue # Continue the for-loop 128 | else: 129 | if myTeamID != entityBaseTeamID: # If localPlayer team is not glowCurrentPlayer entity team 130 | Address((glowCurrentPlayer + bSpottedOffset), process).write(1, 'int') # Set glowCurrentPlayer bspotted to True 131 | 132 | # fucking nigger python with no switch statements kill me 133 | if entityBaseTeamID == 2: # If glowCurrentPlayer entity is a terrorist 134 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x4)), process).write(1.0, 'float') 135 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x8)), process).write(0.0, 'float') 136 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0xC)), process).write(0.0, 'float') 137 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x10)), process).write(1.0, 'float') 138 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x24)), process).write(1, 'int') 139 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x25)), process).write(0, 'int') 140 | elif entityBaseTeamID == 3: # else if glowCurrentPlayer entity is a counter-terrorist 141 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x4)), process).write(0.0, 'float') 142 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x8)), process).write(0.0, 'float') 143 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0xC)), process).write(1.0, 'float') 144 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x10)), process).write(1.0, 'float') 145 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x24)), process).write(1, 'int') 146 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x25)), process).write(0, 'int') 147 | else: 148 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x4)), process).write(0.0, 'float') 149 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x8)), process).write(1.0, 'float') 150 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0xC)), process).write(0.0, 'float') 151 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x10)), process).write(1.0, 'float') 152 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x24)), process).write(1, 'int') 153 | Address((glowPointer + ((glowCurrentPlayerGlowIndex * 0x38) + 0x25)), process).write(0, 'int') 154 | 155 | # BHOP: Automatically start jumping if in game, on the ground, and space is held 156 | def BHOP(process, client, localPlayer, clientState): 157 | global end 158 | global csgoWindow 159 | 160 | while not end: 161 | if win32gui.GetForegroundWindow() == csgoWindow and Address((clientState + clientStateInGameOffset), process).read('int') == 6: # If client is in game 162 | flags = Address((localPlayer + flagsOffset), process).read() # Get client flags 163 | if flags & (1 << 0) and win32api.GetAsyncKeyState(0x20): # If localPlayer on the ground and if space is held 164 | Address((client + forceJumpOffset), process).write(6, 'int') # Autojump 165 | flags = Address((localPlayer + flagsOffset), process).read() # Get the latest flags again 166 | time.sleep(0.01) 167 | 168 | def soundESP(process, client, localPlayer): 169 | global maxSoundESPDistance 170 | global end 171 | global csgoWindow 172 | 173 | while not end: 174 | time.sleep(0.01) 175 | 176 | if win32gui.GetForegroundWindow() == csgoWindow: 177 | closestPlayer = 99999.0 178 | playerCount = Address((client + glowObjectOffset + 0x4), process).read('int') 179 | for i in range(0, playerCount): 180 | ent = Address((client + entityListOffset + ((i - 1) * 0x10)), process).read() # Get current entity based on for-loop variable i 181 | 182 | if ent is 0x0: 183 | break 184 | 185 | entDormant = Address((ent + dormantOffset), process).read('int') # Get boolean that states whether glowCurrentPlayer entity is dormant or not 186 | 187 | if entDormant != 0: 188 | continue 189 | 190 | myTeamID = Address((localPlayer + teamNumOffset), process).read('int') # Get the team ID of the localPlayer 191 | entityBaseTeamID = Address((ent + teamNumOffset), process).read('int') # Get the team ID of the ent entity 192 | 193 | if entityBaseTeamID != 2 and entityBaseTeamID != 3: 194 | continue 195 | 196 | localPlayerX = Address((localPlayer + vecOriginOffset), process).read('float') # Get the X coordinate of the vecOrigin of the localPlayer 197 | localPlayerY = Address((localPlayer + vecOriginOffset + 0x4), process).read('float') # Get the Y coordinate of the vecOrigin of the localPlayer 198 | localPlayerZ = Address((localPlayer + vecOriginOffset + 0x8), process).read('float') # Get the Z coordinate of the vecOrigin of the localPlayer 199 | 200 | entityX = Address((ent + vecOriginOffset), process).read('float') # Get the X coordinate of the vecOrigin of the ent 201 | entityY = Address((ent + vecOriginOffset + 0x4), process).read('float') # Get the Y coordinate of the vecOrigin of the ent 202 | entityZ = Address((ent + vecOriginOffset + 0x8), process).read('float') # Get the Z coordinate of the vecOrigin of the ent 203 | 204 | distance = math.sqrt((pow((entityX - localPlayerX), 2) + pow((entityY - localPlayerY), 2) + pow((entityZ - localPlayerZ), 2))) # Get the distance between localPlayer and ent 205 | 206 | if myTeamID != entityBaseTeamID and distance != 0 and closestPlayer > distance: # If not on localPlayer team and team is either 2 or 3 and distance isnt 0 and distance is less than closestPlayer 207 | closestPlayer = distance 208 | 209 | if closestPlayer != 99999.0 and closestPlayer < maxSoundESPDistance: # If closestPlayer isnt default value and closestPlayer is closer than maxSoundESPDistance 210 | durMath = 1.000/maxSoundESPDistance # Generate baseline mathematical thingy - use ur brain 211 | winsound.Beep(2500, int((durMath * closestPlayer) * 1000)) 212 | 213 | def RCS(process, client, clientState): 214 | oldAimPunchX = 0 # Initializing var (going to be used to store the last aimPunchX) 215 | oldAimPunchY = 0 # Initializing var (going to be used to store the last aimPunchY) 216 | global RCSPerfectPercent # Defines how much RCS we are gonna do 217 | 218 | while True: 219 | if win32gui.GetForegroundWindow() == csgoWindow and Address((clientState + clientStateInGameOffset), process).read('int') == 6: # If we are actually playing in game 220 | localPlayer = Address((client + localPlayerOffset), process).read() # Get the localPlayer 221 | if Address((localPlayer + shotsFiredOffset), process).read('int') > 1: # If we have fired more than 1 shots 222 | viewAngleX = Address((clientState + clientStateViewAnglesOffset), process).read('float') # Get the X viewAngle 223 | viewAngleY = Address((clientState + clientStateViewAnglesOffset + 0x4), process).read('float') # Get the Y viewAngle 224 | 225 | aimPunchX = Address((localPlayer + aimPunchOffset), process).read('float') # Get the X aimPunch 226 | aimPunchY = Address((localPlayer + aimPunchOffset + 0x4), process).read('float') # Get the Y aimPunch 227 | 228 | viewAngleX -= (aimPunchX - oldAimPunchX) * (RCSPerfectPercent * 0.02) # Subtract our AimPunch from our ViewAngle 229 | viewAngleY -= (aimPunchY - oldAimPunchY) * (RCSPerfectPercent * 0.02) # Subtract our AimPunch from our ViewAngle 230 | 231 | viewAngleX, viewAngleY = normalizeAngles(viewAngleX, viewAngleY) # Normalize our ViewAngles 232 | 233 | Address((clientState + clientStateViewAnglesOffset), process).write(viewAngleX, 'float') 234 | Address((clientState + clientStateViewAnglesOffset + 0x4), process).write(viewAngleY, 'float') 235 | 236 | oldAimPunchX = aimPunchX 237 | oldAimPunchY = aimPunchY 238 | else: 239 | oldAimPunchX = 0 240 | oldAimPunchY = 0 241 | time.sleep(0.01) 242 | 243 | def getDLL(name, PID): 244 | hModule = CreateToolhelp32Snapshot(TH32CS_CLASS.SNAPMODULE, PID) 245 | if hModule is not None: 246 | module_entry = MODULEENTRY32() 247 | module_entry.dwSize = sizeof(module_entry) 248 | success = Module32First(hModule, byref(module_entry)) 249 | while success: 250 | if module_entry.th32ProcessID == PID: 251 | if module_entry.szModule == name: 252 | return module_entry.modBaseAddr 253 | success = Module32Next(hModule, byref(module_entry)) 254 | 255 | CloseHandle(hModule) 256 | return 0 257 | 258 | # main: Main function, starts all the threads, does glow esp, waits for end key, etc :) 259 | def main(): 260 | global triggerBotEnabled 261 | global autoBHOPEnabled 262 | global glowESPEnabled 263 | global soundESPEnabled 264 | global end 265 | global csgoWindow 266 | global rcsEnabled 267 | 268 | processHandle = Process(name="csgo") # Get csgo process 269 | if not processHandle: # If handle is bad 270 | print("CSGO not found. Exiting.") # CSGO wasn't found ;''''( 271 | exit(1) 272 | 273 | print("CSGO found, getting necessary modules.") 274 | client = getDLL("client.dll", processHandle.pid) # Get client.dll module 275 | print("Got client.dll.") 276 | 277 | engine = getDLL("engine.dll", processHandle.pid) # Get engine.dll module 278 | print("Got engine.dll.") 279 | 280 | print("Hack started, press END to exit.") 281 | 282 | clientState = Address((engine + clientStateOffset), processHandle).read() # Get clientState pointer 283 | localPlayer = Address((client + localPlayerOffset), processHandle).read() # Get localPlayer pointer 284 | 285 | csgoWindow = win32gui.FindWindow(None, "Counter-Strike: Global Offensive") 286 | if csgoWindow is None: 287 | print("The CSGO Window was not found.") 288 | exit(1) 289 | 290 | if triggerBotEnabled: 291 | try: 292 | thread.start_new_thread(triggerBot, (processHandle, client, clientState, )) # Start triggerBot function threaded 293 | except: 294 | print("Could not start triggerbot thread :(") 295 | 296 | if autoBHOPEnabled: 297 | try: 298 | thread.start_new_thread(BHOP, (processHandle, client, localPlayer, clientState, )) # Start BHOP function threaded 299 | except: 300 | print("Could not start bhop thread :(") 301 | 302 | 303 | if soundESPEnabled: 304 | try: 305 | thread.start_new_thread(soundESP, (processHandle, client, localPlayer, )) # Start soundESP function threaded 306 | except: 307 | print("Could not start playerCounter thread :(") 308 | 309 | if rcsEnabled: 310 | try: 311 | thread.start_new_thread(RCS, (processHandle, client, clientState,)) # Start RCS function threaded 312 | except: 313 | print("Could not start rcs thread :(") 314 | 315 | while not win32api.GetAsyncKeyState(0x23): # While END key isn't touched 316 | if Address((clientState + clientStateInGameOffset), processHandle).read('int') == 6: # If client is in game 317 | if glowESPEnabled and win32gui.GetForegroundWindow() == csgoWindow: 318 | glowESP(processHandle, client) # Call glowESP function non-threaded 319 | time.sleep(0.01) 320 | end = True # Tells the threads to stop looping, prevents future problems 321 | time.sleep(0.01) 322 | 323 | if __name__ == "__main__": 324 | main() --------------------------------------------------------------------------------