|
|
|
#! /usr/bin/python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Author: kelvinBen
|
|
|
|
# Github: https://github.com/kelvinBen/AppInfoScanner
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import shutil
|
|
|
|
import zipfile
|
|
|
|
import binascii
|
|
|
|
import platform
|
|
|
|
import libs.core as cores
|
|
|
|
from queue import Queue
|
|
|
|
|
|
|
|
class iOSTask(object):
|
|
|
|
elf_file_name = ""
|
|
|
|
def __init__(self,path):
|
|
|
|
self.path = path
|
|
|
|
self.file_queue = Queue()
|
|
|
|
self.shell_flag = False
|
|
|
|
self.file_identifier= []
|
|
|
|
self.permissions = []
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
file_path = self.path
|
|
|
|
if file_path.split(".")[-1] == 'ipa':
|
|
|
|
self.__decode_ipa__(cores.output_path)
|
|
|
|
self.__scanner_file_by_ipa__(cores.output_path)
|
|
|
|
elif self.__get_file_header__(file_path):
|
|
|
|
self.file_queue.put(file_path)
|
|
|
|
else:
|
|
|
|
raise Exception("Retrieval of this file type is not supported. Select IPA file or Mach-o file.")
|
|
|
|
return {"shell_flag":self.shell_flag,"file_queue":self.file_queue,"comp_list":[],"packagename":None,"file_identifier":self.file_identifier,"permissions":self.permissions}
|
|
|
|
|
|
|
|
def __get_file_header__(self,file_path):
|
|
|
|
hex_hand = 0x0
|
|
|
|
macho_name = os.path.split(file_path)[-1]
|
|
|
|
self.file_identifier.append(macho_name)
|
|
|
|
with open(file_path,"rb") as macho_file:
|
|
|
|
macho_file.seek(hex_hand,0)
|
|
|
|
magic = binascii.hexlify(macho_file.read(4)).decode().upper()
|
|
|
|
macho_magics = ["CFFAEDFE","CEFAEDFE","BEBAFECA","CAFEBABE"]
|
|
|
|
if magic in macho_magics:
|
|
|
|
self.__shell_test__(macho_file,hex_hand)
|
|
|
|
macho_file.close()
|
|
|
|
return True
|
|
|
|
macho_file.close()
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def __shell_test__(self,macho_file,hex_hand):
|
|
|
|
while True:
|
|
|
|
magic = binascii.hexlify(macho_file.read(4)).decode().upper()
|
|
|
|
if magic == "2C000000":
|
|
|
|
macho_file.seek(hex_hand,0)
|
|
|
|
encryption_info_command = binascii.hexlify(macho_file.read(24)).decode()
|
|
|
|
cryptid = encryption_info_command[-8:len(encryption_info_command)]
|
|
|
|
if cryptid == "01000000":
|
|
|
|
self.shell_flag = True
|
|
|
|
break
|
|
|
|
hex_hand = hex_hand + 4
|
|
|
|
|
|
|
|
def __scanner_file_by_ipa__(self,output):
|
|
|
|
scanner_file_suffix = ["plist","js","xml","html"]
|
|
|
|
scanner_dir = os.path.join(output,"Payload")
|
|
|
|
self.__get_scanner_file__(scanner_dir,scanner_file_suffix)
|
|
|
|
|
|
|
|
def __get_scanner_file__(self,scanner_dir,file_suffix):
|
|
|
|
dir_or_files = os.listdir(scanner_dir)
|
|
|
|
for dir_file in dir_or_files:
|
|
|
|
dir_file_path = os.path.join(scanner_dir,dir_file)
|
|
|
|
if os.path.isdir(dir_file_path):
|
|
|
|
if dir_file.endswith(".app"):
|
|
|
|
self.elf_file_name = dir_file.replace(".app","")
|
|
|
|
self.__get_scanner_file__(dir_file_path,file_suffix)
|
|
|
|
else:
|
|
|
|
if self.elf_file_name == dir_file:
|
|
|
|
self.__get_file_header__(dir_file_path)
|
|
|
|
self.file_queue.put(dir_file_path)
|
|
|
|
continue
|
|
|
|
if cores.resource_flag:
|
|
|
|
dir_file_suffix = dir_file.split(".")
|
|
|
|
if len(dir_file_suffix) > 1:
|
|
|
|
if dir_file_suffix[-1] in file_suffix:
|
|
|
|
self.__get_file_header__(dir_file_path)
|
|
|
|
self.file_queue.put(dir_file_path)
|
|
|
|
|
|
|
|
def __decode_ipa__(self,output_path):
|
|
|
|
with zipfile.ZipFile(self.path,"r") as zip_files:
|
|
|
|
zip_file_names = zip_files.namelist()
|
|
|
|
zip_files.extract(zip_file_names[0],output_path)
|
|
|
|
try:
|
|
|
|
new_zip_file = zip_file_names[0].encode('cp437').decode('utf-8')
|
|
|
|
except UnicodeEncodeError:
|
|
|
|
new_zip_file = zip_file_names[0].encode('utf-8').decode('utf-8')
|
|
|
|
|
|
|
|
old_zip_dir = self.__get_parse_dir__(output_path,zip_file_names[0])
|
|
|
|
new_zip_dir = self.__get_parse_dir__(output_path,new_zip_file)
|
|
|
|
os.rename(old_zip_dir,new_zip_dir)
|
|
|
|
|
|
|
|
for zip_file in zip_file_names:
|
|
|
|
old_ext_path = zip_files.extract(zip_file,output_path)
|
|
|
|
start = str(old_ext_path).index("Payload")
|
|
|
|
dir_path = old_ext_path[start:len(old_ext_path)]
|
|
|
|
old_ext_path = os.path.join(output_path,dir_path)
|
|
|
|
try:
|
|
|
|
new_zip_file = zip_file.encode('cp437').decode('utf-8')
|
|
|
|
except UnicodeEncodeError:
|
|
|
|
new_zip_file = zip_file.encode('utf-8').decode('utf-8')
|
|
|
|
|
|
|
|
new_ext_path = os.path.join(output_path,new_zip_file)
|
|
|
|
|
|
|
|
if platform.system() == "Windows":
|
|
|
|
new_ext_path = new_ext_path.replace("/","\\")
|
|
|
|
|
|
|
|
if not os.path.exists(new_ext_path):
|
|
|
|
dir_path = os.path.dirname(new_ext_path)
|
|
|
|
if not os.path.exists(dir_path):
|
|
|
|
os.makedirs(dir_path)
|
|
|
|
shutil.move(old_ext_path, new_ext_path)
|
|
|
|
if os.path.exists(old_ext_path):
|
|
|
|
try:
|
|
|
|
# mac发生权限问题的时候做处理
|
|
|
|
os.remove(old_ext_path)
|
|
|
|
except Exception:
|
|
|
|
shutil.rmtree(old_ext_path)
|
|
|
|
|
|
|
|
|
|
|
|
def __get_parse_dir__(self,output_path,file_path):
|
|
|
|
start = file_path.index("Payload/")
|
|
|
|
end = file_path.index(".app")
|
|
|
|
root_dir = file_path[start:end]
|
|
|
|
if platform.system() == "Windows":
|
|
|
|
root_dir = root_dir.replace("/","\\")
|
|
|
|
old_root_dir = os.path.join(output_path,root_dir+".app")
|
|
|
|
return old_root_dir
|