Advertisement
dcjoedog

Modified UNSELF.C file

Oct 21st, 2011
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.02 KB | None | 0 0
  1. // Copyright 2010       Sven Peter <svenpeter@gmail.com>
  2. // Licensed under the terms of the GNU GPL, version 2
  3. // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
  4.  
  5. #include "tools.h"
  6. #include "types.h"
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <assert.h>
  11. #include <stdlib.h>
  12.  
  13. #define MAX_SECTIONS    255
  14.  
  15. static u8 *self = NULL;
  16. static u8 *elf = NULL;
  17. static FILE *out = NULL;
  18.  
  19. static u64 info_offset;
  20. static u32 key_ver;
  21. static u64 phdr_offset;
  22. static u64 shdr_offset;
  23. static u64 sec_offset;
  24. static u64 ver_offset;
  25. static u64 version;
  26. static u64 elf_offset;
  27. static u64 meta_offset;
  28. static u64 header_len;
  29. static u64 filesize;
  30. static u32 arch64;
  31. static u32 n_sections;
  32.  
  33. static struct elf_hdr ehdr;
  34.  
  35. static u32 app_type;
  36.  
  37. static struct {
  38.     u32 offset;
  39.     u32 size;
  40.     u32 compressed;
  41.     u32 size_uncompressed;
  42.     u32 elf_offset;
  43. } self_sections[MAX_SECTIONS];
  44.  
  45. static void read_header(void)
  46. {
  47.     key_ver =    be16(self + 0x08);
  48.     meta_offset = be32(self + 0x0c);
  49.     header_len =  be64(self + 0x10);
  50.     filesize =    be64(self + 0x18);
  51.     info_offset = be64(self + 0x28);
  52.     elf_offset =  be64(self + 0x30);
  53.     phdr_offset = be64(self + 0x38) - elf_offset;
  54.     shdr_offset = be64(self + 0x40) - elf_offset;
  55.     sec_offset =  be64(self + 0x48);
  56.     ver_offset =  be64(self + 0x50);
  57.  
  58.     version =   be64(self + info_offset + 0x10);
  59.     app_type =    be32(self + info_offset + 0x0c);
  60.  
  61.     elf = self + elf_offset;
  62.     arch64 = elf_read_hdr(elf, &ehdr);
  63. }
  64.  
  65. struct self_sec {
  66.     u32 idx;
  67.     u64 offset;
  68.     u64 size;
  69.     u32 compressed;
  70.     u32 encrypted;
  71.     u64 next;
  72. };
  73.  
  74. static void read_section(u32 i, struct self_sec *sec)
  75. {
  76.     u8 *ptr;
  77.  
  78.     ptr = self + sec_offset + i*0x20;
  79.  
  80.     sec->idx = i;
  81.     sec->offset     = be64(ptr + 0x00);
  82.     sec->size       = be64(ptr + 0x08);
  83.     sec->compressed = be32(ptr + 0x10) == 2 ? 1 : 0;
  84.     sec->encrypted  = be32(ptr + 0x20);
  85.     sec->next       = be64(ptr + 0x20);
  86. }
  87.  
  88. static int qsort_compare(const void *a, const void *b)
  89. {
  90.     const struct self_sec *sa, *sb;
  91.     sa = a;
  92.     sb = b;
  93.  
  94.     if (sa->offset > sb->offset)
  95.         return 1;
  96.     else if(sa->offset < sb->offset)
  97.         return -1;
  98.     else
  99.         return 0;
  100. }
  101.  
  102. static void read_sections(void)
  103. {
  104.     struct self_sec s[MAX_SECTIONS];
  105.     struct elf_phdr p;
  106.     u32 i;
  107.     u32 j;
  108.     u32 n_secs;
  109.     u32 self_offset, elf_offset;
  110.  
  111.     memset(s, 0, sizeof s);
  112.     for (i = 0, j = 0; i < ehdr.e_phnum; i++) {
  113.         read_section(i, &s[j]);
  114.         if (s[j].compressed)
  115.             j++;
  116.     }
  117.  
  118.     n_secs = j;
  119.     qsort(s, n_secs, sizeof(*s), qsort_compare);
  120.  
  121.     elf_offset = 0;
  122.     self_offset = header_len;
  123.     j = 0;
  124.     i = 0;
  125.     while (elf_offset < filesize) {
  126.         if (i == n_secs) {
  127.             self_sections[j].offset = self_offset;
  128.             self_sections[j].size = filesize - elf_offset;
  129.             self_sections[j].compressed = 0;
  130.             self_sections[j].size_uncompressed = filesize - elf_offset;
  131.             self_sections[j].elf_offset = elf_offset;
  132.             elf_offset = filesize;
  133.         } else if (self_offset == s[i].offset) {
  134.             self_sections[j].offset = self_offset;
  135.             self_sections[j].size = s[i].size;
  136.             self_sections[j].compressed = 1;
  137.             elf_read_phdr(arch64, elf + phdr_offset +
  138.                     (ehdr.e_phentsize * s[i].idx), &p);
  139.             self_sections[j].size_uncompressed = p.p_filesz;
  140.             self_sections[j].elf_offset = p.p_off;
  141.  
  142.             elf_offset = p.p_off + p.p_filesz;
  143.             self_offset = s[i].next;
  144.             i++;
  145.         } else {
  146.             elf_read_phdr(arch64, elf + phdr_offset +
  147.                     (ehdr.e_phentsize * s[i].idx), &p);
  148.             self_sections[j].offset = self_offset;
  149.             self_sections[j].size = p.p_off - elf_offset;
  150.             self_sections[j].compressed = 0;
  151.             self_sections[j].size_uncompressed = self_sections[j].size;
  152.             self_sections[j].elf_offset = elf_offset;
  153.  
  154.             elf_offset += self_sections[j].size;
  155.             self_offset += s[i].offset - self_offset;
  156.         }
  157.         j++;
  158.     }
  159.  
  160.     n_sections = j;
  161. }
  162.  
  163. static void write_elf(void)
  164. {
  165.     u32 i;
  166.     u8 *bfr;
  167.     u32 size;
  168.     u32 offset = 0;
  169.  
  170.     for (i = 0; i < n_sections; i++) {
  171.         fseek(out, self_sections[i].elf_offset, SEEK_SET);
  172.         offset = self_sections[i].elf_offset;
  173.         if (self_sections[i].compressed) {
  174.             size = self_sections[i].size_uncompressed;
  175.  
  176.             bfr = malloc(size);
  177.             if (bfr == NULL)
  178.                 fail("failed to allocate %d bytes", size);
  179.  
  180.             offset += size;
  181.    
  182.             decompress(self + self_sections[i].offset,
  183.                        self_sections[i].size,
  184.                    bfr, size);
  185.             fwrite(bfr, size, 1, out);
  186.             free(bfr);
  187.         } else {
  188.             bfr = self + self_sections[i].offset;
  189.             size = self_sections[i].size;
  190.             offset += size;
  191.    
  192.             fwrite(bfr, size, 1, out);
  193.         }
  194.     }
  195. }
  196.  
  197. static void remove_shnames(u64 shdr_offset, u16 n_shdr, u64 shstrtab_offset, u32 strtab_size)
  198. {
  199.     u16 i;
  200.     u32 size;
  201.     struct elf_shdr s;
  202.  
  203.     if (arch64)
  204.         size = 0x40;
  205.     else
  206.         size = 0x28;
  207.  
  208.     for (i = 0; i < n_shdr; i++) {
  209.         elf_read_shdr(arch64, elf + shdr_offset + i * size, &s);
  210.  
  211.         s.sh_name = 0;
  212.         if (s.sh_type == 3) {
  213.             s.sh_offset = shstrtab_offset;
  214.             s.sh_size = strtab_size;
  215.         }
  216.  
  217.         elf_write_shdr(arch64, elf + shdr_offset + i * size, &s);
  218.     }
  219. }
  220.  
  221. static void check_elf(void)
  222. {
  223.     u8 bfr[0x48];
  224.     u64 elf_offset;
  225.     u64 phdr_offset;
  226.     u64 shdr_offset;
  227.     u64 phdr_offset_new;
  228.     u64 shdr_offset_new;
  229.     u64 shstrtab_offset;
  230.     u16 n_phdr;
  231.     u16 n_shdr;
  232.     const char shstrtab[] = ".unknown\0\0";
  233.     const char elf_magic[4] = {0x7f, 'E', 'L', 'F'};
  234.  
  235.     fseek(out, 0, SEEK_SET);
  236.     fread(bfr, 4, 1, out);
  237.  
  238.     if (memcmp(bfr, elf_magic, sizeof elf_magic) == 0)
  239.         return;
  240.  
  241.     elf_offset =  be64(self + 0x30);
  242.     phdr_offset = be64(self + 0x38) - elf_offset;
  243.     shdr_offset = be64(self + 0x40) - elf_offset;
  244.  
  245.     if (arch64) {
  246.         fseek(out, 0x48, SEEK_SET);
  247.         phdr_offset_new = 0x48;
  248.  
  249.         fseek(out, 0, SEEK_END);
  250.         shdr_offset_new = ftell(out);
  251.  
  252.         n_phdr = be16(elf + 0x38);
  253.         n_shdr = be16(elf + 0x3c);
  254.         shstrtab_offset = shdr_offset_new + n_shdr * 0x40;
  255.  
  256.         remove_shnames(shdr_offset, n_shdr, shstrtab_offset, sizeof shstrtab);
  257.  
  258.         fseek(out, phdr_offset_new, SEEK_SET);
  259.         fwrite(elf + phdr_offset, 0x38, n_phdr, out);
  260.  
  261.         fseek(out, shdr_offset_new, SEEK_SET);
  262.         fwrite(elf + shdr_offset, 0x40, n_shdr, out);
  263.  
  264.         wbe64(elf + 0x20, phdr_offset_new);
  265.         wbe64(elf + 0x28, shdr_offset_new);
  266.  
  267.         fseek(out, SEEK_SET, 0);
  268.         fwrite(elf, 0x48, 1, out);
  269.  
  270.         fseek(out, shstrtab_offset, SEEK_SET);
  271.         fwrite(shstrtab, sizeof shstrtab, 1, out);
  272.     } else {
  273.         fseek(out, 0x34, SEEK_SET);
  274.         phdr_offset_new = 0x34;
  275.         fseek(out, 0, SEEK_END);
  276.         shdr_offset_new = ftell(out);
  277.  
  278.         n_phdr = be16(elf + 0x2c);
  279.         n_shdr = be16(elf + 0x30);
  280.         shstrtab_offset = shdr_offset_new + n_shdr * 0x40;
  281.  
  282.         remove_shnames(shdr_offset, n_shdr, shstrtab_offset, sizeof shstrtab);
  283.    
  284.         fseek(out, phdr_offset_new, SEEK_SET);
  285.         fwrite(elf + phdr_offset, 0x20, n_phdr, out);
  286.  
  287.         fseek(out, shdr_offset_new, SEEK_SET);
  288.         fwrite(elf + shdr_offset, 0x28, n_shdr, out);
  289.  
  290.         wbe32(elf + 0x1c, phdr_offset_new);
  291.         wbe32(elf + 0x20, shdr_offset_new);
  292.  
  293.         fseek(out, SEEK_SET, 0);
  294.         fwrite(elf, 0x34, 1, out);
  295.  
  296.         fseek(out, shstrtab_offset, SEEK_SET);
  297.         fwrite(shstrtab, sizeof shstrtab, 1, out);
  298.     }
  299. }
  300.  
  301. static struct keylist *self_load_keys(void)
  302. {
  303.     enum sce_key id;
  304.  
  305.     switch (app_type) {
  306.         case 1:
  307.             id = KEY_LV0;
  308.             break;
  309.         case 2:
  310.             id = KEY_LV1;
  311.             break;
  312.         case 3:
  313.             id = KEY_LV2;
  314.             break;
  315.         case 4:
  316.             id = KEY_APP;
  317.             break;
  318.         case 5:
  319.             id = KEY_ISO;
  320.             break;
  321.         case 6:
  322.             id = KEY_LDR;
  323.             break;
  324.         case 7:
  325.             id = KEY_PKG;
  326.             break;
  327.         case 8:
  328.             id = KEY_DRM;
  329.             break;
  330.         default:
  331.             fail("invalid type: %08x", app_type);  
  332.     }
  333.  
  334.     return keys_get(id);
  335. }
  336.  
  337. static void self_decrypt(void)
  338. {
  339.     struct keylist *klist;
  340.  
  341.     klist = self_load_keys();
  342.     if (klist == NULL)
  343.         fail("no key found");
  344.  
  345.     if (sce_decrypt_header(self, klist) < 0)
  346.         fail("self_decrypt_header failed");
  347.  
  348.     if (sce_decrypt_data(self) < 0)
  349.         fail("self_decrypt_data failed");
  350. }
  351.  
  352. int main(int argc, char *argv[])
  353. {
  354.     if (argc != 3)
  355.         fail("usage: unself in.self out.elf");
  356.  
  357.     self = mmap_file(argv[1]);
  358.  
  359.     if (be32(self) != 0x53434500)
  360.         fail("not a SELF");
  361.  
  362.     read_header();
  363.     read_sections();
  364.  
  365.     if (key_ver != 0x8000)
  366.         self_decrypt();
  367.  
  368.     out = fopen(argv[2], "w+");
  369.  
  370.     write_elf();
  371.     check_elf();
  372.  
  373.     fclose(out);
  374.  
  375.     return 0;
  376. }
  377.  
  378.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement