2011

Перед тем как мы начнем понимать структуру систем защиты Android, мы должны рассмотреть работу программ на устройстве. Приложение работает в изолированной среде на устройстве. Каждое приложение имеет свои собственные разрешения и область рабочей памяти. Различные приложения могут взаимодействовать между собой. Приложение может запросить систему для выделения ресурсов только через предписания. Все приложения для Android скомпилированы в файл Android Package (APK). APK и устанавливается на устройство.

Формат APK является вариантом формата JAR.

Файл APK обычно содержит две папки:
  • META-INF
  • res


со следующими файлами:
  • AndroidManifest.xml
  • classes.dex
  • resources.arsc


AndroidManifest.xml и classes.dex - два основных файла, которые будем рассматривать.

AndroidManifest.xml представляет основную информацию о приложении системе Android; система должна получить информацию о приложении до того как она выполнит какую-либо функцию приложения. Помимо этого, файл выполняет следующие функции:
  • Содержит Java имя для приложения
  • Приведен список активности приложения, служб, методов предачи и получения информации, вместе с их возможностями. Этот список позволяет системе узнать, какие компоненты существуют и при каких условиях они работают
  • Указывает, какие разрешения должно иметь приложение для получения доступа к API и взаимодействия с другими приложениями
  • Также имеются предписания для доступа других приложений
  • Содержит список библиотек, необходимых для работы приложения


Файл classes.dex содержит код всего приложения для Dalvik.

Сканирование файлов APK ScanDroid'ом и основными утилитами

Приложение ScanDroid сканирует код и определяет возможные уязвимости. Эта статья показывает использование ScanDroid с использованием кода Ruby. Этот код является прототипом для показа возможности использования ScanDroid. Успростим задачу и будем рассматривать три вида уязвимостей для приложений:
1) чтение/запись на локальный носитель;
2) доступ к внешнему URL;
3) создание сокет соединения.

ScanDroid выбирает вышеуказанные файлы из файла APK. Программа конвертирует код Dalvik в Java код и затем сканирует код на возможные уязвимости по ранее установленным правилам.

ScanDroid выполняет следующие операции:
  • Распаковка
    Распаковывает файлы из APK файла
  • Xml
    Конвертирует файлы в xml файлы, а classes в формат .smali
  • dex2clas
    Конвертирует classes.dex в отдельные файлы . class
  • Проверка
    Выполняет проверку кода на возможные уязвимости
  • AndroidManifest
    Выполняет проверку Androidmanifest.xml на наличие дополнительной информации


Промежуточные файлы на каждом этапе процесса создаются для дальнейшего использования. Библиотеки ScanDroid могут быть использованы для ручного выполнения каждой стадии процесса.

Внутри ScanDroid'a

ScanDroid создан с использованием Ruby. Для запуска ScanDroid открываем консоль и пишем:
Код:
ScanDroid.rb –apk <application filename> -rule <rules filename>
Для тестирования используется приложение Android под названием scanme. У нас есть правила в файле

rules.cfg:
Код:
ScanDroid.rb –apk scanme.apk -rule c:\ScanDroid\bin\rules.cfg
Убедись, что ScanDroid запускается из директории установки.

Файл rules.cfg содержит список классов и методов, использующих Java код для обнаружения возможных уязвимостей. 3 возможные уязвимости,к оторые мы предположили, в rules.cfg как:


Мы делаем запрос и пытаемся выполнить поиск по коду.

На выходе получаем:

Создается папка с первыми 3 буквами названия приложения в папке установки:


Эта папка содержит следующие папки:
  • Class: содержит файлы .class
  • Dex: содержит файл classes.dex
  • Src: содержит сконвертированный Java код
  • Xml: содержит читабельные файлы xml
  • Output.txt: содержит строки кода, в которых возможна уязвимость
  • Permissions.txt: содержит список предписаний для приложения


Output.txt


ScanDroid сравнивает правила в rules.cfg с кодом приложения Android. Имя файла, номер строки и строка кода добавляются в output.txt как только находится совпадение.

В нашем примере в 4 строке выходного файла вызывается новый сокет. Код находится в 55 строке файла scanner.java. Вызов сокета делается из приложения. Этот вызов может быть отслежен с помощью ScanDroid'a.

Проще говоря, в файле fread.java пишется информация на локальный носитель. Если информация не защищена, то возможно присутствует уязвимость. OpenFileOutput пишет информацию в файл на устройстве.

Webview вызывает браузер. Webview.loadUrl запускает Url в браузере. ScanDroid может отследить этот вызов, идут ли данные от браузера на вызываемый сайт или еще на какие-либо другие небезопасные сайты.

Permissions.txt


Файл Permissions.txt показывает, какие инструкции приложения берутся из файла

Androidmanifest.xml.

