Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Get annotations for methods #949

Open
12345qwert123456 opened this issue Sep 26, 2023 · 2 comments
Open

Question: Get annotations for methods #949

12345qwert123456 opened this issue Sep 26, 2023 · 2 comments

Comments

@12345qwert123456
Copy link

12345qwert123456 commented Sep 26, 2023

I'm trying to get annotations of methods that retrofit2 uses.
Here is an example code that was obtained using jadx-gui.

.method public abstract authAsync(Ljava/lang/String;)Lkotlinx/coroutines/Deferred;
    .annotation runtime Lretrofit2/http/Headers;
        value = {
            "Content-Type:application/json; charset=utf-8"
        }
    .end annotation
    
    .annotation runtime Lretrofit2/http/POST;
        value = "/api/auth"
    .end annotation
    
    .annotation build Lorg/jetbrains/annotations/NotNull;
    .end annotation

.end method

But I can't figure out how to get something similar using androguard.

>>> type(i)
<class 'androguard.core.analysis.analysis.ClassAnalysis'>
>>> i.get_methods()[0].get_method()
<androguard.core.bytecodes.dvm.EncodedMethod object at 0x0000025728DCBB10>
>>> i.get_methods()[0].get_method().get_information()
{}
>>> i.get_methods()[0].get_method().source()
public abstract kotlinx.coroutines.Deferred authAsync();
>>> i.get_methods()[0].get_method().get_instructions()
[]

I tried using the code from #175, but dvm.map_list.get_item_type("TYPE_ANNOTATIONS_DIRECTORY_ITEM") always return None.
Are there any methods to get annotation?

@ehrenb
Copy link
Contributor

ehrenb commented Jan 7, 2024

I think this is confusing because in the docstring, MapList.get_item_type(ttype) describes a string input for ttype, whereas it actually takes in a dex_types.TypeMapItem enum.

Try replacing:

dvm.map_list.get_item_type("TYPE_ANNOTATIONS_DIRECTORY_ITEM")

with:

from androguard.core.dex import (
        TypeMapItem)
...
dvm.map_list.get_item_type(TypeMapItem.ANNOTATIONS_DIRECTORY_ITEM)
...

Example:

from androguard.misc import AnalyzeAPK
from androguard.core.dex import (
        TypeMapItem)

fpath = 'tests/data/APK/TestActivity.apk'

a,d,dx = AnalyzeAPK(fpath)

for dvm in d:
    for adi in dvm.map_list.get_item_type(TypeMapItem.ANNOTATIONS_DIRECTORY_ITEM):
        if adi.get_method_annotations() == []:
            continue

        # Each annotations_directory_item contains many method_annotation
        for mi in adi.get_method_annotations():
            print(repr(dvm.get_method_by_idx(mi.get_method_idx())))

            # Each method_annotation stores an offset to annotation_set_item
            ann_set_item = dvm.CM.get_obj_by_offset(mi.get_annotations_off())

            # a annotation_set_item has an array of annotation_off_item
            for aoffitem in ann_set_item.get_annotation_off_item():

                # The annotation_off_item stores the offset to an annotation_item
                annotation_item = dvm.CM.get_obj_by_offset(aoffitem.get_annotation_off())

                # The annotation_item stores the visibility and a encoded_annotation
                # this encoded_annotation stores the type IDX, and an array of
                # annotation_element
                # these are again name idx and encoded_value's

                encoded_annotation = annotation_item.get_annotation()

                # Print the class type of the annotation
                print("@{}".format(dvm.CM.get_type(encoded_annotation.get_type_idx())))
                
                for annotation_element in encoded_annotation.get_elements():
                    print("   {} = {}".format(
                        dvm.CM.get_string(annotation_element.get_name_idx()),
                        # Read the EncodedValue and then the real value - which is again some object...
                        annotation_element.get_value().get_value(),
                        ))


            print()

output snippet

...
<androguard.core.dex.EncodedMethod object at 0x7fdee62dfb80>
@Ldalvik/annotation/Throws;
   value = <androguard.core.dex.EncodedArray object at 0x7fdee5fba800>

<androguard.core.dex.EncodedMethod object at 0x7fdee6104d00>
@Ldalvik/annotation/Signature;
   value = <androguard.core.dex.EncodedArray object at 0x7fdee5f6b610>

<androguard.core.dex.EncodedMethod object at 0x7fdee6203c70>
@Ljava/lang/Deprecated;

<androguard.core.dex.EncodedMethod object at 0x7fdee6107bb0>
@Ldalvik/annotation/Signature;
   value = <androguard.core.dex.EncodedArray object at 0x7fdee5faca60>

<androguard.core.dex.EncodedMethod object at 0x7fdee6107be0>
@Ldalvik/annotation/Signature;
   value = <androguard.core.dex.EncodedArray object at 0x7fdee5f97a90>

<androguard.core.dex.EncodedMethod object at 0x7fdee621d0f0>
@Ldalvik/annotation/Signature;
   value = <androguard.core.dex.EncodedArray object at 0x7fdee5fac3a0>

<androguard.core.dex.EncodedMethod object at 0x7fdee621d4b0>
@Ldalvik/annotation/Signature;
   value = <androguard.core.dex.EncodedArray object at 0x7fdee5fa3ca0>

<androguard.core.dex.EncodedMethod object at 0x7fdee621d720>
@Ljava/lang/Deprecated;
...

@LeviKing98
Copy link

I also encountered the same problem. I want to use annotations to determine the type of generics.
However, I can only get the annotated type now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants