def repackageFrw(frwDir, bootClassFolder): """ Repackage the classes.dex into jar of frwDir. """ if OPTIONS.formatFrw == False : return # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) # Some dexFiles are parted, such as framework-classes2.dex regex = re.compile("(.*)-(classes\d?).dex") Log.i(TAG, "Repackage JARs of %s" %(frwDir)) os.chdir(frwDir) for dexFile in os.listdir(bootClassFolder): if dexFile.endswith(".dex"): jarFile = dexFile[0:-4] + ".jar" dexName = "classes.dex" if not os.path.exists(jarFile): # Match out the jar file with regex matcher = regex.match(dexFile) if matcher != None: jarFile = matcher.group(1) + ".jar" dexName = matcher.group(2) + ".dex" Log.d(TAG, "Repackage %s" %(jarFile)) # Put the dex and framework's jar in the same folder, and jar into the jarFile shutil.move(os.path.join(bootClassFolder, dexFile), os.path.join(frwDir, dexName)) Utils.runWithOutput(["jar", "uf", jarFile, dexName]) if os.path.exists(dexName): os.remove(dexName) os.chdir(oldDir)
def getZipType(self): """ Retrieve the OTA package type The property <persist.sys.dalvik.vm.lib> defines the VM type. If libart.so is used, it is an ART package; If libdvm.so is used, it is an DVM package. """ if self.mRoot is None: self.unzip() buildProp = os.path.join(self.mRoot, "system/build.prop") # Retrieve the <persist.sys.dalvik.vm.lib> in build.prop zipType = None if os.path.exists(buildProp): fileHandle = open(buildProp, "r") content = fileHandle.read() vmlib = re.compile("\n.*sys.dalvik.vm.lib.*=\s*(?P<lib>.*)\n") match = vmlib.search(content) if match is not None: libType = match.group("lib") Log.d(TAG, "sys.dalvik.vm.lib=%s" % libType) else: libType = "" fileHandle.close() else: raise Exception("Could not find %s, unknown ota type" % buildProp) if libType.find("art") >= 0: zipType = ZipModel.ART elif libType.find("dvm") >= 0: zipType = ZipModel.DVM return zipType
def setValue(self, value, callback=None): from Msg import Msg Log.i( 'Device', "Set value for device" + self.unid + "|" + self.setid + " :" + value + ", isOnline:%s" % self.isOnline) if self.mySocketWrap != None and self.isOnline == True: Log.i('Device', "Sending expl now") self.setValueCallback = callback Log.d('DeviceSetVal', "[1.1]") msg = self.mySocketWrap.sendValue(self, value, self.callbackSetValue) Log.d('DeviceSetVal', "[1.2]") self.needSetValue = False elif (self.mySocketWrap == None and self.isOnline == True): DB.addAlert(self.unid, self.setid, 1008) if (callback != None): msg = Msg(cmd="device.val.set.error") msg.sendAttempt = -1 callback(msg, self) else: Log.i('Device', "Scheduled for when online") msg = Msg(cmd="device.val.set.scheduled") self.executeTriggerSeq(1) if (callback != None): callback(msg, self) self.needSetValue = True self.updateValueDb(value) if (self.isOnline == False): self.sendHeartBeat() #else: # self.setIsOnline(False) self.lastValue = value
def deoat(self): """ De-oat the OTA package. """ if self.mBootOAT == None: Log.i( TAG, "deoat(): boot.oat not found in %s, nothing need deoat" % self.mRoot) return self if os.path.exists(self.mBootClassFolder): Log.d(TAG, "Delete the already exists %s" % self.mBootClassFolder) shutil.rmtree(self.mBootClassFolder) # Phase 1: de-oat boot.oat OatZip.deoatBootOAT(self.mBootOAT) # Phase 2: de-oat all the other oat files, of which suffix is odex. # [Android 5.0]: All the oat jars are located in the same folder with boot.oat OatZip.deoatFrw(self.mBootOATDir) # Phase 3: de-oat app OatZip.deoatApp(self.mFrwDir, self.mBootClassFolder) OatZip.deoatApp(self.mAppDir, self.mBootClassFolder) OatZip.deoatApp(self.mPrivAppDir, self.mBootClassFolder) return self
def deoat(self): """ De-oat the OTA package. """ if self.mBootOAT == None: Log.i(TAG, "deoat(): boot.oat not found in %s, nothing need deoat" % self.mRoot) return self if os.path.exists(self.mBootClassFolder): Log.d(TAG, "Delete the already exists %s" %self.mBootClassFolder) shutil.rmtree(self.mBootClassFolder) # Phase 1: de-oat boot.oat OatZip.deoatBootOAT(self.mBootOAT) # Phase 2: de-oat all the other oat files, of which suffix is odex. # [Android 5.0]: All the oat jars are located in the same folder with boot.oat OatZip.deoatFrw(self.mBootOATDir) # Phase 3: de-oat app OatZip.deoatApp(self.mFrwDir, self.mBootClassFolder) OatZip.deoatApp(self.mAppDir, self.mBootClassFolder) OatZip.deoatApp(self.mPrivAppDir, self.mBootClassFolder) return self
def deoatApp(oatApkDir, bootClassFolder): """ De-oat app """ if OPTIONS.formatApp == False: return Log.i(TAG, "De-oat files of oat-format in %s, with BOOTCLASSFOLDER=%s" %(oatApkDir, bootClassFolder)) for (dirpath, dirnames, filenames) in os.walk(oatApkDir): dirnames = dirnames # no use, to avoid warning for filename in filenames: if filename.endswith(".odex"): # no need to de-oat if original apk does not exist apkFile = filename[0:-5] + ".apk" apkPath = os.path.dirname(dirpath) if not os.path.exists(os.path.join(apkPath, apkFile)): continue oatApk = os.path.join(dirpath, filename) deoatApk = oatApk[0:-5] + ".dex" if os.path.exists(deoatApk): Log.d(TAG, "Delete the already exists %s" % deoatApk) os.remove(deoatApk) Utils.runWithOutput([OatZip.OAT2DEX, oatApk, bootClassFolder])
def getZipType(self): """ Retrieve the OTA package type The property <persist.sys.dalvik.vm.lib> defines the VM type. If libart.so is used, it is an ART package; If libdvm.so is used, it is an DVM package. """ if self.mRoot is None: self.unzip() buildProp = os.path.join(self.mRoot, "system/build.prop") # Retrieve the <persist.sys.dalvik.vm.lib> in build.prop zipType = None if os.path.exists(buildProp): fileHandle = open(buildProp, "r") content = fileHandle.read() vmlib = re.compile("\n.*sys.dalvik.vm.lib.*=\s*(?P<lib>.*)\n") match = vmlib.search(content) if match is not None: libType = match.group("lib") Log.d(TAG, "sys.dalvik.vm.lib=%s" % libType) fileHandle.close() else: raise Exception("Could not find %s, unknown ota type" %buildProp) if libType.find("art") >= 0: zipType = ZipModel.ART elif libType.find("dvm") >= 0: zipType = ZipModel.DVM return zipType
def deoatApp(oatApkDir, bootClassFolder): """ De-oat app """ if OPTIONS.formatApp == False: return Log.i( TAG, "De-oat files of oat-format in %s, with BOOTCLASSFOLDER=%s" % (oatApkDir, bootClassFolder)) for (dirpath, dirnames, filenames) in os.walk(oatApkDir): dirnames = dirnames # no use, to avoid warning for filename in filenames: if filename.endswith(".odex"): # no need to de-oat if original apk does not exist apkFile = filename[0:-5] + ".apk" apkPath = os.path.dirname(dirpath) if not os.path.exists(os.path.join(apkPath, apkFile)): continue oatApk = os.path.join(dirpath, filename) deoatApk = oatApk[0:-5] + ".dex" if os.path.exists(deoatApk): Log.d(TAG, "Delete the already exists %s" % deoatApk) os.remove(deoatApk) Utils.runWithOutput( [OatZip.OAT2DEX, oatApk, bootClassFolder])
def sendValue(self, device, value, callback=None): msg = Msg(unid=device.unid, setid=device.setid, cmd="device.val.set", value=value, socket=self, callback=callback) Log.d('DeviceSetVal', "[1.1.1]") self.outgoingMSG.append(msg) return msg
def repackageFrwWithArch(frwDir, dexFolder): """ Repackage the classes.dex into jar of frwDir. """ if OPTIONS.formatFrw == False: return # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) Log.i(TAG, "Repackage JARs of %s - %s" % (frwDir, dexFolder)) os.chdir(dexFolder) for dexFile in os.listdir(dexFolder): if dexFile.endswith(".dex") and dexFile.find("classes") == -1: appName = dexFile[0:-4] jarFile = os.path.join(frwDir, appName + ".apk") if not os.path.exists(jarFile): jarFile = jarFile[0:-4] + ".jar" if not os.path.exists(jarFile): dexName = "classes.dex" shutil.move(os.path.join(dexFolder, dexFile), os.path.join(dexFolder, dexName)) Utils.runWithOutput(["jar", "cf", jarFile, dexName]) os.remove(os.path.join(dexFolder, dexName)) continue Log.d(TAG, "Repackage %s" % (jarFile)) if not OatZip.isDeodexed(jarFile): # Put the dex and framework's jar in the same folder, and jar into the jarFile dexName = "classes.dex" shutil.move(os.path.join(dexFolder, dexFile), os.path.join(dexFolder, dexName)) Utils.runWithOutput(["jar", "uf", jarFile, dexName]) os.remove(os.path.join(dexFolder, dexName)) dexName = "classes2.dex" dexFile = appName + "-" + dexName if os.path.exists(os.path.join(dexFolder, dexFile)): shutil.move(os.path.join(dexFolder, dexFile), os.path.join(dexFolder, dexName)) Utils.runWithOutput(["jar", "uf", jarFile, dexName]) os.remove(os.path.join(dexFolder, dexName)) dexName = "classes3.dex" dexFile = appName + "-" + dexName if os.path.exists(os.path.join(dexFolder, dexFile)): shutil.move(os.path.join(dexFolder, dexFile), os.path.join(dexFolder, dexName)) Utils.runWithOutput(["jar", "uf", jarFile, dexName]) os.remove(os.path.join(dexFolder, dexName)) os.chdir(oldDir)
def deoatBootOAT(bootOAT): """ De-oat boot.oat """ bootClassFolder = os.path.dirname(bootOAT) bootClassFolderDex = os.path.join(bootClassFolder, "dex") bootClassFolderOdex = os.path.join(bootClassFolder, "odex") if os.path.exists(bootClassFolderDex): Log.d(TAG, "Delete the already exists %s" % bootClassFolderDex) shutil.rmtree(bootClassFolderDex) if os.path.exists(bootClassFolderOdex): Log.d(TAG, "Delete the already exists %s" % bootClassFolderOdex) shutil.rmtree(bootClassFolderOdex) Log.i(TAG, "De-oat %s" % bootOAT) Utils.runWithOutput([OatZip.OAT2DEX, "boot", bootOAT])
def zip(self): if self.mRoot is None: return origDir = os.path.abspath(os.curdir) Log.i(TAG, "zip from %s to %s" % (self.mRoot, self.mOutZip)) os.chdir(self.mRoot) cmd = "zip -r -y -q tmp *; mv tmp.zip %s" % self.mOutZip Log.d(TAG, commands.getoutput(cmd)) os.chdir(origDir) Log.i(TAG, "Deleting %s" % self.mRoot) shutil.rmtree(self.mRoot) Log.i(TAG, "===> %s" % self.mOutZip)
def deoatBootOAT(frwDir, arch): """ De-oat boot.oat """ bootClassFolder = os.path.join(frwDir, arch) bootOatPath = os.path.join(bootClassFolder, "boot.oat") bootClassFolderDex = os.path.join(frwDir, arch + "-dex") bootClassFolderOdex = os.path.join(frwDir, arch + "-odex") if os.path.exists(bootClassFolderDex): Log.d(TAG, "Delete the already exists %s" % bootClassFolderDex) shutil.rmtree(bootClassFolderDex) if os.path.exists(bootClassFolderOdex): Log.d(TAG, "Delete the already exists %s" % bootClassFolderOdex) shutil.rmtree(bootClassFolderOdex) Log.i(TAG, "De-oat %s" % bootClassFolder) if OPTIONS.use_baksmali: for item in os.listdir(bootClassFolder): if item.endswith(".oat"): oatPath = os.path.join(bootClassFolder, item) dexlist = Utils.runWithResult( [OatZip.BAKSMALI, "list", "dex", oatPath]) jarName = os.path.basename(dexlist[0].strip("\n")) jarOutDir = os.path.join(frwDir, arch + "-odex", jarName + ".out") dexDir = os.path.join(frwDir, arch + "-dex") if not os.path.exists(dexDir): os.makedirs(dexDir) for dex in dexlist: if dex.strip("\n").endswith(".jar"): dexName = "" smaliDir = "smali" dexSaveName = jarName[0:-4] + ".dex" else: dexName = dex.strip("\n").split(":")[1] smaliDir = "smali_" + dexName[0:-4] dexSaveName = jarName[0:-4] + "-" + dexName Log.d( TAG, "baksmali deodex -b %s %s -o %s" % (bootOatPath, os.path.join(oatPath, dexName), os.path.join(jarOutDir, smaliDir))) Utils.runWithOutput([ OatZip.BAKSMALI, "deodex", "-b", bootOatPath, os.path.join(oatPath, dexName), "-o", os.path.join(jarOutDir, smaliDir) ]) Log.d( TAG, "smali assemble %s -o %s" % (os.path.join(jarOutDir, smaliDir), os.path.join(dexDir, dexSaveName))) Utils.runWithOutput([ OatZip.SMALI, "assemble", os.path.join(jarOutDir, smaliDir), "-o", os.path.join(dexDir, dexSaveName) ]) else: Utils.runWithOutput([OatZip.OAT2DEX, "boot", bootClassFolder])
def unzip(self): # Already unziped if self.mRoot is not None: return self.mRoot = tempfile.mkdtemp() Log.i(TAG, "unzip %s to %s" % (self.mInZip, self.mRoot)) cmd = "unzip -q -o %s -d %s" %(self.mInZip, self.mRoot) Log.d(TAG, commands.getoutput(cmd)) self.dedatIfNeeded() # Format path if os.path.exists(os.path.join(self.mRoot, "SYSTEM")): shutil.move(os.path.join(self.mRoot, "SYSTEM"), os.path.join(self.mRoot, "system")) return self
def dedatIfNeeded(self): """ Android 5.0 zip structure: * META-INF (folder containing scripts) * system.new.dat (compressed /system partition) * system.patch.dat * system.transfer.list (see explanation below) """ if not os.path.exists(os.path.join(self.mRoot, "system.new.dat")): return if not os.path.exists(os.path.join(self.mRoot, "system.transfer.list")): return if os.geteuid() != 0: raise Exception("DEDAT should be executed as root.") cmd = "%s %s" % (commands.mkarg(ZipModel.DAT2IMG), commands.mkarg(self.mRoot)) Log.d(TAG, commands.getoutput(cmd))
def findArch(self): """ Find arch and arch2 """ self.arch = "" self.arch2 = "" if OatZip.testArch(self.mFrwDir, "arm64"): self.arch = "arm64" if OatZip.testArch(self.mFrwDir, "arm"): self.arch2 = "arm" elif OatZip.testArch(self.mFrwDir, "x86_64"): self.arch = "x86_64" if OatZip.testArch(self.mFrwDir, "x86"): self.arch2 = "x86" elif OatZip.testArch(self.mFrwDir, "arm"): self.arch = "arm" elif OatZip.testArch(self.mFrwDir, "x86"): self.arch = "x86" else: Log.d(TAG, "unknow arch")
def packageDexToAppWithArch(apkFile, arch): # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) apkPath = os.path.dirname(apkFile) appName = os.path.basename(apkFile) app = appName[0:-4] archPath = os.path.join(apkPath, "oat", arch) # chagnge to arch path os.chdir(archPath) Log.d(TAG, "Repackage %s" % (apkFile)) dexFile = os.path.join(archPath, app + ".dex") # mv $appdir/$app/$arch/$app.dex $appdir/$app/$arch/classes.dex if os.path.exists(dexFile): shutil.move(dexFile, os.path.join(archPath, "classes.dex")) Utils.runWithOutput(["jar", "uf", apkFile, "classes.dex"]) else: Log.d(TAG, "Repackage ERROR %s" % (apkFile)) dexFile = os.path.join(archPath, app + "-classes2.dex") # if [[ -f "$appdir/$app/$arch/$app-classes2.dex" ]]; then # mv $appdir/$app/$arch/$app-classes2.dex $appdir/$app/$arch/classes2.dex if os.path.exists(dexFile): shutil.move(dexFile, os.path.join(archPath, "classes2.dex")) Utils.runWithOutput(["jar", "uf", apkFile, "classes2.dex"]) dexFile = os.path.join(archPath, app + "-classes3.dex") # if [[ -f "$appdir/$app/$arch/$app-classes3.dex" ]]; then # mv $appdir/$app/$arch/$app-classes3.dex $appdir/$app/$arch/classes3.dex if os.path.exists(dexFile): shutil.move(dexFile, os.path.join(archPath, "classes3.dex")) Utils.runWithOutput(["jar", "uf", apkFile, "classes3.dex"]) os.chdir(oldDir)
def repackageApp(appDir): """ Repackage the classes.dex into apk of appDir """ if OPTIONS.formatApp == False: return # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) Log.i(TAG, "Repackage APKs of %s" % (appDir)) for (dirpath, dirnames, filenames) in os.walk(appDir): dirnames = dirnames # no use, to avoid warning for dexFile in filenames: if dexFile.endswith(".dex"): apkFile = dexFile[0:-4] + ".apk" apkPath = os.path.dirname(dirpath) if not os.path.exists(os.path.join(apkPath, apkFile)): Log.d(TAG, "No apk matched with %s, Ignore" % dexFile) continue dexName = "classes.dex" Log.d(TAG, "Repackage %s" % (apkPath)) # Put the dex and apk in the same folder, and jar into the apk shutil.move(os.path.join(dirpath, dexFile), os.path.join(apkPath, dexName)) os.chdir(apkPath) Utils.runWithOutput(["jar", "uf", apkFile, dexName]) if os.path.exists(dexName): os.remove(dexName) shutil.rmtree(dirpath) os.chdir(oldDir)
def deoatFrwOatWithArch(frwDir, arch): """ De-oat framework oat """ if not OPTIONS.formatFrw: return Log.i(TAG, "De-oat files of oat-format in %s/oat" % frwDir) archDir = os.path.join(frwDir, arch) #odexDir = os.path.join(archDir, "odex") oatDir = os.path.join(frwDir, "oat", arch) if not os.path.exists(oatDir): return for item in os.listdir(oatDir): if item.endswith(".odex"): jarFile = os.path.join(frwDir, item[0:-5] + ".jar") if not OatZip.isDeodexed(jarFile): odexFile = os.path.join(oatDir, item) if OPTIONS.use_baksmali: bootOatPath = os.path.join(archDir, "boot.oat") jarOutDir = os.path.join(oatDir, item[0:-5] + ".jar.out") dexFile = os.path.join(oatDir, item[0:-5] + ".dex") Log.d( TAG, "baksmali deodex -b %s %s -o %s" % (bootOatPath, odexFile, jarOutDir)) Utils.runWithOutput([ OatZip.BAKSMALI, "deodex", "-b", bootOatPath, odexFile, "-o", jarOutDir ]) Log.d(TAG, "smali assemble %s -o %s" % (jarOutDir, dexFile)) Utils.runWithOutput([ OatZip.SMALI, "assemble", jarOutDir, "-o", dexFile ]) else: Utils.runWithOutput( [OatZip.OAT2DEX, odexFile, archDir])
def repackageApp(appDir): """ Repackage the classes.dex into apk of appDir """ if OPTIONS.formatApp == False: return # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) Log.i(TAG, "Repackage APKs of %s" %(appDir)) for (dirpath, dirnames, filenames) in os.walk(appDir): dirnames = dirnames # no use, to avoid warning for dexFile in filenames: if dexFile.endswith(".dex"): apkFile = dexFile[0:-4] + ".apk" apkPath = os.path.dirname(dirpath) if not os.path.exists(os.path.join(apkPath, apkFile)): Log.d(TAG, "No apk matched with %s, Ignore" %dexFile) continue dexName = "classes.dex" Log.d(TAG, "Repackage %s" %(apkPath)) # Put the dex and apk in the same folder, and jar into the apk shutil.move(os.path.join(dirpath, dexFile), os.path.join(apkPath, dexName)) os.chdir(apkPath) Utils.runWithOutput(["jar", "uf", apkFile, dexName]) if os.path.exists(dexName): os.remove(dexName) shutil.rmtree(dirpath) os.chdir(oldDir)
def senderWorker(self): while (True): proceeded = [] toRemove = [] for i in range(len(self.outgoingMSG)): msg = self.outgoingMSG[i] if (msg not in proceeded): if (msg.timer % 7 == 0): Log.d('SocketWrap', "Time for msg", msg.toJSON(), msg, "proceeded", msg in proceeded, 'len', len(proceeded)) if (msg.sendAttempt > 3): if (msg.timer > 25): #DB.addAlert(msg.unid, msg.setid,1006, msg = msg.toJSON()) msg.sendAttempt = -1 msg.cmd += ".error" if (msg.callback != None): msg.callback(msg) toRemove.append(i) else: Log.i('SocketWrap', "Reattempt to send message :" + msg.toJSON(), msg) msg.sendAttempt = msg.sendAttempt + 1 self.sendMsg(msg) proceeded.append(msg) Log.d('SocketWrap', "proceeded arr", msg in proceeded, 'len', len(proceeded)) msg.timer += 1 for i in range(len(toRemove)): try: del self.outgoingMSG[i] except: pass time.sleep(1)
def repackageFrw(frwDir, bootClassFolder): """ Repackage the classes.dex into jar of frwDir. """ if OPTIONS.formatFrw == False: return # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) # Some dexFiles are parted, such as framework-classes2.dex regex = re.compile("(.*)-(classes\d?).dex") Log.i(TAG, "Repackage JARs of %s" % (frwDir)) os.chdir(frwDir) for dexFile in os.listdir(bootClassFolder): if dexFile.endswith(".dex"): jarFile = dexFile[0:-4] + ".jar" dexName = "classes.dex" if not os.path.exists(jarFile): # Match out the jar file with regex matcher = regex.match(dexFile) if matcher != None: jarFile = matcher.group(1) + ".jar" dexName = matcher.group(2) + ".dex" Log.d(TAG, "Repackage %s" % (jarFile)) # Put the dex and framework's jar in the same folder, and jar into the jarFile shutil.move(os.path.join(bootClassFolder, dexFile), os.path.join(frwDir, dexName)) Utils.runWithOutput(["jar", "uf", jarFile, dexName]) if os.path.exists(dexName): os.remove(dexName) os.chdir(oldDir)
def parseValueToFormatSing(self, format, value): if format == 'sint': Log.d("Device/ValToForm", "value", value, (int(value) - 128)) return str(int(value) - 128) else: return value
def parseFormatToValueSing(self, format, value): if format == 'sint': Log.d("Device/FormToVal", "value", value, (int(value) + 128)) return str(int(value) + 128) else: return value
def reciveWorker(self): self.tcpConn.settimeout(10) try: if self.IP == '127.0.0.1' or self.IP == 'localhost': self.interface = 0 else: self.interface = 1 self.tcpConn.setblocking(1) self.sendMsg(Msg(cmd="device.heartbeat", socket=self, setid="0001")) #self.tcpConn.setblocking(0) i = 0 start = time.clock() while True: ready = False sleep(0.002) try: if ((time.clock() - start) > 5.0): self.tcpConn.sendall("\n".encode()) start = time.clock() data = self.tcpConn.recv(2048).decode('utf-8') if (len(data) > 3): for line in data.split("\n"): if (line != ""): Log.i('SocketWrap', "Received MSG: " + line) msg = Msg.fromJSONstr(self, line) if (msg.cmd == "ACK" or msg.cmd == "0"): msg.cmd = "ACK" Log.i( 'SocketWrap', "ACK recived. Looking for awating msgs " + msg.toJSON()) toRemove = [] for i in range(len(self.outgoingMSG)): if (i > len(self.outgoingMSG)): break msgS = self.outgoingMSG[i] if (msgS.setid == msg.setid and msgS.unid == msg.unid): Log.i( 'SocketWrap/ACK', "Msg for ACK found:" + msgS.toJSON(), msg) if (msgS.callback != None): Log.d('SocketWrap/ACK', "Calling callback") msgS.callback(msg) if (msgS.socket != None): msgS.socket.sendAck( setid=msgS.setid, unid=msgS.unid) toRemove.append(i) #break for i in range(len(toRemove)): try: del self.outgoingMSG[i] except: pass Log.i('SocketWrap', "ACK proceed complete") elif (msg.cmd == "device.reg.new" or msg.cmd == "10"): msg.cmd = "device.reg.new" self.registerDevice(msg.unid) #msg.callback = self.sendMsg #SocketWrap.outgoingMSG.append(msg) elif (msg.cmd == "device.reg.renew" or msg.cmd == "device.heartbeat" or msg.cmd == "12" or msg.cmd == "1"): Log.i('SocketWrap', "Got MSG: " + msg.toJSON()) allId = msg.unid + '' + msg.setid if allId not in SocketWrap.allUnits: Log.e( 'SocketWrap', "Not able to find device by ID " + allId + " . Registering as new") self.registerDevice( msg.unid, msg.setid) continue msg.device = SocketWrap.allUnits[allId] device = msg.device device.mySocketWrap = self device.setIsOnline(True) self.units[allId] = device SocketWrap.onlineUnits[allId] = device if (msg.cmd == "12"): msg.cmd = "device.reg.renew" elif (msg.cmd == "1"): msg.cmd = "device.heartbeat" if (msg.socket != None): msg.socket.sendAck(setid=msg.setid, unid=msg.unid) #else: self.sendAck(setid=msg.setid, unid=msg.unid) #if(device.isOnline ==False): Log.i( 'SocketWrap', "Dir: " + device.direction + ", nedStVal = %s" % device.needSetValue) if 'O' in device.direction and device.needSetValue == True: Log.i('SocketWrap', "Sending last missed value") device.needSetValue = False #self.tcpConn.send(allId+''+device.parseFormatToValue(device.lastValue)+'\r\n') DB.registerEvent( device.unid, device.setid, 'SocketWrap', 'device register renew.') device.setValue(device.lastValue) msg.callback = self.onNeedSetValueAck #SocketWrap.outgoingMSG.append(msg) elif (msg.cmd == "device.val.input" or msg.cmd == "20"): msg.cmd = "device.val.input" self.sendAck(setid=msg.setid, unid=msg.unid) self.onValueRecieved( msg.unid, msg.setid, msg.value) elif (msg.cmd == "device.val.set" or msg.cmd == "22"): msg.cmd = "device.val.set" allId = msg.unid + '' + msg.setid if allId not in SocketWrap.allUnits: Log.e('SocketWrap', "Not able to get device ID") return device = SocketWrap.allUnits[allId] Log.d('DeviceSetVal', "[1]") device.setValue(msg.value, callback=sendMsg) Log.d('DeviceSetVal', "[2]") msg.callback = self.sendMsg #SocketWrap.outgoingMSG.append(msg) #socketWrap.onValueRecieved(msg.unid,msg.setid,value) Log.d('DeviceSetVal', "[3]") Log.i('SocketWrap', "MSG proceed complete") except ValueError as e: Log.e('SocketWrap/ValueError', "While E " + str(e), traceback.format_exc()) '''except socket.timeout: #self.tcpConn.setblocking(0) try: if i == 5: i = 0 self.tcpConn.send("\n") i+=1 except: break #pass except socket.error as e: #print("[D] While E ", e) try: if i == 25: i = 0 #self.tcpConn.send("\n") self.tcpConn.send(" ") i+=1 except: break #pass except Exception as e: exc = str(e) Log.e('SocketWrap/ValueError',exc)''' #finally: except socket.error: Log.e('SocketWrap/Thread/1', "Closing socket: %s " % socket.error, traceback.format_exc()) except Exception as e: exc = str(e) Log.e('SocketWrap/Thread/2', exc, traceback.format_exc()) Log.i('SocketWrap', "Closing driver ") #self.tcpConn.shutdown(2) self.tcpConn.close() self.onClientDisConnected() Log.i('SocketWrap', "Client disConnected: " + self.IP + ":" + self.port) if 'socketWrap' in locals(): del self
def deodexOneFile(odexFile, deodexFile): """ De-odex one file. """ if not odexFile.endswith(".odex"): return temp = tempfile.mktemp() # Phase 1: Baksmali the odex file cmd = ["baksmali", "-x", odexFile, "-d", "framework", "-I", "-o", os.path.join(temp, "out")] if OPTIONS.apiLevel != None: cmd.extend(["-a", OPTIONS.apiLevel]) if OPTIONS.classpath != None: cmd.extend(["-c", OPTIONS.classpath]) cmd = " ".join(cmd) Log.d(TAG, cmd) Log.d(TAG, commands.getoutput(cmd)) # Phase 2: Smali the files into dex oldDir = os.path.abspath(os.curdir) os.chdir(temp) cmd = "smali out/ -o classes.dex" Log.d(TAG, commands.getoutput(cmd)) #Utils.runWithOutput(["smali", "out", "-o", "classes.dex"]) # Phase 3: Package if os.path.exists(deodexFile): #cmd = ["jar", "uf", deodexFile, "classes.dex"] cmd = "jar uf %s classes.dex" % deodexFile else: #cmd = ["jar", "cf", deodexFile, "classes.dex"] cmd = "jar cf %s classes.dex" % deodexFile Log.d(TAG, commands.getoutput(cmd)) #Utils.runWithOutput(cmd) os.chdir(oldDir) if os.path.exists(odexFile): os.remove(odexFile) Log.i(TAG, "Delete %s" %temp) shutil.rmtree(temp) # Phase 4: zipalign #Utils.runWithOutput(["zipalign", "4", deodexFile, deodexFile+".aligned"]) #Utils.runWithOutput(["mv", deodexFile+".aligned", deodexFile]) cmd = "zipalign 4 %s %s" %(deodexFile, deodexFile+".aligned") Log.d(TAG, commands.getoutput(cmd)) cmd = "mv %s %s" %(deodexFile+".aligned", deodexFile) Log.d(TAG, cmd)
def dealWithAdditionalApks(systemDir, frwDir, arch, arch2, allAppDirs): ''' deal with additional apks ''' if OPTIONS.formatApp == False: return # Keep the old directory, we will change back after some operations. oldDir = os.path.abspath(os.curdir) bootClassFolderArch = os.path.join(frwDir, arch) bootClassFolderArch2 = os.path.join(frwDir, arch2) for (dirpath, dirnames, filenames) in os.walk(systemDir): # Exclude scanned directories if dirpath in allAppDirs: continue dirnames = dirnames # no use, to avoid warning for filename in filenames: if filename.endswith(".apk") or filename.endswith(".jar"): apkFile = os.path.join(dirpath, filename) if not OatZip.check_validate(apkFile, arch, arch2): continue archDir = os.path.join(dirpath, "oat", arch) #app name app = filename[0:-4] if os.path.exists(archDir): if not OatZip.isDeodexed(apkFile): odexFile = os.path.join(archDir, app + ".odex") if os.path.exists(odexFile): if OPTIONS.use_baksmali: bootOatPath = os.path.join( frwDir, arch, "boot.oat") dexOutDir = os.path.join( archDir, app + ".out") dexFile = os.path.join( archDir, app + ".dex") Log.d( TAG, "baksmali deodex -b %s %s -o %s" % (bootOatPath, odexFile, dexOutDir)) Utils.runWithOutput([ OatZip.BAKSMALI, "deodex", "-b", bootOatPath, odexFile, "-o", dexOutDir ]) Log.d( TAG, "smali assemble %s -o %s" % (dexOutDir, dexFile)) Utils.runWithOutput([ OatZip.SMALI, "assemble", dexOutDir, "-o", dexFile ]) else: Utils.runWithOutput([ OatZip.OAT2DEX, odexFile, bootClassFolderArch ]) OatZip.packageDexToAppWithArch(apkFile, arch) #rm -rf $appdir/$app/$arch shutil.rmtree(archDir) arch2Dir = os.path.join(dirpath, "oat", arch2) if os.path.exists(arch2Dir): if not OatZip.isDeodexed(apkFile): odexFile2 = os.path.join(arch2Dir, app + ".odex") if os.path.exists(odexFile2): if OPTIONS.use_baksmali: bootOatPath2 = os.path.join( frwDir, arch2, "boot.oat") dexOutDir2 = os.path.join( arch2Dir, app + ".out") dexFile2 = os.path.join( arch2Dir, app + ".dex") Log.d( TAG, "baksmali deodex -b %s %s -o %s" % (bootOatPath2, odexFile2, dexOutDir2)) Utils.runWithOutput([ OatZip.BAKSMALI, "deodex", "-b", bootOatPath2, odexFile2, "-o", dexOutDir2 ]) Log.d( TAG, "smali assemble %s -o %s" % (dexOutDir2, dexFile2)) Utils.runWithOutput([ OatZip.SMALI, "assemble", dexOutDir2, "-o", dexFile2 ]) else: Utils.runWithOutput([ OatZip.OAT2DEX, odexFile2, bootClassFolderArch2 ]) OatZip.packageDexToAppWithArch(apkFile, arch2) #rm -rf $appdir/$app/$arch shutil.rmtree(arch2Dir) if os.path.exists(os.path.join(dirpath, "oat")): shutil.rmtree(os.path.join(dirpath, "oat"))
def deoatAppWithArch(appsDir, frwDir, arch, arch2): """ De-oat app """ if OPTIONS.formatApp == False: return Log.i(TAG, "De-oat files of oat-format in %s" % (appsDir)) bootClassFolderArch = os.path.join(frwDir, arch + "-odex") bootClassFolderArch2 = os.path.join(frwDir, arch2 + "-odex") #for app in $( ls $appdir ); do for app in os.listdir(appsDir): appPath = os.path.join(appsDir, app) apkFile = os.path.join(appPath, app + ".apk") archPath = os.path.join(appPath, "oat", arch) #if [[ -d "$appdir/$app/$arch" ]]; if os.path.exists(archPath): odexFile = os.path.join(archPath, app + ".odex") if OPTIONS.use_baksmali: bootOatPath = os.path.join(frwDir, arch, "boot.oat") dexOutDir = os.path.join(archPath, app + ".out") dexFile = os.path.join(archPath, app + ".dex") Log.d( TAG, "baksmali deodex -b %s %s -o %s" % (bootOatPath, odexFile, dexOutDir)) Utils.runWithOutput([ OatZip.BAKSMALI, "deodex", "-b", bootOatPath, odexFile, "-o", dexOutDir ]) Log.d(TAG, "smali assemble %s -o %s" % (dexOutDir, dexFile)) Utils.runWithOutput( [OatZip.SMALI, "assemble", dexOutDir, "-o", dexFile]) else: #java -Xmx512m -jar $oat2dex $appdir/$app/$arch/$app.odex $framedir/$arch/odex Utils.runWithOutput( [OatZip.OAT2DEX, odexFile, bootClassFolderArch]) else: # if exists arch2 if arch2.strip(): arch2Path = os.path.join(appPath, "oat", arch2) if os.path.exists(arch2Path): odexFile2 = os.path.join(arch2Path, app + ".odex") if OPTIONS.use_baksmali: bootOatPath2 = os.path.join( frwDir, arch2, "boot.oat") dexOutDir2 = os.path.join(arch2Path, app + ".out") dexFile2 = os.path.join(arch2Path, app + ".dex") Log.d( TAG, "baksmali deodex -b %s %s -o %s" % (bootOatPath2, odexFile2, dexOutDir2)) Utils.runWithOutput([ OatZip.BAKSMALI, "deodex", "-b", bootOatPath2, odexFile2, "-o", dexOutDir2 ]) Log.d( TAG, "smali assemble %s -o %s" % (dexOutDir2, dexFile2)) Utils.runWithOutput([ OatZip.SMALI, "assemble", dexOutDir2, "-o", dexFile2 ]) else: Utils.runWithOutput([ OatZip.OAT2DEX, odexFile2, bootClassFolderArch2 ])
def deodexOneFile(odexFile, deodexFile): """ De-odex one file. """ if not odexFile.endswith(".odex"): return temp = tempfile.mktemp() # Phase 1: Baksmali the odex file cmd = [ "baksmali", "-x", odexFile, "-d", "framework", "-I", "-o", os.path.join(temp, "out") ] if OPTIONS.apiLevel != None: cmd.extend(["-a", OPTIONS.apiLevel]) if OPTIONS.classpath != None: cmd.extend(["-c", OPTIONS.classpath]) cmd = " ".join(cmd) Log.d(TAG, cmd) Log.d(TAG, commands.getoutput(cmd)) # Phase 2: Smali the files into dex oldDir = os.path.abspath(os.curdir) os.chdir(temp) cmd = "smali out/ -o classes.dex" Log.d(TAG, commands.getoutput(cmd)) #Utils.runWithOutput(["smali", "out", "-o", "classes.dex"]) # Phase 3: Package if os.path.exists(deodexFile): #cmd = ["jar", "uf", deodexFile, "classes.dex"] cmd = "jar uf %s classes.dex" % deodexFile else: #cmd = ["jar", "cf", deodexFile, "classes.dex"] cmd = "jar cf %s classes.dex" % deodexFile Log.d(TAG, commands.getoutput(cmd)) #Utils.runWithOutput(cmd) os.chdir(oldDir) if os.path.exists(odexFile): os.remove(odexFile) Log.i(TAG, "Delete %s" % temp) shutil.rmtree(temp) # Phase 4: zipalign #Utils.runWithOutput(["zipalign", "4", deodexFile, deodexFile+".aligned"]) #Utils.runWithOutput(["mv", deodexFile+".aligned", deodexFile]) cmd = "zipalign 4 %s %s" % (deodexFile, deodexFile + ".aligned") Log.d(TAG, commands.getoutput(cmd)) cmd = "mv %s %s" % (deodexFile + ".aligned", deodexFile) Log.d(TAG, cmd)
def client_thread(conn, addr): conn.settimeout(7) conn.setblocking(1) try: #conn.setblocking(0) i =0 while API.threadRun: ready = False time.sleep(0.2) try: data = conn.recv(1024) if not data: break #print(data) jsonObj = json.loads(data.decode('utf-8')) if ('token' not in jsonObj or jsonObj['token'] != API.token): conn.send(json.dumps({"errcode": "2003", "msg": "Wrong API token"}).encode()) conn.close() else: payload = jsonObj['data'] if ('cmd' in payload): cmd = payload['cmd'] if (cmd == 'device.value.set'): device = Device.findDeviceById(payload['unitId'],payload['setId']) Log.i('API/OnValueACK',"Is device online: %i"%device.isOnline) while(API.socketAwaitACK !=None): continue if (device != None): API.socketAwaitACK = conn device.setValue(payload['value'].strip(), callback=API.onValueSetACK) else: conn.send(json.dumps({"errcode": "3002", "msg": "No such device", "payload":payload}).encode()) elif (cmd == 'device.value.schedule'): device = Device.findDeviceById(payload['unitId'],payload['setId']) Log.i('API/OnValueSchedule',"Is device online: %i"%device.isOnline) if (device != None): value = payload['value'].strip() print("'",value,"'") date = payload['date'] unid = device.unid setid = device.setid scriptStr = f''' newVal = '{value}' unit = Device.findDeviceById('{unid}','{setid}') smsStr = 'sms,all,*' if unit != None: unit.setValue(newVal) smsStr = smsStr + 'Value {value} set ok' else: smsStr = smsStr + 'Error setting value {value}' modems = Device.findDeviceById('0078','') if len(modems)>0: for key, modem in modems.items(): modem.setValue(smsStr) ''' uscript = ''.join(random.choice(string.ascii_uppercase + string.digits) for i in range(5))+".py" dir = common.config['HubServer']['USCRIPTS_PATH']+'Temp/' path = dir+uscript if not os.path.exists(dir): os.makedirs(dir) outFile = open(path, "w+", encoding="utf-8") outFile.write(scriptStr) outFile.close() DB.sqlInsert(f""" INSERT INTO `schedule` ( `type`, `time`, `lastTimeRun`, `nextTimeRun`, `script_name`, `active` ) VALUES ( '1', '{date}', '', '', '{uscript}', '1' ); """) from Tasker import Task Task.getAllTasks() conn.send(json.dumps({"errcode": "0", "data": {}}).encode()) else: conn.send(json.dumps({"errcode": "3002", "msg": "No such device", "payload":payload}).encode()) elif (cmd == 'device.conf.set'): device = Device.findDeviceById(payload['unitId'],payload['setId']) Log.i('API/OnValueACK',"Is device online: %i"%device.isOnline) while(API.socketAwaitACK !=None): continue if (device != None): if(device.isOnline): API.socketAwaitACK = conn device.setSettings(payload['value'], callback=API.onValueSetACK) else: conn.send(json.dumps({"errcode": "3003", "msg": "Device offline", "payload":payload}).encode()) else: conn.send(json.dumps({"errcode": "3002", "msg": "No such device", "payload":payload}).encode()) elif (cmd == 'device.reg.notif'): unid = payload['unitId'] setid = payload['setId'] devices = Device.findDeviceById(unid) msg = Msg(unid = unid, setid = setid, cmd="device.reg.notif") while(API.socketAwaitACK !=None): continue isNeedAll = True Log.d("API/NotifyNew",devices) for key, device in devices.items(): if(device.mySocketWrap != None): API.socketAwaitACK = conn device.mySocketWrap.sendMsg(msg) isNeedAll = False break Log.d("API/NotifyNew","[4]Point") if isNeedAll: for socketWrap in SocketWrap.allSockets: socketWrap.sendMsg(msg) #print("Disc/Is device online",SocketWrap.allUnits["00B40172"].isOnline) conn.send(json.dumps({"errcode": "0", "data": {}}).encode()) elif ('wifi.update' in cmd): interface = 'wlan0' name = payload['ssid'] password = payload['password'] os.system('iwconfig ' + interface + ' essid ' + name + ' key ' + password) conn.send(json.dumps({"errcode": "0", "data": {}}).encode()) elif ('config.update' in cmd): if ('db' in cmd): common.config.set('DataBase', 'HOST', payload['host']) common.config.set('DataBase', 'USER', payload['login']) common.config.set('DataBase', 'PASSW', payload['password']) common.config.set('DataBase', 'DB', payload['dbname']) common.config.set('DataBase', 'CHARSET', payload['charset']) DB.close() DB.start() Log.i('API/ConfigUpdate/DB',"MySQL reconnect") conn.send(json.dumps({"errcode": "0", "data": {}}).encode()) elif ('schedule.update' in cmd): from Tasker import Task Task.getAllTasks() conn.send(json.dumps({"errcode": "0", "data": {}}).encode()) elif ('uscript.run' in cmd): from Tasker import Task res = Task.runUserScriptEnv(payload['uscript']) conn.send(json.dumps({"errcode": "0", "data": res}).encode()) elif (cmd == 'system.stat.get'): response = {} response['Hub_version'] = common.config['HubServer']['VERSION'] if ('PortalConnect' in common.config): response['Hub_id'] = common.config['PortalConnect']['id'] response['CPU_load'] = str(psutil.cpu_percent()) + '%' memory = psutil.virtual_memory() # Divide from Bytes -> KB -> MB available = round(memory.available/1024.0/1024.0,1) total = round(memory.total/1024.0/1024.0,1) response['Memory'] = str(available) + 'MB free / ' + str(total) + 'MB total ( ' + str(memory.percent) + '% )' disk = psutil.disk_usage('/') disk_total = round(disk.total / 2**30,2) # GiB. disk_used = round(disk.used / 2**30,2) disk_free = round(disk.free / 2**30,2) disk_percent_used = disk.percent response['Disk'] = str(disk_free) + 'GB free / ' + str(disk_total) + 'GB total ( ' + str(disk_percent_used) + '% )' conn.send(json.dumps({"errcode": "0", "data": response}).encode()) elif (cmd == 'system.cmd'): shell = payload['shell'] Log.i('API',"Executing shell cmd %s"%shell) #res = str(check_output(shell.split(" ") )) res = subprocess.Popen(shell, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=10,shell=True, cwd=os.path.dirname(os.path.realpath(__file__))+"/../" ) stdout,stderr = res.communicate() Log.i('API/',"Executing shell cmd res %s"%stdout) res = stdout.decode('utf-8') resLo = res.lower() if ("error" in resLo or "not exists" in resLo or "forbidden" in resLo or "not allow" in resLo or "failed" in resLo): conn.send(json.dumps({"errcode": "2006", "msg": res}).encode()) else: conn.send(json.dumps({"errcode": "0", "data": res}).encode()) else: conn.send(json.dumps({"errcode": "2005", "data": {'cmd':cmd}}).encode()) except socket.timeout: try: if i == 5: i = 0 conn.send("\n") i+=1 except: break except socket.error as e: try: if i == 25: i = 0 conn.send(" ") i+=1 except: break except ValueError as e: Log.e('API/ValueError',"While E: %s"%e) except: conn.send(json.dumps({"errcode": "2003", "msg": "Error proceeding request"}).encode()) Log.e('API/ValueError',"During API request execution fail") except socket.error as e: Log.e('API/ValueError'," Closing driver: %s"% e) except ValueError as e: Log.e('API/ValueError'," Closing driver: %s"% e) conn.close() Log.i('API/',"API client disconnected: " + addr[0] + ":" + str(addr[1]))