Monaca個人プランでcordova-plugin-crypt-fileを使って難読化

参考にしたサイト

【Monaca】リバースエンジニアリング対策「cordova-plugin-crypt-file」注意点

【Cordova】Ver.6.3.1「cordova-plugin-crypt-file」ENOENT: no such file or directory, open ‘DecryptResource.java’ エラー回避方法

概要

プラグインの書き換え

「cordova-plugin-crypt-file」の「plugin.xml」をエディタで開き、暗号化対象外のファイルやフォルダを追加してビルドする。

<HTML>

<cryptfiles>
<include>
<file regex=”\.(htm|html|js|css)$” />
</include>
<exclude>
</exclude>
</cryptfiles>

</HTML>

 

これを下記のように書き換える

<HTML>

<file regex=”\.(htm|html|js|css)$” />
</include>
<exclude>
<file regex=”angular” />
<file regex=”cordova-js-src” />
<file regex=”json” />
<file regex=”onsenui” />
<file regex=”plugins” />
<file regex=”scripts” />
<file regex=”cordova\.js” />
<file regex=”cordova_plugins\.js” />
</exclude>
</cryptfiles>

</HTML>

ポイント

 

 

g.jp/archives/1218

参考にしたのは下記 http://hatopp.wpblog.jp/archives/1881

 

<code>

