From b96266fade98922b233813300a0d273a41527098 Mon Sep 17 00:00:00 2001 From: Manu Sridharan Date: Fri, 22 May 2015 16:36:40 -0700 Subject: [PATCH] Small changes to proxy server code. 1. allow for AST handler module in esnstrument_cli.js 2. directly pass arguments from proxy.py into esnstrument_cli.js. This allows for passing additional arguments besides the analyses. Now we must require passing '--analysis' for each analysis (README has been updated). We still turn relative paths into absolute paths, as before. --- README.md | 4 +- scripts/proxy.py | 13 +++--- src/js/commands/esnstrument_cli.js | 64 +++++++++++++++++------------- src/js/commands/instrument.js | 13 +----- src/js/commands/jalangi.js | 13 ++---- src/js/instrument/instUtil.js | 10 +++++ 6 files changed, 60 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 49dd8ec0..574697f8 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ commands: mkdir tmp cd tmp - mitmdump -q --anticache -s "../scripts/proxy.py ../src/js/sample_analyses/ChainedAnalyses.js ../src/js/runtime/analysisCallbackTemplate.js" + mitmdump -q --anticache -s "../scripts/proxy.py --analysis ../src/js/sample_analyses/ChainedAnalyses.js --analysis ../src/js/runtime/analysisCallbackTemplate.js" In your browser, the http and https proxy should be set to 127.0.0.1:8080. Now if you load a website in your browser, all JavaScript files associated with the website will get instrumented on-the-fly. @@ -95,7 +95,7 @@ On a mac, proxy can be set and launched automatically by giving the following co mkdir tmp cd tmp - ../scripts/mitmproxywrapper.py -t -q --anticache -s "../scripts/proxy.py ../src/js/sample_analyses/ChainedAnalyses.js ../src/js/runtime/analysisCallbackTemplate.js" + ../scripts/mitmproxywrapper.py -t -q --anticache -s "../scripts/proxy.py --analysis ../src/js/sample_analyses/ChainedAnalyses.js --analysis ../src/js/runtime/analysisCallbackTemplate.js" The proxy can be disabled by re-executing the last command. The last command enables proxy and starts the mitmproxy if the proxy is not currently enabled. If the proxy is currently enabled, the command disables the proxy. diff --git a/scripts/proxy.py b/scripts/proxy.py index 8009aa68..0ffb7af4 100644 --- a/scripts/proxy.py +++ b/scripts/proxy.py @@ -15,7 +15,7 @@ sys.path.insert(0, JALANGI_HOME+'/scripts') import sj -analysis = ' --analysis '.join([' ']+ANALYSES) +extraArgs = ' --analysis '.join([' ']+ANALYSES) def processFile (content, ext): try: @@ -24,7 +24,7 @@ def processFile (content, ext): print "Storing and instrumenting "+fileName+"."+ext with open(fileName+"."+ext, "w") as text_file: text_file.write(content) - sj.execute(sj.INSTRUMENTATION_SCRIPT+' --inlineIID --inlineSource '+analysis+' '+fileName+'.'+ext) + sj.execute(sj.INSTRUMENTATION_SCRIPT+' --inlineIID --inlineSource '+extraArgs+' '+fileName+'.'+ext) with open (fileName+"_jalangi_."+ext, "r") as text_file: data = text_file.read() return data @@ -34,12 +34,11 @@ def processFile (content, ext): return content def start(context, argv): - global ANALYSES - global analysis + global extraArgs if len(argv) > 1: - ANALYSES = [os.path.abspath(os.path.join(WORKING_DIR,x)) for x in argv[1:]] - analysis = ' --analysis '.join([' ']+ANALYSES) - print analysis + def mapper(p): return p if p.startswith('--') else os.path.abspath(os.path.join(WORKING_DIR,p)) + extraArgs = ' '.join(map(mapper, [x for x in argv[1:]])) + print extraArgs def response(context, flow): flow.response.decode() diff --git a/src/js/commands/esnstrument_cli.js b/src/js/commands/esnstrument_cli.js index 9c1073a3..f72f0cfb 100644 --- a/src/js/commands/esnstrument_cli.js +++ b/src/js/commands/esnstrument_cli.js @@ -75,33 +75,36 @@ if (typeof J$ === 'undefined') { - function rewriteInlineScript(src, metadata) { - //var instname = instUtil.createFilenameForScript(metadata.url); - //var origname = createOrigScriptFilename(instname); - - var origname = md5(src)+".js"; - var instname = makeInstCodeFileName(origname); - - try { - var instCodeAndData = instrumentCode( - { - code: src, - isEval: false, - origCodeFileName: sanitizePath(origname), - instCodeFileName: sanitizePath(instname), - inlineSourceMap: inlineIID, - inlineSource: inlineSource, - url: url - }); - - } catch (e) { - console.log(src); - throw e; + function rewriteInlineScript(astHandler) { + return function (src, metadata) { + //var instname = instUtil.createFilenameForScript(metadata.url); + //var origname = createOrigScriptFilename(instname); + + var origname = md5(src)+".js"; + var instname = makeInstCodeFileName(origname), instCodeAndData; + + try { + instCodeAndData = instrumentCode( + { + code: src, + isEval: false, + origCodeFileName: sanitizePath(origname), + instCodeFileName: sanitizePath(instname), + inlineSourceMap: inlineIID, + inlineSource: inlineSource, + url: url + }); + + } catch (e) { + console.log(src); + throw e; + } + instUtil.applyASTHandler(instCodeAndData, astHandler, sandbox); + fs.writeFileSync(path.join(outDir, origname), src, "utf8"); + fs.writeFileSync(makeSMapFileName(path.join(outDir, instname)), instCodeAndData.sourceMapString, "utf8"); + fs.writeFileSync(path.join(outDir, instname), instCodeAndData.code, "utf8"); + return instCodeAndData.code; } - fs.writeFileSync(path.join(outDir, origname), src, "utf8"); - fs.writeFileSync(makeSMapFileName(path.join(outDir, instname)), instCodeAndData.sourceMapString, "utf8"); - fs.writeFileSync(path.join(outDir, instname), instCodeAndData.code, "utf8"); - return instCodeAndData.code; } function getJalangiRoot() { @@ -158,6 +161,7 @@ if (typeof J$ === 'undefined') { parser.addArgument(['--inlineSource'], {help: "Inline original source as string in J$.iids.code in the instrumented file", action: 'storeTrue'}); parser.addArgument(['--initParam'], { help: "initialization parameter for analysis, specified as key:value", action:'append'}); parser.addArgument(['--noResultsGUI'], { help: "disable insertion of results GUI code in HTML", action:'storeTrue'}); + parser.addArgument(['--astHandlerModule'], {help: "Path to a node module that exports a function to be used for additional AST handling after instrumentation"}); parser.addArgument(['--outDir'], { help: "Directory containing scripts inlined in html", defaultValue: process.cwd() @@ -182,6 +186,10 @@ if (typeof J$ === 'undefined') { }); var args = parser.parseArgs(); + var astHandler = null; + if (args.astHandlerModule) { + astHandler = require(args.astHandlerModule); + } var initParams = args.initParam; inlineIID = args.inlineIID; inlineSource = args.inlineSource; @@ -205,6 +213,7 @@ if (typeof J$ === 'undefined') { var origCode = fs.readFileSync(fileName, "utf8"); var instCodeAndData, instCode; + var inlineRewriter = rewriteInlineScript(astHandler); if (fileName.endsWith(".js")) { instCodeAndData = instrumentCode( { @@ -216,11 +225,12 @@ if (typeof J$ === 'undefined') { inlineSource: inlineSource, url: url }); + instUtil.applyASTHandler(instCodeAndData, astHandler, sandbox); fs.writeFileSync(makeSMapFileName(instFileName), instCodeAndData.sourceMapString, "utf8"); fs.writeFileSync(instFileName, instCodeAndData.code, "utf8"); } else { var jalangiRoot = getJalangiRoot(); - instCode = proxy.rewriteHTML(origCode, "http://foo.com", rewriteInlineScript, ""); + instCode = proxy.rewriteHTML(origCode, "http://foo.com", inlineRewriter, ""); var headerStr = ''; headerStr += instUtil.getInlinedScripts(analyses, initParams, extraAppScripts, EXTRA_SCRIPTS_DIR, jalangiRoot); diff --git a/src/js/commands/instrument.js b/src/js/commands/instrument.js index 9d5fa720..84cdf794 100644 --- a/src/js/commands/instrument.js +++ b/src/js/commands/instrument.js @@ -112,15 +112,6 @@ if (typeof J$ === 'undefined') { var astHandler = options.astHandler; - function applyASTHandler(instResult) { - if (astHandler) { - var info = astHandler(instResult.instAST); - if (info) { - instResult.code = sandbox.Constants.JALANGI_VAR + ".ast_info = " + JSON.stringify(info) + ";\n" + instResult.code; - } - } - return instResult.code; - } /** * extra scripts to inject into the application and instrument @@ -150,7 +141,7 @@ if (typeof J$ === 'undefined') { }; var instResult = sandbox.instrumentCode(options); - var instrumentedCode = applyASTHandler(instResult); + var instrumentedCode = instUtil.applyASTHandler(instResult, astHandler, sandbox); fs.writeFileSync(path.join(copyDir, instname).replace(/.js$/, "_jalangi_.json"), instResult.sourceMapString, "utf8"); fs.writeFileSync(path.join(copyDir, origname), src); fs.writeFileSync(path.join(copyDir, instname), instrumentedCode); @@ -310,7 +301,7 @@ if (typeof J$ === 'undefined') { } } if (instResult) { - var instrumentedCode = applyASTHandler(instResult); + var instrumentedCode = instUtil.applyASTHandler(instResult, astHandler, sandbox); fs.writeFileSync(this.instScriptName.replace(/.js$/, "_jalangi_.json"), instResult.sourceMapString, "utf8"); this.push(instrumentedCode); } diff --git a/src/js/commands/jalangi.js b/src/js/commands/jalangi.js index 220d7a9a..f54c0cb2 100644 --- a/src/js/commands/jalangi.js +++ b/src/js/commands/jalangi.js @@ -22,6 +22,7 @@ /*global J$ */ var argparse = require('argparse'); +var instUtil = require('../instrument/instUtil'); var parser = new argparse.ArgumentParser({ addHelp: true, description: "Command-line utility to perform Jalangi2's instrumentation and analysis" @@ -41,15 +42,7 @@ if (args.astHandlerModule) { astHandler = require(args.astHandlerModule); } -function applyASTHandler(instResult) { - if (astHandler) { - var info = astHandler(instResult.instAST); - if (info) { - instResult.code = J$.Constants.JALANGI_VAR + ".ast_info = " + JSON.stringify(info) + ";\n" + instResult.code; - } - } - return instResult.code; -} + if (args.script_and_args.length === 0) { console.error("must provide script to record"); @@ -109,7 +102,7 @@ Module._extensions['.js'] = function (module, filename) { inlineSourceMap: !!args.inlineIID, inlineSource: !!args.inlineSource }); - applyASTHandler(instCodeAndData); + instUtil.applyASTHandler(instCodeAndData, astHandler, J$); fs.writeFileSync(makeSMapFileName(instFilename), instCodeAndData.sourceMapString, "utf8"); fs.writeFileSync(instFilename, instCodeAndData.code, "utf8"); module._compile(instCodeAndData.code, filename); diff --git a/src/js/instrument/instUtil.js b/src/js/instrument/instUtil.js index b6de8d52..584ab90f 100644 --- a/src/js/instrument/instUtil.js +++ b/src/js/instrument/instUtil.js @@ -116,6 +116,15 @@ function genInitParamsCode(initParams) { return ""; } +function applyASTHandler(instResult, astHandler, sandbox) { + if (astHandler) { + var info = astHandler(instResult.instAST); + if (info) { + instResult.code = sandbox.Constants.JALANGI_VAR + ".ast_info = " + JSON.stringify(info) + ";\n" + instResult.code; + } + } + return instResult.code; +} function headerCodeInit(root) { headerSources.forEach(function (src) { @@ -176,6 +185,7 @@ exports.setHeaders = setHeaders; exports.getHeaderCode = getHeaderCode; exports.getHeaderCodeAsScriptTags = getHeaderCodeAsScriptTags; exports.genInitParamsCode = genInitParamsCode; +exports.applyASTHandler = applyASTHandler; exports.isInlineScript = isInlineScript; exports.headerSources = headerSources; exports.createFilenameForScript = createFilenameForScript;