下面列出了org.objectweb.asm.Opcodes# LDC 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public LoadIntStep() {
super((a) ->
{
if(!(a instanceof LdcInsnNode))
return true;
return ((LdcInsnNode)a).cst instanceof Integer;
},Opcodes.ICONST_M1,
Opcodes.ICONST_0,
Opcodes.ICONST_1,
Opcodes.ICONST_2,
Opcodes.ICONST_3,
Opcodes.ICONST_4,
Opcodes.ICONST_5,
Opcodes.LDC,
Opcodes.BIPUSH,
Opcodes.SIPUSH
);
}
@Override
public boolean isConstant() {
switch (opcode) {
case Opcodes.ACONST_NULL:
case Opcodes.ICONST_0:
case Opcodes.ICONST_1:
case Opcodes.ICONST_2:
case Opcodes.ICONST_3:
case Opcodes.ICONST_4:
case Opcodes.ICONST_5:
case Opcodes.ICONST_M1:
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.FCONST_2:
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
case Opcodes.LCONST_0:
case Opcodes.LCONST_1:
case Opcodes.LDC:
return true;
}
return super.isConstant();
}
private static void checkSimpleDateFormat(ClassContext context, MethodNode method,
MethodInsnNode node, int minSdk) {
if (minSdk >= 9) {
// Already OK
return;
}
if (node.name.equals(CONSTRUCTOR_NAME) && !node.desc.equals("()V")) { //$NON-NLS-1$
// Check first argument
AbstractInsnNode prev = LintUtils.getPrevInstruction(node);
if (prev != null && !node.desc.equals("(Ljava/lang/String;)V")) { //$NON-NLS-1$
prev = LintUtils.getPrevInstruction(prev);
}
if (prev != null && prev.getOpcode() == Opcodes.LDC) {
LdcInsnNode ldc = (LdcInsnNode) prev;
Object cst = ldc.cst;
if (cst instanceof String) {
String pattern = (String) cst;
boolean isEscaped = false;
for (int i = 0; i < pattern.length(); i++) {
char c = pattern.charAt(i);
if (c == '\'') {
isEscaped = !isEscaped;
} else if (!isEscaped && (c == 'L' || c == 'c')) {
String message = String.format(
"The pattern character '%1$c' requires API level 9 (current " +
"min is %2$d) : \"`%3$s`\"", c, minSdk, pattern);
report(context, message, node, method, pattern, null,
SearchHints.create(FORWARD));
return;
}
}
}
}
}
}
private boolean isEqual(AbstractInsnNode ain)
{
if(ain.getNext() == null)
return false;
if(ain.getOpcode() == Opcodes.LDC && ain.getNext().getOpcode() == Opcodes.LDC
&& ((LdcInsnNode)ain).cst.equals(((LdcInsnNode)ain.getNext()).cst))
return true;
if(ain.getOpcode() >= Opcodes.ILOAD && ain.getOpcode() <= Opcodes.ALOAD
&& ain.getNext().getOpcode() == ain.getOpcode()
&& ((VarInsnNode)ain).var == ((VarInsnNode)ain.getNext()).var)
return true;
return false;
}
private boolean willPush(AbstractInsnNode ain)
{
if(ain.getOpcode() == Opcodes.LDC && (((LdcInsnNode)ain).cst instanceof Long || ((LdcInsnNode)ain).cst instanceof Double))
return false;
return (Utils.willPushToStack(ain.getOpcode()) || ain.getOpcode() == Opcodes.NEW) && ain.getOpcode() != Opcodes.GETSTATIC
&& ain.getOpcode() != Opcodes.LLOAD && ain.getOpcode() != Opcodes.DLOAD;
}
private boolean willPush(AbstractInsnNode ain)
{
if(ain.getOpcode() == Opcodes.LDC && (((LdcInsnNode)ain).cst instanceof Long || ((LdcInsnNode)ain).cst instanceof Double))
return false;
return (Utils.willPushToStack(ain.getOpcode()) || ain.getOpcode() == Opcodes.NEW) && ain.getOpcode() != Opcodes.GETSTATIC
&& ain.getOpcode() != Opcodes.LLOAD && ain.getOpcode() != Opcodes.DLOAD;
}
private boolean willPush2(AbstractInsnNode ain)
{
return ain.getOpcode() == Opcodes.LCONST_0 || ain.getOpcode() == Opcodes.LCONST_1
|| ain.getOpcode() == Opcodes.DCONST_0 || ain.getOpcode() == Opcodes.DCONST_1
|| (ain.getOpcode() == Opcodes.LDC &&
(((LdcInsnNode)ain).cst instanceof Long || ((LdcInsnNode)ain).cst instanceof Double))
|| ain.getOpcode() == Opcodes.LLOAD || ain.getOpcode() == Opcodes.DLOAD;
}
private boolean willPush(AbstractInsnNode ain)
{
if(ain.getOpcode() == Opcodes.LDC && (((LdcInsnNode)ain).cst instanceof Long || ((LdcInsnNode)ain).cst instanceof Double))
return false;
return Utils.willPushToStack(ain.getOpcode()) && ain.getOpcode() != Opcodes.GETSTATIC
&& ain.getOpcode() != Opcodes.LLOAD && ain.getOpcode() != Opcodes.DLOAD;
}
public static boolean isArg(Instruction instr) {
if (instr instanceof ArithmeticExpression) {
return true;
}
if (instr instanceof AssignableExpression) {
StringBuilder dummy = new StringBuilder();
if (((AssignableExpression)instr).assignTo(null, dummy)) {
return true;
}
}
int opcode = instr.getOpcode();
switch (opcode) {
case Opcodes.FLOAD:
case Opcodes.DLOAD:
case Opcodes.ILOAD:
case Opcodes.LLOAD:
case org.objectweb.asm.Opcodes.ICONST_0:
case org.objectweb.asm.Opcodes.ICONST_1:
case org.objectweb.asm.Opcodes.ICONST_2:
case org.objectweb.asm.Opcodes.ICONST_3:
case org.objectweb.asm.Opcodes.ICONST_4:
case org.objectweb.asm.Opcodes.ICONST_5:
case org.objectweb.asm.Opcodes.ICONST_M1:
case org.objectweb.asm.Opcodes.LCONST_0:
case org.objectweb.asm.Opcodes.LCONST_1:
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.FCONST_2:
case org.objectweb.asm.Opcodes.BIPUSH:
case org.objectweb.asm.Opcodes.SIPUSH:
case Opcodes.LDC:
return true;
}
return false;
}
public InsnValue createConstant(AbstractInsnNode insn) throws AnalyzerException {
switch (insn.getOpcode()) {
case Opcodes.ACONST_NULL:
return InsnValue.NULL_REFERENCE_VALUE;
case Opcodes.ICONST_M1:
case Opcodes.ICONST_0:
case Opcodes.ICONST_1:
case Opcodes.ICONST_2:
case Opcodes.ICONST_3:
case Opcodes.ICONST_4:
case Opcodes.ICONST_5:
case Opcodes.BIPUSH:
case Opcodes.SIPUSH:
return InsnValue.intValue(insn);
case Opcodes.LCONST_0:
case Opcodes.LCONST_1:
return InsnValue.longValue(insn.getOpcode());
case Opcodes.FCONST_0:
case Opcodes.FCONST_1:
case Opcodes.FCONST_2:
return InsnValue.floatValue(insn.getOpcode());
case Opcodes.DCONST_0:
case Opcodes.DCONST_1:
return InsnValue.doubleValue(insn.getOpcode());
case Opcodes.LDC:
Object obj = ((LdcInsnNode) insn).cst;
if (obj instanceof Type) {
return new InsnValue((Type) obj);
} else {
Type t = Type.getType(obj.getClass());
int sort = t.getSort();
// Non-included types:
// Type.ARRAY
// Type.VOID
// Type.METHOD
switch (sort) {
case Type.BOOLEAN:
return InsnValue.intValue((int) obj);
case Type.CHAR:
return InsnValue.charValue((char) obj);
case Type.BYTE:
return InsnValue.byteValue((byte) obj);
case Type.SHORT:
return InsnValue.shortValue((short) obj);
case Type.INT:
return InsnValue.intValue((int) obj);
case Type.FLOAT:
return InsnValue.floatValue((float) obj);
case Type.LONG:
return InsnValue.longValue((long) obj);
case Type.DOUBLE:
return InsnValue.doubleValue((double) obj);
case Type.OBJECT:
return new InsnValue(t, obj);
}
return new InsnValue(t);
}
case Opcodes.NEW:
return new InsnValue(Type.getType(((TypeInsnNode) insn).desc));
case Opcodes.JSR:
// TODO: IDK if this is right.
return InsnValue.REFERENCE_VALUE;
}
return null;
}
public LdcInsnNode() {
super(Opcodes.LDC);
this.cst = "";
}
@Override
public boolean transform() throws Throwable {
DelegatingProvider provider = new DelegatingProvider();
provider.register(new JVMMethodProvider());
provider.register(new JVMComparisonProvider());
provider.register(new MappedMethodProvider(classes));
provider.register(new MappedFieldProvider());
AtomicInteger count = new AtomicInteger();
Set<MethodNode> decryptor = new HashSet<>();
System.out.println("[Smoke] [StringEncryptionTransformer] Starting");
for(ClassNode classNode : classes.values())
for(MethodNode method : classNode.methods)
{
InstructionModifier modifier = new InstructionModifier();
Frame<SourceValue>[] frames;
try
{
frames = new Analyzer<>(new SourceInterpreter()).analyze(classNode.name, method);
}catch(AnalyzerException e)
{
oops("unexpected analyzer exception", e);
continue;
}
for(AbstractInsnNode ain : TransformerHelper.instructionIterator(method))
if(ain instanceof MethodInsnNode)
{
MethodInsnNode m = (MethodInsnNode)ain;
String strCl = m.owner;
if(m.desc.equals("(Ljava/lang/String;I)Ljava/lang/String;"))
{
Frame<SourceValue> f = frames[method.instructions.indexOf(m)];
if(f.getStack(f.getStackSize() - 2).insns.size() != 1
|| f.getStack(f.getStackSize() - 1).insns.size() != 1)
continue;
AbstractInsnNode a1 = f.getStack(f.getStackSize() - 2).insns.iterator().next();
AbstractInsnNode a2 = f.getStack(f.getStackSize() - 1).insns.iterator().next();
if(a1.getOpcode() != Opcodes.LDC || !Utils.isInteger(a2))
continue;
Object obfString = ((LdcInsnNode)a1).cst;
int number = Utils.getIntValue(a2);
Context context = new Context(provider);
if(classes.containsKey(strCl))
{
ClassNode innerClassNode = classes.get(strCl);
MethodNode decrypterNode = innerClassNode.methods.stream().filter(mn -> mn.name.equals(m.name) && mn.desc.equals(m.desc)).findFirst().orElse(null);
if(isSmokeMethod(decrypterNode))
{
String value = MethodExecutor.execute(classNode, decrypterNode, Arrays.asList(JavaValue.valueOf(obfString), new JavaInteger(number)), null, context);
modifier.remove(a2);
modifier.remove(a1);
modifier.replace(m, new LdcInsnNode(value));
decryptor.add(decrypterNode);
count.getAndIncrement();
}
}
}
}
modifier.apply(method);
}
System.out.println("[Smoke] [StringEncryptionTransformer] Decrypted " + count + " encrypted strings");
System.out.println("[Smoke] [StringEncryptionTransformer] Removed " + cleanup(decryptor) + " decryption methods");
System.out.println("[Smoke] [StringEncryptionTransformer] Done");
return true;
}
private static void overclockServer(ClassNode node, boolean isObfuscated)
{
// We're attempting to replace this code (from the heart of MinecraftServer.run):
/*
{
while (i > 50L)
{
i -= 50L;
this.tick();
}
}
Thread.sleep(Math.max(1L, 50L - i));
*/
// With this:
/*
{
while (i > TimeHelper.serverTickLength)
{
i -= TimeHelper.serverTickLength;
this.tick();
}
}
Thread.sleep(Math.max(1L, TimeHelper.serverTickLength - i));
*/
// This allows us to alter the tick length via TimeHelper.
final String methodName = "run";
final String methodDescriptor = "()V"; // No params, returns void.
System.out.println("MALMO: Found MinecraftServer, attempting to transform it");
for (MethodNode method : node.methods)
{
if (method.name.equals(methodName) && method.desc.equals(methodDescriptor))
{
System.out.println("MALMO: Found MinecraftServer.run() method, attempting to transform it");
for (AbstractInsnNode instruction : method.instructions.toArray())
{
if (instruction.getOpcode() == Opcodes.LDC)
{
Object cst = ((LdcInsnNode)instruction).cst;
if ((cst instanceof Long) && (Long)cst == 50)
{
System.out.println("MALMO: Transforming LDC");
AbstractInsnNode replacement = new FieldInsnNode(Opcodes.GETSTATIC, "com/microsoft/Malmo/Utils/TimeHelper", "serverTickLength", "J");
method.instructions.set(instruction, replacement);
}
}
}
}
}
}
public Ldc(Object o) {
super(Opcodes.LDC);
cst = o;
}
/**
* Constructs a new {@link LdcInsnNode}.
*
* @param value
* the constant to be loaded on the stack. This parameter must be a non null {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object value) {
super(Opcodes.LDC);
this.cst = value;
}
/**
* Constructs a new {@link LdcInsnNode}.
*
* @param value the constant to be loaded on the stack. This parameter must be a non null {@link
* Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object value) {
super(Opcodes.LDC);
this.cst = value;
}
/**
* Constructs a new {@link LdcInsnNode}.
*
* @param cst
* the constant to be loaded on the stack. This parameter must be a
* non null {@link Integer}, a {@link Float}, a {@link Long}, a
* {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object cst) {
super(Opcodes.LDC);
this.cst = cst;
}
/**
* Constructs a new {@link LdcInsnNode}.
*
* @param value the constant to be loaded on the stack. This parameter must be a non null {@link
* Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object value) {
super(Opcodes.LDC);
this.cst = value;
}
/**
* Constructs a new {@link LdcInsnNode}.
*
* @param value the constant to be loaded on the stack. This parameter must be a non null {@link
* Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object value) {
super(Opcodes.LDC);
this.cst = value;
}