githubより、「cordova-plugin-crypt-file-master.zip」ファイルをダウンロードし、解凍します。
解凍したフォルダ内にある[hooks]フォルダのafter_prepare.jsを下記の内容に書き換えて保存します。
※34行目と58行目が違います。after_prepare.jsJavaScript

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 module.exports = function(context) {     var path              = context.requireCordovaModule(‘path’),        fs                = context.requireCordovaModule(‘fs’),        crypto            = context.requireCordovaModule(‘crypto’),        Q                 = context.requireCordovaModule(‘q’),        cordova_util      = context.requireCordovaModule(‘cordova-lib/src/cordova/util’),        platforms         = context.requireCordovaModule(‘cordova-lib/src/platforms/platforms’),        Parser            = context.requireCordovaModule(‘cordova-lib/src/cordova/metadata/parser’),        ParserHelper      = context.requireCordovaModule(‘cordova-lib/src/cordova/metadata/parserhelper/ParserHelper’),        ConfigParser      = context.requireCordovaModule(‘cordova-common’).ConfigParser;     var deferral = new Q.defer();    var projectRoot = cordova_util.cdProjectRoot();     var key = crypto.randomBytes(24).toString(‘base64’);    var iv = crypto.randomBytes(12).toString(‘base64’);     console.log(‘key=’ + key + ‘, iv=’ + iv)     var targetFiles = loadCryptFileTargets();     context.opts.platforms.filter(function(platform) {        var pluginInfo = context.opts.plugin.pluginInfo;        return pluginInfo.getPlatformsArray().indexOf(platform) > -1;            }).forEach(function(platform) {        var platformPath = path.join(projectRoot, ‘platforms’, platform);        var platformApi = platforms.getPlatformApi(platform, platformPath);        var platformInfo = platformApi.getPlatformInfo();        var wwwDir = platformInfo.locations.www;         findCryptFiles(wwwDir).filter(function(file) {            return isCryptFile(file.replace(wwwDir, ”));        }).forEach(function(file) {            var content = fs.readFileSync(file, ‘utf-8’);            fs.writeFileSync(file, encryptData(content, key, iv), ‘utf-8’);            console.log(‘encrypt: ‘ + file);        });         if (platform == ‘ios’) {            var pluginDir;            try {              var ios_parser = context.requireCordovaModule(‘cordova-lib/src/cordova/metadata/ios_parser’),                  iosParser = new ios_parser(platformPath);              pluginDir = path.join(iosParser.cordovaproj, ‘Plugins’, context.opts.plugin.id);            } catch (err) {              var xcodeproj_dir = fs.readdirSync(platformPath).filter(function(e) { return e.match(/\.xcodeproj$/i); })[0],                  xcodeproj = path.join(platformPath, xcodeproj_dir),                  originalName = xcodeproj.substring(xcodeproj.lastIndexOf(path.sep)+1, xcodeproj.indexOf(‘.xcodeproj’)),                  cordovaproj = path.join(platformPath, originalName);               pluginDir = path.join(cordovaproj, ‘Plugins’, context.opts.plugin.id);            }            replaceCryptKey_ios(pluginDir, key, iv);         } else if (platform == ‘android’) {            var pluginDir = path.join(platformPath, ‘src’);            replaceCryptKey_android(pluginDir, key, iv);             var cfg = new ConfigParser(platformInfo.projectConfig.path);            cfg.doc.getroot().getchildren().filter(function(child, idx, arr) {                return (child.tag == ‘content’);            }).forEach(function(child) {                child.attrib.src = ‘/+++/’ + child.attrib.src;            });             cfg.write();        }    });     deferral.resolve();    return deferral.promise;      function findCryptFiles(dir) {        var fileList = [];        var list = fs.readdirSync(dir);        list.forEach(function(file) {            fileList.push(path.join(dir, file));        });        // sub dir        list.filter(function(file) {            return fs.statSync(path.join(dir, file)).isDirectory();        }).forEach(function(file) {            var subDir = path.join(dir, file)            var subFileList = findCryptFiles(subDir);            fileList = fileList.concat(subFileList);        });         return fileList;    }     function loadCryptFileTargets() {        var xmlHelpers = context.requireCordovaModule(‘cordova-common’).xmlHelpers;         var pluginXml = path.join(context.opts.plugin.dir, ‘plugin.xml’);         var include = [];        var exclude = [];         var doc = xmlHelpers.parseElementtreeSync(pluginXml);        var cryptfiles = doc.findall(‘cryptfiles’);        if (cryptfiles.length > 0) {            cryptfiles[0]._children.forEach(function(elm) {                elm._children.filter(function(celm) {                    return celm.tag == ‘file’ && celm.attrib.regex && celm.attrib.regex.trim().length > 0;                }).forEach(function(celm) {                    if (elm.tag == ‘include’) {                        include.push(celm.attrib.regex.trim());                    } else if (elm.tag == ‘exclude’) {                        exclude.push(celm.attrib.regex.trim());                    }                });            })        }         return {‘include’: include, ‘exclude’: exclude};    }     function isCryptFile(file) {        if (!targetFiles.include.some(function(regexStr) { return new RegExp(regexStr).test(file); })) {            return false;        }        if (targetFiles.exclude.some(function(regexStr) { return new RegExp(regexStr).test(file); })) {            return false;        }        return true;    }     function encryptData(input, key, iv) {        var cipher = crypto.createCipheriv(‘aes-256-cbc’, key, iv);        var encrypted = cipher.update(input, ‘utf8’, ‘base64’) + cipher.final(‘base64’);         return encrypted;    }     function replaceCryptKey_ios(pluginDir, key, iv) {        var sourceFile = path.join(pluginDir, ‘CDVCryptURLProtocol.m’);        var content = fs.readFileSync(sourceFile, ‘utf-8’);         var includeArrStr = targetFiles.include.map(function(pattern) { return ‘@”‘ + pattern.replace(‘\\’, ‘\\\\’) + ‘”‘; }).join(‘, ‘);        var excludeArrStr = targetFiles.exclude.map(function(pattern) { return ‘@”‘ + pattern.replace(‘\\’, ‘\\\\’) + ‘”‘; }).join(‘, ‘);         content = content.replace(/kCryptKey = @”.*”;/, ‘kCryptKey = @”‘ + key + ‘”;’)                         .replace(/kCryptIv = @”.*”;/, ‘kCryptIv = @”‘ + iv + ‘”;’)                         .replace(/kIncludeFiles\[\] = {.*};/, ‘kIncludeFiles\[\] = { ‘ + includeArrStr + ‘ };’)                         .replace(/kExcludeFiles\[\] = {.*};/, ‘kExcludeFiles\[\] = { ‘ + excludeArrStr + ‘ };’)                         .replace(/kIncludeFileLength = [0-9]+;/, ‘kIncludeFileLength = ‘ + targetFiles.include.length + ‘;’)                         .replace(/kExcludeFileLength = [0-9]+;/, ‘kExcludeFileLength = ‘ + targetFiles.exclude.length + ‘;’);         fs.writeFileSync(sourceFile, content, ‘utf-8’);    }     function replaceCryptKey_android(pluginDir, key, iv) {        var sourceFile = path.join(pluginDir, ‘com/tkyaji/cordova/DecryptResource.java’);        var content = fs.readFileSync(sourceFile, ‘utf-8’);         var includeArrStr = targetFiles.include.map(function(pattern) { return ‘”‘ + pattern.replace(‘\\’, ‘\\\\’) + ‘”‘; }).join(‘, ‘);        var excludeArrStr = targetFiles.exclude.map(function(pattern) { return ‘”‘ + pattern.replace(‘\\’, ‘\\\\’) + ‘”‘; }).join(‘, ‘);         content = content.replace(/CRYPT_KEY = “.*”;/, ‘CRYPT_KEY = “‘ + key + ‘”;’)                         .replace(/CRYPT_IV = “.*”;/, ‘CRYPT_IV = “‘ + iv + ‘”;’)                         .replace(/INCLUDE_FILES = new String\[\] {.*};/, ‘INCLUDE_FILES = new String[] { ‘ + includeArrStr + ‘ };’)                         .replace(/EXCLUDE_FILES = new String\[\] {.*};/, ‘EXCLUDE_FILES = new String[] { ‘ + excludeArrStr + ‘ };’);         fs.writeFileSync(sourceFile, content, ‘utf-8’);    }}

a http://hatopp.wpblog.jp/archives/1218

<code>

変更前

1234567     <cryptfiles>        <include>            <file regex=”\.(htm|html|js|css)$” />        </include>        <exclude>        </exclude>    </cryptfiles>

変更後XHTML

123456789101112131415     <cryptfiles>        <include>            <file regex=”\.(htm|html|js|css)$” />        </include>        <exclude>            <file regex=”angular” />            <file regex=”cordova-js-src” />            <file regex=”json” />            <file regex=”onsenui” />            <file regex=”plugins” />            <file regex=”scripts” />            <file regex=”cordova\.js” />            <file regex=”cordova_plugins\.js” />        </exclude>    </cryptfiles>

</code>

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です