commit 698d6f61211ba12dac3055b1a945b98f1efc4c9e Author: Collin Date: Tue Feb 17 22:43:40 2026 +0100 upload files diff --git a/GTASPRXPS4.sln b/GTASPRXPS4.sln new file mode 100644 index 0000000..8b59118 --- /dev/null +++ b/GTASPRXPS4.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.36422.26 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GTASPRXPS4", "GTASPRXPS4.vcxproj", "{82CE3C65-C144-4D91-8A5B-324A963546C3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ORBIS = Debug|ORBIS + Release|ORBIS = Release|ORBIS + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {82CE3C65-C144-4D91-8A5B-324A963546C3}.Debug|ORBIS.ActiveCfg = Debug|ORBIS + {82CE3C65-C144-4D91-8A5B-324A963546C3}.Debug|ORBIS.Build.0 = Debug|ORBIS + {82CE3C65-C144-4D91-8A5B-324A963546C3}.Release|ORBIS.ActiveCfg = Release|ORBIS + {82CE3C65-C144-4D91-8A5B-324A963546C3}.Release|ORBIS.Build.0 = Release|ORBIS + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2A7492B0-84F4-4E66-8BCA-1CF48EB16BC0} + EndGlobalSection +EndGlobal diff --git a/GTASPRXPS4.vcxproj b/GTASPRXPS4.vcxproj new file mode 100644 index 0000000..7bfae57 --- /dev/null +++ b/GTASPRXPS4.vcxproj @@ -0,0 +1,96 @@ + + + + + Debug + ORBIS + + + Release + ORBIS + + + + {82ce3c65-c144-4d91-8a5b-324a963546c3} + + + + DynamicLibrary + + + DynamicLibrary + + + v142 + + + v142 + + + + + + + + + + + + + + + + + + + + + + GTAServer + + + GTAServer + + + + _DEBUG;%(PreprocessorDefinitions); + true + + + NonAslr + $(SCE_ORBIS_SDK_DIR)\target\lib\libSceImeDialog_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceSysmodule_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceMsgDialog_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceCommonDialog_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceSystemService_stub.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceSystemService_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libScePosix_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceNet_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceHttp_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libScePad_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceUserService_stub_weak.a;%(AdditionalDependencies) + + + cd /d "$(TargetDir)" +call "$(TargetDir)make_sprx.bat" + + + + + + NDEBUG;%(PreprocessorDefinitions); + Level2 + + + cd /d "$(TargetDir)" +call "$(TargetDir)make_sprx.bat" + + + + $(SCE_ORBIS_SDK_DIR)\target\lib\libSceImeDialog_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceSysmodule_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceMsgDialog_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceCommonDialog_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceSystemService_stub.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceSystemService_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libScePosix_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceNet_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceHttp_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libScePad_stub_weak.a;$(SCE_ORBIS_SDK_DIR)\target\lib\libSceUserService_stub_weak.a;%(AdditionalDependencies) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GTASPRXPS4.vcxproj.filters b/GTASPRXPS4.vcxproj.filters new file mode 100644 index 0000000..7fb9b8f --- /dev/null +++ b/GTASPRXPS4.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;cc;s;asm + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;pssli + + + {5FAE8098-8EE5-44A0-ABB6-C797B807CDE6} + pssl;scu + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/GTASPRXPS4.vcxproj.user b/GTASPRXPS4.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/GTASPRXPS4.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ORBIS_Debug/GTASPRXPS4.log b/ORBIS_Debug/GTASPRXPS4.log new file mode 100644 index 0000000..e954a00 --- /dev/null +++ b/ORBIS_Debug/GTASPRXPS4.log @@ -0,0 +1,30 @@ + prx.cpp +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(257,12): warning : unused variable 'g_user_logged_in' [-Wunused-variable] + static int g_user_logged_in = 0; + ^ +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(258,29): warning : unused variable 'g_user_id' [-Wunused-variable] + static SceUserServiceUserId g_user_id = 1; + ^ +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(259,12): warning : unused variable 'g_login_event_pending' [-Wunused-variable] + static int g_login_event_pending = 1; + ^ +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(260,12): warning : unused variable 'g_logout_event_pending' [-Wunused-variable] + static int g_logout_event_pending = 0; + ^ + 4 warnings generated. + orbis-ld 4.50.0.4213 (rel,orbis,4.500 @342832 x64) C:\Program Files (x86)\SCE\ORBIS SDKs\4.500\host_tools\bin\orbis-ld.exe +Command line : warning : L0474: The --addressing= option only applies to main modules and will be ignored + GTASPRXPS4.vcxproj -> C:\Users\DontCry361x\Documents\GTASPRXPS4\ORBIS_Debug\GTAServer.prx + [INFO] Running fself.py ... + loading elf file: GTAServer.prx + saving fake signed elf file: test.sprx + processing segment #00... + processing segment #01... + processing segment #02... + processing segment #07... + processing segment #08... + done + [OK] SPRX created. + [INFO] Uploading to PS4... + Connecting to 192.168.137.241:2121 ... +C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(148,5): warning MSB5021: Terminating the task executable "cmd" and its child processes because the build was canceled. diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate b/ORBIS_Debug/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate new file mode 100644 index 0000000..1869063 --- /dev/null +++ b/ORBIS_Debug/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.0:PlatformToolSet=Clang:EnableManagedIncrementalBuild=:VCToolArchitecture=:WindowsTargetPlatformVersion= +Debug|ORBIS|C:\Users\DontCry361x\Documents\GTASPRXPS4\| diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog new file mode 100644 index 0000000..b1ce1d8 Binary files /dev/null and b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog differ diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog new file mode 100644 index 0000000..b85a36d Binary files /dev/null and b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog differ diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog new file mode 100644 index 0000000..2060cfa Binary files /dev/null and b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog differ diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.command.1.tlog b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.command.1.tlog new file mode 100644 index 0000000..4b08a14 Binary files /dev/null and b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.command.1.tlog differ diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.read.1.tlog b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.read.1.tlog new file mode 100644 index 0000000..5c21f1b Binary files /dev/null and b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.read.1.tlog differ diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.write.1.tlog b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.write.1.tlog new file mode 100644 index 0000000..36d6c6a Binary files /dev/null and b/ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.write.1.tlog differ diff --git a/ORBIS_Debug/GTASPRXPS4.tlog/unsuccessfulbuild b/ORBIS_Debug/GTASPRXPS4.tlog/unsuccessfulbuild new file mode 100644 index 0000000..e69de29 diff --git a/ORBIS_Debug/GTAServer.prx b/ORBIS_Debug/GTAServer.prx new file mode 100644 index 0000000..7a19bcb Binary files /dev/null and b/ORBIS_Debug/GTAServer.prx differ diff --git a/ORBIS_Debug/Syscall.o b/ORBIS_Debug/Syscall.o new file mode 100644 index 0000000..a93dc73 Binary files /dev/null and b/ORBIS_Debug/Syscall.o differ diff --git a/ORBIS_Debug/fself.py b/ORBIS_Debug/fself.py new file mode 100644 index 0000000..3ce7008 --- /dev/null +++ b/ORBIS_Debug/fself.py @@ -0,0 +1,816 @@ +#!/usr/bin/env python + +import sys, os, struct, traceback +import hashlib, hmac +import argparse, re, string + +def int_with_base_type(val): + return int(val, 0) + +def try_parse_int(x, base=0): + try: + return int(x, base) if isinstance(x, str) else int(x) + except: + return None + +def align_up(x, alignment): + return (x + (alignment - 1)) & ~(alignment - 1) + +def align_down(x, alignment): + return x & ~(alignment - 1) + +def ilog2(x): + if x <= 0: + raise ValueError('math domain error') + return len(bin(x)) - 3 + +def is_intervals_overlap(p1, p2): + return p1[0] <= p2[1] and p1[1] <= p2[0] + +def check_file_magic(f, expected_magic): + old_offset = f.tell() + try: + magic = f.read(len(expected_magic)) + except: + return False + finally: + f.seek(old_offset) + return magic == expected_magic + +def parse_version(version): + major, minor, patch = (version >> 8) & 0xFF, version & 0xFF, 0 # FIXME + major = 10 * (major >> 4) + (major & 0xF) + minor = 10 * (minor >> 4) + (minor & 0xF) + return '{0:d}.{1:02d}.{2:03d}'.format(major, minor, patch) + +def sha256(data): + return hashlib.sha256(data).digest() + +def hmac_sha256(key, data): + return hmac.new(key=key, msg=data, digestmod=hashlib.sha256).digest() + +class ElfError(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + +class ElfEHdr(object): + FMT = '<4s5B6xB' + EX_FMT = '<2HI3QI6H' + + MAGIC = '\x7FELF' + CLASS64 = 0x2 + DATA2LSB = 0x1 + EM_X86_64 = 0x3E + EV_CURRENT = 0x1 + + ET_EXEC = 0x2 + ET_SCE_EXEC = 0xFE00 + ET_SCE_EXEC_ASLR = 0xFE10 + ET_SCE_DYNAMIC = 0xFE18 + + def __init__(self): + self.magic = None + self.machine_class = None + self.data_encoding = None + self.version = None + self.os_abi = None + self.abi_version = None + self.nident_size = None + self.type = None + self.machine = None + self.version = None + self.entry = None + self.phoff = None + self.shoff = None + self.flags = None + self.ehsize = None + self.phentsize = None + self.phnum = None + self.shentsize = None + self.shnum = None + self.shstridx = None + + def load(self, f): + if not check_file_magic(f, ElfEHdr.MAGIC): + raise ElfError('Invalid magic.') + + self.magic, self.machine_class, self.data_encoding, self.version, self.os_abi, self.abi_version, self.nident_size = struct.unpack(ElfEHdr.FMT, f.read(struct.calcsize(ElfEHdr.FMT))) + if self.machine_class != ElfEHdr.CLASS64 or self.data_encoding != ElfEHdr.DATA2LSB: + raise ElfError('Unsupported class or data encoding.') + self.type, self.machine, self.version, self.entry, self.phoff, self.shoff, self.flags, self.ehsize, self.phentsize, self.phnum, self.shentsize, self.shnum, self.shstridx = struct.unpack(ElfEHdr.EX_FMT, f.read(struct.calcsize(ElfEHdr.EX_FMT))) + if self.machine != ElfEHdr.EM_X86_64 or self.version != ElfEHdr.EV_CURRENT: + raise ElfError('Unsupported machine type or version.') + if self.phentsize != struct.calcsize(ElfPHdr.FMT) or (self.shentsize > 0 and self.shentsize != struct.calcsize(ElfSHdr.FMT)): + raise ElfError('Unsupported header entry size.') + if self.type not in [ElfEHdr.ET_EXEC, ElfEHdr.ET_SCE_EXEC, ElfEHdr.ET_SCE_EXEC_ASLR, ElfEHdr.ET_SCE_DYNAMIC]: + raise ElfError('Unsupported type.') + + def save(self, f): + f.write(struct.pack(ElfEHdr.FMT, self.magic, self.machine_class, self.data_encoding, self.version, self.os_abi, self.abi_version, self.nident_size)) + f.write(struct.pack(ElfEHdr.EX_FMT, self.type, self.machine, self.version, self.entry, self.phoff, self.shoff, self.flags, self.ehsize, self.phentsize, self.phnum, self.shentsize, self.shnum, self.shstridx)) + + def has_segments(self): + return self.phentsize > 0 and self.phnum > 0 + + def has_sections(self): + return self.shentsize > 0 and self.shnum > 0 + +class ElfPHdr(object): + FMT = '<2I6Q' + + PT_LOAD = 0x1 + PT_DYNAMIC = 0x2 + PT_INTERP = 0x3 + PT_TLS = 0x7 + PT_GNU_EH_FRAME = 0x6474E550 + PT_GNU_STACK = 0x6474E551 + PT_SCE_RELA = 0x60000000, + PT_SCE_DYNLIBDATA = 0x61000000 + PT_SCE_PROCPARAM = 0x61000001 + PT_SCE_MODULE_PARAM = 0x61000002 + PT_SCE_RELRO = 0x61000010 + PT_SCE_COMMENT = 0x6FFFFF00 + PT_SCE_VERSION = 0x6FFFFF01 + + PF_EXEC = 0x1 + PF_WRITE = 0x2 + PF_READ = 0x4 + PF_READ_EXEC = PF_READ | PF_EXEC + PF_READ_WRITE = PF_READ | PF_WRITE + + def __init__(self, idx): + self.idx = idx + self.type = None + self.flags = None + self.offset = None + self.vaddr = None + self.paddr = None + self.filesz = None + self.memsz = None + self.align = None + + def load(self, f): + self.type, self.flags, self.offset, self.vaddr, self.paddr, self.filesz, self.memsz, self.align = struct.unpack(ElfPHdr.FMT, f.read(struct.calcsize(ElfPHdr.FMT))) + + def save(self, f): + f.write(struct.pack(ElfPHdr.FMT, self.type, self.flags, self.offset, self.vaddr, self.paddr, self.filesz, self.memsz, self.align)) + + def name(self): + if self.type == ElfPHdr.PT_LOAD: + if (self.flags & ElfPHdr.PF_READ_EXEC) == ElfPHdr.PF_READ_EXEC: + return '.text' + elif (self.flags & ElfPHdr.PF_READ_WRITE) == ElfPHdr.PF_READ_WRITE: + return '.data' + else: + return '.load_{0:02}'.format(self.idx) + else: + return { + ElfPHdr.PT_DYNAMIC: '.dynamic', + ElfPHdr.PT_INTERP: '.interp', + ElfPHdr.PT_TLS: '.tls', + ElfPHdr.PT_GNU_EH_FRAME: '.eh_frame_hdr', + ElfPHdr.PT_SCE_DYNLIBDATA: '.sce_dynlib_data', + ElfPHdr.PT_SCE_PROCPARAM: '.sce_process_param', + ElfPHdr.PT_SCE_MODULE_PARAM: '.sce_module_param', + ElfPHdr.PT_SCE_COMMENT: '.sce_comment', + }.get(self.type, None) + + def class_name(self): + if (self.flags & ElfPHdr.PF_READ_EXEC) == ElfPHdr.PF_READ_EXEC: + return 'CODE' + else: + return 'DATA' + +class ElfSHdr(object): + FMT = '<2I4Q2I2Q' + + def __init__(self, idx): + self.idx = idx + self.name = None + self.type = None + self.flags = None + self.addr = None + self.offset = None + self.size = None + self.link = None + self.info = None + self.align = None + self.entsize = None + + def load(self, f): + self.name, self.type, self.flags, self.addr, self.offset, self.size, self.link, self.info, self.align, self.entsize = struct.unpack(ElfSHdr.FMT, f.read(struct.calcsize(ElfSHdr.FMT))) + + def save(self, f): + f.write(struct.pack(ElfSHdr.FMT, self.name, self.type, self.flags, self.addr, self.offset, self.size, self.link, self.info, self.align, self.entsize)) + +class ElfFile(object): + def __init__(self, **kwargs): + self.ehdr = None + self.phdrs = None + self.shdrs = None + self.file_size = None + self.digest = None + self.segments = None + self.sections = None + self.ignore_shdrs = 'ignore_shdrs' in kwargs and kwargs['ignore_shdrs'] + + def load(self, f): + start_offset = f.tell() + data = f.read() + self.file_size = len(data) + self.digest = sha256(data) + f.seek(start_offset) + + self.ehdr = ElfEHdr() + self.ehdr.load(f) + + if self.ignore_shdrs: + self.ehdr.shnum = 0 + + self.phdrs = [] + self.segments = [] + if self.ehdr.has_segments(): + for i in xrange(self.ehdr.phnum): + f.seek(start_offset + self.ehdr.phoff + i * self.ehdr.phentsize) + phdr = ElfPHdr(i) + phdr.load(f) + self.phdrs.append(phdr) + if phdr.filesz > 0: + f.seek(start_offset + phdr.offset) + data = f.read(phdr.filesz) + else: + data = '' + self.segments.append(data) + + self.shdrs = [] + self.sections = [] + if self.ehdr.has_sections(): + for i in xrange(self.ehdr.shnum): + f.seek(start_offset + self.ehdr.shoff + i * self.ehdr.shentsize) + shdr = ElfSHdr(i) + shdr.load(f) + self.shdrs.append(shdr) + if phdr.filesz > 0: + f.seek(start_offset + shdr.offset) + data = f.read(phdr.filesz) + else: + data = '' + self.sections.append(data) + + def save(self, f, no_sections=False): + start_offset = f.tell() + + self.ehdr.save(f) + + if not no_sections: + if self.ehdr.has_sections(): + for i in xrange(self.ehdr.shnum): + f.seek(start_offset + self.ehdr.shoff + i * self.ehdr.shentsize) + shdr = self.shdrs[i] + shdr.save(f) + + if self.ehdr.has_segments(): + for i in xrange(self.ehdr.phnum): + f.seek(start_offset + self.ehdr.phoff + i * self.ehdr.phentsize) + phdr = self.phdrs[i] + phdr.save(f) + +DIGEST_SIZE = 0x20 +SIGNATURE_SIZE = 0x100 +BLOCK_SIZE = 0x4000 +DEFAULT_BLOCK_SIZE = 0x1000 + +SELF_CONTROL_BLOCK_TYPE_NPDRM = 0x3 +SELF_NPDRM_CONTROL_BLOCK_CONTENT_ID_SIZE = 0x13 +SELF_NPDRM_CONTROL_BLOCK_RANDOM_PAD_SIZE = 0xD + +EMPTY_DIGEST = '\0' * DIGEST_SIZE +EMPTY_SIGNATURE = '\0' * SIGNATURE_SIZE + +class SignedElfEntry(object): + FMT = '<4Q' + + PROPS_ORDER_SHIFT = 0 + PROPS_ORDER_MASK = 0x1 + PROPS_ENCRYPTED_SHIFT = 1 + PROPS_ENCRYPTED_MASK = 0x1 + PROPS_SIGNED_SHIFT = 2 + PROPS_SIGNED_MASK = 0x1 + PROPS_COMPRESSED_SHIFT = 3 + PROPS_COMPRESSED_MASK = 0x1 + PROPS_WINDOW_BITS_SHIFT = 8 + PROPS_WINDOW_BITS_MASK = 0x7 + PROPS_HAS_BLOCKS_SHIFT = 11 + PROPS_HAS_BLOCKS_MASK = 0x1 + PROPS_BLOCK_SIZE_SHIFT = 12 + PROPS_BLOCK_SIZE_MASK = 0xF + PROPS_HAS_DIGESTS_SHIFT = 16 + PROPS_HAS_DIGESTS_MASK = 0x1 + PROPS_HAS_EXTENTS_SHIFT = 17 + PROPS_HAS_EXTENTS_MASK = 0x1 + PROPS_HAS_META_SEGMENT_SHIFT = 20 + PROPS_HAS_META_SEGMENT_MASK = 0x1 + PROPS_SEGMENT_INDEX_SHIFT = 20 + PROPS_SEGMENT_INDEX_MASK = 0xFFFF + PROPS_DEFAULT_BLOCK_SIZE = 0x1000 + PROPS_META_SEGMENT_MASK = 0xF0000 + + def __init__(self, index): + self.index = index + + self.props = None + self.offset = None + self.filesz = None + self.memsz = None + + self.data = None + + def save(self, f): + f.write(struct.pack(SignedElfEntry.FMT, self.props, self.offset, self.filesz, self.memsz)) + + @property + def order(self): + return (self.props >> SignedElfEntry.PROPS_ORDER_SHIFT) & SignedElfEntry.PROPS_ORDER_MASK + + @order.setter + def order(self, value): + self.props &= ~(SignedElfEntry.PROPS_ORDER_MASK << SignedElfEntry.PROPS_ORDER_SHIFT) + self.props |= (value & SignedElfEntry.PROPS_ORDER_MASK) << SignedElfEntry.PROPS_ORDER_SHIFT + + @property + def encrypted(self): + return ((self.props >> SignedElfEntry.PROPS_ENCRYPTED_SHIFT) & SignedElfEntry.PROPS_ENCRYPTED_MASK) != 0 + + @encrypted.setter + def encrypted(self, value): + self.props &= ~(SignedElfEntry.PROPS_ENCRYPTED_MASK << SignedElfEntry.PROPS_ENCRYPTED_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_ENCRYPTED_MASK << SignedElfEntry.PROPS_ENCRYPTED_SHIFT + + @property + def signed(self): + return ((self.props >> SignedElfEntry.PROPS_SIGNED_SHIFT) & SignedElfEntry.PROPS_SIGNED_MASK) != 0 + + @signed.setter + def signed(self, value): + self.props &= ~(SignedElfEntry.PROPS_SIGNED_MASK << SignedElfEntry.PROPS_SIGNED_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_SIGNED_MASK << SignedElfEntry.PROPS_SIGNED_SHIFT + + @property + def compressed(self): + return ((self.props >> SignedElfEntry.PROPS_COMPRESSED_SHIFT) & SignedElfEntry.PROPS_COMPRESSED_MASK) != 0 + + @compressed.setter + def compressed(self, value): + self.props &= ~(SignedElfEntry.PROPS_COMPRESSED_MASK << SignedElfEntry.PROPS_COMPRESSED_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_COMPRESSED_MASK << SignedElfEntry.PROPS_COMPRESSED_SHIFT + + @property + def has_blocks(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_BLOCKS_SHIFT) & SignedElfEntry.PROPS_HAS_BLOCKS_MASK) != 0 + + @has_blocks.setter + def has_blocks(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_BLOCKS_MASK << SignedElfEntry.PROPS_HAS_BLOCKS_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_BLOCKS_MASK << SignedElfEntry.PROPS_HAS_BLOCKS_SHIFT + + @property + def has_digests(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_DIGESTS_SHIFT) & SignedElfEntry.PROPS_HAS_DIGESTS_MASK) != 0 + + @has_digests.setter + def has_digests(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_DIGESTS_MASK << SignedElfEntry.PROPS_HAS_DIGESTS_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_DIGESTS_MASK << SignedElfEntry.PROPS_HAS_DIGESTS_SHIFT + + @property + def has_extents(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_EXTENTS_SHIFT) & SignedElfEntry.PROPS_HAS_EXTENTS_MASK) != 0 + + @has_extents.setter + def has_extents(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_EXTENTS_MASK << SignedElfEntry.PROPS_HAS_EXTENTS_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_EXTENTS_MASK << SignedElfEntry.PROPS_HAS_EXTENTS_SHIFT + + @property + def has_meta_segment(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_META_SEGMENT_SHIFT) & SignedElfEntry.PROPS_HAS_META_SEGMENT_MASK) != 0 + + @has_meta_segment.setter + def has_meta_segment(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_META_SEGMENT_MASK << SignedElfEntry.PROPS_HAS_META_SEGMENT_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_META_SEGMENT_MASK << SignedElfEntry.PROPS_HAS_META_SEGMENT_SHIFT + + @property + def wbits(self): + return (self.props >> SignedElfEntry.PROPS_WINDOW_BITS_SHIFT) & SignedElfEntry.PROPS_WINDOW_BITS_MASK + + @wbits.setter + def wbits(self, value): + self.props &= ~(SignedElfEntry.PROPS_WINDOW_BITS_MASK << SignedElfEntry.PROPS_WINDOW_BITS_SHIFT) + self.props |= (value & SignedElfEntry.PROPS_WINDOW_BITS_MASK) << SignedElfEntry.PROPS_WINDOW_BITS_SHIFT + + @property + def block_size(self): + if self.has_blocks: + return 1 << (12 + (self.props >> SignedElfEntry.PROPS_BLOCK_SIZE_SHIFT) & SignedElfEntry.PROPS_BLOCK_SIZE_MASK) + else: + return DEFAULT_BLOCK_SIZE + + @block_size.setter + def block_size(self, value): + self.props &= ~(SignedElfEntry.PROPS_BLOCK_SIZE_MASK << SignedElfEntry.PROPS_BLOCK_SIZE_SHIFT) + if self.has_blocks: + value = ilog2(value) - 12 + else: + value = 0 # TODO: check + self.props |= (value & SignedElfEntry.PROPS_BLOCK_SIZE_MASK) << SignedElfEntry.PROPS_BLOCK_SIZE_SHIFT + + @property + def segment_index(self): + return (self.props >> SignedElfEntry.PROPS_SEGMENT_INDEX_SHIFT) & SignedElfEntry.PROPS_SEGMENT_INDEX_MASK + + @wbits.setter + def segment_index(self, value): + self.props &= ~(SignedElfEntry.PROPS_SEGMENT_INDEX_MASK << SignedElfEntry.PROPS_SEGMENT_INDEX_SHIFT) + self.props |= (value & SignedElfEntry.PROPS_SEGMENT_INDEX_MASK) << SignedElfEntry.PROPS_SEGMENT_INDEX_SHIFT + + def is_meta_segment(self): # TODO: check + return (self.props & SignedElfEntry.PROPS_META_SEGMENT_MASK) != 0 + + def __repr__(self): + return 'prs:0x{0:X} ofs:0x{1:X} fsz:0x{2:X} msz:0x{3:X}'.format(self.props, self.offset, self.filesz, self.memsz) + +class SignedElfExInfo(object): + FMT = '<4Q32s' + + PTYPE_FAKE = 0x1 + PTYPE_NPDRM_EXEC = 0x4 + PTYPE_NPDRM_DYNLIB = 0x5 + PTYPE_SYSTEM_EXEC = 0x8 + PTYPE_SYSTEM_DYNLIB = 0x9 # including Mono binaries + PTYPE_HOST_KERNEL = 0xC + PTYPE_SECURE_MODULE = 0xE + PTYPE_SECURE_KERNEL = 0xF + + def __init__(self): + self.paid = None + self.ptype = None + self.app_version = None + self.fw_version = None + self.digest = None + + def save(self, f): + f.write(struct.pack(SignedElfExInfo.FMT, self.paid, self.ptype, self.app_version, self.fw_version, self.digest)) + +class SignedElfNpdrmControlBlock(object): + FMT = ' 0: + if val.startswith('0x') or val.startswith('0X'): + val = val[2:] + if len(val) % 2 != 0 or not all(x in string.hexdigits for x in val): + return None + val = val.decode('hex') + val_size = len(val) + + if not exact_size is None and val_size != exact_size: + return None + else: + if not min_size is None and val_size < min_size: + return None + if not max_size is None and val_size > max_size: + return None + + return val + +def input_file_type(val): + if not os.access(val, os.F_OK | os.R_OK) or not os.path.isfile(val): + raise argparse.ArgumentTypeError('invalid input file: {0}'.format(val)) + return val + +def output_file_type(val): + if os.access(val, os.F_OK) and (not os.path.isfile(val) or not os.access(val, os.F_OK | os.W_OK)): + raise argparse.ArgumentTypeError('invalid output file: {0}'.format(val)) + return val + +def auth_info_type(val): + new_val = ensure_hex_string(val, exact_size=0x88) + if new_val is None: + raise argparse.ArgumentTypeError('invalid auth info: {0}'.format(val)) + return new_val + +class MyParser(argparse.ArgumentParser): + def error(self, message): + self.print_help() + sys.stderr.write('\nerror: {0}\n'.format(message)) + sys.exit(2) + +parser = MyParser(description='fake signed elf maker') +parser.add_argument('input', type=input_file_type, default=None, help='elf/prx file path') +parser.add_argument('output', type=output_file_type, default=None, help='self/sprx file path') +parser.add_argument('--paid', type=int_with_base_type, default=0x3100000000000002, help='program authentication id') +parser.add_argument('--ptype', default=None, help='program type {fake, npdrm_exec, npdrm_dynlib, system_exec, system_dynlib, host_kernel, secure_module, secure_kernel}') +parser.add_argument('--app-version', type=int_with_base_type, default=0, help='application version') +parser.add_argument('--fw-version', type=int_with_base_type, default=0, help='firmware version') +parser.add_argument('--auth-info', type=auth_info_type, default=None, help='authentication info') + +if len(sys.argv) == 1: + parser.print_usage() + sys.exit(1) + +args = parser.parse_args() + +paid = args.paid +if not (0 <= paid <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid program authentication id: 0x{0:016X}'.format(paid)) + +ptype = SignedElfExInfo.PTYPE_FAKE +if not args.ptype is None: + ptype = { + 'fake': SignedElfExInfo.PTYPE_FAKE, + 'npdrm_exec': SignedElfExInfo.PTYPE_NPDRM_EXEC, + 'npdrm_dynlib': SignedElfExInfo.PTYPE_NPDRM_DYNLIB, + 'system_exec': SignedElfExInfo.PTYPE_SYSTEM_EXEC, + 'system_dynlib': SignedElfExInfo.PTYPE_SYSTEM_DYNLIB, + 'host_kernel': SignedElfExInfo.PTYPE_HOST_KERNEL, + 'secure_module': SignedElfExInfo.PTYPE_SECURE_MODULE, + 'secure_kernel': SignedElfExInfo.PTYPE_SECURE_KERNEL, + }.get(args.ptype.strip().lower(), None) + if ptype is None: + ptype = try_parse_int(args.ptype) + if ptype is None: + parser.error('invalid program type: 0x{0:016X}'.format(ptype)) +if not (0 <= ptype <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid program type: 0x{0:016X}'.format(ptype)) + +app_version = args.app_version +if not (0 <= app_version <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid application version: 0x{0:016X}'.format(app_version)) + +fw_version = args.fw_version +if not (0 <= fw_version <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid firmware version: 0x{0:016X}'.format(fw_version)) + +auth_info = args.auth_info + +elf_file_path = args.input +fself_file_path = args.output + +print('loading elf file: {0}'.format(elf_file_path)) +try: + with open(elf_file_path, 'rb') as f: + elf_file = ElfFile(ignore_shdrs=True) + elf_file.load(f) +except Exception as err: + traceback.print_exc() + print('') + parser.error('unable to load elf file: {0} ({1})'.format(elf_file_path, err)) + +print('saving fake signed elf file: {0}'.format(fself_file_path)) +try: + with open(fself_file_path, 'wb') as f: + self_file = SignedElfFile(elf_file, paid=paid, ptype=ptype, app_version=app_version, fw_version=fw_version, auth_info=auth_info) + self_file.save(f) +except Exception as err: + traceback.print_exc() + print('') + parser.error('unable to save fself file: {0} ({1})'.format(elf_file_path, err)) + +print('done') \ No newline at end of file diff --git a/ORBIS_Debug/make_sprx.bat b/ORBIS_Debug/make_sprx.bat new file mode 100644 index 0000000..7c2ab9a --- /dev/null +++ b/ORBIS_Debug/make_sprx.bat @@ -0,0 +1,46 @@ +@echo off +setlocal + +REM ============================== +REM RUN FSELF +REM ============================== +echo [INFO] Running fself.py ... +C:\Python27\python.exe fself.py GTAServer.prx test.sprx + +if %errorlevel% neq 0 ( + echo [ERROR] fself failed. + exit /b 1 +) + +echo [OK] SPRX created. + +REM ============================== +REM FTP UPLOAD (WinSCP) +REM ============================== +set WINSCP="C:\Program Files (x86)\WinSCP\winscp.com" +set PS4_IP=192.168.137.241 +set PS4_PORT=2121 +set REMOTE_DIR=/data/GoldHEN/plugins +set FILE=test.sprx + +if not exist "%FILE%" ( + echo [ERROR] %FILE% not found. + exit /b 1 +) + +echo [INFO] Uploading to PS4... + +%WINSCP% ^ + /command ^ + "open ftp://anonymous@%PS4_IP%:%PS4_PORT%/" ^ + "cd %REMOTE_DIR%" ^ + "put %FILE%" ^ + "exit" + +if %errorlevel% neq 0 ( + echo [ERROR] FTP upload failed. + exit /b 1 +) + +echo [OK] FTP upload successful. +exit /b 0 diff --git a/ORBIS_Debug/prx.o b/ORBIS_Debug/prx.o new file mode 100644 index 0000000..3cf2871 Binary files /dev/null and b/ORBIS_Debug/prx.o differ diff --git a/ORBIS_Debug/test.sprx b/ORBIS_Debug/test.sprx new file mode 100644 index 0000000..10c8c9a Binary files /dev/null and b/ORBIS_Debug/test.sprx differ diff --git a/ORBIS_Release/GTASPRXPS4.log b/ORBIS_Release/GTASPRXPS4.log new file mode 100644 index 0000000..5801c20 --- /dev/null +++ b/ORBIS_Release/GTASPRXPS4.log @@ -0,0 +1,21 @@ + prx.cpp +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(257,12): warning : unused variable 'g_user_logged_in' [-Wunused-variable] + static int g_user_logged_in = 0; + ^ +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(258,29): warning : unused variable 'g_user_id' [-Wunused-variable] + static SceUserServiceUserId g_user_id = 1; + ^ +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(259,12): warning : unused variable 'g_login_event_pending' [-Wunused-variable] + static int g_login_event_pending = 1; + ^ +C:\Users\DontCry361x\Documents\GTASPRXPS4\prx.cpp(260,12): warning : unused variable 'g_logout_event_pending' [-Wunused-variable] + static int g_logout_event_pending = 0; + ^ + 4 warnings generated. + GTASPRXPS4.vcxproj -> C:\Users\DontCry361x\Documents\GTASPRXPS4\ORBIS_Release\GTAServer.prx + '"C:\Users\DontCry361x\Documents\GTASPRXPS4\ORBIS_Release\make_sprx.bat"' is not recognized as an internal or external command, + operable program or batch file. +C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(148,5): error MSB3073: The command "cd /d "C:\Users\DontCry361x\Documents\GTASPRXPS4\ORBIS_Release\" +C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(148,5): error MSB3073: call "C:\Users\DontCry361x\Documents\GTASPRXPS4\ORBIS_Release\make_sprx.bat" +C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(148,5): error MSB3073: +C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(148,5): error MSB3073: :VCEnd" exited with code 1. diff --git a/ORBIS_Release/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate b/ORBIS_Release/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate new file mode 100644 index 0000000..e49a8f9 --- /dev/null +++ b/ORBIS_Release/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.0:PlatformToolSet=Clang:EnableManagedIncrementalBuild=:VCToolArchitecture=:WindowsTargetPlatformVersion= +Release|ORBIS|C:\Users\DontCry361x\Documents\GTASPRXPS4\| diff --git a/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog b/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog new file mode 100644 index 0000000..853423a Binary files /dev/null and b/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog differ diff --git a/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog b/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog new file mode 100644 index 0000000..43d01b9 Binary files /dev/null and b/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog differ diff --git a/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog b/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog new file mode 100644 index 0000000..688cd85 Binary files /dev/null and b/ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog differ diff --git a/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.command.1.tlog b/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.command.1.tlog new file mode 100644 index 0000000..7d389c5 Binary files /dev/null and b/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.command.1.tlog differ diff --git a/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.read.1.tlog b/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.read.1.tlog new file mode 100644 index 0000000..37d7251 Binary files /dev/null and b/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.read.1.tlog differ diff --git a/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.write.1.tlog b/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.write.1.tlog new file mode 100644 index 0000000..bdafe7d Binary files /dev/null and b/ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.write.1.tlog differ diff --git a/ORBIS_Release/GTASPRXPS4.tlog/unsuccessfulbuild b/ORBIS_Release/GTASPRXPS4.tlog/unsuccessfulbuild new file mode 100644 index 0000000..e69de29 diff --git a/ORBIS_Release/GTASPRXPS4.vcxproj.FileListAbsolute.txt b/ORBIS_Release/GTASPRXPS4.vcxproj.FileListAbsolute.txt new file mode 100644 index 0000000..9ab3ade --- /dev/null +++ b/ORBIS_Release/GTASPRXPS4.vcxproj.FileListAbsolute.txt @@ -0,0 +1 @@ +C:\Users\DontCry361x\source\repos\GTASPRXPS4\ORBIS_Release\GTAServer.prx diff --git a/ORBIS_Release/GTAServer.prx b/ORBIS_Release/GTAServer.prx new file mode 100644 index 0000000..50e4c89 Binary files /dev/null and b/ORBIS_Release/GTAServer.prx differ diff --git a/ORBIS_Release/GTAServerlol.sprx b/ORBIS_Release/GTAServerlol.sprx new file mode 100644 index 0000000..a43a08d Binary files /dev/null and b/ORBIS_Release/GTAServerlol.sprx differ diff --git a/ORBIS_Release/Syscall.o b/ORBIS_Release/Syscall.o new file mode 100644 index 0000000..f7efc05 Binary files /dev/null and b/ORBIS_Release/Syscall.o differ diff --git a/ORBIS_Release/fself.py b/ORBIS_Release/fself.py new file mode 100644 index 0000000..3ce7008 --- /dev/null +++ b/ORBIS_Release/fself.py @@ -0,0 +1,816 @@ +#!/usr/bin/env python + +import sys, os, struct, traceback +import hashlib, hmac +import argparse, re, string + +def int_with_base_type(val): + return int(val, 0) + +def try_parse_int(x, base=0): + try: + return int(x, base) if isinstance(x, str) else int(x) + except: + return None + +def align_up(x, alignment): + return (x + (alignment - 1)) & ~(alignment - 1) + +def align_down(x, alignment): + return x & ~(alignment - 1) + +def ilog2(x): + if x <= 0: + raise ValueError('math domain error') + return len(bin(x)) - 3 + +def is_intervals_overlap(p1, p2): + return p1[0] <= p2[1] and p1[1] <= p2[0] + +def check_file_magic(f, expected_magic): + old_offset = f.tell() + try: + magic = f.read(len(expected_magic)) + except: + return False + finally: + f.seek(old_offset) + return magic == expected_magic + +def parse_version(version): + major, minor, patch = (version >> 8) & 0xFF, version & 0xFF, 0 # FIXME + major = 10 * (major >> 4) + (major & 0xF) + minor = 10 * (minor >> 4) + (minor & 0xF) + return '{0:d}.{1:02d}.{2:03d}'.format(major, minor, patch) + +def sha256(data): + return hashlib.sha256(data).digest() + +def hmac_sha256(key, data): + return hmac.new(key=key, msg=data, digestmod=hashlib.sha256).digest() + +class ElfError(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + +class ElfEHdr(object): + FMT = '<4s5B6xB' + EX_FMT = '<2HI3QI6H' + + MAGIC = '\x7FELF' + CLASS64 = 0x2 + DATA2LSB = 0x1 + EM_X86_64 = 0x3E + EV_CURRENT = 0x1 + + ET_EXEC = 0x2 + ET_SCE_EXEC = 0xFE00 + ET_SCE_EXEC_ASLR = 0xFE10 + ET_SCE_DYNAMIC = 0xFE18 + + def __init__(self): + self.magic = None + self.machine_class = None + self.data_encoding = None + self.version = None + self.os_abi = None + self.abi_version = None + self.nident_size = None + self.type = None + self.machine = None + self.version = None + self.entry = None + self.phoff = None + self.shoff = None + self.flags = None + self.ehsize = None + self.phentsize = None + self.phnum = None + self.shentsize = None + self.shnum = None + self.shstridx = None + + def load(self, f): + if not check_file_magic(f, ElfEHdr.MAGIC): + raise ElfError('Invalid magic.') + + self.magic, self.machine_class, self.data_encoding, self.version, self.os_abi, self.abi_version, self.nident_size = struct.unpack(ElfEHdr.FMT, f.read(struct.calcsize(ElfEHdr.FMT))) + if self.machine_class != ElfEHdr.CLASS64 or self.data_encoding != ElfEHdr.DATA2LSB: + raise ElfError('Unsupported class or data encoding.') + self.type, self.machine, self.version, self.entry, self.phoff, self.shoff, self.flags, self.ehsize, self.phentsize, self.phnum, self.shentsize, self.shnum, self.shstridx = struct.unpack(ElfEHdr.EX_FMT, f.read(struct.calcsize(ElfEHdr.EX_FMT))) + if self.machine != ElfEHdr.EM_X86_64 or self.version != ElfEHdr.EV_CURRENT: + raise ElfError('Unsupported machine type or version.') + if self.phentsize != struct.calcsize(ElfPHdr.FMT) or (self.shentsize > 0 and self.shentsize != struct.calcsize(ElfSHdr.FMT)): + raise ElfError('Unsupported header entry size.') + if self.type not in [ElfEHdr.ET_EXEC, ElfEHdr.ET_SCE_EXEC, ElfEHdr.ET_SCE_EXEC_ASLR, ElfEHdr.ET_SCE_DYNAMIC]: + raise ElfError('Unsupported type.') + + def save(self, f): + f.write(struct.pack(ElfEHdr.FMT, self.magic, self.machine_class, self.data_encoding, self.version, self.os_abi, self.abi_version, self.nident_size)) + f.write(struct.pack(ElfEHdr.EX_FMT, self.type, self.machine, self.version, self.entry, self.phoff, self.shoff, self.flags, self.ehsize, self.phentsize, self.phnum, self.shentsize, self.shnum, self.shstridx)) + + def has_segments(self): + return self.phentsize > 0 and self.phnum > 0 + + def has_sections(self): + return self.shentsize > 0 and self.shnum > 0 + +class ElfPHdr(object): + FMT = '<2I6Q' + + PT_LOAD = 0x1 + PT_DYNAMIC = 0x2 + PT_INTERP = 0x3 + PT_TLS = 0x7 + PT_GNU_EH_FRAME = 0x6474E550 + PT_GNU_STACK = 0x6474E551 + PT_SCE_RELA = 0x60000000, + PT_SCE_DYNLIBDATA = 0x61000000 + PT_SCE_PROCPARAM = 0x61000001 + PT_SCE_MODULE_PARAM = 0x61000002 + PT_SCE_RELRO = 0x61000010 + PT_SCE_COMMENT = 0x6FFFFF00 + PT_SCE_VERSION = 0x6FFFFF01 + + PF_EXEC = 0x1 + PF_WRITE = 0x2 + PF_READ = 0x4 + PF_READ_EXEC = PF_READ | PF_EXEC + PF_READ_WRITE = PF_READ | PF_WRITE + + def __init__(self, idx): + self.idx = idx + self.type = None + self.flags = None + self.offset = None + self.vaddr = None + self.paddr = None + self.filesz = None + self.memsz = None + self.align = None + + def load(self, f): + self.type, self.flags, self.offset, self.vaddr, self.paddr, self.filesz, self.memsz, self.align = struct.unpack(ElfPHdr.FMT, f.read(struct.calcsize(ElfPHdr.FMT))) + + def save(self, f): + f.write(struct.pack(ElfPHdr.FMT, self.type, self.flags, self.offset, self.vaddr, self.paddr, self.filesz, self.memsz, self.align)) + + def name(self): + if self.type == ElfPHdr.PT_LOAD: + if (self.flags & ElfPHdr.PF_READ_EXEC) == ElfPHdr.PF_READ_EXEC: + return '.text' + elif (self.flags & ElfPHdr.PF_READ_WRITE) == ElfPHdr.PF_READ_WRITE: + return '.data' + else: + return '.load_{0:02}'.format(self.idx) + else: + return { + ElfPHdr.PT_DYNAMIC: '.dynamic', + ElfPHdr.PT_INTERP: '.interp', + ElfPHdr.PT_TLS: '.tls', + ElfPHdr.PT_GNU_EH_FRAME: '.eh_frame_hdr', + ElfPHdr.PT_SCE_DYNLIBDATA: '.sce_dynlib_data', + ElfPHdr.PT_SCE_PROCPARAM: '.sce_process_param', + ElfPHdr.PT_SCE_MODULE_PARAM: '.sce_module_param', + ElfPHdr.PT_SCE_COMMENT: '.sce_comment', + }.get(self.type, None) + + def class_name(self): + if (self.flags & ElfPHdr.PF_READ_EXEC) == ElfPHdr.PF_READ_EXEC: + return 'CODE' + else: + return 'DATA' + +class ElfSHdr(object): + FMT = '<2I4Q2I2Q' + + def __init__(self, idx): + self.idx = idx + self.name = None + self.type = None + self.flags = None + self.addr = None + self.offset = None + self.size = None + self.link = None + self.info = None + self.align = None + self.entsize = None + + def load(self, f): + self.name, self.type, self.flags, self.addr, self.offset, self.size, self.link, self.info, self.align, self.entsize = struct.unpack(ElfSHdr.FMT, f.read(struct.calcsize(ElfSHdr.FMT))) + + def save(self, f): + f.write(struct.pack(ElfSHdr.FMT, self.name, self.type, self.flags, self.addr, self.offset, self.size, self.link, self.info, self.align, self.entsize)) + +class ElfFile(object): + def __init__(self, **kwargs): + self.ehdr = None + self.phdrs = None + self.shdrs = None + self.file_size = None + self.digest = None + self.segments = None + self.sections = None + self.ignore_shdrs = 'ignore_shdrs' in kwargs and kwargs['ignore_shdrs'] + + def load(self, f): + start_offset = f.tell() + data = f.read() + self.file_size = len(data) + self.digest = sha256(data) + f.seek(start_offset) + + self.ehdr = ElfEHdr() + self.ehdr.load(f) + + if self.ignore_shdrs: + self.ehdr.shnum = 0 + + self.phdrs = [] + self.segments = [] + if self.ehdr.has_segments(): + for i in xrange(self.ehdr.phnum): + f.seek(start_offset + self.ehdr.phoff + i * self.ehdr.phentsize) + phdr = ElfPHdr(i) + phdr.load(f) + self.phdrs.append(phdr) + if phdr.filesz > 0: + f.seek(start_offset + phdr.offset) + data = f.read(phdr.filesz) + else: + data = '' + self.segments.append(data) + + self.shdrs = [] + self.sections = [] + if self.ehdr.has_sections(): + for i in xrange(self.ehdr.shnum): + f.seek(start_offset + self.ehdr.shoff + i * self.ehdr.shentsize) + shdr = ElfSHdr(i) + shdr.load(f) + self.shdrs.append(shdr) + if phdr.filesz > 0: + f.seek(start_offset + shdr.offset) + data = f.read(phdr.filesz) + else: + data = '' + self.sections.append(data) + + def save(self, f, no_sections=False): + start_offset = f.tell() + + self.ehdr.save(f) + + if not no_sections: + if self.ehdr.has_sections(): + for i in xrange(self.ehdr.shnum): + f.seek(start_offset + self.ehdr.shoff + i * self.ehdr.shentsize) + shdr = self.shdrs[i] + shdr.save(f) + + if self.ehdr.has_segments(): + for i in xrange(self.ehdr.phnum): + f.seek(start_offset + self.ehdr.phoff + i * self.ehdr.phentsize) + phdr = self.phdrs[i] + phdr.save(f) + +DIGEST_SIZE = 0x20 +SIGNATURE_SIZE = 0x100 +BLOCK_SIZE = 0x4000 +DEFAULT_BLOCK_SIZE = 0x1000 + +SELF_CONTROL_BLOCK_TYPE_NPDRM = 0x3 +SELF_NPDRM_CONTROL_BLOCK_CONTENT_ID_SIZE = 0x13 +SELF_NPDRM_CONTROL_BLOCK_RANDOM_PAD_SIZE = 0xD + +EMPTY_DIGEST = '\0' * DIGEST_SIZE +EMPTY_SIGNATURE = '\0' * SIGNATURE_SIZE + +class SignedElfEntry(object): + FMT = '<4Q' + + PROPS_ORDER_SHIFT = 0 + PROPS_ORDER_MASK = 0x1 + PROPS_ENCRYPTED_SHIFT = 1 + PROPS_ENCRYPTED_MASK = 0x1 + PROPS_SIGNED_SHIFT = 2 + PROPS_SIGNED_MASK = 0x1 + PROPS_COMPRESSED_SHIFT = 3 + PROPS_COMPRESSED_MASK = 0x1 + PROPS_WINDOW_BITS_SHIFT = 8 + PROPS_WINDOW_BITS_MASK = 0x7 + PROPS_HAS_BLOCKS_SHIFT = 11 + PROPS_HAS_BLOCKS_MASK = 0x1 + PROPS_BLOCK_SIZE_SHIFT = 12 + PROPS_BLOCK_SIZE_MASK = 0xF + PROPS_HAS_DIGESTS_SHIFT = 16 + PROPS_HAS_DIGESTS_MASK = 0x1 + PROPS_HAS_EXTENTS_SHIFT = 17 + PROPS_HAS_EXTENTS_MASK = 0x1 + PROPS_HAS_META_SEGMENT_SHIFT = 20 + PROPS_HAS_META_SEGMENT_MASK = 0x1 + PROPS_SEGMENT_INDEX_SHIFT = 20 + PROPS_SEGMENT_INDEX_MASK = 0xFFFF + PROPS_DEFAULT_BLOCK_SIZE = 0x1000 + PROPS_META_SEGMENT_MASK = 0xF0000 + + def __init__(self, index): + self.index = index + + self.props = None + self.offset = None + self.filesz = None + self.memsz = None + + self.data = None + + def save(self, f): + f.write(struct.pack(SignedElfEntry.FMT, self.props, self.offset, self.filesz, self.memsz)) + + @property + def order(self): + return (self.props >> SignedElfEntry.PROPS_ORDER_SHIFT) & SignedElfEntry.PROPS_ORDER_MASK + + @order.setter + def order(self, value): + self.props &= ~(SignedElfEntry.PROPS_ORDER_MASK << SignedElfEntry.PROPS_ORDER_SHIFT) + self.props |= (value & SignedElfEntry.PROPS_ORDER_MASK) << SignedElfEntry.PROPS_ORDER_SHIFT + + @property + def encrypted(self): + return ((self.props >> SignedElfEntry.PROPS_ENCRYPTED_SHIFT) & SignedElfEntry.PROPS_ENCRYPTED_MASK) != 0 + + @encrypted.setter + def encrypted(self, value): + self.props &= ~(SignedElfEntry.PROPS_ENCRYPTED_MASK << SignedElfEntry.PROPS_ENCRYPTED_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_ENCRYPTED_MASK << SignedElfEntry.PROPS_ENCRYPTED_SHIFT + + @property + def signed(self): + return ((self.props >> SignedElfEntry.PROPS_SIGNED_SHIFT) & SignedElfEntry.PROPS_SIGNED_MASK) != 0 + + @signed.setter + def signed(self, value): + self.props &= ~(SignedElfEntry.PROPS_SIGNED_MASK << SignedElfEntry.PROPS_SIGNED_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_SIGNED_MASK << SignedElfEntry.PROPS_SIGNED_SHIFT + + @property + def compressed(self): + return ((self.props >> SignedElfEntry.PROPS_COMPRESSED_SHIFT) & SignedElfEntry.PROPS_COMPRESSED_MASK) != 0 + + @compressed.setter + def compressed(self, value): + self.props &= ~(SignedElfEntry.PROPS_COMPRESSED_MASK << SignedElfEntry.PROPS_COMPRESSED_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_COMPRESSED_MASK << SignedElfEntry.PROPS_COMPRESSED_SHIFT + + @property + def has_blocks(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_BLOCKS_SHIFT) & SignedElfEntry.PROPS_HAS_BLOCKS_MASK) != 0 + + @has_blocks.setter + def has_blocks(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_BLOCKS_MASK << SignedElfEntry.PROPS_HAS_BLOCKS_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_BLOCKS_MASK << SignedElfEntry.PROPS_HAS_BLOCKS_SHIFT + + @property + def has_digests(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_DIGESTS_SHIFT) & SignedElfEntry.PROPS_HAS_DIGESTS_MASK) != 0 + + @has_digests.setter + def has_digests(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_DIGESTS_MASK << SignedElfEntry.PROPS_HAS_DIGESTS_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_DIGESTS_MASK << SignedElfEntry.PROPS_HAS_DIGESTS_SHIFT + + @property + def has_extents(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_EXTENTS_SHIFT) & SignedElfEntry.PROPS_HAS_EXTENTS_MASK) != 0 + + @has_extents.setter + def has_extents(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_EXTENTS_MASK << SignedElfEntry.PROPS_HAS_EXTENTS_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_EXTENTS_MASK << SignedElfEntry.PROPS_HAS_EXTENTS_SHIFT + + @property + def has_meta_segment(self): + return ((self.props >> SignedElfEntry.PROPS_HAS_META_SEGMENT_SHIFT) & SignedElfEntry.PROPS_HAS_META_SEGMENT_MASK) != 0 + + @has_meta_segment.setter + def has_meta_segment(self, value): + self.props &= ~(SignedElfEntry.PROPS_HAS_META_SEGMENT_MASK << SignedElfEntry.PROPS_HAS_META_SEGMENT_SHIFT) + if value: + self.props |= SignedElfEntry.PROPS_HAS_META_SEGMENT_MASK << SignedElfEntry.PROPS_HAS_META_SEGMENT_SHIFT + + @property + def wbits(self): + return (self.props >> SignedElfEntry.PROPS_WINDOW_BITS_SHIFT) & SignedElfEntry.PROPS_WINDOW_BITS_MASK + + @wbits.setter + def wbits(self, value): + self.props &= ~(SignedElfEntry.PROPS_WINDOW_BITS_MASK << SignedElfEntry.PROPS_WINDOW_BITS_SHIFT) + self.props |= (value & SignedElfEntry.PROPS_WINDOW_BITS_MASK) << SignedElfEntry.PROPS_WINDOW_BITS_SHIFT + + @property + def block_size(self): + if self.has_blocks: + return 1 << (12 + (self.props >> SignedElfEntry.PROPS_BLOCK_SIZE_SHIFT) & SignedElfEntry.PROPS_BLOCK_SIZE_MASK) + else: + return DEFAULT_BLOCK_SIZE + + @block_size.setter + def block_size(self, value): + self.props &= ~(SignedElfEntry.PROPS_BLOCK_SIZE_MASK << SignedElfEntry.PROPS_BLOCK_SIZE_SHIFT) + if self.has_blocks: + value = ilog2(value) - 12 + else: + value = 0 # TODO: check + self.props |= (value & SignedElfEntry.PROPS_BLOCK_SIZE_MASK) << SignedElfEntry.PROPS_BLOCK_SIZE_SHIFT + + @property + def segment_index(self): + return (self.props >> SignedElfEntry.PROPS_SEGMENT_INDEX_SHIFT) & SignedElfEntry.PROPS_SEGMENT_INDEX_MASK + + @wbits.setter + def segment_index(self, value): + self.props &= ~(SignedElfEntry.PROPS_SEGMENT_INDEX_MASK << SignedElfEntry.PROPS_SEGMENT_INDEX_SHIFT) + self.props |= (value & SignedElfEntry.PROPS_SEGMENT_INDEX_MASK) << SignedElfEntry.PROPS_SEGMENT_INDEX_SHIFT + + def is_meta_segment(self): # TODO: check + return (self.props & SignedElfEntry.PROPS_META_SEGMENT_MASK) != 0 + + def __repr__(self): + return 'prs:0x{0:X} ofs:0x{1:X} fsz:0x{2:X} msz:0x{3:X}'.format(self.props, self.offset, self.filesz, self.memsz) + +class SignedElfExInfo(object): + FMT = '<4Q32s' + + PTYPE_FAKE = 0x1 + PTYPE_NPDRM_EXEC = 0x4 + PTYPE_NPDRM_DYNLIB = 0x5 + PTYPE_SYSTEM_EXEC = 0x8 + PTYPE_SYSTEM_DYNLIB = 0x9 # including Mono binaries + PTYPE_HOST_KERNEL = 0xC + PTYPE_SECURE_MODULE = 0xE + PTYPE_SECURE_KERNEL = 0xF + + def __init__(self): + self.paid = None + self.ptype = None + self.app_version = None + self.fw_version = None + self.digest = None + + def save(self, f): + f.write(struct.pack(SignedElfExInfo.FMT, self.paid, self.ptype, self.app_version, self.fw_version, self.digest)) + +class SignedElfNpdrmControlBlock(object): + FMT = ' 0: + if val.startswith('0x') or val.startswith('0X'): + val = val[2:] + if len(val) % 2 != 0 or not all(x in string.hexdigits for x in val): + return None + val = val.decode('hex') + val_size = len(val) + + if not exact_size is None and val_size != exact_size: + return None + else: + if not min_size is None and val_size < min_size: + return None + if not max_size is None and val_size > max_size: + return None + + return val + +def input_file_type(val): + if not os.access(val, os.F_OK | os.R_OK) or not os.path.isfile(val): + raise argparse.ArgumentTypeError('invalid input file: {0}'.format(val)) + return val + +def output_file_type(val): + if os.access(val, os.F_OK) and (not os.path.isfile(val) or not os.access(val, os.F_OK | os.W_OK)): + raise argparse.ArgumentTypeError('invalid output file: {0}'.format(val)) + return val + +def auth_info_type(val): + new_val = ensure_hex_string(val, exact_size=0x88) + if new_val is None: + raise argparse.ArgumentTypeError('invalid auth info: {0}'.format(val)) + return new_val + +class MyParser(argparse.ArgumentParser): + def error(self, message): + self.print_help() + sys.stderr.write('\nerror: {0}\n'.format(message)) + sys.exit(2) + +parser = MyParser(description='fake signed elf maker') +parser.add_argument('input', type=input_file_type, default=None, help='elf/prx file path') +parser.add_argument('output', type=output_file_type, default=None, help='self/sprx file path') +parser.add_argument('--paid', type=int_with_base_type, default=0x3100000000000002, help='program authentication id') +parser.add_argument('--ptype', default=None, help='program type {fake, npdrm_exec, npdrm_dynlib, system_exec, system_dynlib, host_kernel, secure_module, secure_kernel}') +parser.add_argument('--app-version', type=int_with_base_type, default=0, help='application version') +parser.add_argument('--fw-version', type=int_with_base_type, default=0, help='firmware version') +parser.add_argument('--auth-info', type=auth_info_type, default=None, help='authentication info') + +if len(sys.argv) == 1: + parser.print_usage() + sys.exit(1) + +args = parser.parse_args() + +paid = args.paid +if not (0 <= paid <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid program authentication id: 0x{0:016X}'.format(paid)) + +ptype = SignedElfExInfo.PTYPE_FAKE +if not args.ptype is None: + ptype = { + 'fake': SignedElfExInfo.PTYPE_FAKE, + 'npdrm_exec': SignedElfExInfo.PTYPE_NPDRM_EXEC, + 'npdrm_dynlib': SignedElfExInfo.PTYPE_NPDRM_DYNLIB, + 'system_exec': SignedElfExInfo.PTYPE_SYSTEM_EXEC, + 'system_dynlib': SignedElfExInfo.PTYPE_SYSTEM_DYNLIB, + 'host_kernel': SignedElfExInfo.PTYPE_HOST_KERNEL, + 'secure_module': SignedElfExInfo.PTYPE_SECURE_MODULE, + 'secure_kernel': SignedElfExInfo.PTYPE_SECURE_KERNEL, + }.get(args.ptype.strip().lower(), None) + if ptype is None: + ptype = try_parse_int(args.ptype) + if ptype is None: + parser.error('invalid program type: 0x{0:016X}'.format(ptype)) +if not (0 <= ptype <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid program type: 0x{0:016X}'.format(ptype)) + +app_version = args.app_version +if not (0 <= app_version <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid application version: 0x{0:016X}'.format(app_version)) + +fw_version = args.fw_version +if not (0 <= fw_version <= 0xFFFFFFFFFFFFFFFF): + parser.error('invalid firmware version: 0x{0:016X}'.format(fw_version)) + +auth_info = args.auth_info + +elf_file_path = args.input +fself_file_path = args.output + +print('loading elf file: {0}'.format(elf_file_path)) +try: + with open(elf_file_path, 'rb') as f: + elf_file = ElfFile(ignore_shdrs=True) + elf_file.load(f) +except Exception as err: + traceback.print_exc() + print('') + parser.error('unable to load elf file: {0} ({1})'.format(elf_file_path, err)) + +print('saving fake signed elf file: {0}'.format(fself_file_path)) +try: + with open(fself_file_path, 'wb') as f: + self_file = SignedElfFile(elf_file, paid=paid, ptype=ptype, app_version=app_version, fw_version=fw_version, auth_info=auth_info) + self_file.save(f) +except Exception as err: + traceback.print_exc() + print('') + parser.error('unable to save fself file: {0} ({1})'.format(elf_file_path, err)) + +print('done') \ No newline at end of file diff --git a/ORBIS_Release/prx.o b/ORBIS_Release/prx.o new file mode 100644 index 0000000..36169b5 Binary files /dev/null and b/ORBIS_Release/prx.o differ diff --git a/Syscall.cpp b/Syscall.cpp new file mode 100644 index 0000000..ae73fe5 --- /dev/null +++ b/Syscall.cpp @@ -0,0 +1,18 @@ +__asm__( + ".att_syntax prefix\n" + ".globl orbis_syscall\n" + "orbis_syscall:\n" + " movq $0, %rax\n" + " movq %rcx, %r10\n" + " syscall\n" + " jb err\n" + " retq\n" + "err:\n" + " pushq %rax\n" + " callq __error\n" + " popq %rcx\n" + " movl %ecx, 0(%rax)\n" + " movq $0xFFFFFFFFFFFFFFFF, %rax\n" + " movq $0xFFFFFFFFFFFFFFFF, %rdx\n" + " retq\n" +); \ No newline at end of file diff --git a/Syscall.h b/Syscall.h new file mode 100644 index 0000000..216639d --- /dev/null +++ b/Syscall.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + int orbis_syscall(int num, ...); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/prx.cpp b/prx.cpp new file mode 100644 index 0000000..2aa6cf3 --- /dev/null +++ b/prx.cpp @@ -0,0 +1,1082 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Syscall.h" +#include "utility" + +int (*sceSysUtilSendSystemNotificationWithText)( + int messageType, + const char* message + ); + +int (*sceNpCheckNpAvailabilityOriginal)(void); + +int (*sceNpGetStateOriginal)( + SceUserServiceUserId userId, + int* state + ); + +int (*sceNpGetOnlineIdOriginal)( + SceUserServiceUserId userId, + SceNpOnlineId* onlineId + ); + +int (*sceNpGetAccountIdOriginal)( + SceUserServiceUserId userId, + SceNpAccountId* accountId + ); + +int (*sceNpRegisterStateCallbackOriginal)( + SceNpStateCallbackA callback, + void* userdata + ); + +int (*sceNpRegisterGamePresenceCallbackOriginal)( + SceNpGamePresenceCallbackA callback, + void* userdata + ); + +int32_t(*sceUserServiceGetEventOriginal)( + SceUserServiceEvent* event + ); + +int (*sceNpGetGamePresenceStatusOriginal)( + SceUserServiceUserId userId, + SceNpGamePresenceStatus* status + ); + +int (*sceNpGetNpIdOriginal)( + SceUserServiceUserId userId, + SceNpId* npId + ); + +int (*sceCommonDialogInitializeOriginal)(void); + +int (*sceNpAuthCreateAsyncRequestOriginal)( + const SceNpAuthCreateAsyncRequestParameter* + ); + +int (*sceNpCreateAsyncRequestOriginal)( + const SceNpCreateAsyncRequestParameter* + ); + +int (*sceNpPollAsyncOriginal)( + int reqId, + int* result + ); + +int (*sceNpAuthPollAsyncOriginal)( + int reqId, + int* result + ); + +int (*sceNpAuthGetAuthorizationCodeOriginal)( + int reqId, + const SceNpAuthGetAuthorizationCodeParameterA* param, + SceNpAuthorizationCode* authCode, + int* issuerId + ); + +int32_t(*sceNpCommerceDialogInitializeOriginal)(void); + +int32_t(*sceNpCommerceDialogOpenOriginal)( + const SceNpCommerceDialogParam* param + ); + +SceCommonDialogStatus(*sceNpCommerceDialogUpdateStatusOriginal)(void); + +int32_t(*sceNpCommerceDialogTerminateOriginal)(void); + +int32_t(*sceNpCommerceDialogGetResultOriginal)( + SceNpCommerceDialogResult* result + ); + +int32_t(*sceNpCommerceShowPsStoreIconOriginal)( + SceNpCommercePsStoreIconPos pos + ); + +int32_t(*sceNpCommerceHidePsStoreIconOriginal)(void); + +int (*sceNpBandwidthTestInitStartOriginal)( + const SceNpBandwidthTestInitParam* param + ); + +int (*sceNpBandwidthTestGetStatusOriginal)( + int contextId, + int* status + ); + +int (*sceNpBandwidthTestShutdownOriginal)( + int contextId, + SceNpBandwidthTestResult* result + ); + +int (*sceNpGetParentalControlInfoOriginal)( + int reqId, + SceUserServiceUserId userId, + int8_t* age, + SceNpParentalControlInfo* info + ); + +int (*sceNpCheckPlusOriginal)( + int reqId, + const SceNpCheckPlusParameter* param, + SceNpCheckPlusResult* result + ); + +int (*sceNpSetContentRestrictionOriginal)( + const SceNpContentRestriction* restriction + ); + +int (*sceNpGetAccountCountryOriginal)( + SceUserServiceUserId userId, + SceNpCountryCode* countryCode + ); + +int (*sceNpGetAccountDateOfBirthOriginal)( + SceUserServiceUserId userId, + SceNpDate* date + ); + +int (*sceNpWordFilterCreateTitleCtxOriginal)( + SceUserServiceUserId selfId + ); + +int (*sceNpWordFilterCreateAsyncRequestOriginal)( + int titleCtxId, + const SceNpWordFilterCreateAsyncRequestParameter* param + ); + +int (*sceNpWordFilterSanitizeCommentOriginal)( + int reqId, + const char* comment, + char* sanitizedComment, + void* option + ); + +int (*sceNpWordFilterPollAsyncOriginal)( + int reqId, + int* result + ); + +int32_t(*sceNpWebApiUtilityParseNpIdOriginal)(const char* jsonNpId, SceNpId* npId); + + +#include +int sceNpGetOnlineIdHook(int32_t userid, SceNpOnlineId* onlineId) +{ + printf("[NP] sceNpGetOnlineIdHook(userId=%d)\n", userid); + + memcpy(onlineId->data, "DontCry361x", 13); + onlineId->term = '\0'; + + return 0; +} + + +int sceNpCheckNpAvailabilityhook() +{ + printf("[NP] sceNpCheckNpAvailabilityHook() -> OK\n"); + return 0; +} + +#define ENABLE_HOOK_LOGS 1 + +#if ENABLE_HOOK_LOGS +#define HOOK_LOG(fmt, ...) \ + printf("[HOOK] " fmt "\n", ##__VA_ARGS__) +#else +#define HOOK_LOG(fmt, ...) +#endif + +int sceNpGetStateHook(int32_t userId, int* state) +{ + *state = 2; + + HOOK_LOG("sceNpGetState(userId=%d) -> state=%d", userId, *state); + return 0; +} + + +int sceNpGetAccountIdHook(int32_t userId, SceNpAccountId* accountId) +{ + *accountId = 0x1; + HOOK_LOG("userId=%d accountId=0x%lX", userId, *accountId); + return 0; +} + + +static SceNpStateCallbackA g_state_cb = NULL; +static void* g_state_userdata = NULL; +static int g_state_cb_id = 1; + +int sceNpRegisterStateCallbackHook(SceNpStateCallbackA callback, void* userdata) +{ + g_state_cb = callback; + g_state_userdata = userdata; + + HOOK_LOG("callback=%p userdata=%p id=%d", callback, userdata, g_state_cb_id); + return g_state_cb_id; +} + +static SceNpGamePresenceCallbackA g_presence_cb = NULL; +static void* g_presence_userdata = NULL; +static int g_presence_cb_id = 2; + +int sceNpRegisterGamePresenceCallbackHook(SceNpGamePresenceCallbackA callback, void* userdata) +{ + g_presence_cb = callback; + g_presence_userdata = userdata; + + HOOK_LOG("callback=%p userdata=%p id=%d", callback, userdata, g_presence_cb_id); + return g_presence_cb_id; +} + +static int g_user_logged_in = 0; +static SceUserServiceUserId g_user_id = 1; +static int g_login_event_pending = 1; +static int g_logout_event_pending = 0; + +int32_t sceUserServiceGetEventHook(SceUserServiceEvent* event) +{ + return SCE_USER_SERVICE_ERROR_NO_EVENT; +} + +int sceNpGetGamePresenceStatusHook(SceUserServiceUserId userId, SceNpGamePresenceStatus* pStatus) +{ + *pStatus = SCE_NP_GAME_PRESENCE_STATUS_ONLINE; + + return 0; +} + +int sceNpGetNpIdHook(SceUserServiceUserId userId, SceNpId* npId) +{ + memset(npId, 0, sizeof(SceNpId)); + memcpy(npId->handle.data, "DontCry361x", 13); + npId->handle.term = '\0'; + + return 0; +} + +static int g_common_dialog_system_initialized = 0; +int sceCommonDialogInitializeHook() +{ + g_common_dialog_system_initialized = 1; + return SCE_OK; +} + +#define FAKE_ONLINE_ID "DontCry361x" +int32_t sceNpWebApiUtilityParseNpIdHook(const char* pJsonNpId, SceNpId* pNpId) +{ + memset(pNpId, 0, sizeof(SceNpId)); + + memcpy( + pNpId->handle.data, + FAKE_ONLINE_ID, + strlen(FAKE_ONLINE_ID) + ); + pNpId->handle.term = '\0'; + + return SCE_OK; +} + +#include + +#define MAX_AUTH_REQUESTS 16 + +static int g_next_auth_req_id = 1; +static int g_active_auth_requests = 0; +static int g_auth_request_alive[MAX_AUTH_REQUESTS]; + +int sceNpAuthCreateAsyncRequestHook(const SceNpAuthCreateAsyncRequestParameter* pParam) +{ + int reqId = g_next_auth_req_id++; + + g_active_auth_requests++; + g_auth_request_alive[reqId % MAX_AUTH_REQUESTS] = 1; + + HOOK_LOG("AUTH async created reqId=%d active=%d", + reqId, g_active_auth_requests); + + return reqId; +} + + +#define MAX_NP_REQUESTS 32 + +static int g_next_np_req_id = 1; +static int g_active_np_requests = 0; +static int g_np_request_alive[MAX_NP_REQUESTS]; + + +int sceNpCreateAsyncRequestHook(const SceNpCreateAsyncRequestParameter* pParam) +{ + int reqId = g_next_np_req_id++; + + g_active_np_requests++; + g_np_request_alive[reqId % MAX_NP_REQUESTS] = 1; + + HOOK_LOG("NP async created reqId=%d active=%d", + reqId, g_active_np_requests); + + return reqId; +} + + +#define MAX_NP_REQUESTS 32 + +static int g_np_request_finished[MAX_NP_REQUESTS]; + +#include +int sceNpPollAsyncHook(int reqId, int* pResult) +{ + static int logged[MAX_NP_REQUESTS] = { 0 }; + + int idx = reqId % MAX_NP_REQUESTS; + + if (!g_np_request_finished[idx] && !logged[idx]) { + HOOK_LOG("reqId=%d FINISHED", reqId); + logged[idx] = 1; + } + + *pResult = SCE_OK; + g_np_request_finished[idx] = 1; + return SCE_NP_POLL_ASYNC_RET_FINISHED; +} + + +#define MAX_AUTH_REQUESTS 16 + +static int g_auth_request_finished[MAX_AUTH_REQUESTS]; + +int sceNpAuthPollAsyncHook(int reqId, int* pResult) +{ + if (reqId <= 0 || !pResult) { + return SCE_NP_AUTH_ERROR_INVALID_ARGUMENT; + } + + int idx = reqId % MAX_AUTH_REQUESTS; + + if (!g_auth_request_alive[idx]) { + return SCE_NP_AUTH_ERROR_REQUEST_NOT_FOUND; + } + + if (!g_auth_request_finished[idx]) { + g_auth_request_finished[idx] = 1; + *pResult = SCE_OK; + return SCE_NP_AUTH_POLL_ASYNC_RET_FINISHED; + } + + *pResult = SCE_OK; + return SCE_NP_AUTH_POLL_ASYNC_RET_FINISHED; +} + +#define FAKE_AUTH_CODE "FAKE_AUTH_CODE_1234567890" //im 99% sure this is wrong? +int sceNpAuthGetAuthorizationCodeHook(int reqId, const SceNpAuthGetAuthorizationCodeParameterA* param, SceNpAuthorizationCode* authCode, int* issuerId) +{ + if (reqId <= 0 || !param || !authCode) { + return SCE_NP_AUTH_ERROR_INVALID_ARGUMENT; + } + + if (param->size != sizeof(SceNpAuthGetAuthorizationCodeParameterA)) { + return SCE_NP_AUTH_ERROR_INVALID_SIZE; + } + + if (!param->clientId || !param->scope) { + return SCE_NP_AUTH_ERROR_INVALID_ARGUMENT; + } + + if (param->userId == 0) { + return SCE_NP_ERROR_USER_NOT_FOUND; + } + + int idx = reqId % MAX_AUTH_REQUESTS; + if (!g_auth_request_alive[idx]) { + return SCE_NP_AUTH_ERROR_REQUEST_NOT_FOUND; + } + + memset(authCode, 0, sizeof(SceNpAuthorizationCode)); + memcpy(authCode->code, FAKE_AUTH_CODE, strlen(FAKE_AUTH_CODE)); + + if (issuerId) { + *issuerId = 0; + } + + g_auth_request_finished[idx] = 1; + + return 0; +} + +static int g_common_dialog_initialized = 0; +static int g_common_dialog_busy = 0; + +static SceCommonDialogStatus g_common_dialog_status = SCE_COMMON_DIALOG_STATUS_NONE; + +int32_t sceNpCommerceDialogInitializeHook(void) +{ + HOOK_LOG("called"); + + if (g_common_dialog_initialized) + return SCE_COMMON_DIALOG_ERROR_ALREADY_INITIALIZED; + + g_common_dialog_initialized = 1; + g_common_dialog_status = SCE_COMMON_DIALOG_STATUS_INITIALIZED; + return SCE_OK; +} + +#include +static int g_np_commerce_initialized = 0; + +static SceCommonDialogStatus g_np_commerce_status = +SCE_COMMON_DIALOG_STATUS_NONE; + +int32_t sceNpCommerceDialogOpenHook(const SceNpCommerceDialogParam* param) +{ + HOOK_LOG("userId=%d mode=%d", param ? param->userId : -1, param ? param->mode : -1); + + if (!param) return SCE_COMMON_DIALOG_ERROR_ARG_NULL; + + g_common_dialog_busy = 1; + g_np_commerce_status = SCE_COMMON_DIALOG_STATUS_RUNNING; + return SCE_OK; +} + + +SceCommonDialogStatus sceNpCommerceDialogUpdateStatus_hook(void) { + if (g_np_commerce_status == SCE_COMMON_DIALOG_STATUS_RUNNING) { + g_np_commerce_status = SCE_COMMON_DIALOG_STATUS_FINISHED; + g_common_dialog_busy = 0; + } + + return g_np_commerce_status; +} + +int32_t sceNpCommerceDialogTerminateHook() +{ + if (!g_np_commerce_initialized) { + return SCE_COMMON_DIALOG_ERROR_NOT_INITIALIZED; + } + + g_np_commerce_status = SCE_COMMON_DIALOG_STATUS_NONE; + g_common_dialog_busy = 0; + g_np_commerce_initialized = 0; + + return SCE_OK; +} + +int32_t sceNpCommerceDialogGetResultHook(SceNpCommerceDialogResult* result) +{ + HOOK_LOG("called"); + + memset(result, 0, sizeof(*result)); + result->result = SCE_COMMON_DIALOG_RESULT_OK; + result->authorized = true; + + return result->result; +} + + +int32_t sceNpCommerceShowPsStoreIconHook(SceNpCommercePsStoreIconPos pos) +{ + return SCE_OK; +} + +int32_t sceNpCommerceHidePsStoreIconHook() +{ + return 0; +} + +#define MAX_BANDWIDTH_CONTEXTS 4 + +static int g_bw_next_ctx_id = 0; +static int g_bw_ctx_active[MAX_BANDWIDTH_CONTEXTS]; +static int g_bw_ctx_finished[MAX_BANDWIDTH_CONTEXTS]; + + +int sceNpBandwidthTestInitStartHook(const SceNpBandwidthTestInitParam* param) +{ + if (!param) { + return SCE_NP_BANDWIDTH_TEST_ERROR_INVALID_ARGUMENT; + } + + if (param->size != sizeof(SceNpBandwidthTestInitParam)) { + return SCE_NP_BANDWIDTH_TEST_ERROR_INVALID_SIZE; + } + + int ctxId = g_bw_next_ctx_id % MAX_BANDWIDTH_CONTEXTS; + HOOK_LOG("ctxId=%d", ctxId); + g_bw_next_ctx_id++; + + g_bw_ctx_active[ctxId] = 1; + g_bw_ctx_finished[ctxId] = 0; + + return ctxId; +} + +int sceNpBandwidthTestGetStatusHook(int contextId, int* status) +{ + if (!status) { + return SCE_NP_BANDWIDTH_TEST_ERROR_INVALID_ARGUMENT; + } + + if (contextId < 0 || + contextId >= MAX_BANDWIDTH_CONTEXTS || + !g_bw_ctx_active[contextId]) { + return SCE_NP_BANDWIDTH_TEST_ERROR_CONTEXT_NOT_AVAILABLE; + } + + *status = SCE_NP_BANDWIDTH_TEST_STATUS_FINISHED; + g_bw_ctx_finished[contextId] = 1; + + return 0; +} + +int sceNpBandwidthTestShutdownHook(int contextId, SceNpBandwidthTestResult* result) +{ + if (!result) { + return SCE_NP_BANDWIDTH_TEST_ERROR_INVALID_ARGUMENT; + } + + if (contextId < 0 || + contextId >= MAX_BANDWIDTH_CONTEXTS || + !g_bw_ctx_active[contextId]) { + return SCE_NP_BANDWIDTH_TEST_ERROR_CONTEXT_NOT_AVAILABLE; + } + + memset(result, 0, sizeof(SceNpBandwidthTestResult)); + result->downloadBps = 100.0 * 1000 * 1000; // 100 Mbit/s + result->uploadBps = 20.0 * 1000 * 1000; // 20 Mbit/s + result->result = 0; + + g_bw_ctx_active[contextId] = 0; + g_bw_ctx_finished[contextId] = 0; + + HOOK_LOG("ctxId=%d DL=100Mbps UL=20Mbps", contextId); + + + return 0; +} + +int sceNpGetParentalControlInfoHook(int reqId, SceUserServiceUserId userId, int8_t* pAge, SceNpParentalControlInfo* pInfo) +{ + if (reqId <= 0 || !pAge || !pInfo) { + return SCE_NP_ERROR_INVALID_ARGUMENT; + } + + *pAge = 18; + + // Parental Control: alles erlaubt + memset(pInfo, 0, sizeof(SceNpParentalControlInfo)); + pInfo->contentRestriction = false; + pInfo->chatRestriction = false; + pInfo->ugcRestriction = false; + + return 0; +} + +int sceNpCheckPlusHook(int reqId, const SceNpCheckPlusParameter* pParam, SceNpCheckPlusResult* pResult) +{ + if (reqId <= 0 || !pParam || !pResult) { + return SCE_NP_ERROR_INVALID_ARGUMENT; + } + + if (pParam->size != sizeof(SceNpCheckPlusParameter)) { + return SCE_NP_ERROR_INVALID_ARGUMENT; + } + + memset(pResult, 0, sizeof(SceNpCheckPlusResult)); + pResult->authorized = true; + + return 0; +} + +int sceNpSetContentRestrictionHook(const SceNpContentRestriction* pRestriction) +{ + if (!pRestriction || + pRestriction->size != sizeof(SceNpContentRestriction)) { + return SCE_NP_ERROR_INVALID_ARGUMENT; + } + + return SCE_OK; +} + +#include +int sceNpGetAccountCountryHook(int32_t userId, SceNpCountryCode* countryCode) +{ + countryCode->data[0] = 'd'; + countryCode->data[1] = 'e'; + countryCode->term = '\0'; + countryCode->padding[0] = 0; + + return 0; +} + +int sceNpGetAccountDateOfBirthHook(SceUserServiceUserId userId, SceNpDate* pDateOfBirth) +{ + if (!pDateOfBirth) { + return SCE_NP_ERROR_INVALID_ARGUMENT; + } + + pDateOfBirth->year = 1990; + pDateOfBirth->month = 10; + pDateOfBirth->day = 19; + + return SCE_OK; +} + +static int g_next_wordfilter_ctx = 1; + +int sceNpWordFilterCreateTitleCtxA_hook(SceUserServiceUserId selfId) +{ + int id = g_next_wordfilter_ctx++; + HOOK_LOG("selfId=%d ctxId=%d", selfId, id); + return id; +} + +static int g_next_wordfilter_req = 1; + +int sceNpWordFilterCreateAsyncRequestHook(int titleCtxId, const SceNpWordFilterCreateAsyncRequestParameter* pParam) +{ + if (titleCtxId <= 0) { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + return g_next_wordfilter_req++; +} + +#include +#include +#include +#include +#include + +int64_t sceNpWordFilterSanitizeCommentHook(int reqId, char* comment, char* sanitizedComment, void* option) +{ + HOOK_LOG("reqId=%d comment=\"%s\"", reqId, comment); + strncpy(sanitizedComment, comment, 1024); + sanitizedComment[1024] = '\0'; + return 0; +} + +int sceNpWordFilterPollAsyncHook(int reqId, int* result) +{ + if (reqId <= 0) { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + if (!result) { + return SCE_NP_COMMUNITY_ERROR_INVALID_ID; + } + + *result = 0; + + return SCE_NP_WORD_FILTER_POLL_ASYNC_RET_FINISHED; +} + +//static void* g_SingletonInstance = nullptr; +// +//int sceNpWebApiRegisterServicePushEventCallbackHook(uint32_t param_1, uint32_t param_2, uint64_t param_3, uint64_t param_4) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// return 0; +//} +// +//int sceNpWebApiUnregisterServicePushEventCallbackHook(uint32_t param_1, uint32_t param_2) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// return 0; +//} +// +//int sceNpWebApiCreatePushEventFilterHook(uint32_t param_1, uint64_t param_2, uint64_t param_3) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// return 0; +//} +// +//int sceNpWebApiDeletePushEventFilterHook(uint32_t param_1, uint32_t param_2) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// return 0; +//} +// +//int sceNpWebApiCreateServicePushEventFilterHook(uint32_t param_1, uint32_t param_2, uint64_t param_3, uint32_t param_4, uint64_t param_5, uint64_t param_6) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// return 2; +//} +// +//int sceNpWebApiDeleteServicePushEventFilterHook(uint32_t param_1, uint32_t param_2) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// return 0; +//} +// +//int sceNpWebApiRegisterPushEventCallbackHook(uint32_t param_1, uint32_t param_2, uint64_t param_3, uint64_t param_4) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// return 0; +//} +// +//#include +//#include +//#include +// +//static std::atomic g_RequestIdCounter(1); +// +//uint64_t sceNpWebApiCreateRequestHook(uint32_t param_1, const char* param_2, const char* param_3, uint32_t param_4, uint64_t* param_5, uint64_t* param_6) { +// if (!param_6 || !param_2 || !param_3) { +// return 0xFFFFFFFFFFFFFFFF; +// } +// uint64_t requestId = g_RequestIdCounter.fetch_add(1); +// +// void* requestStruct = malloc(0x108); +// if (!requestStruct) { +// return 0xFFFFFFFFFFFFFFFF; +// } +// +// memset(requestStruct, 0, 0x108); +// *(uint64_t*)requestStruct = requestId; +// *(uint32_t*)((uintptr_t)requestStruct + 8) = param_1; +// +// strncpy((char*)((uintptr_t)requestStruct + 0x38), param_2, 0x40); +// strncpy((char*)((uintptr_t)requestStruct + 0x78), param_3, 0x40); +// +// if (!param_5) { +// strcpy((char*)((uintptr_t)requestStruct + 0xB8), "application/json"); +// } +// *param_6 = requestId; +// +// return 0; +//} +// +//uint64_t sceNpWebApiDeleteRequestHook(uint64_t param_1) { +// return 0; +//} +// +//void sceNpWebApiCreateHandleHook(uint32_t param_1) { +// if (!g_SingletonInstance) { +// g_SingletonInstance = malloc(0x168); +// memset(g_SingletonInstance, 0, 0x168); +// +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x38) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x40) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x88) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x90) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xD8) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0xE0) = 8; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x128) = 7; +// *(uint64_t*)((uintptr_t)g_SingletonInstance + 0x130) = 8; +// +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x140), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x144), uint32_t(1)); +// std::atomic_store((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), uint32_t(1)); +// } +// +// std::atomic_fetch_add((std::atomic*)((uintptr_t)g_SingletonInstance + 0x148), 1); +// +// return; +//} +// +//int sceNpWebApiSendRequestHook(uint64_t param_1, int64_t param_2, int64_t param_3) { +// return 0; +//} +// +//uint64_t sceNpWebApiGetHttpStatusCodeHook(uint64_t param_1, uint32_t* param_2) { +// if (param_2 != nullptr) { +// *param_2 = 200; +// return 0; +// } +// +// return 0xFFFFFFFFFFFFFFFF; +//} +// +//uint64_t sceNpWebApiReadDataHook(uint64_t param_1, void* param_2, uint64_t param_3) { +// +// if (param_2 == nullptr || param_3 == 0) { +// return 0; +// } +// memset(param_2, 0, param_3); +// +// return param_3; +//} + +void memcpy_p(unsigned long Address, const void* Data, unsigned long Length) +{ + if (!Address || !Length) + { + printf("No target (0x%lx) or length (%li) provided!\n", Address, Length); + return; + } + sceKernelMprotect((void*)Address, Length, 0x7); + memcpy((void*)Address, Data, Length); +} + +void WriteJump(void* target, void* replacement) +{ + unsigned char jump[14] = { + 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + *(uint64_t*)(jump + 6) = (uint64_t)replacement; + + memcpy_p((unsigned long)target, jump, sizeof(jump)); +} + +bool ApplyDirectHooks() +{ + struct DirectHook { + unsigned long address; + void* hookFunction; + void** originalFunction; + const char* description; + }; + + DirectHook directHooks[] = { + {0x2B41240, (void*)sceNpCheckNpAvailabilityhook, (void**)&sceNpCheckNpAvailabilityOriginal, "sceNpCheckNpAvailability"}, + {0x2B40ED0, (void*)sceNpGetStateHook, (void**)&sceNpGetStateOriginal, "sceNpGetState"}, + {0x2B40EE0, (void*)sceNpGetOnlineIdHook, (void**)&sceNpGetOnlineIdOriginal, "sceNpGetOnlineId"}, + {0x2B40ef0, (void*)sceNpGetAccountIdHook, (void**)&sceNpGetAccountIdOriginal, "sceNpGetAccountId"}, + {0x2B410a0, (void*)sceNpRegisterStateCallbackHook, (void**)&sceNpRegisterStateCallbackOriginal, "sceNpRegisterStateCallback"}, + {0x2B410b0, (void*)sceNpRegisterGamePresenceCallbackHook, (void**)&sceNpRegisterGamePresenceCallbackOriginal, "sceNpRegisterGamePresenceCallback"}, + {0x2B410d0, (void*)sceUserServiceGetEventHook, (void**)&sceUserServiceGetEventOriginal, "sceUserServiceGetEvent"}, + {0x2B41230, (void*)sceNpGetGamePresenceStatusHook, (void**)&sceNpGetGamePresenceStatusOriginal, "sceNpGetGamePresenceStatus"}, + {0x2B41360, (void*)sceCommonDialogInitializeHook, (void**)&sceCommonDialogInitializeOriginal, "sceCommonDialogInitialize"}, + {0x2B41640, (void*)sceNpGetNpIdHook, (void**)&sceNpGetNpIdOriginal, "sceNpGetNpId"}, + //{0x2B41610, (void*)sceNpWebApiUtilityParseNpIdHook, (void**)&sceNpWebApiUtilityParseNpIdOriginal, "sceNpWebApiUtilityParseNpId"}, + {0x2B41250, (void*)sceNpAuthCreateAsyncRequestHook, (void**)&sceNpAuthCreateAsyncRequestOriginal, "sceNpAuthCreateAsyncRequest"}, + {0x2B41200, (void*)sceNpCreateAsyncRequestHook, (void**)&sceNpCreateAsyncRequestOriginal, "sceNpCreateAsyncRequest"}, + {0x2B412B0, (void*)sceNpPollAsyncHook, (void**)&sceNpPollAsyncOriginal, "sceNpPollAsync"}, + {0x2B412C0, (void*)sceNpAuthPollAsyncHook, (void**)&sceNpAuthPollAsyncOriginal, "sceNpAuthPollAsync"}, + {0x2B41260, (void*)sceNpAuthGetAuthorizationCodeHook, (void**)&sceNpAuthGetAuthorizationCodeOriginal, "sceNpAuthGetAuthorizationCode"}, + {0x2B41070, (void*)sceNpCommerceDialogInitializeHook, (void**)&sceNpCommerceDialogInitializeOriginal, "sceNpCommerceDialogInitialize"}, + {0x2B41080, (void*)sceNpCommerceDialogOpenHook, (void**)&sceNpCommerceDialogOpenOriginal, "sceNpCommerceDialogOpen"}, + {0x2B412F0, (void*)sceNpCommerceDialogUpdateStatus_hook, (void**)&sceNpCommerceDialogUpdateStatusOriginal, "sceNpCommerceDialogUpdateStatus"}, + {0x2B41380, (void*)sceNpCommerceDialogTerminateHook, (void**)&sceNpCommerceDialogTerminateOriginal, "sceNpCommerceDialogTerminate"}, + {0x2B41300, (void*)sceNpCommerceDialogGetResultHook, (void**)&sceNpCommerceDialogGetResultOriginal, "sceNpCommerceDialogGetResult"}, + {0x2B41390, (void*)sceNpCommerceShowPsStoreIconHook, (void**)&sceNpCommerceShowPsStoreIconOriginal, "sceNpCommerceShowPsStoreIcon"}, + {0x2B413A0, (void*)sceNpCommerceHidePsStoreIconHook, (void**)&sceNpCommerceHidePsStoreIconOriginal, "sceNpCommerceHidePsStoreIcon"}, + {0x2B41320, (void*)sceNpBandwidthTestInitStartHook, (void**)&sceNpBandwidthTestInitStartOriginal, "sceNpBandwidthTestInitStart"}, + {0x2B41310, (void*)sceNpBandwidthTestGetStatusHook, (void**)&sceNpBandwidthTestGetStatusOriginal, "sceNpBandwidthTestGetStatus"}, + {0x2B40F70, (void*)sceNpBandwidthTestShutdownHook, (void**)&sceNpBandwidthTestShutdownOriginal, "sceNpBandwidthTestShutdown"}, + {0x2B41210, (void*)sceNpGetParentalControlInfoHook, (void**)&sceNpGetParentalControlInfoOriginal, "sceNpGetParentalControlInfo"}, + {0x2B412A0, (void*)sceNpCheckPlusHook, (void**)&sceNpCheckPlusOriginal, "sceNpCheckPlus"}, + {0x2B40EB0, (void*)sceNpSetContentRestrictionHook, (void**)&sceNpSetContentRestrictionOriginal, "sceNpSetContentRestriction"}, + {0x2B41280, (void*)sceNpGetAccountCountryHook, (void**)&sceNpGetAccountCountryOriginal, "sceNpGetAccountCountry"}, + {0x2B41290, (void*)sceNpGetAccountDateOfBirthHook, (void**)&sceNpGetAccountDateOfBirthOriginal, "sceNpGetAccountDateOfBirth"}, + {0x2B41650, (void*)sceNpWordFilterCreateTitleCtxA_hook, (void**)&sceNpWordFilterCreateTitleCtxOriginal, "sceNpWordFilterCreateTitleCtx"}, + {0x2B41660, (void*)sceNpWordFilterCreateAsyncRequestHook, (void**)&sceNpWordFilterCreateAsyncRequestOriginal, "sceNpWordFilterCreateAsyncRequest"}, + {0x2B41670, (void*)sceNpWordFilterSanitizeCommentHook, (void**)&sceNpWordFilterSanitizeCommentOriginal, "sceNpWordFilterSanitizeComment"}, + {0x2B41680, (void*)sceNpWordFilterPollAsyncHook, (void**)&sceNpWordFilterPollAsyncOriginal, "sceNpWordFilterPollAsync"}, + //{0x2B415C0, (void*)sceNpWebApiRegisterServicePushEventCallbackHook, (void**)&sceNpWebApiRegisterServicePushEventCallbackOriginal, "sceNpWebApiRegisterServicePushEventCallback"}, + //{0x2B41000, (void*)sceNpWebApiUnregisterServicePushEventCallbackHook, (void**)&sceNpWebApiUnregisterServicePushEventCallbackOriginal, "sceNpWebApiUnregisterServicePushEventCallback"}, + //{0x2B41560, (void*)sceNpWebApiCreatePushEventFilterHook, (void**)&sceNpWebApiCreatePushEventFilterOriginal, "sceNpWebApiCreatePushEventFilter"}, + //{0x2B41010, (void*)sceNpWebApiDeletePushEventFilterHook, (void**)&sceNpWebApiDeletePushEventFilterOriginal, "sceNpWebApiDeletePushEventFilter"}, + //{0x2B415B0, (void*)sceNpWebApiCreateServicePushEventFilterHook, (void**)&sceNpWebApiCreateServicePushEventFilterOriginal, "sceNpWebApiCreateServicePushEventFilter"}, + //{0x2B41590, (void*)sceNpWebApiDeleteServicePushEventFilterHook, (void**)&sceNpWebApiDeleteServicePushEventFilterOriginal, "sceNpWebApiDeleteServicePushEventFilter"}, + //{0x2B41570, (void*)sceNpWebApiRegisterPushEventCallbackHook, (void**)&sceNpWebApiRegisterPushEventCallbackOriginal, "sceNpWebApiRegisterPushEventCallback"}, + //{0x2B41580, (void*)sceNpWebApiCreateRequestHook, (void**)&sceNpWebApiCreateRequestOriginal, "sceNpWebApiCreateRequest"}, + //{0x2B415D0, (void*)sceNpWebApiDeleteRequestHook, (void**)&sceNpWebApiDeleteRequestOriginal, "sceNpWebApiDeleteRequest"}, + //{0x2B415A0, (void*)sceNpWebApiCreateHandleHook, (void**)&sceNpWebApiCreateHandleOriginal, "sceNpWebApiCreateHandle"}, + //{0x2B415E0, (void*)sceNpWebApiSendRequestHook, (void**)&sceNpWebApiSendRequestOriginal, "sceNpWebApiSendRequest"}, + //{0x2B415F0, (void*)sceNpWebApiGetHttpStatusCodeHook, (void**)&sceNpWebApiGetHttpStatusCodeOriginal, "sceNpWebApiGetHttpStatusCode"}, + //{0x2B41600, (void*)sceNpWebApiReadDataHook, (void**)&sceNpWebApiReadDataOriginal, "sceNpWebApiReadData"}, + }; + + + for (auto& hook : directHooks) { + if (hook.address != 0) { + WriteJump((void*)hook.address, hook.hookFunction); + printf("Direct hook applied to 0x%lx: %s\n", hook.address, hook.description); + } + } + + return true; +} + +void* main_thread(void*) +{ + sceKernelUsleep(10 * 1000); + + //https patches + //memcpy_p(0x2C045B4, "\x68\x74\x74\x70\x00\x00", 6); + //memcpy_p(0x2C0D09B, "\x68\x74\x74\x70\x00\x00", 6); + //memcpy_p(0x2C0D7FE, "\x68\x74\x74\x70\x3A\x2F\x2F\x00\x00", 9); + //memcpy_p(0x2C3889C, "\x68\x74\x74\x70\x3A\x2F\x2F\x00\x00", 9); + //memcpy_p(0x2C1047E, "\x68\x74\x74\x70\x3A\x2F\x2F\x25\x73\x00\x00", 11); + //memcpy_p(0x2C0EFC6, "\x68\x74\x74\x70\x3A\x2F\x2F\x25\x73\x2F\x25\x73\x00\x00", 14); + //memcpy_p(0x2C0DF11, "\x68\x74\x74\x70\x3A\x2F\x2F\x00\x00", 9); + //memcpy_p(0x2C0D7FE, "\x68\x74\x74\x70\x3A\x2F\x2F\x00\x00", 9); + //memcpy_p(0x2C0EF9B, "\x68\x74\x74\x70\x3A\x2F\x2F\x70\x72\x6F\x64\x2E\x25\x73\x2F\x25\x73\x00\x00", 19); + //memcpy_p(0x2C131F2, "\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x00\x00", 13); + + ////remove auth- + //memcpy_p(0x2C0F8D4, "\x25\x73\x00\x00\x00\x00\x00\x00", 8); + + //memcpy_p(0x2C0FA32, "\x72\x6F\x73\x2E\x70\x61\x72\x61\x64\x69\x73\x65\x73\x70\x72\x78\x2E\x65\x73\x00\x00\x00", 22); + //memcpy_p(0x1E85A85, "\xBE\x00\x00\x00\x00", 5); //0000000001A85A85 + //memcpy_p(0x19314C8, "\x41\xB8\x43\x03\x00\x00", 6); //15314C8 + + //memcpy_p(0x2C39CD4, "\x25\x73\x2D\x25\x73\x00\x00\x00\x00\x00\x00", 11); + //memcpy_p(0x190B8A0, "\xB0\x01\xC3", 3); + + if (ApplyDirectHooks()) { + sceSysUtilSendSystemNotificationWithText(222, "hooked successfully!"); + } + else { + sceSysUtilSendSystemNotificationWithText(222, "hooking failed!"); + } + + scePthreadExit(0); + return nullptr; +} + +pthread_t threadid; +extern "C" int module_start(size_t args, const void* argp) +{ + int sysutil = sceKernelLoadStartModule("libSceSysUtil.sprx", 0, NULL, 0, 0, 0); + orbis_syscall(591, sysutil, "sceSysUtilSendSystemNotificationWithText", &sceSysUtilSendSystemNotificationWithText); + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); + pthread_create(&threadid, NULL, main_thread, NULL); + + return SCE_OK; +} + +extern "C" int module_stop(size_t args, const void* argp) +{ + return SCE_OK; +} \ No newline at end of file