Permalink
Browse files

rough kip patching stuff

  • Loading branch information...
fgsfdsfgs committed Aug 1, 2018
1 parent e80b2ca commit 210cf55b146884790492ddd13cfff77a1891bd0f
Showing with 358 additions and 10 deletions.
  1. +32 −10 src/firmware.c
  2. +88 −0 src/kippatches.c
  3. +32 −0 src/kippatches.h
  4. +206 −0 src/kippatches/fs.inc
View
@@ -23,6 +23,7 @@
#include "package.h"
#include "error.h"
#include "firmware.h"
#include "kippatches.h"
#define VERSION "v0.1"
@@ -141,13 +142,19 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) {
if(!customKern) {
//TODO
}
u8 kipHash[0x20];
//Patch FS module (truly not my proudest code TODO cleanup)
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips, link) {
//Patch FS
if(ki->kip1->tid == 0x0100000000000000) {
print("Patching FS\n");
// calc hash of source kip
se_calc_sha256(kipHash, ki->kip1, ki->size);
se_calc_sha256(kipHash, ki->kip1, ki->size);
//Create header
size_t sizeDiff = ki->kip1->sections[0].size_decomp - ki->kip1->sections[0].size_comp;
size_t newSize = ki->size + sizeDiff;
@@ -158,16 +165,31 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) {
if(!i) {
//Get decomp .text segment
u8 *kipDecompText = blz_decompress(moddedKip->data, moddedKip->sections[i].size_comp);
/*
* PATCHES HERE
*/
moddedKip->flags = 0x3E;
memcpy((void*)moddedKip->data, kipDecompText, moddedKip->sections[i].size_decomp);
kippatchset_t *pset = kippatch_find_set(kipHash, kip_patches);
if (!pset) {
print(" could not find patchset with matching hash\n");
usleep(6666666);
} else {
int res = kippatch_apply_set(kipDecompText, moddedKip->sections[i].size_decomp, pset, NULL);
if (res) {
gfx_con_setcol(&gfx_con, RED, 0, 0);
print("Error: kippatch_apply_set() returned %d\n", res);
gfx_con_setcol(&gfx_con, ORANGE, 0, 0);
usleep(6666666);
}
}
// recompress
// u32 isize = moddedKip->sections[i].size_decomp;
// u8 *kipRecompText = blz_compress(kipDecompText, &isize);
moddedKip->flags = 0x3E; // remove this when/if compression works
memcpy((void*)moddedKip->data, kipDecompText, moddedKip->sections[i].size_decomp); // isize
free(kipDecompText);
// free(kipRecompText);
pos += moddedKip->sections[i].size_comp;
moddedKip->sections[i].size_comp = moddedKip->sections[i].size_decomp;
moddedKip->sections[i].size_comp = moddedKip->sections[i].size_decomp; // isize;
} else {
if(moddedKip->sections[i].offset == 0) continue;
memcpy((void*)moddedKip->data + pos + sizeDiff, (void*)ki->kip1->data + pos, moddedKip->sections[i].size_comp);
View
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2018 Reisyukaku
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "hwinit/types.h"
#include "kippatches.h"
#include "kippatches/fs.inc"
// TODO: get full hashes somewhere and not just the first 16 bytes
kippatchset_t kip_patches[] = {
{ "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe\x68\xdc\xb2\x0b\x41\x09\x5b\xb4", fs_kip_patches_100 }, // FS 1.0.0
{ "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96\x4a\x12\x1f\x04\xb6\x1b\x17\x5e", fs_kip_patches_100 }, // FS 1.0.0 "exfat"
{ "FS", "\xcd\x7b\xbe\x18\xd6\x13\x0b\x28\xf6\x2f\x19\xfa\x79\x45\x53\x5b", fs_kip_patches_200 }, // FS 2.0.0
{ "FS", "\xe7\x66\x92\xdf\xaa\x04\x20\xe9\xfd\xd6\x8e\x43\x63\x16\x18\x18", fs_kip_patches_200 }, // FS 2.0.0 exfat
{ "FS", "\x0d\x70\x05\x62\x7b\x07\x76\x7c\x0b\x96\x3f\x9a\xff\xdd\xe5\x66", fs_kip_patches_210 }, // FS 2.1.0
{ "FS", "\xdb\xd8\x5f\xca\xcc\x19\x3d\xa8\x30\x51\xc6\x64\xe6\x45\x2d\x32", fs_kip_patches_210 }, // FS 2.1.0 exfat
{ "FS", "\xa8\x6d\xa5\xe8\x7e\xf1\x09\x7b\x23\xda\xb5\xb4\xdb\xba\xef\xe7", fs_kip_patches_300 }, // FS 3.0.0
{ "FS", "\x98\x1c\x57\xe7\xf0\x2f\x70\xf7\xbc\xde\x75\x31\x81\xd9\x01\xa6", fs_kip_patches_300 }, // FS 3.0.0 exfat
{ "FS", "\x57\x39\x7c\x06\x3f\x10\xb6\x31\x3f\x4d\x83\x76\x53\xcc\xc3\x71", fs_kip_patches_301 }, // FS 3.0.1
{ "FS", "\x07\x30\x99\xd7\xc6\xad\x7d\x89\x83\xbc\x7a\xdd\x93\x2b\xe3\xd1", fs_kip_patches_301 }, // FS 3.0.1 exfat
{ "FS", "\x06\xe9\x07\x19\x59\x5a\x01\x0c\x62\x46\xff\x70\x94\x6f\x10\xfb", fs_kip_patches_401 }, // FS 4.0.1
{ "FS", "\x54\x9b\x0f\x8d\x6f\x72\xc4\xe9\xf3\xfd\x1f\x19\xea\xce\x4a\x5a", fs_kip_patches_401 }, // FS 4.0.1 exfat
{ "FS", "\x80\x96\xaf\x7c\x6a\x35\xaa\x82\x71\xf3\x91\x69\x95\x41\x3b\x0b", fs_kip_patches_410 }, // FS 4.1.0
{ "FS", "\x02\xd5\xab\xaa\xfd\x20\xc8\xb0\x63\x3a\xa0\xdb\xae\xe0\x37\x7e", fs_kip_patches_410 }, // FS 4.1.0 exfat
{ "FS", "\xa6\xf2\x7a\xd9\xac\x7c\x73\xad\x41\x9b\x63\xb2\x3e\x78\x5a\x0c", fs_kip_patches_500 }, // FS 5.0.0
{ "FS", "\xce\x3e\xcb\xa2\xf2\xf0\x62\xf5\x75\xf8\xf3\x60\x84\x2b\x32\xb4", fs_kip_patches_500 }, // FS 5.0.0 exfat
{ "FS", "\x76\xf8\x74\x02\xc9\x38\x7c\x0f\x0a\x2f\xab\x1b\x45\xce\xbb\x93", fs_kip_patches_510 }, // FS 5.1.0
{ "FS", "\x10\xb2\xd8\x16\x05\x48\x85\x99\xdf\x22\x42\xcb\x6b\xac\x2d\xf1", fs_kip_patches_510 }, // FS 5.1.0 exfat
{ NULL, NULL, NULL },
};
int kippatch_apply(u8 *kipdata, u64 kipdata_len, kippatch_t *patch) {
if (!patch || !patch->diffs) return -1;
for (kipdiff_t *diff = patch->diffs; diff->len; ++diff) {
if (!diff->len || diff->offset + diff->len > kipdata_len)
return 1 + (int)(diff - patch->diffs);
u8 *start = kipdata + diff->offset;
if (memcmp(start, diff->orig_bytes, diff->len))
return 1 + (int)(diff - patch->diffs);
// TODO: maybe start copying after every diff has been verified?
memcpy(start, diff->patch_bytes, diff->len);
}
return 0;
}
int kippatch_apply_set(u8 *kipdata, u64 kipdata_len, kippatchset_t *patchset, char **filter) {
for (kippatch_t *p = patchset->patches; p && p->name; ++p) {
/*int found = 0;
for (char **filtname = filter; filtname && *filtname; ++filtname) {
if (!strcmp(p->name, *filtname)) {
found = 1;
break;
}
}
if (!found) continue;*/
int r = kippatch_apply(kipdata, kipdata_len, p);
if (r) return r;
}
return 0;
}
kippatchset_t *kippatch_find_set(u8 *kiphash, kippatchset_t *patchsets) {
for (kippatchset_t *ps = patchsets; ps && ps->kip_name; ++ps) {
if (!memcmp(kiphash, ps->kip_hash, 0x10))
return ps;
}
return NULL;
}
View
@@ -0,0 +1,32 @@
#pragma once
#include "hwinit/types.h"
typedef struct kipdiff_s {
u64 offset; // offset from kipDecompText
u32 len; // length of below strings, NULL signifies end of patch
const char *orig_bytes; // original byte string (this must match exactly)
const char *patch_bytes; // replacement byte string (same length)
} kipdiff_t;
// a single patch for a particular kip version
typedef struct kippatch_s {
const char *name; // name/id of the patch, NULL signifies end of patchset
kipdiff_t *diffs; // array of kipdiff_t's to apply
} kippatch_t;
// a group of patches that patch the same thing in the same kip,
// but for different kip/fw versions
typedef struct kippatchset_s {
const char *kip_name; // name/id of the kip, NULL signifies end of patchset list
const char *kip_hash; // sha256 of the right version of the kip
kippatch_t *patches; // set of patches for this version of the kip
} kippatchset_t;
// fs
extern kippatchset_t kip_patches[];
int kippatch_apply(u8 *kipdata, u64 kipdata_len, kippatch_t *patch);
int kippatch_apply_set(u8 *kipdata, u64 kipdata_len, kippatchset_t *patchset, char **filter);
kippatchset_t *kippatch_find_set(u8 *kiphash, kippatchset_t *patchsets);
View
@@ -0,0 +1,206 @@
static kipdiff_t fs_diffs_100_nosigchk[3] = {
{ 0x194A0, 4, "\xBA\x09\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x3A79C, 4, "\xE0\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_100_nocmac[5] = {
{ 0x45C78, 16, "\x29\x01\x0C\x0A\xEA\x17\x9F\x1A\x1F\x01\x04\xF1\x29\x01\x0A\x0A", "\x1F\x20\x03\xD5\xEA\x17\x9F\x1A\x1F\x01\x04\xF1\x1F\x20\x03\xD5" },
{ 0x46488, 8, "\x29\x01\x0D\x0A\x29\x01\x0F\x0A", "\x1F\x20\x03\xD5\x1F\x20\x03\xD5" },
{ 0x46498, 8, "\x29\x01\x0B\x0A\x8B\x09\x40\x39", "\x1F\x20\x03\xD5\x8B\x09\x40\x39" },
{ 0x464A8, 8, "\x1F\x01\x04\xF1\x29\x01\x0A\x0A", "\x1F\x01\x04\xF1\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_200_nosigchk[3] = {
{ 0x15DF4, 4, "\xBC\x0A\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x3F720, 4, "\x00\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_200_nocmac[6] = {
{ 0x4E744, 4, "\x29\x01\x0C\x0A", "\x1F\x20\x03\xD5" },
{ 0x4E750, 4, "\x29\x01\x0A\x0A", "\x1F\x20\x03\xD5" },
{ 0x4EF50, 8, "\x29\x01\x0D\x0A\x29\x01\x0F\x0A", "\x1F\x20\x03\xD5\x1F\x20\x03\xD5" },
{ 0x4EF5C, 4, "\x29\x01\x0B\x0A", "\x1F\x20\x03\xD5" },
{ 0x4EF70, 4, "\x29\x01\x0A\x0A", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_210_nosigchk[3] = {
{ 0x15F64, 4, "\xDF\x0A\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x3FAF8, 4, "\x00\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_210_nocmac[6] = {
{ 0x4EB24, 4, "\x29\x01\x0C\x0A", "\x1F\x20\x03\xD5" },
{ 0x4EB30, 4, "\x29\x01\x0A\x0A", "\x1F\x20\x03\xD5" },
{ 0x4F330, 8, "\x29\x01\x0D\x0A\x29\x01\x0F\x0A", "\x1F\x20\x03\xD5\x1F\x20\x03\xD5" },
{ 0x4F33C, 4, "\x29\x01\x0B\x0A", "\x1F\x20\x03\xD5" },
{ 0x4F350, 4, "\x29\x01\x0A\x0A", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_300_nosigchk[3] = {
{ 0x18E24, 4, "\x52\x0C\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x49EC8, 4, "\x40\x04\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_300_nocmac[6] = {
{ 0x5B1D8, 4, "\x80\x0A\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x5B6D4, 4, "\x00\x02\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x5F72C, 4, "\x80\x14\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x5FF40, 4, "\x00\x08\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x600B8, 4, "\xE0\x04\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_301_nosigchk[3] = {
{ 0x18E90, 4, "\x52\x0C\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x49F34, 4, "\xE0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_301_nocmac[6] = {
{ 0x5B294, 4, "\x80\x0A\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x5B790, 4, "\x00\x02\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x5F7E8, 4, "\x80\x14\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x5FFFC, 4, "\x00\x08\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x60174, 4, "\xE0\x04\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_401_nosigchk[3] = {
{ 0x1C4FC, 4, "\x3C\x2F\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x57934, 4, "\xE0\x02\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_401_nocmac[6] = {
{ 0x6C540, 4, "\xC0\x0A\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x6CA54, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x715B0, 4, "\xA0\x0C\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x71DCC, 4, "\xA0\x04\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x76300, 4, "\x00\x05\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_401_nogc[3] = {
{ 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
{ 0xAAC98, 8, "\x80\x02\xA0\x52\x40\x40\x91\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_410_nogc[3] = {
{ 0xA34BC, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
{ 0xAACFC, 8, "\x80\x02\xA0\x52\x40\x40\x91\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_500_nosigchk[3] = {
{ 0x22DDC, 4, "\x7D\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x7D490, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_500_nocmac[8] = {
{ 0x8F478, 4, "\x80\x0A\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x8F988, 4, "\xA0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x94F94, 4, "\x60\x0C\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x958DC, 4, "\x60\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x95A1C, 4, "\x20\x07\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x9C6C8, 4, "\xC0\x05\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x9C7F4, 4, "\xC0\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_500_nogc[3] = {
{ 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ 0xD74FC, 8, "\x40\x40\x91\x52\x80\x02\xA0\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_510_nosigchk[3] = {
{ 0x22E0C, 4, "\x85\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ 0x7D860, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_510_nocmac[8] = {
{ 0x8F848, 4, "\x80\x0A\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x8FD58, 4, "\xA0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x95364, 4, "\x60\x0C\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x95CAC, 4, "\x60\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x95DEC, 4, "\x20\x07\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x9CA98, 4, "\xC0\x05\x00\x36", "\x1F\x20\x03\xD5" },
{ 0x9CBC4, 4, "\xC0\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
static kipdiff_t fs_diffs_510_nogc[3] = {
{ 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ 0xD78CC, 8, "\x40\x40\x91\x52\x80\x02\xA0\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" },
{ 0, 0, "NULL", "NULL" },
};
/* patches */
static kippatch_t fs_kip_patches_100[] = {
{ "nosigchk", fs_diffs_100_nosigchk },
{ "nocmac", fs_diffs_100_nocmac },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_200[] = {
{ "nosigchk", fs_diffs_200_nosigchk },
{ "nocmac", fs_diffs_200_nocmac },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_210[] = {
{ "nosigchk", fs_diffs_210_nosigchk },
{ "nocmac", fs_diffs_210_nocmac },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_300[] = {
{ "nosigchk", fs_diffs_300_nosigchk },
{ "nocmac", fs_diffs_300_nocmac },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_301[] = {
{ "nosigchk", fs_diffs_301_nosigchk },
{ "nocmac", fs_diffs_301_nocmac },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_401[] = {
{ "nosigchk", fs_diffs_401_nosigchk },
{ "nocmac", fs_diffs_401_nocmac },
{ "nogc", fs_diffs_401_nogc },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_410[] = {
{ "nosigchk", fs_diffs_401_nosigchk },
{ "nocmac", fs_diffs_401_nocmac },
{ "nogc", fs_diffs_410_nogc },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_500[] = {
{ "nosigchk", fs_diffs_500_nosigchk },
{ "nocmac", fs_diffs_500_nocmac },
{ "nogc", fs_diffs_500_nogc },
{ NULL, NULL }
};
static kippatch_t fs_kip_patches_510[] = {
{ "nosigchk", fs_diffs_510_nosigchk },
{ "nocmac", fs_diffs_510_nocmac },
{ "nogc", fs_diffs_510_nogc },
{ NULL, NULL }
};

0 comments on commit 210cf55

Please sign in to comment.