Использование библиотек ScanDroid в Interactive Ruby (Irb)

Каждый отдельный процесс ScanDroid'a может быть использован отдельно в Irb.

Запустим Irb из командной строки и загрузим библиотеку ScanDroid'a, использую команду load:


Затем создадим объект для класса ScanDroid. Пусть это будет объект t:
Код:
. t=ScanDroid.new
Первым делом нужно извлечь файлы из APK
Код:
t.extract(‘filename.apk’)
Код для извлечения:
Код:
Zip::ZipFile.open(filename) {|file|
file.each do |f|
f_path = File.join(destination, f.name)
FileUtils.mkdir_p(File.dirname(f_path))
file.extract(f, f_path)
end
}
Этот код использует ruby gem Zip для извлечения всех файлов из APK в нужную директорию. Все файлы проверены и располагаются согласно их структуре.

Все распакованные файлы хранятся в папке dex


Затем нужно сконвертировать файлы xml в читабельный формат:


Для xml мы будем использовать утилиту apktool:


Выполняем apktool. Первый параметр - расположение файла apk и второй - папка для распаковки.


Сейчас нам нужно сконвертировать файлы dex в файлы class. Будем использовать утилиту dex2jar для конвертирования кода Dalvik в файлы Java .jar.


Код:
cmd=Dir.getwd+"/bin/dex2jar/dex2jar.bat"+cur+"/#{filename[0,3]}/dex"+"/
ses.dex"
system(cmd)
dest=Dir.getwd+"/#{filename[0,3]}/class"
jar2zip=Dir.getwd+"/#{filename[0,3]}/dex/classes.dex.dex2jar.jar"
Zip::ZipFile.open(jar2zip) {|file|
file.each do |f|
f_path = File.join(dest, f.name)
FileUtils.mkdir_p(File.dirname(f_path))
file.extract(f, f_path)
end
Сгенерированный jar распаковывается использованием Zip gem of Ruby на файлы class, которые хранятся в директории class.

Полученные файлы нужно сконвертировать в Java код - clas2jav. Выполняем:
Код:
t.clas2jav (‘applicationname.apk’)
Используем Java декомпиоятор JAD. Выполняем:
Код:
jad -o -r -sjava –d /src /class /**/*.class
src - директория, в которую сохранятся все java файлы,
/class - сохраняются class файлы,
/**/*.class - JAD конвертирует все файлы .class, включая те, которые находятся в поддиректориях.

Сейчас у нас есть весь код приложения. Теперь ScanDroid может проверить код ан уязвимости. Для начала мы просканируем AndroidManifest.xml для того чтобы узнать инструкции приложения:


Код:
File.open("#{cur}/#{filename[0,3]}/xml/AndroidManifest.xml","r") d
|infile|
while(line=infile.gets)
if line[/android.permission./]
Каждая из инструкций определяется со значением "android.permission". ScanDroid сканирует код в поиске этих значений и, если найдено совпадение, сохраняет строку в файл.


Нам нужно просканировать код, который мы декомпилировали, на наличие уязвимостей:
Код:
t.check(‘scanme.apk’,’c:/ScanDroid/bin/rules.cfg’)

Код:
if File.file?(entry) and entry[/.+\.java$/]
File.open(entry,"r") do |infile|
while(line = infile.gets)
c=c+1
File.open(rulefile,"r") do |rule|
while(r=rule.gets)
exp= r.chomp
if line[/#{exp}/i]
Сканируем все файлы в директории src и отмечаем каждую строку, определенную в файле rules.cfg. Подтвержренное совпадение выводится в output.txt.

Приложение. Код ScanDroid
ScanDroid.rb
Код:
require 'ScanDroid_lib.rb'
def run
t=ScanDroid.new
case ARGV[0]
when "-apk"
@filename=ARGV[1]
else
system('cls')
puts "Error in correct syntax!\nTry: ScanDroid.rb -apk [Filename.apk] -rule [rule_file]"
Process.exit
end
case ARGV[2]
when "-rule"
@rule=ARGV[3]
else
system('cls')
puts "Error in correct syntax!\nTry: ScanDroid.rb -apk [Filename.apk] -rule [rule_file]"
Process.exit
end
if !@filename
puts "Enter Filename(including extension): "
@filename=gets.chomp
end
if !@rule
puts "Enter Rules File(including extension): "
@rule=gets.chomp
end
if !File.exists?(@filename)
puts "\nCannot find #{@filename}! Please make sure the path of the file is correct."
Process.exit
end
if !File.exists?(@rule)
puts "\nCannot find #{@rule}! Please make sure the path of the file is correct."
Process.exit
end
puts "Working on "+@filename+" ... "
t.extract(@filename)
system('cls')
t.xml(@filename)
system('cls')
t.dex2clas(@filename)
system('cls')
t.clas2jav(@filename)
system('cls')
t.manifest(@filename)
system('cls')
t.check(@filename,@rule)
puts ("\nPermissions Stored at /#{@filename[0,3]}/permissions.txt\n")
end
system('@echo off')
system('prompt.')
run()
system('prompt')
ScanDroid_lib.rb
Код:
require 'zip/zip'
require 'find'
class ScanDroid
def initialize
system('cls')
@flag=1
puts "Checking for files.... "
if File.directory?("bin")
puts "'/bin' directory found."
else
puts "'/bin' directory could not be found. \nPlease run the program from the correct
folder."
Process.exit
end
end
def extract(filename)
destination=Dir.getwd+"/#{filename[0,3]}/dex"
begin
Zip::ZipFile.open(filename) {|file|
file.each do |f|
f_path = File.join(destination, f.name)
FileUtils.mkdir_p(File.dirname(f_path))
file.extract(f, f_path)
end
}
rescue
puts "\nError Unpacking the File! Delete all Previously generated files of this apk."
Process.exit
end
end
def xml(filename)
cur=Dir.getwd
if File.exists?("#{cur}/bin/apktool.bat")
cmd=Dir.getwd+"/bin/apktool.bat d "+cur+"/"+filename+" "+cur+"/#{filename[0,3]}/xml"
puts cmd
system(cmd)
else
puts "Cannot Find apktool.bat!"
Process.exit
end
end
def dex2clas(filename)
cur=Dir.getwd
begin
if File.exists?("#{cur}/bin/dex2jar/dex2jar.bat")
cmd=Dir.getwd+"/bin/dex2jar/dex2jar.bat "+cur+"/#{filename[0,3]}/dex"+"/classes.dex"
system(cmd)
dest=Dir.getwd+"/#{filename[0,3]}/class"
jar2zip=Dir.getwd+"/#{filename[0,3]}/dex/classes.dex.dex2jar.jar"
Zip::ZipFile.open(jar2zip) {|file|
file.each do |f|
f_path = File.join(dest, f.name)
FileUtils.mkdir_p(File.dirname(f_path))
file.extract(f, f_path)
end
}
else
puts "\nCannot find dex2jar.bat in the bin/dex2jar/dex2jar.bat directory!"
Process.exit
end
rescue
puts "\nError Converting Dex to Class!"
Process.exit
end
Dir.chdir(cur)
end
def clas2jav(filename)
cur=Dir.getwd
cmd=cur+"/bin"
system(cmd)
Dir.chdir(Dir.getwd+"/bin")
cmd="jad -o -r -sjava -d"+cur+"/#{filename[0,3]}/src
"+cur+"/#{filename[0,3]}/class"+"/**/*.class"
if File.exists?("jad.exe")
system(cmd)
else
puts "\nJava Decompiler file jad.exe could not be found!"
Process.exit
end
Dir.chdir(cur)
end
def check(filename,rulefile)
cur=Dir.getwd
@flag=1
system('cls')
puts ("Scanning files please wait...")
fc=0
vc=0
Find.find(cur+"/#{filename[0,3]}/src") do |entry|
fc=fc+1
if File.file?(entry) and entry[/.+\.java$/]
c=0
File.open(entry,"r") do |infile|
while(line = infile.gets)
c=c+1
File.open(rulefile,"r") do |rule|
while(r=rule.gets)
exp= r.chomp
if line[/#{exp}/i]
open(cur+"/#{filename[0,3]}/output.txt","a") do |f| f.puts
(File.expand_path(entry)+": Line: #{c}: "+line.strip+"\n") end
vc=vc+1
end
end
end
end
end
end
end
puts ("\nTotal Files Scanned: #{fc}\nPossible Vulnerablities: #{vc}\nOutput File
generated at: #{cur}/#{filename[0,3]}/output.txt\n")
end
def manifest(filename)
cur=Dir.getwd
File.open("#{cur}/#{filename[0,3]}/xml/AndroidManifest.xml","r") do |infile|
while(line=infile.gets)
if line[/android.permission./]
line=line.strip
line=line[50,150]
line=line.strip
line=line.squeeze(" ")
line=line.chop.chop.strip
line=line.chop
puts line
open(cur+"/#{filename[0,3]}/permissions.txt","a") do |f| f.puts (line+"\n") end
end
end
end
puts ("\nPermissions Stored at #{cur}/#{filename[0,3]}/permissions.txt\n")
end
end
Утилиты
Dex2jar: http://code.google.com/p/dex2jar/
Apktool: http://code.google.com/p/android-apktool/
Java Decompiler: http://www.varaneckas.com/jad/

© Rushil Shah Blueinfy Team
© Ex0rcist from GR TeaM
© Resident of r0 Crew