The Bytecode Club
Some anti-debugging stuff for Java - Printable Version

+- The Bytecode Club (https://the.bytecode.club)
+-- Forum: Lobby (https://the.bytecode.club/forumdisplay.php?fid=1)
+--- Forum: Programming (https://the.bytecode.club/forumdisplay.php?fid=86)
+--- Thread: Some anti-debugging stuff for Java (/showthread.php?tid=288)



Some anti-debugging stuff for Java - bloo - 01-11-2015

Checking launch args:
Code:
public static void checkLaunchArgs() {
List<String> launchArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
for (String s : launchArgs) {
if (s.startsWith("-Xbootclasspath") || s.startsWith("-Xdebug") || s.startsWith("-agentlib")
|| s.startsWith("-javaagent:") || s.startsWith("-Xrunjdwp:") || s.startsWith("-verbose")) {
System.exit(0);
}
}
}
Freezing VisualVM upon contact (kinda funny, you'll need an agent for this though):
Code:
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    if ("com/sun/jmx/remote/util/ClassLogger".equals(className)) {
      System.exit(0);
    }
    return classfileBuffer;
  }
I don't know if the Visual VM one works on other operating systems, tested on Java 7 with Windows 8.1

If you can manage to get your hands on an OS appropriate Attach native library at runtime (attach.dll, attach.so), it makes for some nice malware. Tongue

Killing off ClassFileTransformers the reverser may have attached by using your own (might vary, it's likely):
Code:
public static void transformerCheck(Instrumentation inst, ClassFileTransformer... transformers) {
    Class<? extends Instrumentation> instClass = inst.getClass();
    Class<?>[] c = new Class<?>[2];
    Field[] f = new Field[3];
    a: for (Field field : instClass.getDeclaredFields()) {
      Class<?> fieldType = field.getType();
if (!fieldType.isPrimitive()) {
for (Field field1 : fieldType.getDeclaredFields()) {
if (field1.getType().isArray()) {
Class<?> arrayType = field1.getType().getComponentType();
            for (Field field2 : arrayType.getDeclaredFields()) {
              if (field2.getType().isAssignableFrom(ClassFileTransformer.class)) {
                c[0] = fieldType;
                c[1] = arrayType;
                f[0] = field;
                f[1] = field1;
                f[2] = field2;
                break a;
              }
            }
          }
        }
      }
    }
    try {
      for (Field f1 : f) {
        f1.setAccessible(true);
      }
      Object[] o = (Object[]) f[1].get(f[0].get(inst));
      ClassFileTransformer[] loaded = new ClassFileTransformer[o.length];

      for (int i = 0; i < loaded.length; i++) {
        loaded[i] = (ClassFileTransformer) f[2].get(o[i]);
      }
      for (int i = 0; i < loaded.length; i++) {
        for (int i1 = 0; i1 < loaded.length; i1++) {
          if (i1 == i) {
            continue;
          }
          if (loaded[i] == loaded[i1]) {
            loaded[i] = null;
            break;
          }
        }
      }
      int numLoaded = 0;
      for (int i = 0; i < loaded.length; i++) {
        if (loaded[i] == null) {
          o[i] = null;
        } else {
          numLoaded++;
        }
      }

      Object[] oNew = (Object[]) Array.newInstance(c[1], numLoaded);
      for (int i = 0, i1 = i; i < o.length; i++) {
        if (o[i] != null) {
          oNew[i1] = o[i];
          i1++;
        }
      }
      f[1].set(f[0].get(inst), oNew);
      
      loaded = new ClassFileTransformer[oNew.length];

      for (int i = 0; i < loaded.length; i++) {
        loaded[i] = (ClassFileTransformer) f[2].get(oNew[i]);
      }
      
      if (transformers.length == loaded.length) {
        for (int i = 0; i < loaded.length; i++) {
          if (transformers[i] != loaded[i]) {
            System.exit(0);
          }
        }
      } else {
        System.exit(0);
      }
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }
  }
where "transformers" is an array of all the ones that are SUPPOSED to be attached (i.e. your own, not theirs)


RE: Some anti-debugging stuff for Java - Konloch - 01-11-2015

(01-11-2015, 08:13 AM)bloo Wrote:  Checking launch args:
Code:
public static void checkLaunchArgs() {
List<String> launchArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
for (String s : launchArgs) {
if (s.startsWith("-Xbootclasspath") || s.startsWith("-Xdebug") || s.startsWith("-agentlib")
|| s.startsWith("-javaagent:") || s.startsWith("-Xrunjdwp:") || s.startsWith("-verbose")) {
System.exit(0);
}
}
}
Freezing VisualVM upon contact (kinda funny, you'll need an agent for this though):
Code:
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    if ("com/sun/jmx/remote/util/ClassLogger".equals(className)) {
      System.exit(0);
    }
    return classfileBuffer;
  }
I don't know if the Visual VM one works on other operating systems, tested on Java 7 with Windows 8.1

If you can manage to get your hands on an OS appropriate Attach native library at runtime (attach.dll, attach.so), it makes for some nice malware. Tongue

Killing off ClassFileTransformers the reverser may have attached by using your own (might vary, it's likely):
Code:
public static void transformerCheck(Instrumentation inst, ClassFileTransformer... transformers) {
    Class<? extends Instrumentation> instClass = inst.getClass();
    Class<?>[] c = new Class<?>[2];
    Field[] f = new Field[3];
    a: for (Field field : instClass.getDeclaredFields()) {
      Class<?> fieldType = field.getType();
if (!fieldType.isPrimitive()) {
for (Field field1 : fieldType.getDeclaredFields()) {
if (field1.getType().isArray()) {
Class<?> arrayType = field1.getType().getComponentType();
            for (Field field2 : arrayType.getDeclaredFields()) {
              if (field2.getType().isAssignableFrom(ClassFileTransformer.class)) {
                c[0] = fieldType;
                c[1] = arrayType;
                f[0] = field;
                f[1] = field1;
                f[2] = field2;
                break a;
              }
            }
          }
        }
      }
    }
    try {
      for (Field f1 : f) {
        f1.setAccessible(true);
      }
      Object[] o = (Object[]) f[1].get(f[0].get(inst));
      ClassFileTransformer[] loaded = new ClassFileTransformer[o.length];

      for (int i = 0; i < loaded.length; i++) {
        loaded[i] = (ClassFileTransformer) f[2].get(o[i]);
      }
      for (int i = 0; i < loaded.length; i++) {
        for (int i1 = 0; i1 < loaded.length; i1++) {
          if (i1 == i) {
            continue;
          }
          if (loaded[i] == loaded[i1]) {
            loaded[i] = null;
            break;
          }
        }
      }
      int numLoaded = 0;
      for (int i = 0; i < loaded.length; i++) {
        if (loaded[i] == null) {
          o[i] = null;
        } else {
          numLoaded++;
        }
      }

      Object[] oNew = (Object[]) Array.newInstance(c[1], numLoaded);
      for (int i = 0, i1 = i; i < o.length; i++) {
        if (o[i] != null) {
          oNew[i1] = o[i];
          i1++;
        }
      }
      f[1].set(f[0].get(inst), oNew);
      
      loaded = new ClassFileTransformer[oNew.length];

      for (int i = 0; i < loaded.length; i++) {
        loaded[i] = (ClassFileTransformer) f[2].get(oNew[i]);
      }
      
      if (transformers.length == loaded.length) {
        for (int i = 0; i < loaded.length; i++) {
          if (transformers[i] != loaded[i]) {
            System.exit(0);
          }
        }
      } else {
        System.exit(0);
      }
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }
  }
where "transformers" is an array of all the ones that are SUPPOSED to be attached (i.e. your own, not theirs)

Now this is very sexy! Thanks for this share.


RE: Some anti-debugging stuff for Java - bloo - 01-11-2015

Forgot about this one, though it's simple, it can be rather annoying when scattered around randomly.
Instruction Stepping:
Code:
long s = System.nanoTime();
if (System.nanoTime() - s > 100000) {
System.exit(0);
}
Obviously this should be in somewhere that's not going to be lagging. 100000 nanoseconds is a bit of a stretch for 3 instructions to process, since System.nanoTime() calls should be pretty fast. Tongue


RE: Some anti-debugging stuff for Java - Bibl - 01-11-2015

what, this is useless. i can just edit the jar and run. who in 2k15 even uses agents anyway


RE: Some anti-debugging stuff for Java - zooty - 01-11-2015

(01-11-2015, 09:05 AM)Bibl Wrote:  what, this is useless. i can just edit the jar and run. who in 2k15 even uses agents anyway

stops skids tho


RE: Some anti-debugging stuff for Java - Bibl - 01-11-2015

i dont want to decrease program performance by adding unmaintainable time checks to stop ddong from copy 3 lines of my killaura tho


RE: Some anti-debugging stuff for Java - bloo - 01-11-2015

(01-11-2015, 10:49 AM)Bibl Wrote:  i dont want to decrease program performance by adding unmaintainable time checks to stop ddong from copy 3 lines of my killaura tho

If you were doing this just for a hacked client, I'd say fuck the agent and just put the other two checks in arbitrary places. The stepper check shouldn't decrease much in performance if it's not called every MS. And who the hell sees a call to System.nanoTime() somewhere arbitrary in obfuscated code and scrutinizes it?