/*---------------------------------------- * x86x64checker.js * Copyright (C) 2020 StraightApps.com, All Rights Reserved * October 8, 2020 初期版 *-----------------------------------------*/ /*---------------------------------------- * 引数が file のアロー関数を定義 * readAsArrayBufferReader が関数のように使える。 * 呼び出しは、readAsArrayBufferReader( file ) のようになる。 *-----------------------------------------*/ const readAsArrayBufferReader = (file) => // 引数が1つのアロー関数(引数が1つならカッコを省略可能) { const reader = new FileReader(); // 新しい FileReader オブジェクトを作成 // Promise は、非同期処理の最終的な完了もしくは失敗を表すオブジェクト。 // 引数が2つのアロー関数を定義(仮引数名は MDN の通り) return new Promise( (resolve, reject) => { // 読み込みエラーとなった error イベントのハンドラを定義 reader.onerror = () => // 引数がないアロー関数(カッコは省略できない) { reader.abort(); // 読み込み処理を中断する reject('Unknown error occurred during reading the file'); // reject にエラー理由を設定 }; // 読み込みが正常に完了した load イベントのハンドラを定義 reader.onload = () => { resolve( reader.result ); // resolve に reader.result を代入 }; // onloadstart など、細かいものもある(リンク切れ・・・なくなった?)。 // https://developer.mozilla.org/ja/docs/Web/API/FileReader // 指定された Blob(または file オブジェクト)の内容の読み込みを開始し、 // 終了すると、result 属性にファイルのデータを表す ArrayBuffer が格納されます。 reader.readAsArrayBuffer(file); // Blob.arrayBuffer メソッドが新しいものである。 }); // Promise の終わり }; // readAsArrayBufferReader の終わり /*---------------------------------------- * html のロードが終わったら実行される onload 関数 *-----------------------------------------*/ function onload() { const f = document.getElementById('infile'); // input type="file" が変更されたときに実行する関数をアロー関数で定義 f.addEventListener('change', (evt) => { // 引数が evt のアロー関数 const input = evt.target; // input type="file" 要素 if (input.files.length == 0) { // 長さが 0、すなわちキャンセルの場合 let p = document.getElementById('result'); p.innerHTML = 'キャンセルされたか、ファイルサイズ 0 です。'; let e = document.getElementById('evidence'); e.innerHTML = ''; return; } let file = input.files[0]; // 選択されたファイル情報 //alert(file); // "[object file]" と表示される if (!file) { let p = document.getElementById('result'); p.innerHTML = 'ファイル情報が無効です。'; let e = document.getElementById('evidence'); e.innerHTML = ''; return; } // ファイルサイズを制限する場合 //if (file.size > 50 * 1024) { //} // 非同期でファイルを読み込みます。 readAsArrayBufferReader(file) // Promise が結果を返したら、then が実行される(引数1つのアロー関数) .then( (buff) => { let bin = ''; // 「根拠」として出力するバイナリデータ文字列 //let dat = new Uint8Array( buff ); // ファイルから読み込んだ buff 全体を 8 ビット符号なし整数配列に変換 let dat = new Uint8Array( buff, 0, Math.min( file.size, 1024 ) ); // 同 buff の先頭 1024 バイトを、8 ビット符号なし整数配列に変換 // x86(32bit) : 50 45 00 00 4C 01 の並びを検出 // x64(64bit) : 50 45 00 00 64 86 の並びを検出 // exe でも dll でも、いずれも 0x0200 より前にあるようなので、1024 = 0x400 で十分 let x86 = 0; // 50 が見つかったら 1 に、45 が見つかったら 2 に・・・、連続一致が途切れたら 0 に戻す。 let x64 = 0; // 16 バイト単位で検査します。 for (let i = 0; i * 16 < dat.length; i++) { let line = ''; // 1行のデータ let p = i * 16; // dat に対する 16 バイトブロックの先頭 let b = dat.slice( p, Math.min(dat.length, p + 16) ); // p バイト目から最大 16 バイト先までを取り込み for (const e of b) { // 「変数 of 配列」により配列1要素ずつ取り出し e に設定する let h = e .toString(16) // 16 進数の文字列に変換 .toUpperCase() // 英大文字に変換 .padStart(2, '0'); // 2桁になるよう先頭を 0 で埋める line += ' ' + h; // 1行のデータに追記 // データの並びを判断します if ( x86 != 6 ){ x86 = checkIfX86( h, x86 ); } if ( x64 != 6 ){ x64 = checkIfX64( h, x64 ); } } let addr = p .toString(16) .toUpperCase() .padStart(8, '0'); line = `${addr}:${line}\n`; // 「テンプレートリテラル」で行データを作成 bin += line; if ( x86 < 1 && x64 < 1 ){ bin = ''; } // 結果が出た場合は、ここで終わります。 if ( x86 == 6 || x64 == 6 ){ break; } } let res = document.getElementById('result'); if ( x86 == 6 ){ res.innerHTML = '32 ビットです。'; } else if ( x64 == 6 ){ res.innerHTML = '64 ビットです。'; } else{ res.innerHTML = '判定できませんでした。'; } let pre = document.getElementById('evidence'); pre.innerHTML = bin; }) // .then のアロー関数の終わり // Promise が拒絶(reject)した場合の処理 .catch( (reason) => { alert(reason); }); // .catch のアロー関数の終わり }); // addEventListener 関数のアロー関数の終わり } //---------------------------------------- // html のロードが終わったら、onload を実行 window.addEventListener('load', onload, false); /*---------------------------------------- * 32 ビットを示すバイト並びかどうかの判定 * x86(32bit) : 50 45 00 00 4C 01 の並びを検出 *-----------------------------------------*/ function checkIfX86( h, x86 ) { // 0x50 なら、文字列の開始の可能性があります。 if ( h == "50" ){ return 1; } // 0x45 なら、0x50 に続く場合のみ、判定対象です。 if ( h == "45" ){ if ( x86 == 1 ){ return 2; } return 0; } // 0x00 なら、0x45 または 0x00 に続く場合のみ、判定対象です。 if ( h == "00" ){ if ( x86 == 2 ){ // 0x45 の次 return 3; } if ( x86 == 3 ){ // 0x00 の次 return 4; } return 0; } // 0x4C なら、2つ目の 0x00 に続く場合のみ、判定対象です。 if ( h == "4C" ){ if ( x86 == 4 ){ return 5; } return 0; } // 0x01 なら、0x4C に続く場合のみ、判定対象です。 if ( h == "01" ){ if ( x86 == 5 ){ return 6; } return 0; } // 上記以外の値は、判定対象ではありません。 return 0; } /*---------------------------------------- * 64 ビットを示すバイト並びかどうかの判定 * x64(64bit) : 50 45 00 00 64 86 の並びを検出 *-----------------------------------------*/ function checkIfX64( h, x64 ) { // 0x50 なら、文字列の開始の可能性があります。 if ( h == "50" ){ return 1; } // 0x45 なら、0x50 に続く場合のみ、判定対象です。 if ( h == "45" ){ if ( x64 == 1 ){ return 2; } return 0; } // 0x00 なら、0x45 または 0x00 に続く場合のみ、判定対象です。 if ( h == "00" ){ if ( x64 == 2 ){ // 0x45 の次 return 3; } if ( x64 == 3 ){ // 0x00 の次 return 4; } return 0; } // 0x64 なら、2つ目の 0x00 に続く場合のみ、判定対象です。 if ( h == "64" ){ if ( x64 == 4 ){ return 5; } return 0; } // 0x86 なら、0x64 に続く場合のみ、判定対象です。 if ( h == "86" ){ if ( x64 == 5 ){ return 6; } return 0; } // 上記以外の値は、判定対象ではありません。 return 0; }