mirror of
https://github.com/pxb1988/dex2jar.git
synced 2024-12-04 11:43:34 +00:00
introduce a new tool to decrypt string in class file
--HG-- branch : 0.0.9.x
This commit is contained in:
parent
7505ba9ad6
commit
8e91365c6a
23
dex-tools/src/main/bin/d2j-decrpyt-string.bat
Normal file
23
dex-tools/src/main/bin/d2j-decrpyt-string.bat
Normal file
@ -0,0 +1,23 @@
|
||||
@echo off
|
||||
|
||||
REM
|
||||
REM dex2jar - Tools to work with android .dex and java .class files
|
||||
REM Copyright (c) 2009-2012 Panxiaobo
|
||||
REM
|
||||
REM Licensed under the Apache License, Version 2.0 (the "License");
|
||||
REM you may not use this file except in compliance with the License.
|
||||
REM You may obtain a copy of the License at
|
||||
REM
|
||||
REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
REM
|
||||
REM Unless required by applicable law or agreed to in writing, software
|
||||
REM distributed under the License is distributed on an "AS IS" BASIS,
|
||||
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
REM See the License for the specific language governing permissions and
|
||||
REM limitations under the License.
|
||||
REM
|
||||
|
||||
set CLASSPATH=
|
||||
FOR %%i IN ("%~dp0lib\*.jar") DO CALL "%~dp0setclasspath.bat" %%i
|
||||
|
||||
java -Xms512m -Xmx1024m -cp "%CLASSPATH%" "com.googlecode.dex2jar.tools.DecryptStringCmd" %*
|
40
dex-tools/src/main/bin/d2j-decrpyt-string.sh
Normal file
40
dex-tools/src/main/bin/d2j-decrpyt-string.sh
Normal file
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# dex2jar - Tools to work with android .dex and java .class files
|
||||
# Copyright (c) 2009-2012 Panxiaobo
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# copy from $Tomcat/bin/startup.sh
|
||||
# resolve links - $0 may be a softlink
|
||||
PRG="$0"
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`/"$link"
|
||||
fi
|
||||
done
|
||||
PRGDIR=`dirname "$PRG"`
|
||||
#
|
||||
|
||||
_classpath="."
|
||||
for k in "$PRGDIR"/lib/*.jar
|
||||
do
|
||||
_classpath="${_classpath}:${k}"
|
||||
done
|
||||
java -Xms512m -Xmx1024m -classpath "${_classpath}" "com.googlecode.dex2jar.tools.DecryptStringCmd" $@
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* dex2jar - Tools to work with android .dex and java .class files
|
||||
* Copyright (c) 2009-2012 Panxiaobo
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.googlecode.dex2jar.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import p.rn.util.FileOut;
|
||||
import p.rn.util.FileOut.OutHandler;
|
||||
import p.rn.util.FileWalker;
|
||||
import p.rn.util.FileWalker.StreamHandler;
|
||||
import p.rn.util.FileWalker.StreamOpener;
|
||||
|
||||
public class DecryptStringCmd extends BaseCmd {
|
||||
public static void main(String[] args) {
|
||||
new DecryptStringCmd().doMain(args);
|
||||
}
|
||||
|
||||
public DecryptStringCmd() {
|
||||
super("d2j-decrpyt-string [options] <jar>", "Decrypt in class file");
|
||||
}
|
||||
|
||||
@Opt(opt = "f", longOpt = "force", hasArg = false, description = "force overwrite")
|
||||
private boolean forceOverwrite = false;
|
||||
@Opt(opt = "o", longOpt = "output", description = "output of .jar files, default is $current_dir/[jar-name]-decrypted.jar", argName = "out")
|
||||
private File output;
|
||||
|
||||
@Opt(opt = "mo", longOpt = "decrypt-method-owner", description = "the owner of the mothed which can decrypt the stings, example: java.lang.String", argName = "owner")
|
||||
private String methodOwner;
|
||||
@Opt(opt = "mn", longOpt = "decrypt-method-name", description = "the owner of the mothed which can decrypt the stings, the method's signature must be static (Ljava/lang/String;)Ljava/lang/String;", argName = "name")
|
||||
private String methodName;
|
||||
@Opt(opt = "cp", longOpt = "classpath", description = "", argName = "cp")
|
||||
private String classpath;
|
||||
|
||||
@Override
|
||||
protected void doCommandLine() throws Exception {
|
||||
if (remainingArgs.length != 1) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
File jar = new File(remainingArgs[0]);
|
||||
if (!jar.exists()) {
|
||||
System.err.println(jar + " is not exists");
|
||||
return;
|
||||
}
|
||||
if (methodName == null || methodOwner == null) {
|
||||
System.err.println("Please set --decrypt-method-owner and --decrypt-method-name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (output == null) {
|
||||
if (jar.isDirectory()) {
|
||||
output = new File(jar.getName() + "-decrypted.jar");
|
||||
} else {
|
||||
output = new File(FilenameUtils.getBaseName(jar.getName()) + "-decrypted.jar");
|
||||
}
|
||||
}
|
||||
|
||||
if (output.exists() && !forceOverwrite) {
|
||||
System.err.println(output + " exists, use --force to overwrite");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
if (classpath != null) {
|
||||
list.addAll(Arrays.asList(classpath.split(";|:")));
|
||||
}
|
||||
list.add(jar.getAbsolutePath());
|
||||
URL[] urls = new URL[list.size()];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
urls[i] = new File(list.get(i)).toURI().toURL();
|
||||
}
|
||||
final Method jmethod;
|
||||
try {
|
||||
URLClassLoader cl = new URLClassLoader(urls);
|
||||
jmethod = cl.loadClass(methodOwner).getMethod(methodName, String.class);
|
||||
jmethod.setAccessible(true);
|
||||
} catch (Exception ex) {
|
||||
System.err.println("can't load method: String " + methodOwner + "." + methodName + "(String), message:"
|
||||
+ ex.getMessage());
|
||||
return;
|
||||
}
|
||||
final String methodOwnerInternalType = this.methodOwner.replace('.', '/');
|
||||
final OutHandler fo = FileOut.create(output, true);
|
||||
try {
|
||||
new FileWalker().withStreamHandler(new StreamHandler() {
|
||||
|
||||
@Override
|
||||
public void handle(boolean isDir, String name, StreamOpener current, Object nameObject)
|
||||
throws IOException {
|
||||
if (isDir || !name.endsWith(".class")) {
|
||||
fo.write(isDir, name, current == null ? null : current.get(), nameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
ClassReader cr = new ClassReader(current.get());
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
for (Object m0 : cn.methods) {
|
||||
MethodNode m = (MethodNode) m0;
|
||||
if (m.instructions == null) {
|
||||
continue;
|
||||
}
|
||||
AbstractInsnNode p = m.instructions.getFirst();
|
||||
while (p != null) {
|
||||
if (p.getOpcode() == Opcodes.LDC) {
|
||||
LdcInsnNode ldc = (LdcInsnNode) p;
|
||||
if (ldc.cst instanceof String) {
|
||||
String v = (String) ldc.cst;
|
||||
AbstractInsnNode q = p.getNext();
|
||||
if (q.getOpcode() == Opcodes.INVOKESTATIC) {
|
||||
MethodInsnNode mn = (MethodInsnNode) q;
|
||||
if (mn.name.equals(methodName)
|
||||
&& mn.desc.equals("(Ljava/lang/String;)Ljava/lang/String;")
|
||||
&& mn.owner.equals(methodOwnerInternalType)) {
|
||||
try {
|
||||
Object newValue = jmethod.invoke(null, v);
|
||||
ldc.cst = newValue;
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
m.instructions.remove(q);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p = p.getNext();
|
||||
}
|
||||
}
|
||||
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
cn.accept(cw);
|
||||
fo.write(false, cr.getClassName() + ".class", cw.toByteArray(), null);
|
||||
}
|
||||
}).walk(jar);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fo);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,4 +18,5 @@ d2j-apk-sign=com.googlecode.dex2jar.tools.ApkSign
|
||||
d2j-init-deobf=com.googlecode.dex2jar.tools.DeObfInitCmd
|
||||
d2j-jar-remap=com.googlecode.dex2jar.tools.JarRemap
|
||||
d2j-jar-access=com.googlecode.dex2jar.tools.JarAccessCmd
|
||||
d2j-decrpyt-string=com.googlecode.dex2jar.tools.DecryptStringCmd
|
||||
#EOF
|
||||
|
Loading…
Reference in New Issue
Block a user