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

How to decode the string length when it is very long? #1587

Closed
cmeiyuan opened this Issue Aug 14, 2017 · 7 comments

Comments

Projects
None yet
2 participants
@cmeiyuan

cmeiyuan commented Aug 14, 2017

As we know,we use StringBlock.getUtf8() or StringBlock.getUtf16() to decode the string's length,usually they can work well.
but,when a string is very very long,such as the length is 0x8888,so the first four bytes are [0x88,0x88,0x88,0x88].

How should I decode it's length?

image

@iBotPeaches

This comment has been minimized.

Show comment
Hide comment
@iBotPeaches

iBotPeaches Aug 14, 2017

Owner

Do you have an APK with these large string block entry? I will investigate.

Owner

iBotPeaches commented Aug 14, 2017

Do you have an APK with these large string block entry? I will investigate.

@cmeiyuan

This comment has been minimized.

Show comment
Hide comment
@cmeiyuan

cmeiyuan Aug 15, 2017

I'm sorry to have given you so late.

app-debug.apk.zip

cmeiyuan commented Aug 15, 2017

I'm sorry to have given you so late.

app-debug.apk.zip

@iBotPeaches

This comment has been minimized.

Show comment
Hide comment
@iBotPeaches

iBotPeaches Aug 15, 2017

Owner

Apktool seems to be decoding this fine. So unsure what you are asking. If you are asking how it does it.

Read this: https://github.com/iBotPeaches/platform_frameworks_base/blob/apktool_7.1/include/androidfw/ResourceTypes.h#L420

/**
 * Definition for a pool of strings.  The data of this chunk is an
 * array of uint32_t providing indices into the pool, relative to
 * stringsStart.  At stringsStart are all of the UTF-16 strings
 * concatenated together; each starts with a uint16_t of the string's
 * length and each ends with a 0x0000 terminator.  If a string is >
 * 32767 characters, the high bit of the length is set meaning to take
 * those 15 bits as a high word and it will be followed by another
 * uint16_t containing the low word.
 *
 * If styleCount is not zero, then immediately following the array of
 * uint32_t indices into the string table is another array of indices
 * into a style table starting at stylesStart.  Each entry in the
 * style table is an array of ResStringPool_span structures.
 */
Owner

iBotPeaches commented Aug 15, 2017

Apktool seems to be decoding this fine. So unsure what you are asking. If you are asking how it does it.

Read this: https://github.com/iBotPeaches/platform_frameworks_base/blob/apktool_7.1/include/androidfw/ResourceTypes.h#L420

/**
 * Definition for a pool of strings.  The data of this chunk is an
 * array of uint32_t providing indices into the pool, relative to
 * stringsStart.  At stringsStart are all of the UTF-16 strings
 * concatenated together; each starts with a uint16_t of the string's
 * length and each ends with a 0x0000 terminator.  If a string is >
 * 32767 characters, the high bit of the length is set meaning to take
 * those 15 bits as a high word and it will be followed by another
 * uint16_t containing the low word.
 *
 * If styleCount is not zero, then immediately following the array of
 * uint32_t indices into the string table is another array of indices
 * into a style table starting at stylesStart.  Each entry in the
 * style table is an array of ResStringPool_span structures.
 */
@cmeiyuan

This comment has been minimized.

Show comment
Hide comment
@cmeiyuan

cmeiyuan Aug 16, 2017

I think StringBlock has a bug than can not decode length correctly.

app-debug.zip

1. I define a very long string in strings.xml.

image

2. I toast the string's length in MainActivity.java, the length is 0x8888.

public class MainActivity extends AppCompatActivity {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.tv_hello);
        String str = getString(R.string.test);
        // the length of str is 0x8888
        Toast.makeText(this, "0x" + Integer.toHexString(str.length()), Toast.LENGTH_SHORT).show();
        textView.setText(str);
    }
}

3. I decode the length by ARSCDecoder.java, but the length is 0x888.

I modify the ARSCDecoder.java that only change some private fields to public and I will upload it.

