mirror of
https://github.com/rvtr/TwlToolsRED.git
synced 2025-10-31 06:41:18 -04:00
srlの改竄検出コマンドラインツールを追加
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@557 7061adef-622a-194b-ae81-725974e89856
This commit is contained in:
parent
3788fbc745
commit
18fa074d21
15
build/tools/TamperDetectorForSrl/Readme.txt
Normal file
15
build/tools/TamperDetectorForSrl/Readme.txt
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
例)
|
||||
./tamperdetector.exe --g ./srl/GENUINE_AAAA.srl --m ./srl/MAGICON_AAAA.srl
|
||||
|
||||
|
||||
効果)
|
||||
ヘッダ改竄状況、ファイル改竄状況の順に表示されます。
|
||||
|
||||
オフセットやサイズが改竄されている場合
|
||||
(双方のsrlファイル上でチェック対象のファイルが存在しているアドレスが
|
||||
異なるケース)にも対応しています。
|
||||
|
||||
サイズが改竄されている場合は小さいほうのサイズでチェックされます。
|
||||
|
||||
最後に srlファイル中の BMPファイルを全て PC上のカレントパスにエクスポートします。
|
||||
110
build/tools/TamperDetectorForSrl/banner.h
Normal file
110
build/tools/TamperDetectorForSrl/banner.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*---------------------------------------------------------------------------*
|
||||
Project: TwlSDK - tools - makebanner
|
||||
File: banner.h
|
||||
|
||||
Copyright 2003-2008 Nintendo. All rights reserved.
|
||||
|
||||
These coded instructions, statements, and computer programs contain
|
||||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||||
Company Ltd., and are protected by Federal copyright law. They may
|
||||
not be disclosed to third parties or copied or duplicated in any form,
|
||||
in whole or in part, without the prior written consent of Nintendo.
|
||||
|
||||
*---------------------------------------------------------------------------*/
|
||||
#ifndef TWL_OS_COMMON_BANNER_H_
|
||||
#define TWL_OS_COMMON_BANNER_H_
|
||||
|
||||
// define data---------------------------------------------
|
||||
|
||||
#define BANNER_IMAGE_SIZE (32 * 32 / (8/4))
|
||||
#define BANNER_PLTT_SIZE (16 * 2)
|
||||
#define BANNER_LANG_LENGTH 128
|
||||
#define BANNER_LANG_SIZE (BANNER_LANG_LENGTH * 2)
|
||||
|
||||
#define BANNER_VER_NTR_MIN 1 // NTRバナーver.MIN.
|
||||
#define BANNER_VER_NTR_MAX 3 // NTRバナーver.MAX.(smaller than UCHAR_MAX)
|
||||
#define BANNER_VER_TWL_MIN 3 // TWLバナーver.MIN.
|
||||
#define BANNER_VER_TWL_MAX 3 // TWLバナーver.MAX.(smaller than UCHAR_MAX)
|
||||
|
||||
#define BANNER_CHINESE_SUPPORT_VER 2 // 中国語サポートver.
|
||||
#define BANNER_KOREAN_SUPPORT_VER 3 // 韓国語サポートver.
|
||||
|
||||
#define BANNER_LANG_NUM_RSV 8 // 言語予約領域数
|
||||
#define BANNER_ANIME_PATTERN_NUM 8 // バナーアニメパターン数
|
||||
#define BANNER_ANIME_CONTROL_INFO_NUM 64 // バナーアニメコントロール情報数
|
||||
|
||||
|
||||
typedef enum {
|
||||
BANNER_PRIO_JAPANESE = 0,
|
||||
BANNER_PRIO_ENGLISH,
|
||||
BANNER_PRIO_FRENCH,
|
||||
BANNER_PRIO_GERMAN,
|
||||
BANNER_PRIO_ITALIAN,
|
||||
BANNER_PRIO_SPANISH,
|
||||
BANNER_PRIO_CHINESE,
|
||||
BANNER_PRIO_KOREAN,
|
||||
BANNER_LANG_NUM,
|
||||
|
||||
BANNER_LANG_NUM_V1 = BANNER_PRIO_CHINESE,
|
||||
BANNER_LANG_NUM_V2 = BANNER_PRIO_KOREAN - BANNER_PRIO_CHINESE,
|
||||
BANNER_LANG_NUM_V3 = BANNER_LANG_NUM - BANNER_PRIO_KOREAN
|
||||
}BannerLanguagePriorityIdx;
|
||||
|
||||
|
||||
// プラットフォームコード
|
||||
typedef enum {
|
||||
BANNER_PLATFORM_NTR = 0,
|
||||
BANNER_PLATFORM_TWL = 1,
|
||||
|
||||
BANNER_PLATFORM_MAX = 2
|
||||
}BannerPlatformCode;
|
||||
|
||||
|
||||
// バナーヘッダ
|
||||
typedef struct {
|
||||
u8 version;
|
||||
u8 platform; // 上記BannerPlatformCodeで指定
|
||||
u16 crc16_v1;
|
||||
u16 crc16_v2;
|
||||
u16 crc16_v3;
|
||||
u16 crc16_anime;
|
||||
u8 reserved_B[ 22 ];
|
||||
}BannerHeader;
|
||||
|
||||
|
||||
// バナーver.1 ボディ
|
||||
typedef struct {
|
||||
u8 image[ BANNER_IMAGE_SIZE ];
|
||||
u8 pltt[ BANNER_PLTT_SIZE ];
|
||||
u16 gameName[ BANNER_LANG_NUM_V1 ][ BANNER_LANG_LENGTH ];
|
||||
}BannerFileV1;
|
||||
|
||||
|
||||
// バナーver.2 ボディ追加分
|
||||
typedef struct {
|
||||
u16 gameName[ BANNER_LANG_NUM_V2 ][ BANNER_LANG_LENGTH ];
|
||||
}BannerFileV2;
|
||||
|
||||
|
||||
// バナーver.3 ボディ追加分
|
||||
typedef struct {
|
||||
u16 gameName[ BANNER_LANG_NUM_V3 ][ BANNER_LANG_LENGTH ];
|
||||
}BannerFileV3;
|
||||
|
||||
|
||||
// バナーgameName 言語拡張予約領域
|
||||
typedef struct {
|
||||
u16 gameName[ BANNER_LANG_NUM_RSV ][ BANNER_LANG_LENGTH ];
|
||||
}BannerFileRsv;
|
||||
|
||||
|
||||
// NTRバナーファイル構造体
|
||||
typedef struct {
|
||||
BannerHeader h;
|
||||
BannerFileV1 v1;
|
||||
BannerFileV2 v2;
|
||||
BannerFileV3 v3;
|
||||
}NTRBannerFile;
|
||||
|
||||
|
||||
#endif //TWL_OS_COMMON_BANNER_H_
|
||||
446
build/tools/TamperDetectorForSrl/checker.cpp
Normal file
446
build/tools/TamperDetectorForSrl/checker.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "checker.h"
|
||||
#include "nitro_romheader.h"
|
||||
|
||||
extern Entry gEntry;
|
||||
extern Entry mEntry;
|
||||
|
||||
void Checker::Initialize( FILE* myGfp, FILE* myMfp, void* myGbuf, void* myMbuf, u32 size)
|
||||
{
|
||||
gfp = myGfp;
|
||||
mfp = myMfp;
|
||||
gBuf = myGbuf;
|
||||
mBuf = myMbuf;
|
||||
buffer_size = size;
|
||||
|
||||
gEntry.Initialize();
|
||||
mEntry.Initialize();
|
||||
}
|
||||
|
||||
bool Checker::LoadHeader( void* gHeaderBuf, void* mHeaderBuf)
|
||||
{
|
||||
size_t readed;
|
||||
|
||||
fseek( gfp, 0, SEEK_SET);
|
||||
readed = fread( gHeaderBuf, sizeof(RomHeader), 1, gfp);
|
||||
if( readed == 1)
|
||||
{
|
||||
fseek( mfp, 0, SEEK_SET);
|
||||
readed = fread( mHeaderBuf, sizeof(RomHeader), 1, mfp);
|
||||
if( readed == sizeof(RomHeader))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Checker::Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isDataOnly, PrintLevel print_enable)
|
||||
{
|
||||
long nowgfp, nowmfp;
|
||||
int result = 0;
|
||||
u32 check_size, rest_size;
|
||||
int i, loop_num;
|
||||
bool function_result = true;
|
||||
|
||||
check_size = (g_size < m_size)? g_size : m_size;
|
||||
rest_size = check_size;
|
||||
|
||||
if( !isDataOnly)
|
||||
{
|
||||
/* 指定アドレスとサイズのチェック */
|
||||
if( g_offset == m_offset)
|
||||
{
|
||||
if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) {
|
||||
printf( " offset:0x%x(改竄されていない)\n", g_offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
function_result = false;
|
||||
if( print_enable) {
|
||||
printf( " offset:0x%x ---> offset:0x%x(改竄されている)\n", g_offset, m_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if( g_size == m_size)
|
||||
{
|
||||
if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) {
|
||||
printf( " size:0x%x(改竄されていない)\n", g_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
function_result = false;
|
||||
if( print_enable) {
|
||||
printf( " size:0x%x ---> size:0x%x(改竄されている)\n", g_size, m_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool filled = true;
|
||||
int totalResult = 0;
|
||||
int j;
|
||||
|
||||
nowgfp = ftell( gfp);
|
||||
nowmfp = ftell( mfp);
|
||||
/* メモリ内容のチェック(サイズが異なる場合は小さいサイズで) */
|
||||
fseek( gfp, g_offset, SEEK_SET);
|
||||
fseek( mfp, m_offset, SEEK_SET);
|
||||
|
||||
if( rest_size > buffer_size)
|
||||
{
|
||||
loop_num = (rest_size / buffer_size);
|
||||
for( i=0; i<loop_num; i++)
|
||||
{
|
||||
fread( gBuf, buffer_size, 1, gfp);
|
||||
fread( mBuf, buffer_size, 1, mfp);
|
||||
result = memcmp( gBuf, mBuf, buffer_size);
|
||||
if( result != 0)
|
||||
{
|
||||
totalResult = 1;
|
||||
}
|
||||
if( filled) // FILLチェック
|
||||
{
|
||||
for( j=0; j<buffer_size; j++)
|
||||
{
|
||||
if( *((u8*)mBuf + j) != *((u8*)mBuf))
|
||||
{
|
||||
// printf( ".%d, %d, 0x%x, 0x%x\n", i, j, *((u8*)mBuf+j), *((u8*)mBuf));
|
||||
filled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rest_size = (rest_size % buffer_size);
|
||||
}
|
||||
|
||||
if( rest_size)
|
||||
{
|
||||
fread( gBuf, rest_size, 1, gfp);
|
||||
fread( mBuf, rest_size, 1, mfp);
|
||||
result = memcmp( gBuf, mBuf, rest_size);
|
||||
if( result != 0)
|
||||
{
|
||||
totalResult = 1;
|
||||
}
|
||||
if( filled) // FILLチェック
|
||||
{
|
||||
for( j=0; j<(int)rest_size; j++)
|
||||
{
|
||||
if( *((u8*)mBuf + j) != *((u8*)mBuf))
|
||||
{
|
||||
// printf( "..%d, %d, 0x%x, 0x%x\n", i, j, *((u8*)mBuf+j), *((u8*)mBuf));
|
||||
filled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* メモリ内容チェック結果 */
|
||||
if( result == 0)
|
||||
{
|
||||
if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) {
|
||||
printf( " data:(改竄されていない)\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
function_result = false;
|
||||
if( filled)
|
||||
{
|
||||
if( print_enable) {
|
||||
printf( " data:(0x%xでフィルされている)\n", *((u8*)mBuf));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( print_enable) {
|
||||
printf( " data:(改竄されている)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ファイルポインタを戻す
|
||||
fseek( gfp, nowgfp, SEEK_SET);
|
||||
fseek( mfp, nowmfp, SEEK_SET);
|
||||
return function_result;
|
||||
}
|
||||
|
||||
|
||||
void Checker::AnalyzeBanner( RomHeader* gHeaderBuf, RomHeader* mHeaderBuf)
|
||||
{
|
||||
BannerHeader gBannerHeader;
|
||||
BannerHeader mBannerHeader;
|
||||
u32 banner_size[3] = {
|
||||
sizeof( BannerFileV1),
|
||||
sizeof( BannerFileV1) + sizeof( BannerFileV2),
|
||||
sizeof( BannerFileV1) + sizeof( BannerFileV2) + sizeof( BannerFileV3),
|
||||
};
|
||||
|
||||
fseek( gfp, (u32)(gHeaderBuf->banner_offset), SEEK_SET);
|
||||
fseek( mfp, (u32)(mHeaderBuf->banner_offset), SEEK_SET);
|
||||
|
||||
fread( &gBannerHeader, sizeof(BannerHeader), 1, gfp);
|
||||
fread( &mBannerHeader, sizeof(BannerHeader), 1, mfp);
|
||||
|
||||
printf( "------- Banner Header -------\n");
|
||||
Diff( (u32)(gHeaderBuf->banner_offset), sizeof(BannerHeader),
|
||||
(u32)(mHeaderBuf->banner_offset), sizeof(BannerHeader),
|
||||
false, PRINT_LEVEL_1);
|
||||
if( (((gBannerHeader.version) < 1) || ((gBannerHeader.version) > 3)) ||
|
||||
(((mBannerHeader.version) < 1) || ((mBannerHeader.version) > 3)))
|
||||
{
|
||||
printf( " invalid banner version!\n");
|
||||
return;
|
||||
}
|
||||
printf( "------- Banner Body -------\n");
|
||||
Diff( (u32)(gHeaderBuf->banner_offset) + sizeof(BannerHeader), banner_size[gBannerHeader.version],
|
||||
(u32)(mHeaderBuf->banner_offset) + sizeof(BannerHeader), banner_size[mBannerHeader.version],
|
||||
false, PRINT_LEVEL_1);
|
||||
}
|
||||
|
||||
|
||||
void Checker::AnalyzeFNT( RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable)
|
||||
{
|
||||
int i;
|
||||
ROM_FNTDir currentDir;
|
||||
MyDirEntry tmpDirEntry;
|
||||
MyDirEntry* pDirEntry;
|
||||
|
||||
// ルートディレクトリの情報を読む
|
||||
fseek( fp, (u32)(headerBuf->fnt_offset), SEEK_SET);
|
||||
fread( ¤tDir, sizeof(ROM_FNTDir), 1, fp);
|
||||
|
||||
// ディレクトリテーブル全体を読む
|
||||
fseek( fp, (u32)(headerBuf->fnt_offset), SEEK_SET);
|
||||
fread( &fntBuf, sizeof(ROM_FNTDir) * currentDir.parent_id, 1, fp);
|
||||
|
||||
// ルートディレクトリのparent_idは総ディレクトリ数を表す
|
||||
for( i=0; i<currentDir.parent_id; i++)
|
||||
{
|
||||
entry->InitializeEntry( &tmpDirEntry);
|
||||
if( i == 0)
|
||||
{
|
||||
if( print_enable) {
|
||||
printf( "------- dir_id : 0xf000 (root) -------\n");
|
||||
}
|
||||
tmpDirEntry.self_id = 0xF000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( print_enable) {
|
||||
printf( "------- dir_id : 0x%x (child dir of 0x%x) -------\n", (0xF000 + i), fntBuf[i].parent_id);
|
||||
}
|
||||
tmpDirEntry.self_id = (0xF000 + i);
|
||||
tmpDirEntry.parent_id = fntBuf[i].parent_id;
|
||||
}
|
||||
if( !entry->FindDirEntry( tmpDirEntry.self_id))
|
||||
{ // 見つからなかったら追加
|
||||
pDirEntry = (MyDirEntry*)malloc( sizeof(MyDirEntry));
|
||||
entry->CopyEntry( pDirEntry, &tmpDirEntry);
|
||||
entry->addDirEntry( pDirEntry);
|
||||
}
|
||||
|
||||
FindEntry( fntBuf[i].entry_start,
|
||||
fntBuf[i].entry_file_id,
|
||||
headerBuf, fp, entry, tmpDirEntry.self_id,
|
||||
print_enable);
|
||||
}
|
||||
}
|
||||
|
||||
void Checker::FindEntry( u32 fnt_offset, u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, u16 parent_id, PrintLevel print_enable)
|
||||
{
|
||||
EntryInfo entryInfo;
|
||||
char entryNames[FILE_NAME_LENGTH];
|
||||
u16 dir_id;
|
||||
MyDirEntry* dirEntry;
|
||||
MyFileEntry* fileEntry;
|
||||
|
||||
fseek( fp, (u32)(headerBuf->fnt_offset) + fnt_offset, SEEK_SET);
|
||||
while( 1)
|
||||
{
|
||||
fread( &entryInfo, sizeof(char), 1, fp);
|
||||
if( (entryInfo.entry_type == 0) && (entryInfo.entry_name_length == 0)) // 終端チェック
|
||||
{
|
||||
break;
|
||||
}
|
||||
fread( entryNames, entryInfo.entry_name_length, 1, fp);
|
||||
entryNames[entryInfo.entry_name_length] = '\0';
|
||||
if( entryInfo.entry_type == 0) // ファイル
|
||||
{
|
||||
if( print_enable) {
|
||||
printf( "- %s(file_id:0x%d)\n", entryNames, entry_id);
|
||||
}
|
||||
/* パス解析用 */
|
||||
fileEntry = (MyFileEntry*)malloc( sizeof(MyFileEntry));
|
||||
entry->InitializeEntry( fileEntry);
|
||||
fileEntry->self_id = entry_id;
|
||||
fileEntry->parent_id = parent_id;
|
||||
entry->SetName( fileEntry, entryNames, entryInfo.entry_name_length);
|
||||
entry->addFileEntry( fileEntry);
|
||||
|
||||
FindAllocation( entry_id, headerBuf, fp, entry, print_enable);
|
||||
entry_id++;
|
||||
}
|
||||
else // ディレクトリ
|
||||
{
|
||||
fread( &dir_id, sizeof(u16), 1, fp);
|
||||
if( print_enable) {
|
||||
printf( "- [%s](dir_id:0x%x)\n", entryNames, dir_id);
|
||||
}
|
||||
/* パス解析用 */
|
||||
dirEntry = entry->FindDirEntry( dir_id);
|
||||
if( !dirEntry)
|
||||
{ // 見つからなかったら追加
|
||||
dirEntry = (MyDirEntry*)malloc( sizeof(MyDirEntry));
|
||||
entry->InitializeEntry( dirEntry);
|
||||
dirEntry->self_id = dir_id;
|
||||
dirEntry->parent_id = parent_id;
|
||||
entry->addDirEntry( dirEntry);
|
||||
}
|
||||
entry->SetName( dirEntry, entryNames, entryInfo.entry_name_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Checker::FindAllocation( u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable)
|
||||
{
|
||||
ROM_FAT currentRomFat;
|
||||
long nowfp;
|
||||
nowfp = ftell( fp);
|
||||
|
||||
fseek( fp,
|
||||
(u32)(headerBuf->fat_offset) + (sizeof(ROM_FAT) * entry_id),
|
||||
SEEK_SET);
|
||||
fread( ¤tRomFat, sizeof(ROM_FAT), 1, fp);
|
||||
if( print_enable) {
|
||||
printf( " fat top:0x%x, bottom:0x%x, len:0x%x\n",
|
||||
(u32)(currentRomFat.top), (u32)(currentRomFat.bottom),
|
||||
(u32)(currentRomFat.bottom) - (u32)(currentRomFat.top));
|
||||
}
|
||||
Diff( (u32)(currentRomFat.top), (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top),
|
||||
(u32)(currentRomFat.top), (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top),
|
||||
true, print_enable);
|
||||
|
||||
/* パス解析用 */
|
||||
MyFileEntry* fileEntry = entry->FindFileEntry( entry_id);
|
||||
fileEntry->top = (u32)(currentRomFat.top);
|
||||
fileEntry->bottom = (u32)(currentRomFat.bottom);
|
||||
|
||||
// ファイルポインタを戻す
|
||||
fseek( fp, nowfp, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
/* ROM内のBMPファイルを全て切り出して出力する */
|
||||
#define BMP_BUFFER_SIZE (512*1024)
|
||||
u32 tmpBuf[BMP_BUFFER_SIZE / 4];
|
||||
void Checker::ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable)
|
||||
{
|
||||
int i;
|
||||
MyFileEntry *currentEntry = gEntry->fileEntry;
|
||||
MyFileEntry *hisEntry;
|
||||
// u32* tmpBuf = (u32*)malloc( BMP_BUFFER_SIZE);
|
||||
u32 file_size, rest_size;
|
||||
int loop_num;
|
||||
FILE* fp;
|
||||
|
||||
while( currentEntry)
|
||||
{
|
||||
if( currentEntry->name_length > 4)
|
||||
{
|
||||
if( memcmp( ¤tEntry->name[currentEntry->name_length - 4], ".bmp", 4) == 0)
|
||||
{
|
||||
file_size = (currentEntry->bottom - currentEntry->top);
|
||||
rest_size = file_size;
|
||||
|
||||
loop_num = file_size / BMP_BUFFER_SIZE;
|
||||
fp = fopen( currentEntry->name, "w");
|
||||
|
||||
fseek( gfp, currentEntry->top, SEEK_SET);
|
||||
if( rest_size > BMP_BUFFER_SIZE)
|
||||
{
|
||||
for( i=0; i<loop_num; i++)
|
||||
{
|
||||
fread( tmpBuf, BMP_BUFFER_SIZE, 1, gfp);
|
||||
fwrite( tmpBuf, BMP_BUFFER_SIZE, 1, fp);
|
||||
}
|
||||
rest_size = (rest_size % BMP_BUFFER_SIZE);
|
||||
}
|
||||
if( rest_size)
|
||||
{
|
||||
fread( tmpBuf, rest_size, 1, gfp);
|
||||
fwrite( tmpBuf, rest_size, 1, fp);
|
||||
}
|
||||
fclose( fp);
|
||||
}
|
||||
}
|
||||
if( print_enable) {
|
||||
printf( "- %s exported.\n", currentEntry->full_path_name);
|
||||
}
|
||||
currentEntry = (MyFileEntry*)(currentEntry->next);
|
||||
};
|
||||
// free( tmpBuf);
|
||||
}
|
||||
|
||||
/* ディレクトリとファイルをチェックする */
|
||||
void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry)
|
||||
{
|
||||
{
|
||||
MyDirEntry *currentEntry = gEntry->dirEntry;
|
||||
MyDirEntry *hisEntry;
|
||||
|
||||
printf( "------- directory check -------\n");
|
||||
while( currentEntry)
|
||||
{
|
||||
printf( "- %s", currentEntry->full_path_name);
|
||||
|
||||
hisEntry = mEntry->FindDirEntry( currentEntry->full_path_name);
|
||||
if( hisEntry)
|
||||
{
|
||||
printf( "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( " --->(存在していない)\n");
|
||||
}
|
||||
|
||||
currentEntry = (MyDirEntry*)(currentEntry->next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MyFileEntry *currentEntry = gEntry->fileEntry;
|
||||
MyFileEntry *hisEntry;
|
||||
printf( "------- file check -------\n");
|
||||
while( currentEntry)
|
||||
{
|
||||
printf( "- %s", currentEntry->full_path_name);
|
||||
|
||||
hisEntry = mEntry->FindFileEntry( currentEntry->full_path_name);
|
||||
if( hisEntry)
|
||||
{
|
||||
printf( "\n");
|
||||
if( Diff( currentEntry->top, (currentEntry->bottom - currentEntry->top),
|
||||
hisEntry->top, (hisEntry->bottom - hisEntry->top),
|
||||
false, PRINT_LEVEL_1) == false)
|
||||
{
|
||||
printf( "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( " --->(存在していない)\n");
|
||||
}
|
||||
|
||||
currentEntry = (MyFileEntry*)(currentEntry->next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Checker::Finalize( void)
|
||||
{
|
||||
}
|
||||
|
||||
64
build/tools/TamperDetectorForSrl/checker.h
Normal file
64
build/tools/TamperDetectorForSrl/checker.h
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
#ifndef CHECKER_H_
|
||||
#define CHECKER_H_
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "nitro_romheader.h"
|
||||
#include "banner.h"
|
||||
#include "entry.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 entry_name_length:7; // ファイル名の長さ (0-127)
|
||||
u8 entry_type :1; // ファイルエントリの場合は 0
|
||||
} EntryInfo;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PRINT_LEVEL_0 = 0,
|
||||
PRINT_LEVEL_1,
|
||||
PRINT_LEVEL_2
|
||||
} PrintLevel;
|
||||
|
||||
|
||||
class Checker
|
||||
{
|
||||
private:
|
||||
bool initialized;
|
||||
FILE* gfp;
|
||||
FILE* mfp;
|
||||
void* gBuf;
|
||||
void* mBuf;
|
||||
u32 buffer_size;
|
||||
ROM_FNTDir fntBuf[4096];
|
||||
void* dirTableBuf;
|
||||
|
||||
public:
|
||||
void Initialize( FILE* myGfp, FILE* myMfp, void* myGbuf, void* myMbuf, u32 size);
|
||||
|
||||
/* ヘッダを読むだけ */
|
||||
bool LoadHeader( void* gHeaderBuf, void* mHeaderBuf);
|
||||
|
||||
/* ROMの特定領域に差がないかどうか調べる */
|
||||
bool Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isDataOnly, PrintLevel print_enable);
|
||||
|
||||
void Finalize( void);
|
||||
|
||||
/* ROMのバナー領域に対して Diff をかける */
|
||||
void AnalyzeBanner( RomHeader* gHeaderBuf, RomHeader* mHeaderBuf);
|
||||
|
||||
/* FNT と FAT を解析して、各ファイルに対して Diff をかける */
|
||||
void AnalyzeFNT( RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable);
|
||||
void FindEntry( u32 fnt_offset, u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, u16 parent_id, PrintLevel print_enable);
|
||||
void FindAllocation( u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable);
|
||||
|
||||
void CheckAllEntries( Entry* gEntry, Entry* mEntry);
|
||||
|
||||
/* ROM内のBMPファイルを全て切り出して出力する */
|
||||
void ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable);
|
||||
};
|
||||
|
||||
#endif
|
||||
305
build/tools/TamperDetectorForSrl/entry.cpp
Normal file
305
build/tools/TamperDetectorForSrl/entry.cpp
Normal file
@ -0,0 +1,305 @@
|
||||
#include <string.h>
|
||||
#include "entry.h"
|
||||
#include "nitro_romheader.h"
|
||||
|
||||
|
||||
//void Entry::Initialize( void)
|
||||
void Entry::Initialize( void)
|
||||
{
|
||||
dirEntry = NULL;
|
||||
fileEntry = NULL;
|
||||
}
|
||||
|
||||
void Entry::InitializeEntry( MyDirEntry* myDirEntry)
|
||||
{
|
||||
myDirEntry->name = NULL;
|
||||
myDirEntry->full_path_name = NULL;
|
||||
myDirEntry->name_length = 0;
|
||||
myDirEntry->full_path_name_length = 0;
|
||||
myDirEntry->self_id = 0xFFFF;
|
||||
myDirEntry->parent_id = 0;
|
||||
myDirEntry->parent = NULL;
|
||||
myDirEntry->next = NULL;
|
||||
}
|
||||
|
||||
void Entry::InitializeEntry( MyFileEntry* myFileEntry)
|
||||
{
|
||||
myFileEntry->name = NULL;
|
||||
myFileEntry->full_path_name = NULL;
|
||||
myFileEntry->name_length = 0;
|
||||
myFileEntry->full_path_name_length = 0;
|
||||
myFileEntry->top = 0;
|
||||
myFileEntry->bottom = 0;
|
||||
myFileEntry->self_id = 0xFFFF;
|
||||
myFileEntry->parent_id = 0;
|
||||
myFileEntry->parent = NULL;
|
||||
myFileEntry->next = NULL;
|
||||
}
|
||||
|
||||
void Entry::CopyEntry( MyDirEntry* dest, MyDirEntry* src)
|
||||
{
|
||||
memcpy( dest, src, sizeof(MyFileEntry));
|
||||
}
|
||||
|
||||
void Entry::SetName( MyDirEntry* myDirEntry, char* fname, u16 len)
|
||||
{
|
||||
myDirEntry->name = (char*)malloc( sizeof(MyDirEntry));
|
||||
memset( myDirEntry->name, 0, len+1);
|
||||
memcpy( myDirEntry->name, fname, len);
|
||||
|
||||
myDirEntry->name_length = len;
|
||||
}
|
||||
|
||||
void Entry::SetName( MyFileEntry* myFileEntry, char* fname, u16 len)
|
||||
{
|
||||
myFileEntry->name = (char*)malloc( FILE_NAME_LENGTH);
|
||||
memset( myFileEntry->name, 0, len+1);
|
||||
memcpy( myFileEntry->name, fname, len);
|
||||
|
||||
myFileEntry->name_length = len;
|
||||
}
|
||||
|
||||
void Entry::addDirEntry( MyDirEntry* myDirEntry)
|
||||
{
|
||||
MyDirEntry *currentEntry = dirEntry;
|
||||
if( !currentEntry)
|
||||
{
|
||||
dirEntry = myDirEntry;
|
||||
return;
|
||||
}
|
||||
while( currentEntry->next)
|
||||
{
|
||||
currentEntry = (MyDirEntry*)(currentEntry->next);
|
||||
}
|
||||
currentEntry->next = myDirEntry;
|
||||
myDirEntry->next = NULL;
|
||||
}
|
||||
|
||||
|
||||
void Entry::addFileEntry( MyFileEntry* myFileEntry)
|
||||
{
|
||||
MyFileEntry *currentEntry = fileEntry;
|
||||
if( !currentEntry)
|
||||
{
|
||||
fileEntry = myFileEntry;
|
||||
return;
|
||||
}
|
||||
while( currentEntry->next)
|
||||
{
|
||||
currentEntry = (MyFileEntry*)(currentEntry->next);
|
||||
}
|
||||
currentEntry->next = myFileEntry;
|
||||
myFileEntry->next = NULL;
|
||||
}
|
||||
|
||||
|
||||
MyDirEntry* Entry::FindDirEntry( u16 id)
|
||||
{
|
||||
MyDirEntry *currentEntry = dirEntry;
|
||||
while( currentEntry)
|
||||
{
|
||||
if( currentEntry->self_id == id)
|
||||
{
|
||||
return currentEntry;
|
||||
}
|
||||
// printf( "%s, 0x%x, 0x%x\n", __FUNCTION__, currentEntry->self_id, id);
|
||||
currentEntry = (MyDirEntry*)(currentEntry->next);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MyFileEntry* Entry::FindFileEntry( u16 id)
|
||||
{
|
||||
MyFileEntry *currentEntry = fileEntry;
|
||||
while( currentEntry)
|
||||
{
|
||||
if( currentEntry->self_id == id)
|
||||
{
|
||||
return currentEntry;
|
||||
}
|
||||
// printf( "%s, 0x%x, 0x%x\n", __FUNCTION__, currentEntry->self_id, id);
|
||||
currentEntry = (MyFileEntry*)(currentEntry->next);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MyDirEntry* Entry::FindDirEntry( char* my_full_path_name)
|
||||
{
|
||||
MyDirEntry *currentEntry = dirEntry;
|
||||
while( currentEntry)
|
||||
{
|
||||
if( strcmp( currentEntry->full_path_name, my_full_path_name) == 0)
|
||||
{
|
||||
return currentEntry;
|
||||
}
|
||||
currentEntry = (MyDirEntry*)(currentEntry->next);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MyFileEntry* Entry::FindFileEntry( char* my_full_path_name)
|
||||
{
|
||||
MyFileEntry *currentEntry = fileEntry;
|
||||
while( currentEntry)
|
||||
{
|
||||
if( strcmp( currentEntry->full_path_name, my_full_path_name) == 0)
|
||||
{
|
||||
return currentEntry;
|
||||
}
|
||||
currentEntry = (MyFileEntry*)(currentEntry->next);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void Entry::AutoSetFullPath( void)
|
||||
{
|
||||
MyDirEntry *currentDirEntry = dirEntry;
|
||||
while( currentDirEntry)
|
||||
{
|
||||
SetFullPath( currentDirEntry);
|
||||
currentDirEntry = (MyDirEntry*)(currentDirEntry->next);
|
||||
}
|
||||
|
||||
MyFileEntry *currentFileEntry = fileEntry;
|
||||
while( currentFileEntry)
|
||||
{
|
||||
SetFullPath( currentFileEntry);
|
||||
currentFileEntry = (MyFileEntry*)(currentFileEntry->next);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::SetFullPath( MyDirEntry *targetDirEntry)
|
||||
{
|
||||
char tmp_name[256];
|
||||
u16 total_length;
|
||||
|
||||
MyDirEntry *currentDirEntry = targetDirEntry;
|
||||
total_length = 0;
|
||||
tmp_name[255] = '\0';
|
||||
while( currentDirEntry)
|
||||
{
|
||||
total_length += (currentDirEntry->name_length);
|
||||
memcpy( &(tmp_name[255 - total_length]), currentDirEntry->name, currentDirEntry->name_length);
|
||||
if( currentDirEntry->self_id != 0xF000) // rootディレクトリでなければ
|
||||
{
|
||||
total_length++; // '/'のぶん
|
||||
tmp_name[255 - total_length] = '/';
|
||||
}
|
||||
currentDirEntry = (MyDirEntry*)(currentDirEntry->parent);
|
||||
}
|
||||
targetDirEntry->full_path_name = (char*)malloc( total_length + 1);
|
||||
targetDirEntry->full_path_name_length = total_length;
|
||||
memset( targetDirEntry->full_path_name, 0, total_length + 1);
|
||||
memcpy( targetDirEntry->full_path_name, &(tmp_name[255 - total_length]), total_length);
|
||||
}
|
||||
|
||||
void Entry::SetFullPath( MyFileEntry *targetFileEntry)
|
||||
{
|
||||
char tmp_name[256];
|
||||
u16 total_length;
|
||||
|
||||
MyFileEntry *currentFileEntry = targetFileEntry;
|
||||
MyDirEntry *parentDirEntry;
|
||||
total_length = 0;
|
||||
tmp_name[255] = '\0';
|
||||
{
|
||||
total_length += (currentFileEntry->name_length);
|
||||
memcpy( &(tmp_name[255 - total_length]), currentFileEntry->name, currentFileEntry->name_length);
|
||||
total_length++; // '/'のぶん
|
||||
tmp_name[255 - total_length] = '/';
|
||||
|
||||
parentDirEntry = (MyDirEntry*)(currentFileEntry->parent);
|
||||
if( parentDirEntry)
|
||||
{
|
||||
total_length += parentDirEntry->full_path_name_length;
|
||||
memcpy( &(tmp_name[255 - total_length]), parentDirEntry->full_path_name, parentDirEntry->full_path_name_length);
|
||||
}
|
||||
}
|
||||
targetFileEntry->full_path_name = (char*)malloc( total_length + 1);
|
||||
memset( targetFileEntry->full_path_name, 0, total_length + 1);
|
||||
memcpy( targetFileEntry->full_path_name, &(tmp_name[255 - total_length]), total_length);
|
||||
}
|
||||
|
||||
/* parent リンクを繋げる */
|
||||
void Entry::FollowParent( void)
|
||||
{
|
||||
MyDirEntry *currentDirEntry = dirEntry;
|
||||
while( currentDirEntry)
|
||||
{
|
||||
currentDirEntry->parent = FindDirEntry( currentDirEntry->parent_id);
|
||||
currentDirEntry = (MyDirEntry*)(currentDirEntry->next);
|
||||
}
|
||||
|
||||
MyFileEntry *currentFileEntry = fileEntry;
|
||||
while( currentFileEntry)
|
||||
{
|
||||
currentFileEntry->parent = FindDirEntry( currentFileEntry->parent_id);
|
||||
// printf( "%s, 0x%x, 0x%x\n", __FUNCTION__, currentFileEntry->parent_id, (u32)currentFileEntry->parent);
|
||||
currentFileEntry = (MyFileEntry*)(currentFileEntry->next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Entry::PrintAllDirEntry( void)
|
||||
{
|
||||
MyDirEntry *currentEntry = dirEntry;
|
||||
printf( "------- all directories are -------\n");
|
||||
while( currentEntry)
|
||||
{
|
||||
// printf( "directory : %s\n", currentEntry->name);
|
||||
printf( "fullpath : %s\n", currentEntry->full_path_name);
|
||||
// printf( "id : 0x%x\n", currentEntry->self_id);
|
||||
// printf( "parent id : 0x%x\n", currentEntry->parent_id);
|
||||
currentEntry = (MyDirEntry*)(currentEntry->next);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::PrintAllFileEntry( void)
|
||||
{
|
||||
MyFileEntry *currentEntry = fileEntry;
|
||||
printf( "------- all files are -------\n");
|
||||
while( currentEntry)
|
||||
{
|
||||
// printf( "file : %s\n", currentEntry->name);
|
||||
printf( "fullpath : %s\n", currentEntry->full_path_name);
|
||||
// printf( "id : 0x%x\n", currentEntry->self_id);
|
||||
// printf( "parent id : 0x%x\n", currentEntry->parent_id);
|
||||
currentEntry = (MyFileEntry*)(currentEntry->next);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Entry::CheckAllFiles( Checker* checker, MyFileEntry *anotherFileEntry)
|
||||
{
|
||||
MyFileEntry *currentEntry = fileEntry;
|
||||
MyFileEntry *hisEntry;
|
||||
while( currentEntry)
|
||||
{
|
||||
printf( "- %s", currentEntry->full_path_name);
|
||||
|
||||
hisEntry = FindFileEntry( currentEntry->full_path_name);
|
||||
if( hisEntry)
|
||||
{
|
||||
printf( " --->(存在している)\n");
|
||||
checker.Diff( currentEntry->top, (currentEntry->bottom - currentEntry->top),
|
||||
hisEntry->top, (hisEntry->bottom - hisEntry->top),
|
||||
false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( " --->(存在していない)\n");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/* フルパスをセットする(事前にFollowParent()を済ませておくことが必要) */
|
||||
void Entry::Finalize()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
83
build/tools/TamperDetectorForSrl/entry.h
Normal file
83
build/tools/TamperDetectorForSrl/entry.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef ENTRY_H_
|
||||
#define ENTRY_H_
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "nitro_romheader.h"
|
||||
#include "banner.h"
|
||||
//#include "checker.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* name;
|
||||
char* full_path_name;
|
||||
u8 name_length;
|
||||
u8 full_path_name_length;
|
||||
u16 self_id;
|
||||
u16 parent_id;
|
||||
void* parent;
|
||||
void* next;
|
||||
} MyDirEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* name;
|
||||
char* full_path_name;
|
||||
u8 name_length;
|
||||
u8 full_path_name_length;
|
||||
u32 top;
|
||||
u32 bottom;
|
||||
u16 self_id;
|
||||
u16 parent_id;
|
||||
void* parent;
|
||||
void* next;
|
||||
} MyFileEntry;
|
||||
|
||||
|
||||
class Entry
|
||||
{
|
||||
// private:
|
||||
public:
|
||||
MyDirEntry* dirEntry;
|
||||
MyFileEntry* fileEntry;
|
||||
|
||||
public:
|
||||
void Initialize( void);
|
||||
|
||||
void InitializeEntry( MyDirEntry* myDirEntry);
|
||||
void InitializeEntry( MyFileEntry* myFileEntry);
|
||||
|
||||
void CopyEntry( MyDirEntry* dest, MyDirEntry* src);
|
||||
|
||||
void SetName( MyDirEntry* myDirEntry, char* fname, u16 len);
|
||||
void SetName( MyFileEntry* myDirEntry, char* fname, u16 len);
|
||||
|
||||
void addDirEntry( MyDirEntry* myDirEntry);
|
||||
void addFileEntry( MyFileEntry* myFileEntry);
|
||||
|
||||
MyDirEntry* FindDirEntry( u16 id);
|
||||
MyFileEntry* FindFileEntry( u16 id);
|
||||
|
||||
MyDirEntry* FindDirEntry( char* my_full_path_name);
|
||||
MyFileEntry* FindFileEntry( char* my_full_path_name);
|
||||
|
||||
/* parent リンクを繋げる */
|
||||
void FollowParent( void);
|
||||
|
||||
/* フルパスをセットする */
|
||||
void AutoSetFullPath( void);
|
||||
void SetFullPath( MyDirEntry *targetDirEntry);
|
||||
void SetFullPath( MyFileEntry *targetFileEntry);
|
||||
|
||||
void PrintAllDirEntry( void);
|
||||
void PrintAllFileEntry( void);
|
||||
|
||||
// void CheckAllFiles( Checker* checker, MyFileEntry *anotherFileEntry);
|
||||
|
||||
void Finalize();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
168
build/tools/TamperDetectorForSrl/main.cpp
Normal file
168
build/tools/TamperDetectorForSrl/main.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "searcharg.h"
|
||||
#include "nitro_romheader.h"
|
||||
#include "checker.h"
|
||||
|
||||
|
||||
extern char* output_fname;
|
||||
extern char* genuine_fname;
|
||||
extern char* magicon_fname;
|
||||
|
||||
#define BUFFER_SIZE (0x4000)
|
||||
|
||||
Entry gEntry;
|
||||
Entry mEntry;
|
||||
|
||||
RomHeader gHeaderBuf;
|
||||
RomHeader mHeaderBuf;
|
||||
char gBuf[BUFFER_SIZE];
|
||||
char mBuf[BUFFER_SIZE];
|
||||
|
||||
|
||||
/*--- 型のビット数をチェック ---*/
|
||||
bool int_bits(void)
|
||||
{
|
||||
int count = 0;
|
||||
unsigned short usi = ~0U;
|
||||
unsigned long uli = ~0U;
|
||||
|
||||
while (uli) {
|
||||
if (uli & 1U) count++;
|
||||
uli >>= 1;
|
||||
}
|
||||
if( count != 32)
|
||||
{
|
||||
printf("ERROR! unsigned long int : %d bits\n", count);
|
||||
return false;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
while (usi) {
|
||||
if (usi & 1U) count++;
|
||||
usi >>= 1;
|
||||
}
|
||||
if( count != 16)
|
||||
{
|
||||
printf("ERROR! unsigned short int : %d bits\n", count);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
// 処理系の unsignedビット数が想定外ならエラー終了(types.hを変更してビルドし直してください)
|
||||
if( !int_bits())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
SA_searchopt(argc, argv);
|
||||
|
||||
printf("[output_fname]%s\n", output_fname);
|
||||
printf("[genuine_fname]%s\n", genuine_fname);
|
||||
printf("[magicon_fname]%s\n", magicon_fname);
|
||||
|
||||
{
|
||||
FILE* gfp;
|
||||
FILE* mfp;
|
||||
Checker checker;
|
||||
|
||||
gfp = fopen( genuine_fname, "r");
|
||||
mfp = fopen( magicon_fname, "r");
|
||||
|
||||
checker.Initialize( gfp, mfp, gBuf, mBuf, BUFFER_SIZE);
|
||||
checker.LoadHeader( &gHeaderBuf, &mHeaderBuf);
|
||||
|
||||
printf( "------------------\n");
|
||||
printf( "Nitro Rom Header\n");
|
||||
checker.Diff( 0, sizeof(RomHeader), 0, sizeof(RomHeader), false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "ARM9 Static Module\n");
|
||||
checker.Diff( (u32)(gHeaderBuf.arm9.romAddr),
|
||||
(u32)(gHeaderBuf.arm9.romSize),
|
||||
(u32)(mHeaderBuf.arm9.romAddr),
|
||||
(u32)(mHeaderBuf.arm9.romSize),
|
||||
false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "ARM7 Static Module\n");
|
||||
checker.Diff( (u32)(gHeaderBuf.arm7.romAddr),
|
||||
(u32)(gHeaderBuf.arm7.romSize),
|
||||
(u32)(mHeaderBuf.arm7.romAddr),
|
||||
(u32)(mHeaderBuf.arm7.romSize),
|
||||
false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "File Name Table\n");
|
||||
checker.Diff( (u32)(gHeaderBuf.fnt_offset),
|
||||
(u32)(gHeaderBuf.fnt_size),
|
||||
(u32)(mHeaderBuf.fnt_offset),
|
||||
(u32)(mHeaderBuf.fnt_size),
|
||||
false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "File Allocation Table\n");
|
||||
checker.Diff( (u32)(gHeaderBuf.fat_offset),
|
||||
(u32)(gHeaderBuf.fat_size),
|
||||
(u32)(mHeaderBuf.fat_offset),
|
||||
(u32)(mHeaderBuf.fat_size),
|
||||
false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "ARM9 Overlay Table\n");
|
||||
checker.Diff( (u32)(gHeaderBuf.main_ovt_offset),
|
||||
(u32)(gHeaderBuf.main_ovt_size),
|
||||
(u32)(mHeaderBuf.main_ovt_offset),
|
||||
(u32)(mHeaderBuf.main_ovt_size),
|
||||
false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "ARM7 Overlay Table\n");
|
||||
checker.Diff( (u32)(gHeaderBuf.sub_ovt_offset),
|
||||
(u32)(gHeaderBuf.sub_ovt_size),
|
||||
(u32)(mHeaderBuf.sub_ovt_offset),
|
||||
(u32)(mHeaderBuf.sub_ovt_size),
|
||||
false, PRINT_LEVEL_1);
|
||||
printf( "------------------\n");
|
||||
|
||||
printf( "\nBanner\n");
|
||||
checker.AnalyzeBanner( &gHeaderBuf, &mHeaderBuf);
|
||||
|
||||
printf( "\nFNT & FAT\n");
|
||||
checker.AnalyzeFNT( &gHeaderBuf, gfp, &gEntry, PRINT_LEVEL_0);
|
||||
gEntry.FollowParent();
|
||||
gEntry.AutoSetFullPath();
|
||||
|
||||
checker.AnalyzeFNT( &mHeaderBuf, mfp, &mEntry, PRINT_LEVEL_0);
|
||||
mEntry.FollowParent();
|
||||
mEntry.AutoSetFullPath();
|
||||
|
||||
checker.CheckAllEntries( &gEntry, &mEntry);
|
||||
|
||||
checker.ExportGenuineBmpFiles( &gEntry, PRINT_LEVEL_0);
|
||||
/*
|
||||
gEntry.PrintAllDirEntry();
|
||||
gEntry.PrintAllFileEntry();
|
||||
|
||||
mEntry.PrintAllDirEntry();
|
||||
mEntry.PrintAllFileEntry();
|
||||
*/
|
||||
printf( "------------------\n");
|
||||
|
||||
|
||||
// AnalyzeFNT( mHeaderBuf, mfp);
|
||||
|
||||
fclose( gfp);
|
||||
fclose( mfp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
316
build/tools/TamperDetectorForSrl/nitro_romheader.h
Normal file
316
build/tools/TamperDetectorForSrl/nitro_romheader.h
Normal file
@ -0,0 +1,316 @@
|
||||
/*---------------------------------------------------------------------------*
|
||||
nitroeva3/card/rom_filesystem.h
|
||||
*---------------------------------------------------------------------------*/
|
||||
#ifndef NITROEVA3_CARD_ROM_FILESYSTEM_H_
|
||||
#define NITROEVA3_CARD_ROM_FILESYSTEM_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
定数定義
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define FILE_NAME_LENGTH 128
|
||||
|
||||
// マスクROMのヘッダアドレスを獲得
|
||||
#define GetRomHeaderAddr() ((RomHeader *)HW_ROM_HEADER_BUF)
|
||||
|
||||
// 共有ワーク領域のアドレス獲得
|
||||
#define GetSharedWorkAddr() ((SharedWork *)HW_RED_RESERVED) // (HW_MAIN_MEM + 0x007ff800) maybe change later
|
||||
|
||||
#define ROM_FILE_MAIN_PROCESSOR 0
|
||||
#define ROM_FILE_SUB_PROCESSOR 1
|
||||
|
||||
#define ROM_FILE_CARD 0
|
||||
#define ROM_FILE_CARTRIDGE 1
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
型定義
|
||||
*---------------------------------------------------------------------------*/
|
||||
// 共有ワーク構造体
|
||||
typedef struct {
|
||||
u32 nCardID; // NORMALカードID
|
||||
u32 sCardID; // SECUREカードID
|
||||
u16 cardHeaderCrc16; // カードヘッダCRC16
|
||||
u16 cardSecureCrc16; // カードSECURE領域CRC16
|
||||
s16 cardHeaderError; // カードヘッダエラー
|
||||
} SharedWork;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
ファイル名テーブルとは、
|
||||
|
||||
ファイル名からファイルIDを取得するためのテーブル。
|
||||
「ディレクトリ・テーブル」と「エントリ名テーブル」で構成される。
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
char entry_name[FILE_NAME_LENGTH]; // ファイル名 (終端 \0 は省く)
|
||||
|
||||
} ROM_FNT;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
ディレクトリ・テーブルとは、
|
||||
|
||||
ディレクトリ・テーブル構造体の配列として実装されている。
|
||||
各テーブルにはディレクトリIDと呼ばれる番号が割り振られ、格納順にカウント
|
||||
アップされる。ファイルIDと区別するため、ディレクトリIDは、0xF000~0xFFFF。
|
||||
(ファイルIDは、0x0000~0xEFFF)ディレクトリ数は4096、ファイル数は61440まで
|
||||
となる。ルート・ディレクトリは、ディレクトリIDが、0xF000、親ディレクトリIDには
|
||||
ディレクトリ・エントリ数が格納される。
|
||||
|
||||
※ ディレクトリ・テーブル構造体配列の要素数 = ディレクトリ数
|
||||
※ ディレクトリ・テーブル構造体配列の添え字 = ディレクトリID - 0xF000
|
||||
|
||||
以下、ディレクトリ・テーブル構造体の型定義
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
u32 entry_start; // エントリ名の検索位置(ファイル名テーブルの先頭位置からのオフセット)
|
||||
u16 entry_file_id; // 先頭エントリのファイル ID
|
||||
u16 parent_id; // 親ディレクトリの ID
|
||||
|
||||
} ROM_FNTDir;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
エントリ名テーブルとは、
|
||||
|
||||
下記の2種類(ROM_FNTStrFile, ROM_FNTStrDir)の可変長データの集合。
|
||||
エントリがファイル --> ROM_FNTStrFile
|
||||
エントリがディレクトリ --> ROM_FNTStrDir
|
||||
|
||||
同一ディレクトリ内に含まれるエントリは連続した領域に配置される(ファイルIDも連続)。
|
||||
同一ディレクトリ内の最終エントリの次にはエントリ名の長さが0のファイルエントリが置かれる
|
||||
|
||||
##########################################################################
|
||||
(ファイル構成の例:例1)
|
||||
/Nitro.ROM
|
||||
/BQ.DAT
|
||||
/image/APPLE.JPG
|
||||
|
||||
ディレクトリ・テーブル
|
||||
DIR-ID
|
||||
--------------------------------------------------------------------------
|
||||
0xF000 : entry_start = &(Nitro.ROM), entry_file_id = 0, parent_id = 2 (ディレクトリ数)
|
||||
0xF001 : entry_start = &(APPLE.JPG), entry_file_id = 2, parent_id = 0xF000
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
エントリ名・テーブル
|
||||
FILE-ID
|
||||
---(ディレクトリ / )------------------------------------------------------
|
||||
0 : entry_type = 0, entry_name_length = 9, entry_name = "Nitro.ROM"
|
||||
1 : entry_type = 0, entry_name_length = 6, entry_name = "BQ.DAT"
|
||||
: entry_type = 1, entry_name_length = 5, entry_name = "image" dir_id = 0xF001
|
||||
x : entry_type = 0, entry_name_length = 0
|
||||
---(ディレクトリ /image/ )------------------------------------------------
|
||||
2 : entry_type = 0, entry_name_length = 9, entry_name = "APPLE.JPG"
|
||||
x : entry_type = 0, entry_name_length = 0
|
||||
##########################################################################
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
u8 entry_type :1; // ファイルエントリの場合は 0
|
||||
u8 entry_name_length:7; // ファイル名の長さ (0-127)
|
||||
char entry_name[FILE_NAME_LENGTH]; // ファイル名 (終端 \0 は省く)
|
||||
|
||||
} ROM_FNTStrFile;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 entry_type :1; // ディレクトリエントリの場合は 1
|
||||
u8 entry_name_length:7; // ディレクトリ名の長さ (0-127)
|
||||
char entry_name[FILE_NAME_LENGTH]; // ディレクトリ名 (終端 \0 は省く)
|
||||
u8 dir_id_L; // ディレクトリ ID Low 8bit
|
||||
u8 dir_id_H; // ディレクトリ ID High 8bit
|
||||
|
||||
} ROM_FNTStrDir;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
FAT : ファイル・アロケーション・テーブルとは、
|
||||
|
||||
下記の構造体の配列として実装されている。
|
||||
配列の添え字がファイルIDと一致。
|
||||
|
||||
romFatTable を ROM_FAT型 の配列と見なすと、
|
||||
romFat[5].top は、ファイルID=5 のファイルの先頭ROMアドレス
|
||||
|
||||
使用されていないファイルIDに対応するデータには、top = bottom = 0 が入る
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
void* top; // ファイルの先頭 ROM アドレス
|
||||
void* bottom; // ファイルの最終 ROM アドレス
|
||||
|
||||
} ROM_FAT;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
オーバレイ・ヘッダ・テーブルとは、
|
||||
|
||||
オーバレイ・ファイルのロード情報を含んだテーブル。
|
||||
リンク処理時に nef ファイルやオーバレイ・モジュールと同時にバイナリで作成される
|
||||
下記の構造体データの配列として実装され、
|
||||
配列のサイズ = オーバレイ・ファイル数
|
||||
配列の添え字 = オーバレイID
|
||||
|
||||
オーバレイIDはリンク処理時には仮の値が設定されているが、makeromにより実際の値となる
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
u32 id; // オーバーレイ ID
|
||||
void* ram_address; // ロード先頭位置
|
||||
u32 ram_size; // ロードサイズ
|
||||
u32 bss_size; // bss 領域サイズ
|
||||
void* sinit_init; // static initializer 先頭アドレス
|
||||
void* sinit_init_end; // static initializer 最終アドレス
|
||||
u32 file_id; // オーバーレイファイルID
|
||||
u32 rom_size; // オーバーレイファイルサイズ
|
||||
} ROM_OVT;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
常駐モジュール用パラメタ
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
|
||||
u8* rom_address; // 転送元 ROM アドレス
|
||||
u8* entry_address; // 実行開始(エントリ)アドレス
|
||||
u8* ram_address; // 転送先 RAM アドレス
|
||||
s32 rom_size; // 転送 ROM サイズ
|
||||
|
||||
} ROM_ResidentModuleParam; // 常駐の ... resident
|
||||
|
||||
// ROMヘッダ・ブートパラメータ構造体 (オリジナルの定義)
|
||||
typedef struct {
|
||||
u8 *romAddr; // ROMアドレス
|
||||
u8 *entryAddr; // エントリアドレス
|
||||
u8 *ramAddr; // RAMアドレス
|
||||
s32 romSize; // ROMサイズ
|
||||
} BootUsrParam;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
ROMヘッダ構造体
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x000 System Reserved
|
||||
//
|
||||
char title_name[12]; // Soft title name
|
||||
u32 game_code; // Game code
|
||||
|
||||
u16 maker_code; // Maker code
|
||||
u8 machine_code; // Machine code
|
||||
u8 rom_type; // Rom type
|
||||
u8 rom_size; // Rom size
|
||||
|
||||
u8 reserved_A[9]; // System Reserved A ( Set ALL 0 )
|
||||
|
||||
u8 soft_version; // Soft version
|
||||
u8 comp_arm9_boot_area:1; // Compress arm9 boot area
|
||||
u8 comp_arm7_boot_area:1; // Compress arm7 boot area
|
||||
u8 :0;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x020 for Static modules (Section:B)
|
||||
//
|
||||
// ARM9
|
||||
BootUsrParam arm9;
|
||||
|
||||
// ARM7
|
||||
BootUsrParam arm7;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x040 for File Name Table[FNT] (Section:C)
|
||||
//
|
||||
ROM_FNT* fnt_offset; // ROM offset
|
||||
u32 fnt_size; // Table size
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x048 for File Allocation Table[FAT] (Section:E)
|
||||
//
|
||||
ROM_FAT* fat_offset; // ROM offset
|
||||
u32 fat_size; // Table size
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x050 for Overlay Tables[OVT] (Section:D)
|
||||
//
|
||||
// ARM9
|
||||
ROM_OVT* main_ovt_offset; // ROM offset
|
||||
u32 main_ovt_size; // Table size
|
||||
|
||||
// ARM7
|
||||
ROM_OVT* sub_ovt_offset; // ROM offset
|
||||
u32 sub_ovt_size; // Table size
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x060 for ROM control parameter
|
||||
u32 game_cmd_param; // Game command parameter
|
||||
u32 secure_cmd_param; // Secure command parameter
|
||||
u32 banner_offset; // Ctrl Reserved A (Set 0)
|
||||
u16 secure_area_crc16; // Secure area CRC-16
|
||||
u16 secure_cmd_latency; // Secure command latency ((param+2)*256 system cycles)
|
||||
u8 ctrl_reserved_B[16]; // Ctrl Reserved B (Set 0)
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x080 - 0x0C0 System Reserved
|
||||
u8 reserved_B[64]; // System Reserved B (Set 0)
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x0C0 for NINTENDO logo data
|
||||
u8 nintendo_logo[0x9c]; // NINTENDO logo data
|
||||
u16 nintendo_logo_crc16; // CRC-16
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x15E ROM header CRC-16
|
||||
u16 header_crc16; // ROM header CRC-16
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 0x0160 - 0x0180 System Reserved
|
||||
//
|
||||
u8 reserved_C[32]; // Debugger Reserved (Set ALL 0)
|
||||
|
||||
} RomHeader;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
大域変数宣言
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
関数プロトタイプ宣言
|
||||
*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
BOOL get_overlay_info(int card_or_cart, int main_or_sub, u32 id, ROM_OVT *ovt);
|
||||
BOOL my_romfile_load_overlay_segment(int card_or_cart, int main_or_sub, u32 id);
|
||||
void print_overlay_info(int main_or_sub, u32 id);
|
||||
*/
|
||||
|
||||
#endif // NITROEVA3_CARD_ROM_FILESYSTEM_H_
|
||||
|
||||
|
||||
|
||||
85
build/tools/TamperDetectorForSrl/searcharg.cpp
Normal file
85
build/tools/TamperDetectorForSrl/searcharg.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*---------------------------------------------------------------------------*
|
||||
Project: TwlSDK - - makelst
|
||||
File: searcharg.c
|
||||
|
||||
Copyright 2006-2009 Nintendo. All rights reserved.
|
||||
|
||||
These coded instructions, statements, and computer programs contain
|
||||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||||
Company Ltd., and are protected by Federal copyright law. They may
|
||||
not be disclosed to third parties or copied or duplicated in any form,
|
||||
in whole or in part, without the prior written consent of Nintendo.
|
||||
|
||||
*---------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "searcharg.h"
|
||||
|
||||
char* output_fname = NULL;
|
||||
char* genuine_fname = NULL;
|
||||
char* magicon_fname = NULL;
|
||||
|
||||
|
||||
void SA_Usage( void)
|
||||
{
|
||||
fprintf( stderr, "Analyzing Tool\n");
|
||||
fprintf( stderr, "Usage: makelst [-o output-file] [--g genuine-srl-file] [--m magicon-srl-file]\n\n");
|
||||
exit( 1);
|
||||
}
|
||||
|
||||
|
||||
/*ˆø<CB86>”‚ð‰ð<E280B0>Í‚·‚é*/
|
||||
void SA_searchopt( int argc, char* argv[])
|
||||
{
|
||||
int n;
|
||||
struct option optionInfo[] = {
|
||||
{ "genuine", required_argument, NULL, 'g'},
|
||||
{ "magicon", required_argument, NULL, 'm'},
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
if( argc <= 1) {
|
||||
SA_Usage();
|
||||
}
|
||||
|
||||
while( (n = getopt_long( argc, argv, "do:h", &optionInfo[0], NULL))
|
||||
!= -1)
|
||||
{
|
||||
switch( n) {
|
||||
case 'd':
|
||||
// dbg_print_flag = 1;
|
||||
break;
|
||||
case 'o':
|
||||
if( output_fname != NULL) {
|
||||
fprintf( stderr, "ERROR! redefined output filename.\n");
|
||||
SA_Usage();
|
||||
}
|
||||
output_fname = optarg;
|
||||
break;
|
||||
case 'g': // "--genuine"
|
||||
if( genuine_fname != NULL) {
|
||||
fprintf( stderr, "ERROR! redefined genuine filename.\n");
|
||||
SA_Usage();
|
||||
}
|
||||
genuine_fname = optarg;
|
||||
break;
|
||||
case 'm': // "--magicon"
|
||||
if( magicon_fname != NULL) {
|
||||
fprintf( stderr, "ERROR! redefined magicon filename.\n");
|
||||
SA_Usage();
|
||||
}
|
||||
magicon_fname = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
SA_Usage();
|
||||
break;
|
||||
default: // '?'
|
||||
SA_Usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
build/tools/TamperDetectorForSrl/searcharg.h
Normal file
25
build/tools/TamperDetectorForSrl/searcharg.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------*
|
||||
Project: TwlSDK - - makelst
|
||||
File: searcharg.h
|
||||
|
||||
Copyright 2006-2008 Nintendo. All rights reserved.
|
||||
|
||||
These coded instructions, statements, and computer programs contain
|
||||
proprietary information of Nintendo of America Inc. and/or Nintendo
|
||||
Company Ltd., and are protected by Federal copyright law. They may
|
||||
not be disclosed to third parties or copied or duplicated in any form,
|
||||
in whole or in part, without the prior written consent of Nintendo.
|
||||
|
||||
*---------------------------------------------------------------------------*/
|
||||
#ifndef __SEARCH_ARG__
|
||||
#define __SEARCH_ARG__
|
||||
|
||||
|
||||
|
||||
|
||||
/*ˆø<CB86>”‚ð‰ð<E280B0>Í‚·‚é*/
|
||||
void SA_searchopt( int argc, char* argv[]);
|
||||
|
||||
|
||||
|
||||
#endif /*__SEARCH_ARG__*/
|
||||
BIN
build/tools/TamperDetectorForSrl/tamperdetector.exe
Executable file
BIN
build/tools/TamperDetectorForSrl/tamperdetector.exe
Executable file
Binary file not shown.
13
build/tools/TamperDetectorForSrl/types.h
Normal file
13
build/tools/TamperDetectorForSrl/types.h
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
#ifndef NITRO_TYPES_H_
|
||||
#define NITRO_TYPES_H_
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short int u16;
|
||||
typedef unsigned long u32;
|
||||
|
||||
typedef signed short int s16;
|
||||
typedef signed long s32;
|
||||
|
||||
|
||||
#endif /*NITRO_TYPES_H_*/
|
||||
Loading…
Reference in New Issue
Block a user