rizin icon indicating copy to clipboard operation
rizin copied to clipboard

Command `is` gives inaccurate information for methods in APK

Open haeter525 opened this issue 3 years ago • 1 comments

Hi, there. I recently found the is command gives incomplete return types for some methods in APKs. Since that information may mislead the user to incorrect classes, I think it could be considered an issue.

Work environment

Questions Answers
OS/arch/bits (mandatory) Ubuntu 22.04
File format of the file you reverse (mandatory) APK
Architecture/bits of the file (mandatory) Dalvik
rizin -v full output, not truncated (mandatory) rizin 0.4.0 @ linux-x86-64
commit: 0950e823a4502677cbf77cfd0266e8de64875fc0, build: 2022-05-30__05:44:10

Expected behavior

Command is gives the return type and parameters of a method in full.

Actual behavior

Command is truncates the return type or parameters of some methods.

For example, according to the dexs command, we find the method Lokhttp3/internal/platform/OptionalMethod; getMethod in this APK has a return type Ljava/lang/reflect/Method;.

[0x100041174]> dexs
...
    #1             : (in Lokhttp3/internal/platform/OptionalMethod;)
      name          : 'getMethod'
      type          : '(Ljava/lang/Class;)Ljava/lang/reflect/Method;'
      access        : 0x0002 (PRIVATE)
      method_idx    : 2768
      code          : (available)
...

However, command is shows that the method returns an object of reflect.Method.

[0x100041174]> is~2768
2768 0x000697c8 0x1000697c8  LOCAL  METH  66   okhttp3.internal.platform.OptionalMethod reflect.Method getMethod(Class)

The is command seems to remove the java.lang part from the return type. However, the binary may already have another class named reflect.Method.Thus, this inaccurate output might mislead the user to the incorrect one. I think it could be considered an issue.

Steps to reproduce the behavior

  • Open this sample with Rizin.
  • Run the following commands.
aaa
is~2768

haeter525 avatar May 30 '22 12:05 haeter525

After tracing the code, I found the issue probably originated from the Java demangler in rz_libdemangle. Moreover, it seems like the demangler tries to remove any "java/lang" strings from a mangled method.

Here is part of the code of the demangler (link). The full name of the method (the name, the arguments, and the return type) will be passed in as a string named mangled. And we can see the deletion behavior in line 274 below.

char *libdemangle_handler_java(const char *mangled) {
	if (!mangled) {
		return NULL;
	}

	char *name = NULL;
	char *arguments = NULL;
	char *return_type = NULL;

	name = strdup(mangled);
	if (!name) {
		return NULL;
	}

	name = dem_str_replace(name, "java/lang/", "", 1);     // <--- Line 274
	if ((arguments = strchr(name, '(')) && (return_type = strchr(arguments, ')'))) {
		return demangle_method(name, arguments, return_type);
	} else if (name[0] == 'L' && (arguments = strchr(name, '.'))) {
		return demangle_class_object(name, arguments);
	} else if ((arguments = strchr(name, '.'))) {
		return demangle_object_with_type(name, arguments);
	}
	return demangle_any(name);
}

Besides, after using gdb, I also confirm that the issue happened in this function.

haeter525 avatar Jul 07 '22 10:07 haeter525

@haeter525 this should be fixed, right?

wargio avatar Oct 07 '22 16:10 wargio

@wargio Yes. Fixed in v0.4.1. I'm going to close this issue. Thanks!

haeter525 avatar Oct 10 '22 15:10 haeter525