Cleaned up the python in the app and made app spawning faster / more reliable

This commit is contained in:
Cameron Lowell Palmer 2018-02-01 16:03:00 +01:00 committed by Cameron Lowell Palmer
parent 42ff6d12b8
commit 90c17279d2
5 changed files with 289 additions and 314 deletions

4
.gitignore vendored
View File

@ -1 +1,5 @@
.DS_Store
.idea
*.ipa
frida/

View File

@ -1,50 +1,37 @@
# frida-ios-dump
pull decrypted ipa from jailbreak device
Pull a decrypted IPA from a jailbroken device
### Usage
## Usage
## 1. install [frida](http://www.frida.re/) on device and mac
## 2. iproxy 2222 22
## 3. ./dump.py 微信
1. Install [frida](http://www.frida.re/) on device and mac
2. Run usbmuxd/iproxy SSH forwarding over USB (Default 2222 -> 22)
3. Run ./dump.py `Display name` or `Bundle identifier`
```
➜ frida-ios-dump ./dump.py 微信
open target app......
start dump target app......
start dump /var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/WeChat
WeChat 100% 68MB 11.4MB/s 00:05
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/WCDB.framework/WCDB
WCDB 100% 2555KB 11.0MB/s 00:00
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/MMCommon.framework/MMCommon
MMCommon 100% 979KB 10.6MB/s 00:00
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/MultiMedia.framework/MultiMedia
MultiMedia 100% 6801KB 11.1MB/s 00:00
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/mars.framework/mars
mars 100% 7462KB 11.1MB/s 00:00
AppIcon60x60@2x.png 100% 2253 230.9KB/s 00:00
AppIcon60x60@3x.png 100% 4334 834.8KB/s 00:00
AppIcon76x76@2x~ipad.png 100% 2659 620.6KB/s 00:00
AppIcon76x76~ipad.png 100% 1523 358.0KB/s 00:00
AppIcon83.5x83.5@2x~ipad.png 100% 2725 568.9KB/s 00:00
Assets.car 100% 10MB 11.1MB/s 00:00
.......
AppIntentVocabulary.plist 100% 197 52.9KB/s 00:00
AppIntentVocabulary.plist 100% 167 43.9KB/s 00:00
AppIntentVocabulary.plist 100% 187 50.2KB/s 00:00
InfoPlist.strings 100% 1720 416.4KB/s 00:00
TipsPressTalk@2x.png 100% 14KB 2.2MB/s 00:00
mm.strings 100% 404KB 10.2MB/s 00:00
network_setting.html 100% 1695 450.4KB/s 00:00
InfoPlist.strings 100% 1822 454.1KB/s 00:00
mm.strings 100% 409KB 10.2MB/s 00:00
network_setting.html 100% 1819 477.5KB/s 00:00
InfoPlist.strings 100% 1814 466.8KB/s 00:00
mm.strings 100% 409KB 10.3MB/s 00:00
network_setting.html 100% 1819 404.9KB/s 00:00
./dump.py Aftenposten
Start the target app Aftenposten
Dumping Aftenposten to /var/folders/wn/9v1hs8ds6nv_xj7g95zxyl140000gn/T
start dump /var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/AftenpostenApp
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/AFNetworking.framework/AFNetworking
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/ATInternet_iOS_ObjC_SDK.framework/ATInternet_iOS_ObjC_SDK
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/SPTEventCollector.framework/SPTEventCollector
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/SPiDSDK.framework/SPiDSDK
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCore.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreData.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreGraphics.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreImage.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreLocation.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftDarwin.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftDispatch.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftFoundation.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftObjectiveC.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftQuartzCore.dylib
start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftUIKit.dylib
Generating Aftenposten.ipa
Done.
```
congratulations!!! You've got a decrypted ipa file.
Congratulations!!! You've got a decrypted IPA file.
Drag to [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev), Happy hacking!
Drag to [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev), Happy hacking!

52
app.js
View File

@ -1,52 +0,0 @@
//by: AloneMonkey
const LSApplicationWorkspace = ObjC.classes.LSApplicationWorkspace;
function openApplication(appid){
const workspace = LSApplicationWorkspace.defaultWorkspace();
return workspace.openApplicationWithBundleID_(appid);
}
function getbundleid(name){
const workspace = LSApplicationWorkspace.defaultWorkspace();
const apps = workspace.allApplications();
var result;
for(var index = 0; index < apps.count(); index++){
var proxy = apps.objectAtIndex_(index);
if(proxy.localizedName() && proxy.localizedName().toString() == name){
return proxy.bundleIdentifier().toString();
}
}
return ""
};
function getdisplayname(bundleid){
const workspace = LSApplicationWorkspace.defaultWorkspace();
const apps = workspace.allApplications();
var result;
for(var index = 0; index < apps.count(); index++){
var proxy = apps.objectAtIndex_(index);
if(proxy.bundleIdentifier() && proxy.bundleIdentifier().toString() == bundleid){
return proxy.localizedName().toString();
}
}
return ""
}
function handleMessage(message) {
var bundleid;
var displayname;
if(message['name']){
displayname = message['name']
bundleid = getbundleid(displayname);
}else if(message['bundleid']){
bundleid = message['bundleid']
displayname = getdisplayname(bundleid);
}
if(bundleid.length > 0){
openApplication(bundleid);
}
send({ opened: displayname });
}
recv(handleMessage);

14
dump.js
View File

@ -175,9 +175,9 @@ var LC_SEGMENT_64 = 0x19;
var LC_ENCRYPTION_INFO = 0x21;
var LC_ENCRYPTION_INFO_64 = 0x2C;
function pad(str, n) {
return Array(n-str.length+1).join("0")+str;
}
function pad(str, n) {
return Array(n-str.length+1).join("0")+str;
}
function swap32(value) {
value = pad(value.toString(16),8)
@ -214,7 +214,7 @@ function dumpModule(name) {
if(!access(allocStr(newmodpath),0)){
remove(allocStr(newmodpath));
}
var fmodule = open(newmodpath, O_CREAT | O_RDWR, 0);
var foldmodule = open(oldmodpath, O_RDONLY, 0);
@ -288,7 +288,7 @@ function dumpModule(name) {
var segments = [];
for (var i = 0; i < ncmds; i++) {
var cmd = getU32(modbase.add(off));
var cmdsize = getU32(modbase.add(off + 4));
var cmdsize = getU32(modbase.add(off + 4));
if (cmd == LC_ENCRYPTION_INFO || cmd == LC_ENCRYPTION_INFO_64) {
offset_cryptid = off + 16;
crypt_off = getU32(modbase.add(off + 8));
@ -305,11 +305,11 @@ function dumpModule(name) {
lseek(fmodule, crypt_off, SEEK_SET);
write(fmodule, modbase.add(crypt_off), crypt_size);
}
close(fmodule);
close(foldmodule);
return newmodpath
}
}
function handleMessage(message) {
//start dump

462
dump.py
View File

@ -1,270 +1,306 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Author : AloneMonkey
#blog: www.alonemonkey.com
# Author : AloneMonkey
# blog: www.alonemonkey.com
import sys
import codecs
import frida
import threading
import threading
import os
import shutil
import time
import getopt
import tempfile
import subprocess
reload(sys)
sys.setdefaultencoding('utf8')
DUMP_JS = './dump.js'
APP_JS = './app.js'
OUTPUT = "Payload"
script_dir = os.path.dirname(os.path.realpath(__file__))
DUMP_JS = os.path.join(script_dir, 'dump.js')
SSH_USER_HOST='root@localhost:'
SSH_PORT=2222
TEMP_DIR = tempfile.gettempdir()
PAYLOAD_DIR = 'Payload'
PAYLOAD_PATH = os.path.join(TEMP_DIR, PAYLOAD_DIR)
file_dict = {}
opened = threading.Event()
finished = threading.Event()
global session
global name
#show usage
# show usage
def usage():
print '-------------------------frida-ios-dump(by AloneMonkey v2.0)----------------------------'
print '\t%-20s\t%s' % ('-h,--help','Show help menu.');
print '\t%-20s\t%s' % ('displayname','Decrypt the application of the specified display name. ps: ./dump.py 微信');
print '\t%-20s\t%s' % ('-l','List the app has been installed.');
print '\t%-20s\t%s' % ('-b bundleid','Decrypt the application of the specified bundleid. ps: ./dump.py com.tencent.xin');
exit(0)
print '-------------------------frida-ios-dump(by AloneMonkey v2.0)----------------------------'
print '\t%-20s\t%s' % ('-h,--help', 'Show help menu.')
print '\t%-20s\t%s' % ('name', 'Decrypt the application with the specified display name or bundle identifier. ps: ./dump.py 微信')
print '\t%-20s\t%s' % ('-l', 'List the installed apps.')
def get_usb_iphone():
dManager = frida.get_device_manager();
changed = threading.Event()
def on_changed():
changed.set()
dManager.on('changed',on_changed)
dManager = frida.get_device_manager()
changed = threading.Event()
device = None
while device is None:
devices = [dev for dev in dManager.enumerate_devices() if dev.type == 'tether']
if len(devices) == 0:
print 'Waiting for usb device...'
changed.wait()
else:
device = devices[0]
def on_changed():
changed.set()
dManager.off('changed',on_changed)
return device
dManager.on('changed', on_changed)
def gen_ipa(target):
try:
app_name = file_dict["app"]
for key, value in file_dict.items():
if key != "app":
shutil.move(target +"/"+ key, target + "/" + app_name + "/" + value);
(shotname,extension) = os.path.splitext(app_name)
os.system(u''.join(("zip -qr ", name.replace(" ", "\\ "), ".ipa ./Payload")).encode('utf-8').strip());
os.system("rm -rf ./Payload");
except Exception as e:
print e
finished.set();
device = None
while device is None:
devices = [dev for dev in dManager.enumerate_devices() if dev.type == 'tether']
if len(devices) == 0:
print 'Waiting for USB device...'
changed.wait()
else:
device = devices[0]
dManager.off('changed', on_changed)
return device
def generate_ipa(path, display_name, bundle_identifier):
ipa_filename = display_name.replace(' ', '\\ ') + '.ipa'
print 'Generating {}'.format(ipa_filename)
try:
app_name = file_dict['app']
for key, value in file_dict.items():
from_dir = os.path.join(path, key)
to_dir = os.path.join(path, app_name, value)
if key != 'app':
shutil.move(from_dir, to_dir)
target_dir = './' + PAYLOAD_DIR
zip_args = ('zip', '-qr', os.path.join(os.getcwd(), ipa_filename), target_dir)
subprocess.check_call(zip_args, cwd=TEMP_DIR)
shutil.rmtree(PAYLOAD_PATH)
print
except Exception as e:
print e
finished.set()
def on_message(message, data):
global name
if message.has_key('payload'):
payload = message['payload']
if payload.has_key('opened'):
name = payload['opened']
if payload.has_key('dump'):
origin_path = payload['path']
dump_path = payload['dump']
scp_from = SSH_USER_HOST + dump_path.replace(' ', '\ ')
scp_to = PAYLOAD_PATH + u'/'
scp_args = ('scp', '-P {}'.format(SSH_PORT), scp_from, scp_to)
subprocess.check_call(scp_args)
chmod_dir = os.path.join(PAYLOAD_PATH, os.path.basename(dump_path))
chmod_args = ('chmod', '655', chmod_dir)
subprocess.check_call(chmod_args)
index = origin_path.find('.app/')
file_dict[os.path.basename(dump_path)] = origin_path[index + 5:]
if payload.has_key('app'):
app_path = payload['app']
scp_from = SSH_USER_HOST + app_path.replace(' ', '\ ')
scp_to = PAYLOAD_PATH + u'/'
scp_args = ('scp', '-r', '-P {}'.format(SSH_PORT), scp_from, scp_to)
subprocess.check_call(scp_args)
chmod_dir = os.path.join(PAYLOAD_PATH, os.path.basename(app_path))
chmod_args = ('chmod', '755', chmod_dir)
subprocess.check_call(chmod_args)
file_dict['app'] = os.path.basename(app_path)
if payload.has_key('done'):
finished.set()
def on_message(message,data):
global name;
if message.has_key('payload'):
payload = message['payload']
if payload.has_key("opened"):
name = payload["opened"]
opened.set();
if payload.has_key("dump"):
orign_path = payload["path"]
dumppath = payload["dump"]
os.system(u''.join(("scp -P 2222 root@localhost:", dumppath.replace(" ", "\\\\\ "), u" ./" + OUTPUT + u"/")).encode('utf-8').strip())
os.system(u''.join(("chmod 655 ", u'./' + OUTPUT + u'/', os.path.basename(dumppath.replace(" ", "\\ ")))).encode('utf-8').strip())
index = orign_path.find(".app/")
file_dict[os.path.basename(dumppath)] = orign_path[index+5:]
if payload.has_key("app"):
apppath = payload["app"]
os.system(u''.join(("scp -r -P 2222 root@localhost:", apppath.replace(" ", "\\\\\ "), u" ./" + OUTPUT + u"/")).encode('utf-8').strip())
os.system(u''.join(("chmod 755 ", u'./' + OUTPUT + u'/', os.path.basename(apppath.replace(" ", "\\ ")))).encode('utf-8').strip())
file_dict["app"] = os.path.basename(apppath)
if payload.has_key("done"):
gen_ipa(os.getcwd()+"/"+OUTPUT)
finished.set();
def compare_applications(a, b):
a_is_running = a.pid != 0
b_is_running = b.pid != 0
if a_is_running == b_is_running:
if a.name > b.name:
return 1
elif a.name < b.name:
return -1
else:
return 0
elif a_is_running:
a_is_running = a.pid != 0
b_is_running = b.pid != 0
if a_is_running == b_is_running:
if a.name > b.name:
return 1
elif a.name < b.name:
return -1
else:
return 1
return 0
elif a_is_running:
return -1
else:
return 1
def cmp_to_key(mycmp):
"Convert a cmp= function into a key= function"
class K:
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return K
'Convert a cmp= function into a key= function'
def get_applications():
device = get_usb_iphone()
class K:
def __init__(self, obj, *args):
self.obj = obj
try:
applications = device.enumerate_applications()
except Exception as e:
print "Failed to enumerate applications: %s" % e
exit(1)
return
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
return applications
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def list_applications():
applications = get_applications()
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
if len(applications) > 0:
pid_column_width = max(map(lambda app: len("%d" % app.pid), applications))
name_column_width = max(map(lambda app: len(app.name), applications))
identifier_column_width = max(map(lambda app: len(app.identifier), applications))
else:
pid_column_width = 0
name_column_width = 0
identifier_column_width = 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
header_format = "%" + str(pid_column_width) + "s " + "%-" + str(name_column_width) + "s " + "%-" + str(identifier_column_width) + "s"
print header_format % ("PID", "Name", "Identifier")
print "%s %s %s" % (pid_column_width * "-", name_column_width * "-", identifier_column_width * "-")
line_format = "%" + str(pid_column_width) + "s " + "%-" + str(name_column_width) + "s " + "%-" + str(identifier_column_width) + "s"
for app in sorted(applications, key=cmp_to_key(compare_applications)):
if app.pid == 0:
print line_format % ("-", app.name, app.identifier)
else:
print line_format % (app.pid, app.name, app.identifier)
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
def get_pid_by_bundleid(bundleid):
applications = get_applications()
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return [app.pid for app in applications if app.identifier == bundleid][0]
def find_target_app(isbundleid, value):
applications = get_applications()
return K
def get_applications(device):
try:
applications = device.enumerate_applications()
except Exception as e:
print 'Failed to enumerate applications: %s' % e
return
return applications
def list_applications(device):
applications = get_applications(device)
if len(applications) > 0:
pid_column_width = max(map(lambda app: len('{}'.format(app.pid)), applications))
name_column_width = max(map(lambda app: len(app.name), applications))
identifier_column_width = max(map(lambda app: len(app.identifier), applications))
else:
pid_column_width = 0
name_column_width = 0
identifier_column_width = 0
header_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str(
identifier_column_width) + 's'
print header_format % ('PID', 'Name', 'Identifier')
print '%s %s %s' % (pid_column_width * '-', name_column_width * '-', identifier_column_width * '-')
line_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str(
identifier_column_width) + 's'
for app in sorted(applications, key=cmp_to_key(compare_applications)):
if app.pid == 0:
print line_format % ('-', app.name, app.identifier)
else:
print line_format % (app.pid, app.name, app.identifier)
if not isbundleid:
return [app for app in applications if app.name == value]
else:
return [app for app in applications if app.identifier == value]
def load_js_file(session, filename):
source = ''
with codecs.open(filename,'r','utf-8') as f:
source = source + f.read();
script = session.create_script(source);
script.on("message",on_message)
script.load()
return script
source = ''
with codecs.open(filename, 'r', 'utf-8') as f:
source = source + f.read()
script = session.create_script(source)
script.on('message', on_message)
script.load()
return script
def clear_and_quit(session):
if session:
session.detach()
sys.exit(0)
def create_dir(path):
path = path.strip()
path = path.rstrip("\\")
if not os.path.exists(path):
os.makedirs(path)
else:
print path + u" is existed!";
path = path.strip()
path = path.rstrip('\\')
if os.path.exists(path):
print 'Removing {}'.format(path)
shutil.rmtree(path)
os.makedirs(path)
def open_target_app(isbundleid, value):
device = get_usb_iphone();
name = u'SpringBoard';
print "open target app......"
session = device.attach(name);
script = load_js_file(session, APP_JS);
if not isbundleid:
script.post({'name': value})
else:
script.post({'bundleid': value})
opened.wait();
session.detach();
create_dir(os.getcwd()+"/"+OUTPUT)
print 'Waiting for the application to open......'
time.sleep(5);
def start_dump(target):
print "start dump target app......"
device = get_usb_iphone();
session = device.attach(target);
script = load_js_file(session, DUMP_JS);
script.post("dump");
finished.wait();
clear_and_quit(session);
def open_target_app(device, name_or_bundleid):
print 'Start the target app {}'.format(name_or_bundleid)
def dump_by_display_name(display_name):
open_target_app( 0, display_name)
start_dump(display_name);
display_name = ''
bundle_identifier = ''
for application in get_applications(device):
if name_or_bundleid == application.identifier or name_or_bundleid == application.name:
display_name = application.name
bundle_identifier = application.identifier
def dump_by_bundleid(bundleid):
open_target_app( 1, bundleid)
start_dump(get_pid_by_bundleid(bundleid));
try:
pid = device.spawn([bundle_identifier])
device.resume(pid)
create_dir(PAYLOAD_PATH)
time.sleep(1)
except Exception as e:
print e
return (pid, display_name, bundle_identifier)
def start_dump(device, pid, display_name, bundle_identifier):
print 'Dumping {} to {}'.format(display_name, TEMP_DIR)
session = device.attach(pid)
script = load_js_file(session, DUMP_JS)
script.post('dump')
finished.wait()
generate_ipa(PAYLOAD_PATH, display_name, bundle_identifier)
if session:
session.detach()
def check_args():
if len(sys.argv) < 2:
usage()
sys.exit(1)
if len(sys.argv) < 2:
usage()
return 1
try:
opts,args = getopt.getopt(sys.argv[1:],"hlb:",["help"]);
except getopt.GetoptError:
usage()
sys.exit(2)
try:
opts, args = getopt.getopt(sys.argv[1:], 'hl', ['help'])
except getopt.GetoptError:
usage()
return 2
for opt,value in opts:
if opt in ("-h","--help"):
usage()
if opt in ("-l"):
list_applications()
if opt in ("-b"):
if not find_target_app(1, value):
print "can not find target app '%s'" % value
else:
dump_by_bundleid(value)
for opt, value in opts:
if opt in ('-h', '--help'):
usage()
if len(opts) == 0 and len(sys.argv) == 2:
name = sys.argv[1].decode('utf8');
if not find_target_app(0, name):
print "can not find target app '%s'" % name
else:
dump_by_display_name(name)
sys.exit(0)
if opt in '-l':
device = get_usb_iphone()
list_applications(device)
if len(opts) == 0:
name_or_bundleid = ' '.join(sys.argv[1:])
device = get_usb_iphone()
print "Device {}".format(device)
(pid, display_name, bundle_identifier) = open_target_app(device, name_or_bundleid)
start_dump(device, pid, display_name, bundle_identifier)
return 0
if __name__ == '__main__':
exit_code = 0
try:
exit_code = check_args()
except:
exit_code = 1
if os.path.exists(PAYLOAD_PATH):
print 'Deleting ' + PAYLOAD_PATH
shutil.rmtree(PAYLOAD_PATH)
sys.exit(exit_code)
if __name__ == "__main__":
try:
check_args()
pass
except KeyboardInterrupt:
if session:
session.detach()
sys.exit()
except:
pass