moon_aka_sun: (Default)
[personal profile] moon_aka_sun

Как подправить что-то в чужом приложении. Точнее, как заставить это потом работать.

1. Берём apk, разархивируем его, как обычный zip.
2. Из важных файлов в корне будут resources.arsc, classes.dex, Правим их. Насколько я понял, исходники ресурсов лежат в каталоге res, но там править что-либо бесполезно, т.к. всё уже скомпилировано в arsc.
3. Если dex редактировался, то нужно поменять его чек-суммы внутри. Байты 12..31 (здесь и далее нумерация с нуля) -- это SHA1 содержимого файла, начиная с байта 32, а байты 8..11 -- это Adler32-сумма SHA1+всего остального. Пересчитать чек-суммы можно с помощью java-программы (я её запостил также в коммент).
3.1. Компилируем программу: javac ReDEX.java
3.2. Запускаем: java ReDEX classes.dex
3.3. Вручную правим байты 8..31 (например, с помощью HxD или Vim+xxd)
4. Теперь всё что нужно, это запаковать и подписать архив:
4.1. Убираем каталог META-INF, т.к. у нас будет свой.
4.2. Архивируем в обычный zip-файл. Можно и со сжатием 9.
4.3. Генерируем свой ключ с помощью джавовской утилиты: cd C:\Java && mkdir keys && keytool -v -genkey -alias yourname.keystore -keyalg RSA -validity 20000 -keystore keys/yourname.keystore (введите: Password... Password... YourName..., потом ENTER 5 раз, потом yes, потом опять ENTER)
4.4. Подписываем архив: jarsigner -keystore keys\yourname.keystore -signedjar result.archive.apk source.archive.name.apk yourname.keystore
4.5. Внутри архива будет создан каталог META_INF с тремя файлами - ключом и двумя файлами сигнатур.
5. Всё. Можно копировать в андрофон и инсталлировать.

Date: 2011-03-11 12:42 pm (UTC)
From: [identity profile] moon-aka-sun.livejournal.com
/*
* ReDEX.class
* Coded: Timothy Strazzere
*
* 10/29/2008
*
* Pass a .dex file as an argument and it will output the current
* checksum and signature that is in the file, then it will output
* the checksum and signature as it calculates them.
*
*/

// http://strazzere.com/blog/?p=3

import java.security.*;
import java.util.zip.Adler32;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class ReDEX
{

  public static void main(String[] args)
  {
    if(args.length == 1)
    {
      try
      {
        File file = new File(args[0]);

        byte[] barr = null;
        barr = getBytesFromFile(file);

        System.out.print("Original Checksum: ");
        for(int i = 8; i<12; i+=4)
          System.out.printf("0x%02X%02X%02X%02X ", barr[i+3], barr[i+2], barr[i+1], barr[i]);
        System.out.print("\nOriginal Signature: 0x");
        for(int i = 12; i<32; i+=4)
          System.out.printf("%02X%02X%02X%02X ", barr[i], barr[i+1], barr[i+2], barr[i+3]);

        calcSignature(barr);
        calcChecksum(barr);
        System.out.print("\n\nNew Checksum: ");
        for(int i = 8; i<12; i+=4)
          System.out.printf("0x%02X%02X%02X%02X ", barr[i+3], barr[i+2], barr[i+1], barr[i]);
        System.out.print("\nNew Signature: 0x");
        for(int i = 12; i<32; i+=4)
          System.out.printf("%02X%02X%02X%02X ", barr[i], barr[i+1], barr[i+2], barr[i+3]);
      }
      catch(Exception e)
      {
        System.err.println("File input error");
      }
    }
    else
      System.out.println("Invalid parameters");
  }

  public static byte[] getBytesFromFile(File file) throws IOException
  {
    InputStream is = new FileInputStream(file);

    // Get the size of the file
    long length = file.length();

    if (length > Integer.MAX_VALUE)
    {
    // File is too large
    }

    // Create the byte array to hold the data
    byte[] bytes = new byte[(int)length];

    // Read in the bytes
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0)
    {
      offset += numRead;
    }

    // Ensure all the bytes have been read in
    if (offset < bytes.length)
    {
      throw new IOException("Could not completely read file "+file.getName());
    }

    // Close the input stream and return bytes
    is.close();
    return bytes;
  }

  private static void calcSignature(byte bytes[])
  {
    MessageDigest md;
    try
    {
      md = MessageDigest.getInstance("SHA-1");
    }
    catch(NoSuchAlgorithmException ex)
    {
      throw new RuntimeException(ex);
    }
    md.update(bytes, 32, bytes.length - 32);
    try
    {
      int amt = md.digest(bytes, 12, 20);
      if(amt != 20)
        throw new RuntimeException(
            (new StringBuilder()).append("unexpected digest write:").append(amt).append("bytes").toString());
    }
    catch(DigestException ex)
    {
      throw new RuntimeException(ex);
    }
  }

  private static void calcChecksum(byte bytes[])
  {
    Adler32 a32 = new Adler32();
    a32.update(bytes, 12, bytes.length - 12);
    int sum = (int)a32.getValue();
    bytes[8] = (byte)sum;
    bytes[9] = (byte)(sum >> 8);
    bytes[10] = (byte)(sum >> 16);
    bytes[11] = (byte)(sum >> 24);
  }
}

December 2016

S M T W T F S
    123
4 5678910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 11th, 2025 12:37 pm
Powered by Dreamwidth Studios