I am trying to replace a certain class file with my own in an obfuscated jar. The original class file has methods named "new" and "null" so a quick decompile + compile doesn't work.
I tried compiling and using jbe to add new methods named "new" that relayed everything to "new_symbol" functions (with new_symbol beeing the decompiled version of the original "new" function).
This did not work. ("code segment has wrong length in class file")
Does anyone know of a way to refractor method names in class files? And if that isn't possible, a way to reliably create those "proxy functions"?
From google I learned that there are about 1000+ different backend library's but only jbe as fronted for bytecode editing?
EDIT:
Let me try to illustrate it.
Let's say that there is a jar file with a class that provides a function that logs everything you give it to a database.
I'd like to replace that class file with my own, and it should not only log everything to a database, but also print whatever data it gets to the command line.
The problem is, that class file was obfuscated and the obfuscator gave it public method names like "new" or "null". If you try:
public class replacement{
public void new (string data){
...
}
}
And compile that, you get compilation errors.
My idea was to create this :
public class replacement{
public void newsymbol (string data){
...
}
}
And use a bytecode editor to create a function named "new" that calls "newsymbol" with the same arguments. (but I get "code segment wrong length" and other errors going down this route.
My question therefore could be better frased as "give me a way to intercept calls to a class file who's public methods are named "new" "null" "weird_unicode_symbols""....
Scala allows you to use identifiers in names if you surround them by `.
class f{
def `new`():Int = {
return 3
}
}
jd-gui output
import scala.reflect.ScalaSignature;
#ScalaSignature(bytes=/* snip */)
public class f
{
public int jdMethod_new()
{
return 3;
}
}
I assume that jdMethod_ is prefixed in order to make the identifier valid. There is no jdMethod_ when looking at the class file using a hex editor.
However, this does have a flaw when you need to use public fields; scalac never generates public fields, it always makes them private and creates accessors.
So, what turned out to be the best solution for me was to use a hex editor (as suggested by user60561).
Apparantly, the name of every function and field is only saved once in the class file so if you use names with the same amount of bytes you can hexedit your way to victory.
For me it came down to replacing "new" by "abc" and every strange unicode character with a two-char sequence.
Thanks for all the suggestions.
Related
I am developing springboot with GraphQL. Since the data structure is already declared within Protobuf, I tried to use it. This is example of my code.
#Service
public class Query implements GraphQLQueryResolver {
public MyProto getMyProto() {
/**/
}
}
I want make code like upper structure. To to this, I divided job into 2 sections.
Since ".proto file" can be converted to java class, I will use this class as return type.
And The second section is a main matter.
Also Schema is required. At first, I tried to code schema with my hand. But, the real size of proto is about 1000 lines. So, I want to know Is there any way to convert ".proto file" to ".graphqls file".
There is a way. I am using the a protoc plugin for that purpose: go-proto-gql
It is fairly simple to be used, for example:
protoc --gql_out=paths=source_relative:. -I=. ./*.proto
Hope this is working for you as well.
I am new to programming, so let's see if I can explain this well enough.
I am making a Java package. In one of the classes there is a method that creates a file. The name of that file I have it set up as "file.txt", but I want to change it.
Let's say there is a user working on a new project and he imports the library package (the one I am working on). I want for the file that is created to take the name of the class in which the user is working on. For example if the user calls it in a class named Main, I want the file to be called main.txt or Main.txt.
If this is not clear enough please let me know, I'll try to explain it better.
Thanks
Edit: I've tried the getClass().getSimpleName() but it's not working exactly like I want it to. The method is located inside a library called library and the class is called Main.class but is being used by a use that imported the library library and is working on a class called SuperMario.class I want the text file to be called SuperMario.txt instead with getClass().getSimpleName() applied to my method the file will be called Main.txt, because that is the name of the class the method is in. Unfortunately I can't have the method pass the name as a parameter. Can anyone think of a way around this?
In your library, use stacktrace :
public class Called {
public static void calledMethod() {
System.out.println(Thread.currentThread().getStackTrace()[2].getClassName());
// stackTrace 0 is get stack trace.
// stack trace 1 is calledMethod
// stack trace 2 is the calling method aka main in
}
}
The result will be
eu.plop.test.TestClass
You had to search after stacktrace to see if you want the filename, class name, method's name... and then some string works to remove the package if unused.
Java has a build in content types detector, however, it misses some filetypes naturally.
Files.probeContentType(new File(".ttf").toPath());
It appears as if the implementation allows one to add more FileTypeDetectors but I cannot figure out how.
Reference:
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType(java.nio.file.Path)
http://docs.oracle.com/javase/7/docs/api/java/nio/file/spi/FileTypeDetector.html
So how can one add more files to be probed?
On another note, do you consider Javas File.proveContentType to be effecient? Not only does one whas to create a Path object, but it also seems to iterate over these each time. I guess a caching mechanism would be required on top.
To install your own FileTypeDetector you first create your own implementation:
public class MyFileTypeDetector extends java.nio.file.spi.FileTypeDetector {
public String probeContentType(Path path) throws IOException {
return ...
}
}
Then second you add a file /META-INF/services/java.nio.file.spi.FileTypeDetector to the jar which contains your implementation: Its content is the qualified class name of your implementation:
org.example.MyFileTypeDetector
To help solve another problem I have, I'm testing the following code in the postGenerationProcess event of the POI Word widget:
var jce:writeXWPFDocument = new writeXWPFDocument();
var newString3 = jce.doSomething3(xwpfdocument);
print("newString3 = " + newString3);
doSomething3 is defined in a Java class contained in the .nsf.
public class writeXWPFDocument {
public String doSomething3(XWPFDocument xwpfdocument) {
return "DO SOMETHING - xwpfdocument";
}}
When I run this code, I get the error:
Java method 'doSomething3(org.apache.poi.xwpf.usermodel.XWPFDocument)'
on java class 'AZGPackage.writeXWPFDocument' not found
What could be causing this error?
#Knut Hermann - this is a test which relates to the other problem you have been helping me with.
Edit to make the correct answer easier to find:
I have used poi in a few applications. I've encountered similar problems twice: First, usually when I accidentally import a class with the same name from the wrong package (like lotus.local.domino.Database instead of lotus.domino.Database). The other time I encountered this (and the only time the package name was identical) was when I had poi in a plug-in that I had added to the build path and also had it installed by a poi extension library I had built. If you can't cast an object as itself, there is an issue with the ClassLoader, and I don't know what would cause that other than a class being listed twice.
SSJS seems to pass a different object type to the function. Try to change the class of the parameter to Object and for testing return the class name.
In a production code you could check with instanceof if the parameter has the right data type.
In General: consider using a facade pattern, so you keep your complex Java classes away from SSJS
I'm using Java Compiler API to compile in-memory classes. That is, classes are compiled to bytecode (no .classes files stored in disk) and then loaded by reconstructing the bytecode.
Sometimes, I need to compile a class that depends on another, also in-memory compiled, class. For instance: Compile Class A, then compile Class B which depends on Class A.
To solve this, I pass both Class A and Class B as the compilation units needed by the getTask method of the compiler API.
However, I really don't like this solution, as it makes me recompile Class A which was already compiled.
Is there a way to get around this?
EDIT: I found a solution through this link: http://www.ibm.com/developerworks/java/library/j-jcomp/index.html
Yes, this is totally possible as long as you properly implement the ForwardingJavaFileManager. The two most important methods are inferBinaryName() and list(). If you set these two up properly, the compiler will be able to resolve classes that you've previously compiled.
inferBinaryName() must return the class' simple name (e.g. the inferred binary name for com.test.Test would be just Test). Here is my implementation (my subclass of JavaFileObject is called InAppJavaFileObject):
#Override
public String inferBinaryName(Location location, JavaFileObject javaFileObject) {
if(location == StandardLocation.CLASS_PATH && javaFileObject instanceof InAppJavaFileObject) {
return StringUtils.substringBeforeLast(javaFileObject.getName(), ".java");
}
return super.inferBinaryName(location, javaFileObject);
}
Note that I'm stripping off ".java" from the end. When constructing a JavaFileObject, the file name must end in ".java", but if you don't strip the suffix later, the compiler won't find your class.
list() is a little bit more complicated because you have to be careful to play along nicely with your delegate file manager. In my implementation, I keep a map of fully-qualified class name to my subclass of JavaFileObject that I can iterate over:
#Override
public Iterable<JavaFileObject> list(Location action, String pkg, Set<JavaFileObject.Kind> kind, boolean recurse) throws IOException {
Iterable<JavaFileObject> superFiles = super.list(action, pkg, kind, recurse);
// see if there's anything in our cache that matches the criteria.
if(action == StandardLocation.CLASS_PATH && (kind.contains(JavaFileObject.Kind.CLASS) || kind.contains(JavaFileObject.Kind.SOURCE))) {
List<JavaFileObject> ourFiles = new ArrayList<JavaFileObject>();
for(Map.Entry<String,InAppJavaFileObject> entry : files.entrySet()) {
String className = entry.getKey();
if(className.startsWith(pkg) && ("".equals(pkg) || pkg.equals(className.substring(0, className.lastIndexOf('.'))))) {
ourFiles.add(entry.getValue());
}
}
if(ourFiles.size() > 0) {
for(JavaFileObject javaFileObject : superFiles) {
ourFiles.add(javaFileObject);
}
return ourFiles;
}
}
// nothing found in our hash map that matches the criteria... return
// whatever super came up with.
return superFiles;
}
Once you have those methods properly implemented, the rest just works. Enjoy!
That leads to the obvious question of why you want to compile class A separately first. Why not just compile everything in one go?
How if you maintain the modified time of the files and the (in-memory) compiled byte code?
I don't think you can avoid compiling both classes. In fact, if you don't compile both of them, there is a chance that you will end up with binary compatibility problems, or problems with incorrect inlined constants.
This is essentially the same problem as you'd get if you compiled one class and not the other from the command line.
But to be honest, I wouldn't worry about trying to optimize the compilation like that. (And if your application needs to be able to dynamically compile one class and not the other, it has probably has significant design issues.)