Программирование
- Информация о материале
- Автор: Stalko
- Категория: Программирование
- Просмотров: 865
Модификация apk-файла
Вероятно, на пути создания своих форков приложений для Android придётся идти по пути не написания их "с нуля", а модификации уже готовых, зачастую системных приложений.
Постараюсь вкратце описать процесс такой модификации.
Состоит она из четырех этапов:
- Декомпилляция apk
- Внесение правок в код
- Компилляция в apk
- Подписывание apk
Что из себя представляет apk-файл
По своей сути apk-файл - это zip-архив, внутри которого хранятся исполняемые и служебные файлы.
Если Вы поменяете расширение на zip, то сможете увидеть его содержимое.
Но работать с этими файлами нельзя, так как они представлены в бинарном виде, даже XML.
Декомпиляция apk
Декомпиляция apk может быть выполнена с помощью утилиты apktool. bat файл для её запуска Вы можете скачать внизу статьи. Самую последнюю версию утилиты можно взять на сайте авторов.
В Ubuntu apktool устанавливается командами:
Код bash:
export apktool_version=2.3.1 sudo -E sh -c 'wget https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_$apktool_version.jar -O /usr/local/bin/apktool.jar' sudo chmod +r /usr/local/bin/apktool.jar sudo sh -c 'wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool -O /usr/local/bin/apktool' sudo chmod +x /usr/local/bin/apktool
Утилита apktool написана на языке Java и требует установки на компьютер Java 8 (JRE 1.8).
После установки JRE необходимо переименовать файл утилиты в apktool.jar (убрать из имени версию, только в случае, если Вы скачивали файл с официального сайта) и перенести jar и bat файлы в папку, которая описана в системной переменной path.
По сути, после этого мы можем уже начать декомпилировать apk.
Способов получения файла APK много.
Кто-то использует для этого Android Device Bridge (ADB).
Кто-то скачивает файл на компьютер непосредственно из Google Play.
Но лично я использую другой способ. Многие файловые менеджеры позволяют создавать резервные копии приложений. Я, например, использую "Cx Проводник", создаю резервную копию, а потом с его же помощью перебрасываю файл на компьютер через сеть, либо Яндекс диск.
Итак, у нас есть apk-файл, который мы планируем исследовать и поменять. Также у нас есть инструмент, необходимый для его декомпиляции.
Выполняем команду:
Код bash:
apktool d <имя файла. apk>
После этого у нас в том же каталоге, где находится apk, появится папка с тем же именем, внутри которого находится декомпилированная структура файла apk.
Данная структура совпадает с тем, что видели с помощью архиватора, если открывали apk как архив.
Но в ней появилась директория smali, где лежит дезассемблированный код dex-файла, плюс в корне появился файл apktool.yml. Этот файл является служебным файлом apktool и понадобится утилите при обратной сборке проекта.
С этим всем нам и предстоит работать.
В данном способе есть один минус: исходный код получается в small (аналог ассемблера).
Чтобы получить более читаемый код, используют связку dex2jar и jd-gui (В качестве его альтернативы можно использовать Jad, а можно даже использовать облачную декомпиляцию).
Первый позволяет получить из apk файл jar, а второй - собственно дезассемблировать jar.
Также могут пригодиться:
- smali - ассемблер/дизассемблер smali / dex.
- apksigner - программа для подписывания apk (входит в состав Android SDK и требует его установки)
- Android Studio - не помешает, если мы планируем разрабатывать код для Android. Можно сказать, что это целый "комбайн".
- uber-apk-signer - еще вариант для подписывания apk
- Virtuous Ten Studio - программа, с функционалом, аналогичным apktool, но имеющая графический интерфейс и работающая под Windows.
Скачивание файла с помощью ADB
В Windows потребуется предварительно установить USB драйвера для вашего Андроид устройства (если Вы не устанавливали его ранее). В Linux этого скорее всего не потребуется.
Установите Android Device Bridge (ADB). Скачать установочный пакет для Windows можно здесь.
Для установки в Ubuntu используется команда:
Код bash:
sudo apt install android-tools-adb
Подключите Android устройство к компьютеру через USB кабелю.
Вывести список всех установленных на устройстве пакетов можно командой:
Код bash:
adb shell pm list packages
Естественно, если Вы используете Ubuntu, то можете использовать grep для фильтрации вывода и поиска искомого пакета (в Windows команда не сработает).
Код bash:
adb shell pm list packages -f | grep <название_пакета>
Теперь мы можем узнать полный путь к пакету при помощи команды
Код bash:
adb shell pm path <название_пакета (без приставки "package:") >
Теперь мы можем скачать файл с устройства на компьютер:
Код bash:
adb pull <путь к пакету на устройстве> <имя файла на компьютере.apk>
Второй параметр является не обязательным.
Скачивание файла из Google Play
На сайте Google Play необходимо найти требуемое приложение и скопировать его адрес (в строке адреса браузера).
С помощью специальных сервисов, например, этого, скачать файл на компьютер, используя ранее скопированный адрес.
Модификация кода
После декомпиляции мы получили папку со следующей структурой:
META-INF/ | |
META-INF/MANIFEST.MF |
информация о программе:
|
META-INF/CERT.RSA | |
META-INF/CERT.SF | |
res/ | ресурсы, используемые приложением (картинки, иконки и т.д.) |
AndroidManifest.xml | описание приложения ( разрешения, требуемая версия Android , необходимое разрешение экрана) |
classes.dex | исполняемый код виртуальной машины Dalvil, то есть, по сути, сам код приложения |
resources.arsc | файл ресурсов, , в основном строковых, в дополнение к папке |
Также могут присутствовать папки
- assets — аналог папки ресурсов. Основным отличием ресурсов в этом папке является то, что для получения списка asset’ов можно использовать метод AssetManager.list() в коде приложения, получая их динамически;
- lib — оригинальные статические библиотеки Linux, написанные с помощью NDK (Native Development Kit) на C/C++.
Основными объектами модификации являются:
- Ресурсы - их можно напрямую заменять, не изменяя имён. Можно добавлять, удалять, переименовывать, но это потребует изменить файл описания ресурсов.
- Исходный код программы - в зависимости от метода декомпиляции это может быть код на smali, или java.
- Файл AndroidManifest.XML - если нужно изменить набор прав для приложения, ему название и т.д.
Компиляция apk
Сборка модифицированного нами кода выполняется командой
Код bash:
apktool b <имя папки проекта>
После этого внутри директории проекта появятся еще две директории:
- build - в ней лежат скомпилированные файлы
- dist - тут располагается сам готовый файл apk. Но установить его на устройство пока не получится, так как требуется этот файл подписать. Если Вы посмотрите, в этом apk просто отсутствует каталог META-INF, в котором хранится цифровая подпись.
Подписание apk-файла
Мне известно два способа подписания apk-файла:
- С помощью uber-apk-signer
- С помощью apksigner из состава Android SDK
Но хочу оговориться, что установить приложение сразу не получится. Дело в том, что Google Play блокирует установку приложений, у которых электронная подпись отличается от предыдущей версии. Сделано это в целях защиты от установки подложных приложений.
Поэтому "поверх" пересобранное приложение установить нельзя. Нужно предварительно удалить оригинальное и установить своё.
Либо изменить название и установить свой форк рядом с оригиналом.
Подписывание apk с помощью uber-apk-signer
Подписывание выполняется командой:
Код bash:
java -jar uber-apk-signer.jar --apks <имя проекта>/dist/<имя проекта>.apk
В результате в директории с исходным apk появится файл с именем <имя проекта>-aligned-debugSigned.apk
Это и есть наш подписанный файл.
Подписывание apk с помощью apksigner
В отличии от uber-apk-signer в этом приложении можно указать свои параметры для генерации электронной подписи.
На первой вкладке программы (Key Generator) мы создаем ключи, на второй вкладке (APK Signer) производим подписывание apk.
Для создания цифровой подписи необходимо заполнить на первой вкладке следующие поля:
- Target File — файл хранилища ключей;
- Password и Confirm — пароль хранилища;
- Alias — имя ключа в хранилище;
- Alias password и Confirm — пароль секретного ключа;
- Validity — срок жизни ключа (в годах).
Также подпись можно проводить и из командной строки.
Код bash:
apksigner sign --ks <хранилище>.jks | --key <ключ>.pk8 --cert <сертификат>.pem [параметры] <имя приложения>.apk
Следующим шагом мы подписывем apk. На вкладке APK Signer нужно выбрать только что сгенерированный файл, ввести пароль хранилища, алиас ключа и пароль ключа, затем нужно выбрать файл apk и нажимаем кнопку «Sign».
- Информация о материале
- Автор: Stalko
- Категория: Программирование
- Просмотров: 248
Параметры утилиты apktool
Утилита apktool используется для декомпилляции и обратной сборки apk-файлов Android.
Код :Вариант: apktool<br /> -advance,--advanced Вывод расширенной информации. -version,--version Вывод версии apktool Вариант: apktool if|install-framework [ключи] <framework.apk> -p,--frame-path <папка> Сохранить файлы фреймворка в папку <папка> -t,--tag <тэг> Использовать тэг фреймворка <тэг> Вариант: apktool d[ecode] [ключи] <file_apk> -f,--force Принудительно удалить целевую папку -o,--output <папка> Имя папки, в которую будет записан файл. По умолчанию apk.out -p,--frame-path <папка> Использовать файлы фреймоворка, расположенные в папке -r,--no-res Не декодировать ресурсы -s,--no-src Не декодировать исходный код -t,--frame-tag <тэг> Использовать файлы фреймворка, отмеченные тэгом Вариант: apktool b[uild] [ключи] -f,--force-all Игнорировать отслеживание измененных файлов и пересобрать всё -o,--output <папка> Имя выходного apk-файла м путём. По умолчанию dist/name.apk -p,--frame-path <папка> Использовать файлы фреймворка, расположенные в папке
Расширенная информация apktool (выдается по ключу -advance)
Код :usage: apktool [-q|--quiet OR -v|--verbose] <br /> -advance,--advanced prints advance information. <br /> -version,--version prints the version then exits<br />usage: apktool [-q|--quiet OR -v|--verbose] if|install-framework [options] <framework.apk> <br /> -p,--frame-path <dir> Stores framework files into <dir>.<br /> -t,--tag <tag> Tag frameworks using <tag>.<br />usage: apktool [-q|--quiet OR -v|--verbose] d[ecode] [options] <file_apk><br /> -api,--api-level <API> The numeric api-level of the file to generate, e.g. 14 for ICS.<br /> -b,--no-debug-info don't write out debug info (.local, .param, .line, etc.)<br /> -f,--force Force delete destination directory.<br /> --force-manifest Decode the APK's compiled manifest, even if decoding of resources is set to "false".<br /> -k,--keep-broken-res Use if there was an error and some resources were dropped, e.g. "Invalid config flags detected. Dropping resources", but you want to decode them anyway, even with errors. You will have to fix them manually before building.<br /> -m,--match-original Keeps files to closest to original as possible. Prevents rebuild.<br /> --no-assets Do not decode assets.<br /> -o,--output <dir> The name of folder that gets written. Default is apk.out<br /> --only-main-classes Only disassemble the main dex classes (classes[0-9]*.dex) in the root.<br /> -p,--frame-path <dir> Uses framework files located in <dir>.<br /> -r,--no-res Do not decode resources.<br /> -s,--no-src Do not decode sources.<br /> -t,--frame-tag <tag> Uses framework files tagged by <tag>.<br />usage: apktool [-q|--quiet OR -v|--verbose] b[uild] [options] <app_path><br /> -a,--aapt <loc> Loads aapt from specified location.<br /> -api,--api-level <API> The numeric api-level of the file to generate, e.g. 14 for ICS.<br /> -c,--copy-original Copies original AndroidManifest.xml and META-INF. See project page for more info.<br /> -d,--debug Sets android:debuggable to "true" in the APK's compiled manifest<br /> -f,--force-all Skip changes detection and build all files.<br /> -nc,--no-crunch Disable crunching of resource files during the build step.<br /> -o,--output <dir> The name of apk that gets written. Default is dist/name.apk<br /> -p,--frame-path <dir> Uses framework files located in <dir>.<br /> --use-aapt2 Upgrades apktool to use experimental aapt2 binary.<br />usage: apktool [-q|--quiet OR -v|--verbose] publicize-resources <file_path><br />usage: apktool [-q|--quiet OR -v|--verbose] empty-framework-dir [options]<br /> -f,--force Force delete destination directory.<br /> -p,--frame-path <dir> Stores framework files into <dir>.<br />usage: apktool [-q|--quiet OR -v|--verbose] list-frameworks [options]<br /> -p,--frame-path <dir> Stores framework files into <dir>.
- Информация о материале
- Автор: Stalko
- Категория: Программирование
- Просмотров: 1161
Изучаем Ruby. Привет мир! Вывод на экран и ввод с клавиатуры
По устоявшейся традиции начнём с программы «Привет, мир!» (Hello world!)
Для вывода на экран в Ruby используется функция puts
.
Код Ruby:
puts "Привет, мир!" irb(main):001:0> puts "Привет, мир!" Привет, мир! => nil
В Ruby есть несколько способов вывода на экран. Например, мы могли бы написать нашу первую программу таким образом
print "Привет, мир!"
Код Ruby:
irb(main):002:0> print "Привет, мир!" Привет, мир!=> nil
или даже так:
p "Привет, мир!"
При этом обратите внимание, что p – это вовсе не сокращенная запись команды print, как может показаться с первого взгляда. Это отдельный метод. И вывод на экран будет выглядет по другому.
Код Ruby:
irb(main):003:0> p "Привет, мир!" "Привет, мир!" => "Привет, мир!" irb(main):003:0> pp "Привет, мир!" "Привет, мир!" => "Привет, мир!"
В чём разница между этими методами вывода?
puts
и print
почти аналогичны, оба они выводят на экран результат и возвращают nil
, но puts
добавляет перевод строки в конце вывода, а print
– не добавляет.
p
как и puts
выводит результат, добавляет в конце перевод строки, но он также возвращает значение результата, а не nil
.
pp
является расширенной (более красивой - «pretty print») версией p
и его возможности не заметны на примере со строкой (она и так достаточно красива).
Главной особенность Ruby является гибкость его методов. Например для вывода на экран массива Вам не придется создавать цикл. Вывод на экран можно осуществить при помощи тех же функций. Я сознательно ввел в массив пустой элемент. И мы видим, что метод puts
на его месте поставил просто перевод строки
Код Ruby:
irb(main):001:0> puts [1, 2, 3, nil, 4] 1 2 3 4 => nil irb(main):002:0> print [1, 2, 3, nil, 4] [1, 2, 3, nil, 4]=> nil irb(main):003:0> p [1, 2, 3, nil, 4] [1, 2, 3, nil, 4] => [1, 2, 3, nil, 4] irb(main):004:0> pp [1, 2, 3, nil, 4] [1, 2, 3, nil, 4] => [1, 2, 3, nil, 4]
Но мы снова не увидели разницы между p
и pp
!
Для того чтобы её заметить, будем использовать более сложные типы данных, хэши (так в Ruby называются ассоциативные массивы).
Код Ruby:
irb(main):001:0> h = {first:1, second:2, "third" => {sf:"false", ss:3}, "fourth" => {tf:"flag", ts:4}, fifth:5} => {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5} irb(main):002:0> puts h {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5} => nil irb(main):003:0> print h {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5}=> nil irb(main):004:0> p h {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5} => {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5} irb(main):005:0> pp h {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5} => {:first=>1, :second=>2, "third"=>{:sf=>"false", :ss=>3}, "fourth"=>{:tf=>"flag", :ts=>4}, :fifth=>5}
Ну вот, выводить на экран мы научились, но любая программа обычно требует ввода данных извне, например, с клавиатуры.
Логично предположить, что если для вывода используется метод puts
, то для ввода — gets
. Так оно и есть…
Код Ruby:
irb(main):001:0> n = gets 15 => "15\n"
Но почему в конце строки стоит символ перевода строки, и как его убрать? А может его на самом деле и нет? Проверим
Код Ruby:
irb(main):002:0> puts n 15 => nil irb(main):003:0> print n 15 => nil irb(main):004:0> p n "15\n" => "15\n"
puts
и print
нам не показывают перевод строки в явном виде. Хотя если присмотреться, мы заметим, что в выводе print
появился «лишний» перевод строки. А вот метод p
нам явно предъявляет его наличие.
Но что делать, если нам этот перевод строки не нужен?
Код Ruby:
irb(main):005:0> n = gets.chomp 16 => "16" irb(main):006:0> puts n 16 => nil irb(main):007:0> print n 16=> nil irb(main):008:0> p n "16" => "16"
Но до сих пор мы выводили на экран только чистые данные. А как вывести на экран что-то типа «2 + 1 = 3» , где 2 — переменная, введенная с клавиатуры?
Для подмены имени на значение переменной при выводе используется конструкция #{n}
Поэтому мы могли бы использовать такую конструкцию:
Код Ruby:
puts "#{a} + 1 = #{a + 1}"
Но… В ответ мы получаем ошибку
TypeError (no implicit conversion of Integer into String)
Дело в том, что переменная a у нас имеет тип «строка». Ruby не производит автоматического приведения типов, в отличии от, например PHP. В итоге Ruby не может понять, что от него хотят, когда пытаются прибавить число к строке.
Слава богу, в Ruby привести типы — не проблема. Например, приведение строки к целому осуществляется методом to_i
самой строки.
Код Ruby:
puts "#{a} + 1 = #{a.to_i + 1}" irb(main):001:0> a = gets.chomp 2 => "2" irb(main):002:0> puts "#{a} + 1 = #{a + 1}" Traceback (most recent call last): 5: from D:/Program Files/Ruby30-x64/bin/irb.cmd:31:in '<main>' 4: from D:/Program Files/Ruby30-x64/bin/irb.cmd:31:in 'load' 3: from D:/Program Files/Ruby30-x64/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in '<top (required)>' 2: from (irb):2:in '<main>' 1: from (irb):2:in '+' TypeError (no implicit conversion of Integer into String) irb(main):003:0> puts "#{a} + 1 = #{a.to_i + 1}" 2 + 1 = 3 => nil irb(main):004:0> a = 7 => 7 irb(main):005:0> puts "#{a} + 1 = #{a.to_i + 1}" 7 + 1 = 8 => nil
- Информация о материале
- Автор: Stalko
- Категория: Программирование
- Просмотров: 408
Шпаргалка по командам Linux
Не претендуя на полноту освещения всех команд Linux (это почти нереально), начну постепенно выкладывать свои шпаргалки с некоторыми готовыми решениями.
Перезагрузка - reboot
Примонтировать флешку - mount -t vfat -o rw,iocharset=utf-8,codepage=866 /dev/sdb1 /mnt/usb
Примонтировать CD/DVD - mount -t iso9660 -o ro /dev/sr0 /mnt/cd-rom
Размонтировать устройство - umount /mnt/usb
Подключить CD-ROM как репозиторий - sudo apt-cdrom add
Список установленных пакетов - sudo dpkg --get-selections или dpkg -l
Список автоматически установленных пакетов - sudo apt-mark showauto
Получить информацию о пакете (включая версию) - apt-cache show [имя пакета]
Узнать версию пакета - dpkg -s [имя пакета]|grep Version
Регулировка звука из терминала - alsamixer
Настройска энергосберегайки жесткого диска - sudo hdparm -B /dev/sda
Статус запуска процесса - systemctl status [процесс], например systemctl status pure-ftpd.service
Посмотреть лог запуска процессов - journalctl -xe
Конвертировать проект из KVM в VirtualBox - qemu-img convert -O vdi /home/<аккаунт>/.local/share/libvirt/images/<имя проекта>.qcow2 /home/<аккаунт>/<имя проекта>.vdi
Mercurian
Переходим в папку проекта
hg init - создать репозиторий
hg add - добавить файлы
hg commit - отправить изменения
SVN
svnadmin create /home/<аккаунт>/.repos/.svn/<имя проекта> - создать репозиторий
Файлы конфигурации
/etc/fstab - автомонтирование устройств при загрузке