/*
* PDF Scrutinizer, a library for detecting and analyzing malicious PDF documents.
* Copyright 2013 Florian Schmitt <florian@florianschmitt.de>, Fraunhofer FKIE
*
* 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/>.
*/
package de.pdf_scrutinizer.utils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import de.pdf_scrutinizer.data.AnalysisResult;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.io.HexDump;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.pdf_scrutinizer.Scrutinizer;
import de.pdf_scrutinizer.dynamic_heuristics.ShellcodeTester;
public class OutputToFiles extends OutputNull {
private static Log log = LogFactory.getLog(OutputToFiles.class);
private final Scrutinizer scrutinizer;
private String filename_function_calls = "function_calls";
private String filename_dynamic_ICode = "dynamic_ICode";
private String filename_tree_ICode = "tree_ICode";
private String filename_static_ICode = "static_ICode";
private String filename_eval = "eval";
private String filename_extracted = "extracted";
private String filename_shellcode = "shellcode";
private String filename_embedded = "embed";
private String filename_AnalysisResult = "analysis_result";
private PrintStream printStream_eval = null;
private PrintStream printStream_function_calls = null;
private PrintStream printStream_dynamic_logger = null;
private PrintStream printStream_tree_ICode = null;
private PrintStream printStream_static_ICode = null;
private boolean showHexdump = false;
private boolean saveDynamicICode = false;
public OutputToFiles(Scrutinizer scrutinizer, String prefix, String resultFolder) {
this.scrutinizer = scrutinizer;
File file;
if (!(file = new File(resultFolder)).exists()) {
file.mkdir();
}
if (!(file = new File(resultFolder + File.separator + prefix)).exists()) {
file.mkdir();
}
String formatString = "%s%s%s%s%s";
filename_function_calls = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_function_calls);
filename_dynamic_ICode = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_dynamic_ICode);
filename_tree_ICode = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_tree_ICode);
filename_static_ICode = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_static_ICode);
filename_eval = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_eval);
filename_extracted = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_extracted);
filename_shellcode = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_shellcode);
filename_embedded = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_embedded);
filename_AnalysisResult = String.format(formatString, resultFolder, File.separator, prefix, File.separator, filename_AnalysisResult);
try {
printStream_function_calls = new PrintStream(filename_function_calls);
if (saveDynamicICode) {
printStream_dynamic_logger = new PrintStream(filename_dynamic_ICode);
}
printStream_tree_ICode = new PrintStream(filename_tree_ICode);
printStream_static_ICode = new PrintStream(filename_static_ICode);
printStream_eval = new PrintStream(filename_eval);
} catch (FileNotFoundException e) {
log.warn(e);
}
}
private int evalcount = 0;
@Override
public void eval(String x) {
if (printStream_eval != null) {
printStream_eval.print("\nNo: " + evalcount++ + "\n\n");
printStream_eval.print(x);
}
}
@Override
public void functionCalls(String x) {
if (printStream_function_calls != null) {
printStream_function_calls.print(x);
}
}
private int embedStage = 1;
@Override
public void saveAnalysisResult(AnalysisResult result) {
PrintStream stream = null;
try {
stream = new PrintStream(filename_AnalysisResult);
stream.print(AnalysisResultHelper.toString(result));
} catch (FileNotFoundException e) {
log.warn(e);
} finally {
if (stream != null)
stream.close();
}
}
@Override
public void saveEmbedFile(String[] str) {
BufferedWriter fileWriter_embeddedFiles = null;
try {
fileWriter_embeddedFiles = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename_embedded + "." + embedStage++)));
fileWriter_embeddedFiles.write(str[1]);
} catch (FileNotFoundException e) {
log.warn(e);
} catch (IOException e) {
log.warn(e);
} finally {
try {
if (fileWriter_embeddedFiles != null)
fileWriter_embeddedFiles.close();
} catch (IOException e) {
log.warn(e);
}
}
}
@Override
public void saveExtractedcode(List<String> codes) {
PrintStream extracted = null;
try {
extracted = new PrintStream(filename_extracted);
} catch (FileNotFoundException e) {
log.warn(e);
return;
}
int stage = 1;
for (String str : codes) {
extracted.println("stage #" + stage++ + "\n" + str);
}
extracted.close();
}
//Destructor
@Override
protected void finalize() throws Throwable {
if (printStream_dynamic_logger != null) {
printStream_dynamic_logger.close();
}
if (printStream_function_calls != null) {
printStream_function_calls.close();
}
if (printStream_tree_ICode != null) {
printStream_tree_ICode.close();
}
if (printStream_static_ICode != null) {
printStream_static_ICode.close();
}
if (printStream_eval != null) {
printStream_eval.close();
}
super.finalize();
}
private int sccount = 0;
@Override
public void saveShellcode(String sc, String stdout) {
ShellcodeTester tester = scrutinizer.getDynamicHeuristics().getShellcodeTester();
if (tester != null && tester.getSaveShellcode()) {
BufferedWriter fileWriter_shellcode = null;
try {
fileWriter_shellcode = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename_shellcode + sccount + ".bin"), "UTF-16LE"));
fileWriter_shellcode.write(sc);
fileWriter_shellcode.close();
fileWriter_shellcode = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename_shellcode + sccount++ + ".info")));
fileWriter_shellcode.write(stdout);
} catch (UnsupportedEncodingException e) {
log.warn(e);
} catch (FileNotFoundException e) {
log.warn(e);
} catch (IOException e) {
log.warn(e);
} finally {
try {
if (fileWriter_shellcode != null)
fileWriter_shellcode.close();
} catch (IOException e) {
log.warn(e);
}
}
}
}
@Override
public void prettyPrint(String str) {
if (!showHexdump || str.isEmpty())
return;
byte[] data = StringUtils.getBytesUtf16Le(str);
try {
HexDump.dump(data, 0, System.out, 0);
} catch (ArrayIndexOutOfBoundsException e) {
log.warn(e);
} catch (IllegalArgumentException e) {
log.warn(e);
} catch (IOException e) {
log.warn(e);
}
}
@Override
public void dynamicICode(String str) {
printStream_dynamic_logger.print(str);
}
@Override
public void treeICode(String str) {
printStream_tree_ICode.print(str);
}
@Override
public PrintStream getStaticICodePrintStream() {
return printStream_static_ICode;
}
@Override
public void setSaveDynamicICode(boolean saveDynamicICode) {
this.saveDynamicICode = saveDynamicICode;
}
@Override
public boolean getSaveDynamicICode() {
return this.saveDynamicICode;
}
@Override
public void setShowHexdump(boolean showHexdump) {
this.showHexdump = showHexdump;
}
}