Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
* Copyright (c) 2002-2016 Eric Lafortune @ GuardSquare
*
* 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 2 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, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package proguard.retrace;
import proguard.obfuscate.MappingReader;
import java.io.*;
import java.util.*;
/**
* Tool for de-obfuscating stack traces of applications that were obfuscated
* with ProGuard.
*
* @author Eric Lafortune
*/
public class ReTrace
{
private static final String USAGE = "Usage: java proguard.retrace.ReTrace [-regex ] [-verbose] []";
private static final String REGEX_OPTION = "-regex";
private static final String VERBOSE_OPTION = "-verbose";
public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c\\.%m\\s*\\(%s(?::%l)?\\)\\s*(?:~\\[.*\\])?)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)";
// The settings.
private final String regularExpression;
private final boolean verbose;
private final File mappingFile;
/**
* Creates a new ReTrace instance.
* @param regularExpression the regular expression for parsing the lines in
* the stack trace.
* @param verbose specifies whether the de-obfuscated stack trace
* should be verbose.
* @param mappingFile the mapping file that was written out by
* ProGuard.
*/
public ReTrace(String regularExpression,
boolean verbose,
File mappingFile)
{
this.regularExpression = regularExpression;
this.verbose = verbose;
this.mappingFile = mappingFile;
}
/**
* De-obfuscates a given stack trace.
* @param stackTraceReader a reader for the obfuscated stack trace.
* @param stackTraceWriter a writer for the de-obfuscated stack trace.
*/
public void retrace(LineNumberReader stackTraceReader,
PrintWriter stackTraceWriter) throws IOException
{
// Create a pattern for stack frames.
FramePattern pattern = new FramePattern(regularExpression, verbose);
// Create a remapper.
FrameRemapper mapper = new FrameRemapper();
// Read the mapping file.
MappingReader mappingReader = new MappingReader(mappingFile);
mappingReader.pump(mapper);
// Read and process the lines of the stack trace.
while (true)
{
// Read a line.
String obfuscatedLine = stackTraceReader.readLine();
if (obfuscatedLine == null)
{
break;
}
// Try to match it against the regular expression.
FrameInfo obfuscatedFrame = pattern.parse(obfuscatedLine);
if (obfuscatedFrame != null)
{
// Transform the obfuscated frame back to one or more
// original frames.
Iterator retracedFrames =
mapper.transform(obfuscatedFrame).iterator();
String previousLine = null;
while (retracedFrames.hasNext())
{
// Retrieve the next retraced frame.
FrameInfo retracedFrame = retracedFrames.next();
// Format the retraced line.
String retracedLine =
pattern.format(obfuscatedLine, retracedFrame);
// Clear the common first part of ambiguous alternative
// retraced lines, to present a cleaner list of
// alternatives.
String trimmedLine =
previousLine != null &&
obfuscatedFrame.getLineNumber() == 0 ?
trim(retracedLine, previousLine) :
retracedLine;
// Print out the retraced line.
if (trimmedLine != null)
{
stackTraceWriter.println(trimmedLine);
}
previousLine = retracedLine;
}
}
else
{
// Print out the original line.
stackTraceWriter.println(obfuscatedLine);
}
}
stackTraceWriter.flush();
}
/**
* Returns the first given string, with any leading characters that it has
* in common with the second string replaced by spaces.
*/
private String trim(String string1, String string2)
{
StringBuilder line = new StringBuilder(string1);
// Find the common part.
int trimEnd = firstNonCommonIndex(string1, string2);
if (trimEnd == string1.length())
{
return null;
}
// Don't clear the last identifier characters.
trimEnd = lastNonIdentifierIndex(string1, trimEnd) + 1;
// Clear the common characters.
for (int index = 0; index < trimEnd; index++)
{
if (!Character.isWhitespace(string1.charAt(index)))
{
line.setCharAt(index, ' ');
}
}
return line.toString();
}
/**
* Returns the index of the first character that is not the same in both
* given strings.
*/
private int firstNonCommonIndex(String string1, String string2)
{
int index = 0;
while (index < string1.length() &&
index < string2.length() &&
string1.charAt(index) == string2.charAt(index))
{
index++;
}
return index;
}
/**
* Returns the index of the last character that is not an identifier
* character in the given string, at or before the given index.
*/
private int lastNonIdentifierIndex(String line, int index)
{
while (index >= 0 &&
Character.isJavaIdentifierPart(line.charAt(index)))
{
index--;
}
return index;
}
/**
* The main program for ReTrace.
*/
public static void main(String[] args)
{
// Parse the arguments.
if (args.length < 1)
{
System.err.println(USAGE);
System.exit(-1);
}
String regularExpresssion = STACK_TRACE_EXPRESSION;
boolean verbose = false;
int argumentIndex = 0;
while (argumentIndex < args.length)
{
String arg = args[argumentIndex];
if (arg.equals(REGEX_OPTION))
{
regularExpresssion = args[++argumentIndex];
}
else if (arg.equals(VERBOSE_OPTION))
{
verbose = true;
}
else
{
break;
}
argumentIndex++;
}
if (argumentIndex >= args.length)
{
System.err.println(USAGE);
System.exit(-1);
}
// Convert the arguments into File instances.
File mappingFile = new File(args[argumentIndex++]);
File stackTraceFile = argumentIndex < args.length ?
new File(args[argumentIndex]) :
null;
try
{
// Open the input stack trace. We're always using the UTF-8
// character encoding, even for reading from the standard
// input.
LineNumberReader reader =
new LineNumberReader(
new BufferedReader(
new InputStreamReader(stackTraceFile == null ? System.in :
new FileInputStream(stackTraceFile), "UTF-8")));
// Open the output stack trace, again using UTF-8 encoding.
PrintWriter writer =
new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"));
try
{
// Execute ReTrace with the collected settings.
new ReTrace(regularExpresssion, verbose, mappingFile)
.retrace(reader, writer);
}
finally
{
// Close the input stack trace if it was a file.
if (stackTraceFile != null)
{
reader.close();
}
}
}
catch (IOException ex)
{
if (verbose)
{
// Print a verbose stack trace.
ex.printStackTrace();
}
else
{
// Print just the stack trace message.
System.err.println("Error: "+ex.getMessage());
}
System.exit(1);
}
System.exit(0);
}
}