public static void main(String[] args) throws Exception {
    // I unzip app-debug.apk to get the file resources.arsc
    File file = new File("/Users/cmeiyuan/AndroidStudioProjects/RePlugin/replugin-sample/MyApplication4/app/build/outputs/apk/app-debug/resources.arsc");
    FileInputStream in = new FileInputStream(file);
    try {
        ARSCDecoder decoder = new ARSCDecoder(in, new ResTable(), true, true);
        decoder.readTableHeader();
        StringBlock stringBlock = decoder.mTableStrings;
        int count = stringBlock.getCount();
        for (int i = 0; i < count; i++) {
            String s = stringBlock.get(i).toString();
            if (s.startsWith("aaaaa")) {
                // console print:
                // aaaaaaaaaa.....
                // length:2184
                System.out.println(s);
                System.out.println("length:" + s.length());
            }
        }
    } catch (IOException ex) {
        throw new AndrolibException("Could not decode arsc file", ex);
    }
}

cmeiyuan commented Aug 16, 2017

I think StringBlock has a bug than can not decode length correctly.

app-debug.zip

1. I define a very long string in strings.xml.

image

2. I toast the string's length in MainActivity.java, the length is 0x8888.

public class MainActivity extends AppCompatActivity {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.tv_hello);
        String str = getString(R.string.test);
        // the length of str is 0x8888
        Toast.makeText(this, "0x" + Integer.toHexString(str.length()), Toast.LENGTH_SHORT).show();
        textView.setText(str);
    }
}

3. I decode the length by ARSCDecoder.java, but the length is 0x888.

I modify the ARSCDecoder.java that only change some private fields to public and I will upload it.

public static void main(String[] args) throws Exception {
    // I unzip app-debug.apk to get the file resources.arsc
    File file = new File("/Users/cmeiyuan/AndroidStudioProjects/RePlugin/replugin-sample/MyApplication4/app/build/outputs/apk/app-debug/resources.arsc");
    FileInputStream in = new FileInputStream(file);
    try {
        ARSCDecoder decoder = new ARSCDecoder(in, new ResTable(), true, true);
        decoder.readTableHeader();
        StringBlock stringBlock = decoder.mTableStrings;
        int count = stringBlock.getCount();
        for (int i = 0; i < count; i++) {
            String s = stringBlock.get(i).toString();
            if (s.startsWith("aaaaa")) {
                // console print:
                // aaaaaaaaaa.....
                // length:2184
                System.out.println(s);
                System.out.println("length:" + s.length());
            }
        }
    } catch (IOException ex) {
        throw new AndrolibException("Could not decode arsc file", ex);
    }
}
@iBotPeaches

This comment has been minimized.

Show comment
Hide comment
@iBotPeaches

iBotPeaches Aug 16, 2017

Owner

Thanks for the detailed explanation. I will take another look.

Owner

iBotPeaches commented Aug 16, 2017

Thanks for the detailed explanation. I will take another look.

@cmeiyuan

This comment has been minimized.

Show comment
Hide comment
@cmeiyuan

cmeiyuan Aug 16, 2017

Ok!Thanks very much!

cmeiyuan commented Aug 16, 2017

Ok!Thanks very much!

@iBotPeaches

This comment has been minimized.

Show comment
Hide comment
@iBotPeaches

iBotPeaches Aug 16, 2017

Owner

Interesting find. I have tests for this - https://github.com/iBotPeaches/Apktool/blob/master/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/values-en/strings.xml

But it seems in the case of a 0x8888 character string it fails. This is similar to #1291. I guess the UTF16 decoding is improperly determining the length.

Confirmed.

Owner

iBotPeaches commented Aug 16, 2017

Interesting find. I have tests for this - https://github.com/iBotPeaches/Apktool/blob/master/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/res/values-en/strings.xml

But it seems in the case of a 0x8888 character string it fails. This is similar to #1291. I guess the UTF16 decoding is improperly determining the length.

Confirmed.

@iBotPeaches iBotPeaches added Bug and removed Waiting for issuer labels Aug 16, 2017

iBotPeaches added a commit that referenced this issue Dec 7, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment