From 698d6f61211ba12dac3055b1a945b98f1efc4c9e Mon Sep 17 00:00:00 2001 From: Collin Date: Tue, 17 Feb 2026 22:43:40 +0100 Subject: [PATCH] upload files --- GTASPRXPS4.sln | 25 + GTASPRXPS4.vcxproj | 96 ++ GTASPRXPS4.vcxproj.filters | 30 + GTASPRXPS4.vcxproj.user | 4 + ORBIS_Debug/GTASPRXPS4.log | 30 + .../GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate | 2 + .../orbis-clang-cl.command.1.tlog | Bin 0 -> 1630 bytes .../orbis-clang-cl.read.1.tlog | Bin 0 -> 35424 bytes .../orbis-clang-cl.write.1.tlog | Bin 0 -> 470 bytes .../GTASPRXPS4.tlog/orbis-ld.command.1.tlog | Bin 0 -> 2606 bytes .../GTASPRXPS4.tlog/orbis-ld.read.1.tlog | Bin 0 -> 3288 bytes .../GTASPRXPS4.tlog/orbis-ld.write.1.tlog | Bin 0 -> 392 bytes ORBIS_Debug/GTASPRXPS4.tlog/unsuccessfulbuild | 0 ORBIS_Debug/GTAServer.prx | Bin 0 -> 91116 bytes ORBIS_Debug/Syscall.o | Bin 0 -> 2016 bytes ORBIS_Debug/fself.py | 816 +++++++++++++ ORBIS_Debug/make_sprx.bat | 46 + ORBIS_Debug/prx.o | Bin 0 -> 77496 bytes ORBIS_Debug/test.sprx | Bin 0 -> 17765 bytes ORBIS_Release/GTASPRXPS4.log | 21 + .../GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate | 2 + .../orbis-clang-cl.command.1.tlog | Bin 0 -> 3258 bytes .../orbis-clang-cl.read.1.tlog | Bin 0 -> 67970 bytes .../orbis-clang-cl.write.1.tlog | Bin 0 -> 978 bytes .../GTASPRXPS4.tlog/orbis-ld.command.1.tlog | Bin 0 -> 5194 bytes .../GTASPRXPS4.tlog/orbis-ld.read.1.tlog | Bin 0 -> 6644 bytes .../GTASPRXPS4.tlog/orbis-ld.write.1.tlog | Bin 0 -> 824 bytes .../GTASPRXPS4.tlog/unsuccessfulbuild | 0 .../GTASPRXPS4.vcxproj.FileListAbsolute.txt | 1 + ORBIS_Release/GTAServer.prx | Bin 0 -> 69232 bytes ORBIS_Release/GTAServerlol.sprx | Bin 0 -> 19741 bytes ORBIS_Release/Syscall.o | Bin 0 -> 896 bytes ORBIS_Release/fself.py | 816 +++++++++++++ ORBIS_Release/prx.o | Bin 0 -> 32000 bytes Syscall.cpp | 18 + Syscall.h | 11 + prx.cpp | 1082 +++++++++++++++++ 37 files changed, 3000 insertions(+) create mode 100644 GTASPRXPS4.sln create mode 100644 GTASPRXPS4.vcxproj create mode 100644 GTASPRXPS4.vcxproj.filters create mode 100644 GTASPRXPS4.vcxproj.user create mode 100644 ORBIS_Debug/GTASPRXPS4.log create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.command.1.tlog create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.read.1.tlog create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/orbis-ld.write.1.tlog create mode 100644 ORBIS_Debug/GTASPRXPS4.tlog/unsuccessfulbuild create mode 100644 ORBIS_Debug/GTAServer.prx create mode 100644 ORBIS_Debug/Syscall.o create mode 100644 ORBIS_Debug/fself.py create mode 100644 ORBIS_Debug/make_sprx.bat create mode 100644 ORBIS_Debug/prx.o create mode 100644 ORBIS_Debug/test.sprx create mode 100644 ORBIS_Release/GTASPRXPS4.log create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/GTASPRXPS4.lastbuildstate create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.command.1.tlog create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.read.1.tlog create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/orbis-clang-cl.write.1.tlog create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.command.1.tlog create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.read.1.tlog create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/orbis-ld.write.1.tlog create mode 100644 ORBIS_Release/GTASPRXPS4.tlog/unsuccessfulbuild create mode 100644 ORBIS_Release/GTASPRXPS4.vcxproj.FileListAbsolute.txt create mode 100644 ORBIS_Release/GTAServer.prx create mode 100644 ORBIS_Release/GTAServerlol.sprx create mode 100644 ORBIS_Release/Syscall.o create mode 100644 ORBIS_Release/fself.py create mode 100644 ORBIS_Release/prx.o create mode 100644 Syscall.cpp create mode 100644 Syscall.h create mode 100644 prx.cpp 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 0000000000000000000000000000000000000000..b1ce1d8382c287df8bdf1114aa5bde9b849bf3f7 GIT binary patch literal 1630 zcmeH`PfNo<5XIkF@H+%gdPu4G2N68fCQ8xT&{(Yy3^ArPkTjA+@zblnO>^zd77t~} zOlJ4(?3q$pC)uE>CdLQHvq}eyvYiy4{59}1} z>zLK0*CB$3>}p50Vp-@R(Ur(9rZ^YDQ z-snfN$Plx#y7%u*t`)gP)ZKK{pi?@UlD+A!O)tCH&Ai_AOo`8QnU~qqEwY`KzntUk Lv}|fxR=?t3m8}Ie literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b85a36da6004c847695e6c6eaae3896c8e889c0e GIT binary patch literal 35424 zcmdU&*=`$05JmerK>opx$&2A7F^s%XTqMDw$P7t|3W&`A|3s2|rqr1pT9N}J#w~-8 zL~}7OYu~!&@4x;m^YU9cl|$K;W$E<$R2F4ZZp&WJbmgJEFCWU=a(sMzu2-)0N}lJn zm-;)?y{%q*)bCySMUU?EzMbAbD>u5m*1fH6Kb9ZLxB0yI^!9V&Tk-ft7&{?Zmse#~ zu7zhQY_G~s!uwI*?dJjST#ugg+OAyaH9Wr)9X{#zN#E#o`L(>!?KFJbPXFUl_fC4{ zt-jlhXtEgI4+T3tw$VGThVSda5%fO^Q!YI7flez?)k~j;ayQ84x5sfMS=dQddi`v4 zyBQ?vMv`+O`9XGOl9$UTWQlhz^eocmrB;=uUPuo@j7DdWZfN=-yMjKSMB!1|dB%+q z?p>#`1TC$+lvzur=aL_6CpI?^vQf^ba0F^&v`scZ3LT1Ugt$tDb*`S+AHGjU*4t1_(4^_ymUMaUSY5LWqypgC9+a7w@g-)xur6+8(-6X2XdJm=Y`^O z`VZOb5rK2AXeX-NSz?|s%ArC=rJXG2Q)0;+Fhkv>GaAw&C04TD^Om^q7m=)G0Ds z$h~OEtVv#pBreZv!(*x^Bd_VeFo`pl&CU`r5^EDP4#d1l4oX$MWa)v+-A7%^&(5UHIjNVE$C)}} zF>98o7ykLo#l1AZKNa#xD45VC`tVA7uRJCTmfDGEzW|L-b9;JFf-ER!8s@DTUbD9+8Hh}$?v z6FGgJtT`X1tzy|Y@sopVq4(4-*ZSeyR2E#+J8nfScPw;1L)8zJ-W=3A#}=7!Myin~ z`LnoldS%hZb6oVc&`C7FtB-LGkuG%>L^V>$W3$d@7`+^u&Qp4^^y+qJ@hJ2|vYdVG z2Q1{XSt`^_xl*O{%1hO4W|Wx-&Qmq2C!2E6XC=9THtyJ{@+)ezZeNwhBV^%ETgBtV zeXXF?86>YXPtnnZAP(9p-)CNCX|_dEbjy;Z-Z#Z{P|i)CKNBaJi(q1h4IN%wAmQ9B z^LA9V;_M64mhSUY%spT=nRNL+aMg_+@YT!J=V`|dlq^*->Zn=JyhO3-bJ*W&Gk;^d zO+R=mw*C;eyJL&GgQyoCYU6i81&6(w@EodfXVN*|+Lv)>Wz0(M)9A<7&@qFid=2jC z?D(yCouAC(lgS_0utn71)$10?X{ZENT(vWolYeX-i>cU_t9dZLMAr=ZoF{UgQmS$_ zOFYAA3U}qKR}|n!5&ilsHoew^YLtPOuX}guWWh$WMVYK?m2L9s2T4_&H1Q&=m|83P zoNdjblVLGJ0^+<5`}o|RH1M!@Y^^*yQ|umlB`zdyY+m%r+e=i+llM7c-%I8N}d-hZm?C%I^@zp zaIxhln>Vbukh7IAX0j7?E-m(Z(sRpYHL&#Ttwh$S(9F~M?sJ6hleBH*%uF~tQ;dLZg1tQVLoJ6Wms4nHhC4QCQ8L{{kKtg?p;}b;!qka&@R#d6K{t1F z0=}_gSZzqAX*6oQ?%77FC=2=a_&d@oCikEkmd?$~pwvk?V)hdG3arf8fbiz=-^40j z4+erdKXu-d;RmYEwJkRyx zj)OeE)u)dWv_3TCBjeQ}d^m_^kPvqJBP(1JicQDd2cZvHt+Em;5bwt+V;`R5U?W$G zV&X)q4+(RvJH-R{vRFP8Rf0j|Mp3UQ;>2+;%W@?-?TpkIF?c<7blg9`rrY$2Zh3dG zK}RnIkJ9eYFy@NT~y40Mv8n4|%?nQJyKH{U)e?!^k5MGJ@GTxX8%}mii==Qi@ zrsOD}?p_j+Cbb#1@B285|Ev3qd?+4-0juwxG@C0UqlOF?A2mh{Uc1E3#thOyUp1t| z$CHY{%Mm>6<-gSMVxfXU&BlWlvX}Y-AymKkCm2Y*|4XEwS*Okt3%kSaEHg8{9+cz^bVMpz z`@oUFm7ABAJ3IDl=|B5Y=0)awpSdSzA!_9I_DJS7`WO8#I9sWxu@W|`s0FnT)G9vp YUWq$>{kjNm2kRtW^8YL8SA9u10jHEkCIA2c literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4b08a141cde76bb3023f435eee7aa487c7cc0343 GIT binary patch literal 2606 zcmdUxTT22_6ouDw(0`Dg>cJ?oh`@(ZE9oXpMu8+_nndbIGnPTWz54cqI!iFp-dEkUgle_v=_k8^lb+}9~TtG}!zWfdr+m4z}H>1A49JH^)% zRaW4Vb(|jH^{lRZMarwse3-=Ic~&8jff^1yVBTjHv1;lObbjJYp<3*Ou6u!cpbD(t zlCBPu{d@l31!-}^j#$p?YK!^n@38FV;&jyiaK$s)*)Kaqi$r|l0q3lfCGJ~YuONIqkQ%&*^fMT6V{9vp3w>hv`zU!V|oiT6R^uXLs|gdwN<+`v$Quf##2Qvwbgp0WIRO A82|tP literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5c21f1b8c3c57dcce7d81e2990155a8bce213f36 GIT binary patch literal 3288 zcmd6q%}&EG5QOK9#5?o|mk7j<5Vs@_rD~H@NeV%-=!@{|z_)d(PzhCBXe>*PV>`Q( znO*;UeZDK#qr5h1Rj8r%a;jCSW2DiWZgj6}^+SKo%#xWlZgb~6Q(9~0_SCIz>8*Lo zwBT)vwSxABnSPj+F#d5;zb*gK;xW~VV*bx{c2Wd^pD8>a`*%ZCqf7%crDl3UvlV)^ zv@g)}0qrl*&A2NLbe+-Xw50YZp6E_j6u*mx28#tPkF5pT@1McSVi!M-5mUpwZ?V!5 zAsMY#zD%*3P>&i-fiv({g3y7@Scwy7343!e#?EIBlO@I0miW;I^*dBIer;uZfnm#n zF$!Xd(c>s%%BeN#xA55iU@<0q75a9OVtWQz#|}EiUrfxcS+8BB*v7NX?|D2mk9N-L z$cn?$!KwDV;5{Sq=U}MF&na=($B=IW&9&XP3?#?o&jPm(bYcJE!AU1UdNVr93p+H$aZ`dVu~NajLS&R>)2CjXIC ZtT}o@f6i>u4gNlb$G4x;RdFLW`2yKfJGlS= literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7a19bcb10f8cd513be61060b8d8eb2dfd0974be6 GIT binary patch literal 91116 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 literal 0 HcmV?d00001 diff --git a/ORBIS_Debug/Syscall.o b/ORBIS_Debug/Syscall.o new file mode 100644 index 0000000000000000000000000000000000000000..a93dc73f62232ed89883a2208c9ac9422b7f0ac8 GIT binary patch literal 2016 zcmb_c&1(};5TDJ5jiO1kepOKdB3Q&nzWk`DM5?x;XfT#m2!!2rEuqP7c)KadN$}Q# zcMo3t1N;lT6niM>AK+Cy6>oY~s56`Q;>*hxTX5jLnfc9c=FPr0$;-PB@5KybKL|14 z78ue|^w;>%NmN3!0$F6vZ?2Pff9+EynR!K-8`UjBo~@-Ywv95s`H|Fy-7?+f+^WO< zrsw8LY=#wb7pk>#ZZuG4m-8&oO2wI+Q!JE2z%h`#*&%K_3FC@ID51 z2!z{c(|h|Gsvn0*+zsPb`Vj60oq;PnDy+Z5wupEFer)UE2O$s(i|Vns_>ggYpALn7 z9MWU>V??rJD8Ty=kBvo+34|ha%5NG06nWwS#MCQ2DENf`9W{U>8h%6g#}zy&Y*O@W zB(e@4xB%?AV|AAsre$$w6&QC~CJUTi0L=E5h7Sz`@}h8V%e%zWWIq znM=`2+q9eR3r{pN=r063ZZ-XeKbT}-t`|6L?$N>}KQQeT*;uRTIz!vDfnjffX`$}7 zN&g@DhGo?EkX5(DlmC=}(E0!$MVv7C?vh>+#zhGTt_>wsPBsnO=BPc}< zio`2u)A@N^s;mg-tqP(o`GGETOETePZ?T|kuh-YP@(0V?7 zU)23|#QpU|9^KyrF8%(_A*R=)l&eu-1h*K0?Ir*9Kl1f9bf5kY2-DyHnjqe!W)zY6 uQh&ghv=th3qreF6=Ln4I$ow6da@An6OTF>bK literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3cf2871301345f3505cf63cb4d44f777c26fd6ea GIT binary patch literal 77496 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 literal 0 HcmV?d00001 diff --git a/ORBIS_Debug/test.sprx b/ORBIS_Debug/test.sprx new file mode 100644 index 0000000000000000000000000000000000000000..10c8c9afa42c3bbc3267bd5b85c3f3eb5d66a9c2 GIT binary patch literal 17765 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 X+-4Em-Kt_hCCyt}g}4$#K*9b8K?&j? literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..853423a6f620a695f62ca61f477030ca42efd08d GIT binary patch literal 3258 zcmeH}O;5r=5Qg8giT|PTq=yo}V@x~%MM4y5s3<0l1QD=FOASTiuUDUKdu^g3ghMmw zPIq>8=bhP^PQN}MRoA(E_2j9cE~76;9o^`bm98Fiq*EQJkK9AvLsm!Ahd1ORF*}-Q zS9x=h_8C1LBh6+N^j&CMTe3Bh#n{G1#_v)-(X#>#HPuY95-pgG;I<~r=ZaWc=mMVT zJwKzRogBN1M$FzhS`p`6vOClmT}!+A&>0@=rT8=C9Z=TP0;R>{=n73A#1)-rAM*8* zqZnW{hQd@Mhgl|XS5qIw^;rIiE&GpH Pc9p+&m7mv1asGY-EoupH literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..43d01b9ec0ef2243169d8591e8c6e13f2aac78b8 GIT binary patch literal 67970 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 WRh~ib?0SjG;QG=#{baV?O6MDI`JaOT literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..bdafe7d10fa021340bbc52dde814cedbd0ef12d2 GIT binary patch literal 824 zcmc(c!3x4K5JcxJ_$z`a9(t>>h)~;-wNfGIkM!Hsw-&F0SS*1}b~2lt>^$yQ1!YQV zWhxYjNjuf5bmAuJqLnsUsslIh7A(L_?1dT-uh_%RIW?di(X-CpdH3TJus zz+AxTCsJVi&FG!0WVw>LW)o?7&(9q=GoOf_VM4Cy8;{((fJ;YSaS#9L&N#h)^<^9t HpB;Gulw5oq literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..50e4c891abc200b37bf499340adf5f512e61df4b GIT binary patch literal 69232 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..36169b507e2f55754d4c6f90af5e977d417d599a GIT binary patch literal 32000 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 literal 0 HcmV?d00001 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