diff --git a/tools/readself/readself.lpr b/tools/readself/readself.lpr index ef3e3cf8..12dd0256 100644 --- a/tools/readself/readself.lpr +++ b/tools/readself/readself.lpr @@ -2282,6 +2282,12 @@ var obj:elf_obj; begin + DefaultSystemCodePage:=CP_UTF8; + DefaultUnicodeCodePage:=CP_UTF8; + DefaultFileSystemCodePage:=CP_UTF8; + DefaultRTLFileSystemCodePage:=CP_UTF8; + UTF8CompareLocale:=CP_UTF8; + parse_param; if (ParamCount<=1) or (FileName='') then diff --git a/tools/trophy_key_export/trophy_key_export.lpi b/tools/trophy_key_export/trophy_key_export.lpi new file mode 100644 index 00000000..c9de6e6c --- /dev/null +++ b/tools/trophy_key_export/trophy_key_export.lpi @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + </General> + <BuildModes> + <Item Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <Units> + <Unit> + <Filename Value="trophy_key_export.lpr"/> + <IsPartOfProject Value="True"/> + </Unit> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="trophy_key_export"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions> + <Item> + <Name Value="EAbort"/> + </Item> + <Item> + <Name Value="ECodetoolError"/> + </Item> + <Item> + <Name Value="EFOpenError"/> + </Item> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/tools/trophy_key_export/trophy_key_export.lpr b/tools/trophy_key_export/trophy_key_export.lpr new file mode 100644 index 00000000..d945653b --- /dev/null +++ b/tools/trophy_key_export/trophy_key_export.lpr @@ -0,0 +1,369 @@ + +{$mode objfpc}{$H+} + +uses + sysutils, + elf64 in '..\..\sys\elf64.pas'; + +type + p_elf_obj=^elf_obj; + elf_obj=packed record + is_encrypted:Integer; + self:record + hdr :p_self_header; + segs :p_self_segment; + elf_hdr :p_elf64_hdr; + MinSeg :Int64; + MaxSeg :Int64; + end; + elf:record + hdr :p_elf64_hdr; + size:Int64; + end; + size:Int64; + // + min_offset:Int64; + max_offset:Int64; + end; + +procedure free_elf_obj(obj:p_elf_obj); +begin + if (obj=nil) then Exit; + FreeMem(obj^.self.hdr); + FreeMem(obj^.elf.hdr); + obj^:=Default(elf_obj); +end; + +function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; +begin + if (elf_hdr=nil) then Exit(nil); + if (elf_hdr^.e_phoff=0) then + begin + Result:=Pointer(elf_hdr+1); + end else + begin + Result:=Pointer(elf_hdr)+elf_hdr^.e_phoff; + end; +end; + +function maxInt64(a,b:Int64):Int64; inline; +begin + if (a>b) then Result:=a else Result:=b; +end; + +function minInt64(a,b:Int64):Int64; inline; +begin + if (a<b) then Result:=a else Result:=b; +end; + +procedure fixup_offset_size(var offset,size:Int64;max:Int64); +var + s,e:Int64; +begin + s:=offset; + e:=s+size; + + s:=MinInt64(s,max); + e:=MinInt64(e,max); + + offset:=s; + size :=(e-s); +end; + +function load_self(Const name:RawByteString;obj:p_elf_obj):Integer; +Var + F:THandle; + n,s:Int64; + Magic:DWORD; + i,count:Integer; + is_encrypted:Integer; + self_hdr :p_self_header; + self_segs:p_self_segment; + elf_hdr :p_elf64_hdr; + elf_phdr :p_elf64_phdr; + MinSeg :Int64; + MaxSeg :Int64; + src_ofs :Int64; + dst_ofs :Int64; + mem_size :Int64; +begin + Result:=0; + + if (name='') or (obj=nil) then Exit(-1); + + F:=FileOpen(name,fmOpenRead); + if (F=feInvalidHandle) then Exit(-2); + + n:=FileRead(F,Magic,SizeOf(DWORD)); + if (n<>SizeOf(DWORD)) then + begin + FileClose(F); + Exit(-3); + end; + + case Magic of + ELFMAG: //elf64 + begin + obj^.size:=FileSeek(F,0,fsFromEnd); + + if (obj^.size<=0) then + begin + FileClose(F); + Exit(-4); + end; + + obj^.elf.hdr :=GetMem(obj^.size); + obj^.elf.size:=obj^.size; + + FileSeek(F,0,fsFromBeginning); + n:=FileRead(F,obj^.elf.hdr^,obj^.size); + FileClose(F); + + if (n<>obj^.size) then + begin + FreeMem(obj^.elf.hdr); + obj^.elf.hdr:=nil; + Exit(-5); + end; + end; + SELF_MAGIC: + begin + obj^.size:=FileSeek(F,0,fsFromEnd); + + if (obj^.size<=0) then + begin + FileClose(F); + Exit(-4); + end; + + self_hdr:=GetMem(obj^.size); + obj^.self.hdr:=self_hdr; + + FileSeek(F,0,fsFromBeginning); + n:=FileRead(F,self_hdr^,obj^.size); + FileClose(F); + + if (n<>obj^.size) then + begin + FreeMem(obj^.self.hdr); + obj^.self.hdr:=nil; + Exit(-5); + end; + + count:=self_hdr^.Num_Segments; + + self_segs:=Pointer(self_hdr+1); + obj^.self.segs:=self_segs; + + is_encrypted:=0; + if (count<>0) then + For i:=0 to count-1 do + if ((self_segs[i].flags and (SELF_PROPS_ENCRYPTED or SELF_PROPS_COMPRESSED))<>0) then + begin + is_encrypted:=1; + Break; + end; + + obj^.is_encrypted:=is_encrypted; + + elf_hdr:=Pointer(self_segs)+(count*SizeOf(t_self_segment)); + obj^.self.elf_hdr:=elf_hdr; + + elf_phdr:=get_elf_phdr(elf_hdr); + + MinSeg:=High(Int64); + MaxSeg:=0; + + count:=self_hdr^.Num_Segments; + + if (count<>0) then + For i:=0 to count-1 do + if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then + begin + s:=SELF_SEGMENT_INDEX(self_segs[i].flags); + s:=elf_phdr[s].p_offset; + MinSeg:=MinInt64(s,MinSeg); + s:=s+minInt64(self_segs[i].filesz,self_segs[i].filesz); + MaxSeg:=MaxInt64(s,MaxSeg); + end; + + obj^.self.MinSeg:=MinSeg; + obj^.self.MaxSeg:=MaxSeg; + + if (is_encrypted=0) then //load elf + begin + obj^.elf.hdr :=AllocMem(MaxSeg); + obj^.elf.size:=MaxSeg; + + //elf_hdr part + n:=ptruint(elf_hdr)-ptruint(self_hdr); //offset to hdr + s:=self_hdr^.Header_Size+self_hdr^.Meta_size; //offset to end + s:=MinInt64(obj^.size,s); //min size + s:=MaxInt64(s,n)-n; //get size + + //first page + Move(elf_hdr^,obj^.elf.hdr^,s); + + count:=self_hdr^.Num_Segments; + + if (count<>0) then + For i:=0 to count-1 do + if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then + begin + s:=SELF_SEGMENT_INDEX(self_segs[i].flags); + + mem_size:=minInt64(self_segs[i].filesz,self_segs[i].memsz); + + src_ofs:=self_segs[i].offset; //start offset + dst_ofs:=elf_phdr[s].p_offset; //start offset + + fixup_offset_size(src_ofs,mem_size,obj^.size); + fixup_offset_size(dst_ofs,mem_size,MaxSeg); + + Move( (Pointer(self_hdr) +src_ofs)^, //src + (Pointer(obj^.elf.hdr)+dst_ofs)^, //dst + mem_size); //size + end; + end; + + end; + else + begin + FileClose(F); + Exit(-1); + end; + end; + +end; + +Function get_bytes_str(p:PByte;size:Integer):RawByteString; +begin + Result:=''; + while (size<>0) do + begin + Result:=Result+HexStr(P^,2); + Inc(P); + Dec(size); + end; +end; + +type + P_TROPHY_KEY_RECORD=^T_TROPHY_KEY_RECORD; + T_TROPHY_KEY_RECORD=packed record + str_ptr:QWORD; //"01","00" + key_val:Array[0..15] of Byte; + zero :QWORD; + end; + +//30h 0 +//31h 1 +//00h +// +//30h 0 +//30h 0 +//00h + +procedure _search(obj:p_elf_obj); +var + base:Pointer; + size:QWORD; + curr_ptr :Pointer; + curr_size:QWORD; + // + offset :QWORD; + str_val:DWORD; + P_REC :P_TROPHY_KEY_RECORD; +begin + // + base:=obj^.elf.hdr; + size:=obj^.elf.size; + // + curr_ptr :=base; + curr_size:=size-SizeOf(T_TROPHY_KEY_RECORD)*2; + // + while (curr_size<>0) do + begin + offset:=PQWORD(curr_ptr)^; + offset:=offset+$4000; + + if (offset<(size-8)) then + begin + str_val:=PDWORD(base+offset)^; + str_val:=str_val and $FFFFFF; + + if (str_val=$003130) then //"01" + begin + P_REC:=curr_ptr; + + offset:=P_REC[1].str_ptr; + offset:=offset+$4000; + + if (offset<(size-8)) then + begin + str_val:=PDWORD(base+offset)^; + str_val:=str_val and $FFFFFF; + + if (str_val=$003030) then //"00" + begin + Writeln('Trophy keys found!'); + + Writeln('(CEX) Release:',get_bytes_str(@P_REC[0].key_val,16)); + Writeln('(DEX) Debug :',get_bytes_str(@P_REC[1].key_val,16)); + + Writeln; + Exit; + end; + + end; + + end; + + end; + + // + Inc(curr_ptr); + Dec(curr_size); + end; + + Writeln('Trophy keys NOT found!'); +end; + +var + r:Integer; + obj:elf_obj; + + FileName:RawByteString; + +begin + DefaultSystemCodePage:=CP_UTF8; + DefaultUnicodeCodePage:=CP_UTF8; + DefaultFileSystemCodePage:=CP_UTF8; + DefaultRTLFileSystemCodePage:=CP_UTF8; + UTF8CompareLocale:=CP_UTF8; + + if (ParamCount<=1) then + begin + Writeln('Usage: trophy_key_export elf/self-file (SceShellCore.elf)'); + end; + + FileName:=ParamStr(1); + + r:=load_self(FileName,@obj); + + if (r=0) then + begin + if (obj.is_encrypted<>0) then + begin + Writeln('Elf is_encrypted'); + end else + begin + _search(@obj); + end; + end else + begin + Writeln('Error(',r,') load file:',FileName); + end; + + readln; +end. +