Skip to content

Commit

Permalink
Added vpk imports checking. Request by yifanlu.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheOfficialFloW committed Oct 15, 2016
1 parent 6ef0c2f commit ce8113d
Show file tree
Hide file tree
Showing 5 changed files with 575 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
TITLE_ID = VITASHELL
TARGET = VitaShell
OBJS = main.o init.o io_process.o makezip.o package_installer.o network_update.o context_menu.o archive.o photo.o audioplayer.o file.o text.o hex.o sfo.o \
uncommon_dialog.o message_dialog.o ime_dialog.o config.o theme.o language.o utils.o sha1.o list_dialog.o UI2.o touch_shell.o \
uncommon_dialog.o message_dialog.o ime_dialog.o config.o theme.o language.o utils.o elf.o sha1.o list_dialog.o UI2.o touch_shell.o \
minizip/zip.o minizip/unzip.o minizip/ioapi.o bm.o audio/vita_audio.o audio/player.o audio/id3.o \
audio/oggplayer.o audio/mp3player.o audio/mp3xing.o audio/lrcparse.o \
libmad/bit.o libmad/decoder.o libmad/fixed.o libmad/frame.o \
Expand Down
32 changes: 29 additions & 3 deletions archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ static int archive_path_start = 0;
static unzFile uf = NULL;
static FileList archive_list;

int checkForUnsafeImports(void *buffer);

int archiveCheckFilesForUnsafeFself() {
if (!uf)
return -1;
Expand All @@ -45,14 +47,38 @@ int archiveCheckFilesForUnsafeFself() {

// SCE magic
if (magic == 0x00454353) {
char buffer[0x84];
archiveFileRead(ARCHIVE_FD, buffer, sizeof(buffer));
char sce_header[0x84];
archiveFileRead(ARCHIVE_FD, sce_header, sizeof(sce_header));

uint64_t authid = *(uint64_t *)(buffer + 0x7C);
// Check authid flag
uint64_t authid = *(uint64_t *)(sce_header + 0x7C);
if (authid == 0x2F00000000000001 || authid == 0x2F00000000000003) {
archiveFileClose(ARCHIVE_FD);
return 1; // Unsafe
}

// Until here we have read 0x88 bytes
// ELF header starts at header_len, so let's seek to there
uint64_t header_len = *(uint64_t *)(sce_header + 0xC);

int i;
for (i = 0; i < header_len - 0x88; i += sizeof(uint32_t)) {
uint32_t dummy = 0;
archiveFileRead(ARCHIVE_FD, &dummy, sizeof(uint32_t));
}

// Check imports
char *buffer = malloc(archive_entry->size);
if (buffer) {
int size = archiveFileRead(ARCHIVE_FD, buffer, archive_entry->size);
int unsafe = checkForUnsafeImports(buffer);
free(buffer);

if (unsafe) {
archiveFileClose(ARCHIVE_FD);
return 1; // Unsafe
}
}
}

archiveFileClose(ARCHIVE_FD);
Expand Down
109 changes: 109 additions & 0 deletions elf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
VitaShell
Copyright (C) 2015-2016, TheFloW
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that 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 "main.h"
#include "elf.h"

typedef struct {
uint16_t size;
uint16_t lib_version;
uint16_t attribute;
uint16_t num_functions;
uint16_t num_vars;
uint16_t num_tls_vars;
uint32_t reserved1;
uint32_t module_nid;
char *lib_name;
uint32_t reserved2;
uint32_t func_nid_table;
uint32_t func_entry_table;
uint32_t var_nid_table;
uint32_t var_entry_table;
uint32_t tls_nid_table;
uint32_t tls_entry_table;
} SceImportsTable2xx;

typedef struct {
uint16_t size;
uint16_t lib_version;
uint16_t attribute;
uint16_t num_functions;
uint16_t num_vars;
uint16_t unknown1;
uint32_t module_nid;
char *lib_name;
uint32_t func_nid_table;
uint32_t func_entry_table;
uint32_t var_nid_table;
uint32_t var_entry_table;
} SceImportsTable3xx;

void convertToImportsTable3xx(SceImportsTable2xx *import_2xx, SceImportsTable3xx *import_3xx) {
memset(import_3xx, 0, sizeof(SceImportsTable3xx));

if (import_2xx->size == sizeof(SceImportsTable2xx)) {
import_3xx->size = import_2xx->size;
import_3xx->lib_version = import_2xx->lib_version;
import_3xx->attribute = import_2xx->attribute;
import_3xx->num_functions = import_2xx->num_functions;
import_3xx->num_vars = import_2xx->num_vars;
import_3xx->module_nid = import_2xx->module_nid;
import_3xx->lib_name = import_2xx->lib_name;
import_3xx->func_nid_table = import_2xx->func_nid_table;
import_3xx->func_entry_table = import_2xx->func_entry_table;
import_3xx->var_nid_table = import_2xx->var_nid_table;
import_3xx->var_entry_table = import_2xx->var_entry_table;
} else if (import_2xx->size == sizeof(SceImportsTable3xx)) {
memcpy(import_3xx, import_2xx, sizeof(SceImportsTable3xx));
}
}

int checkForUnsafeImports(void *buffer) {
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buffer;
Elf32_Phdr *phdr = (Elf32_Phdr *)((uint32_t)buffer + ehdr->e_phoff);

if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
ehdr->e_ident[EI_MAG3] != ELFMAG3) {
return -1;
}

uint32_t segment = ehdr->e_entry >> 30;
uint32_t offset = ehdr->e_entry & 0x3FFFFFFF;

uint32_t text_addr = (uint32_t)buffer + phdr[segment].p_offset;

SceModuleInfo *mod_info = (SceModuleInfo *)(text_addr + offset);

uint32_t i = mod_info->impTop;
while (i < mod_info->impBtm) {
SceImportsTable3xx import;
convertToImportsTable3xx((void *)text_addr + i, &import);

char *libname = (char *)(text_addr + import.lib_name - phdr[segment].p_vaddr);

if (strcmp(libname, "ScePromoterUtil") == 0 || strcmp(libname, "SceShellSvc") == 0) {
return 1; // Unsafe
}

i += import.size;
}

return 0; // Safe
}
Loading

0 comments on commit ce8113d

Please sign in to comment.