User Tools

Site Tools


howto:fridahooklibrary

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
howto:fridahooklibrary [2017/10/21 21:07]
czokie [DJITermsNotificationController - shouldShowTerms]
howto:fridahooklibrary [2017/11/06 22:59]
czokie [PrettyWoman.sh]
Line 28: Line 28:
 We'll dig into this more later when/if we need to access parameter data etc. We'll dig into this more later when/if we need to access parameter data etc.
  
 +====== PrettyWoman ======
 +As part of this work, I looked at how to "standardise" our hooks, since they all appeared to be based on a couple of patterns. Below, you will find source and a CSV file for "PrettyWoman". This app name was picked by Jezzab because "PrettyWoman - She was a hooker".
 +
 +Anyway. Naming conventions aside. How does it work? There is a shell script that parses a CSV file that contains configuration information for a list of hooks that will be created in the output.
 +
 +===== PrettyWoman.sh =====
 +<code bash PrettyWoman.sh>
 +#!/bin/bash
 +
 +function iosheader {
 +cat <<EOF
 +//
 +// DJI GO 4 - Frida Tweaks
 +//
 +
 +if (ObjC.available) {
 +
 +EOF
 +}
 +
 +function iosfooter {
 +cat <<EOF
 +}
 +EOF
 +}
 +
 +function functionheader {
 +cat <<EOF
 +
 +  //
 +  // ${1}
 +  //
 +
 +EOF
 +}
 +function jsobject {
 +
 +cat <<EOF
 +  var ${1} = ObjC.classes.${1};
 +  var ${3} = ${1}['${2} ${3}:'];
 +  var ${3}Impl = ${3}.implementation;
 +  ${3}.implementation = ObjC.implement(${3}, function (handle, selector, originalResult) {
 +    ${3}Impl(handle, selector, ${4});
 +    if ( originalResult != ${4} ) {
 +      if ( ${7} == 0 || ${CLASS}${METHOD}SeenReplace == 0 ) {
 +        console.log("${5}");
 +        ${CLASS}${METHOD}SeenReplace = 1;
 +      }
 +    } else {
 +      if ( ${7} == 0 || ${CLASS}${METHOD}SeenHit == 0 ) {
 +        console.log("${6}");
 +        ${CLASS}${METHOD}SeenHit = 1;
 +      }
 +    }
 +  });
 +EOF
 +}
 +
 +function jsfunction {
 +cat <<EOF
 +  var ${1} = ObjC.classes.${1};
 +  var ${3} = ${1}['${2} ${3}'];
 +  var ${3}Impl = ${3}.implementation;
 +  ${3}.implementation = ObjC.implement(${3}, function (handle, selector) {
 +    var originalResult = ${3}Impl(handle, selector);
 +    if ( originalResult != ${4} ) {
 +      if ( ${7} == 0 || ${CLASS}${METHOD}SeenReplace == 0 ) {
 +        console.log("${5}");
 +        ${CLASS}${METHOD}SeenReplace = 1;
 +      }
 +    } else {
 +      if ( ${7} == 0 || ${CLASS}${METHOD}SeenHit == 0 ) {
 +        console.log("${6}");
 +        ${CLASS}${METHOD}SeenHit = 1;
 +      }
 +    }
 +    return ${4};
 +  });
 +EOF
 +}
 +
 +
 +function jsfunctioniffcc {
 +cat <<EOF
 +  var ${1} = ObjC.classes.${1};
 +  var ${3} = ${1}['${2} ${3}'];
 +  var ${3}Impl = ${3}.implementation;
 +  ${3}.implementation = ObjC.implement(${3}, function (handle, selector) {
 +    var originalResult = ${3}Impl(handle, selector);
 +    if ( originalResult != ${4} ) {
 +      if ( ${7} == 0 || ${CLASS}${METHOD}SeenReplace == 0 ) {
 +        console.log("${5}");
 +        ${CLASS}${METHOD}SeenReplace = 1;
 +      }
 +    }
 +
 +    if( DJIAppSettingssdr_force_fccSeenReplace == 0 ) {
 +      return ${4}; //mavic
 +    } else {
 +      return originalResult;
 +    }
 +  });
 +EOF
 +}
 +
 +
 +function defines {
 +cat <<EOF
 +//
 +// Create variables that we can use for "one shot" rules
 +//
 +EOF
 +
 +while read X
 +do
 +        #TEMPLATE=`echo $X | cut -d "," -f 1`
 +        CLASS=`echo $X | cut -d "," -f 2`
 +        METHOD=`echo $X | cut -d "," -f 3`
 + PLUSMINUS=`echo $X | cut -d "," -f 4`
 +        #REPLACE=`echo $X | cut -d "," -f 5`
 +        #LOGHIT=`echo $X | cut -d "," -f 6`
 +        #LOGCHANGED=`echo $X | cut -d "," -f 7`
 + #ONESHOT=`echo $X | cut -d "," -f 8`
 +
 + echo "${CLASS}${METHOD}SeenHit=0;"
 + echo "${CLASS}${METHOD}SeenReplace=0;"
 +
 +done < PrettyWoman.csv
 +}
 +
 +function mainloop {
 +while read X
 +do
 +        TEMPLATE=`echo $X | cut -d "," -f 1`
 +        CLASS=`echo $X | cut -d "," -f 2`
 +        METHOD=`echo $X | cut -d "," -f 3`
 + PLUSMINUS=`echo $X | cut -d "," -f 4`
 +        REPLACE=`echo $X | cut -d "," -f 5`
 +        LOGHIT=`echo $X | cut -d "," -f 6`
 +        LOGCHANGED=`echo $X | cut -d "," -f 7`
 + ONESHOT=`echo $X | cut -d "," -f 8`
 +
 +        functionheader "${CLASS} ${METHOD} ${TEMPLATE}"
 +        ${TEMPLATE} ${CLASS} ${PLUSMINUS} ${METHOD} ${REPLACE} "${LOGHIT}" "${LOGCHANGED}" "0${ONESHOT}"
 +done < PrettyWoman.csv
 +}
 +
 +iosheader
 +defines
 +mainloop
 +iosfooter
 +</code>
 +
 +===== PrettyWoman.csv =====
 +Below is a CSV config file for PrettyWoman.sh. This file has the following fields:
 +
 +^Template|The name of a template, as listed in PrettyWoman.sh|
 +^Class|A class name from the DJI Application source code|
 +^Method|The name of a method or function within the class|
 +^PlusMinus|A plus or a minus sign (as defined in the DJI reversed source code)|
 +^OurValue|What should we replace the original function return value with?|
 +^LogMessageTweaked|What to display in debug when we successfully bypass DJI functions etc|
 +^LogSeen|What to display in debug when we are called, but we don't change anything|
 +^OneShot|Set this to 1 if you want to see a log message for this once only|
 +
 +<code text PrettyWoman.csv>
 +jsobject,AFSecurityPolicy,setSSLPinningMode,-,0,[*] SSL Pinning BYPASSED, [*] SSL Pinning not used this time,0
 +jsfunction,DJIAccountManager,checkIsAdminUser,-,1,[*] Flight Records admin user ENABLED,[*] Flight Records admin user already enabled,0
 +jsfunction,DJIAppSettings,canUseIllegalChannels,-,1,[*] Illegal Channels config (32) ENABLED,[*] Illegal Channels config (32) already enabled,0
 +jsfunction,DJIRadioLogic,canUseIllegalChannels,-,1,[*] Illegal Channels SDR (32) ENABLED,[*] Illegal Channels SDR(32) already enabled,0
 +jsfunction,DJIAppSettings,sdr_force_fcc,-,1,[*] Forced FCC Mode ACTIVATED,[*] Forced FCC mode already active,0
 +jsfunction,DJITermsNotificationController,shouldShowTerms,-,0,[*] Terms and conditions BYPASSED,[*] Terms and conditions already accepted,0
 +jsfunction,DJIAppForceUpdateManager,hasChecked,-,1,[*] Upgrade Check: DISABLED,[*] Upgrade Check: Already checked,0
 +jsfunction,DJIUpgradeNotifyViewModel,notifyHidden,-,1,[*] Upgrade Notification DISABLLED,[*] Upgrade Notification already disabled,0
 +jsfunctioniffcc,DJIProductManager,currentProductCode,+,13,[*] Changed product code to MAVIC,,1
 +</code>
 +
 +===== Tweak.js =====
 +
 +This code was generated by PrettyWoman.sh - using the CSV file above. Feel free to just use this set of hooks for your tweaking pleasure.
 +
 +<code java Tweak.js>
 +//
 +// DJI GO 4 - Frida Tweaks
 +//
 +
 +if (ObjC.available) {
 +
 +//
 +// Create variables that we can use for "one shot" rules
 +//
 +AFSecurityPolicysetSSLPinningModeSeenHit=0;
 +AFSecurityPolicysetSSLPinningModeSeenReplace=0;
 +DJIAccountManagercheckIsAdminUserSeenHit=0;
 +DJIAccountManagercheckIsAdminUserSeenReplace=0;
 +DJIAppSettingscanUseIllegalChannelsSeenHit=0;
 +DJIAppSettingscanUseIllegalChannelsSeenReplace=0;
 +DJIRadioLogiccanUseIllegalChannelsSeenHit=0;
 +DJIRadioLogiccanUseIllegalChannelsSeenReplace=0;
 +DJIAppSettingssdr_force_fccSeenHit=0;
 +DJIAppSettingssdr_force_fccSeenReplace=0;
 +DJITermsNotificationControllershouldShowTermsSeenHit=0;
 +DJITermsNotificationControllershouldShowTermsSeenReplace=0;
 +DJIAppForceUpdateManagerhasCheckedSeenHit=0;
 +DJIAppForceUpdateManagerhasCheckedSeenReplace=0;
 +DJIUpgradeNotifyViewModelnotifyHiddenSeenHit=0;
 +DJIUpgradeNotifyViewModelnotifyHiddenSeenReplace=0;
 +DJIProductManagercurrentProductCodeSeenHit=0;
 +DJIProductManagercurrentProductCodeSeenReplace=0;
 +
 +  //
 +  // AFSecurityPolicy setSSLPinningMode jsobject
 +  //
 +
 +  var AFSecurityPolicy = ObjC.classes.AFSecurityPolicy;
 +  var setSSLPinningMode = AFSecurityPolicy['- setSSLPinningMode:'];
 +  var setSSLPinningModeImpl = setSSLPinningMode.implementation;
 +  setSSLPinningMode.implementation = ObjC.implement(setSSLPinningMode, function (handle, selector, originalResult) {
 +    setSSLPinningModeImpl(handle, selector, 0);
 +    if ( originalResult != 0 ) {
 +      if ( 00 == 0 || AFSecurityPolicysetSSLPinningModeSeenReplace == 0 ) {
 +        console.log("[*] SSL Pinning BYPASSED");
 +        AFSecurityPolicysetSSLPinningModeSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || AFSecurityPolicysetSSLPinningModeSeenHit == 0 ) {
 +        console.log(" [*] SSL Pinning not used this time");
 +        AFSecurityPolicysetSSLPinningModeSeenHit = 1;
 +      }
 +    }
 +  });
 +
 +  //
 +  // DJIAccountManager checkIsAdminUser jsfunction
 +  //
 +
 +  var DJIAccountManager = ObjC.classes.DJIAccountManager;
 +  var checkIsAdminUser = DJIAccountManager['- checkIsAdminUser'];
 +  var checkIsAdminUserImpl = checkIsAdminUser.implementation;
 +  checkIsAdminUser.implementation = ObjC.implement(checkIsAdminUser, function (handle, selector) {
 +    var originalResult = checkIsAdminUserImpl(handle, selector);
 +    if ( originalResult != 1 ) {
 +      if ( 00 == 0 || DJIAccountManagercheckIsAdminUserSeenReplace == 0 ) {
 +        console.log("[*] Flight Records admin user ENABLED");
 +        DJIAccountManagercheckIsAdminUserSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJIAccountManagercheckIsAdminUserSeenHit == 0 ) {
 +        console.log("[*] Flight Records admin user already enabled");
 +        DJIAccountManagercheckIsAdminUserSeenHit = 1;
 +      }
 +    }
 +    return 1;
 +  });
 +
 +  //
 +  // DJIAppSettings canUseIllegalChannels jsfunction
 +  //
 +
 +  var DJIAppSettings = ObjC.classes.DJIAppSettings;
 +  var canUseIllegalChannels = DJIAppSettings['- canUseIllegalChannels'];
 +  var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation;
 +  canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) {
 +    var originalResult = canUseIllegalChannelsImpl(handle, selector);
 +    if ( originalResult != 1 ) {
 +      if ( 00 == 0 || DJIAppSettingscanUseIllegalChannelsSeenReplace == 0 ) {
 +        console.log("[*] Illegal Channels config (32) ENABLED");
 +        DJIAppSettingscanUseIllegalChannelsSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJIAppSettingscanUseIllegalChannelsSeenHit == 0 ) {
 +        console.log("[*] Illegal Channels config (32) already enabled");
 +        DJIAppSettingscanUseIllegalChannelsSeenHit = 1;
 +      }
 +    }
 +    return 1;
 +  });
 +
 +  //
 +  // DJIRadioLogic canUseIllegalChannels jsfunction
 +  //
 +
 +  var DJIRadioLogic = ObjC.classes.DJIRadioLogic;
 +  var canUseIllegalChannels = DJIRadioLogic['- canUseIllegalChannels'];
 +  var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation;
 +  canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) {
 +    var originalResult = canUseIllegalChannelsImpl(handle, selector);
 +    if ( originalResult != 1 ) {
 +      if ( 00 == 0 || DJIRadioLogiccanUseIllegalChannelsSeenReplace == 0 ) {
 +        console.log("[*] Illegal Channels SDR (32) ENABLED");
 +        DJIRadioLogiccanUseIllegalChannelsSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJIRadioLogiccanUseIllegalChannelsSeenHit == 0 ) {
 +        console.log("[*] Illegal Channels SDR(32) already enabled");
 +        DJIRadioLogiccanUseIllegalChannelsSeenHit = 1;
 +      }
 +    }
 +    return 1;
 +  });
 +
 +  //
 +  // DJIAppSettings sdr_force_fcc jsfunction
 +  //
 +
 +  var DJIAppSettings = ObjC.classes.DJIAppSettings;
 +  var sdr_force_fcc = DJIAppSettings['- sdr_force_fcc'];
 +  var sdr_force_fccImpl = sdr_force_fcc.implementation;
 +  sdr_force_fcc.implementation = ObjC.implement(sdr_force_fcc, function (handle, selector) {
 +    var originalResult = sdr_force_fccImpl(handle, selector);
 +    if ( originalResult != 1 ) {
 +      if ( 00 == 0 || DJIAppSettingssdr_force_fccSeenReplace == 0 ) {
 +        console.log("[*] Forced FCC Mode ACTIVATED");
 +        DJIAppSettingssdr_force_fccSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJIAppSettingssdr_force_fccSeenHit == 0 ) {
 +        console.log("[*] Forced FCC mode already active");
 +        DJIAppSettingssdr_force_fccSeenHit = 1;
 +      }
 +    }
 +    return 1;
 +  });
 +
 +  //
 +  // DJITermsNotificationController shouldShowTerms jsfunction
 +  //
 +
 +  var DJITermsNotificationController = ObjC.classes.DJITermsNotificationController;
 +  var shouldShowTerms = DJITermsNotificationController['- shouldShowTerms'];
 +  var shouldShowTermsImpl = shouldShowTerms.implementation;
 +  shouldShowTerms.implementation = ObjC.implement(shouldShowTerms, function (handle, selector) {
 +    var originalResult = shouldShowTermsImpl(handle, selector);
 +    if ( originalResult != 0 ) {
 +      if ( 00 == 0 || DJITermsNotificationControllershouldShowTermsSeenReplace == 0 ) {
 +        console.log("[*] Terms and conditions BYPASSED");
 +        DJITermsNotificationControllershouldShowTermsSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJITermsNotificationControllershouldShowTermsSeenHit == 0 ) {
 +        console.log("[*] Terms and conditions already accepted");
 +        DJITermsNotificationControllershouldShowTermsSeenHit = 1;
 +      }
 +    }
 +    return 0;
 +  });
 +
 +  //
 +  // DJIAppForceUpdateManager hasChecked jsfunction
 +  //
 +
 +  var DJIAppForceUpdateManager = ObjC.classes.DJIAppForceUpdateManager;
 +  var hasChecked = DJIAppForceUpdateManager['- hasChecked'];
 +  var hasCheckedImpl = hasChecked.implementation;
 +  hasChecked.implementation = ObjC.implement(hasChecked, function (handle, selector) {
 +    var originalResult = hasCheckedImpl(handle, selector);
 +    if ( originalResult != 1 ) {
 +      if ( 00 == 0 || DJIAppForceUpdateManagerhasCheckedSeenReplace == 0 ) {
 +        console.log("[*] Upgrade Check: DISABLED");
 +        DJIAppForceUpdateManagerhasCheckedSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJIAppForceUpdateManagerhasCheckedSeenHit == 0 ) {
 +        console.log("[*] Upgrade Check: Already checked");
 +        DJIAppForceUpdateManagerhasCheckedSeenHit = 1;
 +      }
 +    }
 +    return 1;
 +  });
 +
 +  //
 +  // DJIUpgradeNotifyViewModel notifyHidden jsfunction
 +  //
 +
 +  var DJIUpgradeNotifyViewModel = ObjC.classes.DJIUpgradeNotifyViewModel;
 +  var notifyHidden = DJIUpgradeNotifyViewModel['- notifyHidden'];
 +  var notifyHiddenImpl = notifyHidden.implementation;
 +  notifyHidden.implementation = ObjC.implement(notifyHidden, function (handle, selector) {
 +    var originalResult = notifyHiddenImpl(handle, selector);
 +    if ( originalResult != 1 ) {
 +      if ( 00 == 0 || DJIUpgradeNotifyViewModelnotifyHiddenSeenReplace == 0 ) {
 +        console.log("[*] Upgrade Notification DISABLLED");
 +        DJIUpgradeNotifyViewModelnotifyHiddenSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJIUpgradeNotifyViewModelnotifyHiddenSeenHit == 0 ) {
 +        console.log("[*] Upgrade Notification already disabled");
 +        DJIUpgradeNotifyViewModelnotifyHiddenSeenHit = 1;
 +      }
 +    }
 +    return 1;
 +  });
 +
 +  //
 +  // DJIProductManager currentProductCode jsfunctioniffcc
 +  //
 +
 +  var DJIProductManager = ObjC.classes.DJIProductManager;
 +  var currentProductCode = DJIProductManager['+ currentProductCode'];
 +  var currentProductCodeImpl = currentProductCode.implementation;
 +  currentProductCode.implementation = ObjC.implement(currentProductCode, function (handle, selector) {
 +    var originalResult = currentProductCodeImpl(handle, selector);
 +    if ( originalResult != 13 ) {
 +      if ( 01 == 0 || DJIProductManagercurrentProductCodeSeenReplace == 0 ) {
 +        console.log("[*] Changed product code to MAVIC");
 +        DJIProductManagercurrentProductCodeSeenReplace = 1;
 +      }
 +    }
 +
 +    if( DJIAppSettingssdr_force_fccSeenReplace == 0 ) {
 +      return 13; //mavic
 +    } else {
 +      return originalResult;
 +    }
 +  });
 +}
 +</code>
 ====== Hooks ====== ====== Hooks ======
 ===== DJITermsNotificationController - shouldShowTerms ===== ===== DJITermsNotificationController - shouldShowTerms =====
Line 84: Line 501:
   });   });
 } }
 +</code>
  
 +===== AFSecurityPolicy - setSSLPinningMode =====
 +<code javascript AFSecurityPolicy.setSSLPinningMode.js>
 +if (ObjC.available) {
 + 
 +  var AFSecurityPolicy = ObjC.classes.AFSecurityPolicy;
 + 
 +  var setSSLPinningMode = AFSecurityPolicy['- setSSLPinningMode:'];
 +  var setSSLPinningModeImpl = setSSLPinningMode.implementation;
 +  setSSLPinningMode.implementation = ObjC.implement(setSSLPinningMode, function (handle, selector, originalResult) {
 +    setSSLPinningModeImpl(handle, selector, 0);
 +    console.log('AFSecurityPolicy:setSSLPinningMode. Changing from: ', originalResult, 'to: 0');
 +  });
 +}
 +</code>
  
 +===== DJIAccountManager - checkIsAdminUser =====
 +<code javascript DJIAccountManager.checkIsAdminUser.js>
 +//Set Admin mode in Flight Records
 +var DJIAccountManager = ObjC.classes.DJIAccountManager;
 +var checkIsAdminUser = DJIAccountManager['- checkIsAdminUser'];
 +var checkIsAdminUserImpl = checkIsAdminUser.implementation;
 +checkIsAdminUser.implementation = ObjC.implement(checkIsAdminUser, function (handle, selector) {
 +     var originalResult = checkIsAdminUserImpl(handle, selector);
 +     console.log('[*] Setting user to Admin for Flight Records');
 +     return 1;
 +});
 +</code>
 +
 +===== DJIUpgradeNotifyViewModel - notifyHidden =====
 +<code javascript DJIUpgradeNotifyViewModel.notifyHidden.js>
 +//Bypass upgrade notification on splash screen
 +var DJIUpgradeNotifyViewModel = ObjC.classes.DJIUpgradeNotifyViewModel;
 +var notifyHidden = DJIUpgradeNotifyViewModel['- notifyHidden'];
 +var notifyHiddenImpl = notifyHidden.implementation;
 +notifyHidden.implementation = ObjC.implement(notifyHidden, function (handle, selector) {
 +     var originalResult = notifyHiddenImpl(handle, selector);
 +     console.log('[*] Disabling Upgrade Notification');
 +     return 1;
 +});
 +</code>
 +
 +===== DJIAppSettings - sdr_force_fcc =====
 +<code javascript DJIAppSettings.sdr_force_fcc.js>
 +//Force FCC Mode
 +var shown=0;
 +var fcc_enabled;
 +
 +var DJIAppSettings = ObjC.classes.DJIAppSettings;
 +var sdr_force_fcc = DJIAppSettings['- sdr_force_fcc'];
 +var sdr_force_fccImpl = sdr_force_fcc.implementation;
 +sdr_force_fcc.implementation = ObjC.implement(sdr_force_fcc, function (handle, selector) {
 +var originalResult = sdr_force_fccImpl(handle, selector);
 +     console.log('[*] Setting Forced FCC Mode');
 +     fcc_enabled = 1;
 +     return 1;
 +});
 +
 +//Fake Mavic for P4 FCC
 +var DJIProductManager = ObjC.classes.DJIProductManager;
 +var currentProductCode = DJIProductManager['+ currentProductCode'];
 +var currentProductCodeImpl = currentProductCode.implementation;
 +currentProductCode.implementation = ObjC.implement(currentProductCode, function (handle, selector) {
 +     var originalResult = currentProductCodeImpl(handle, selector);
 +     if(shown==0) {
 +          console.log('[*] Faking product code for FCC');
 +          shown=1;
 +     }
 +     if(fcc_enabled==0)
 +         return 13; //mavic
 +     else
 +         return originalResult
 +});
 +</code>
 +
 +===== DJIAppForceUpdateManager - hasChecked =====
 +<code javascript DJIAppForceUpdateManager.hasChecked.js>
 +//Bypass DJI Go 4 new app version check
 +var DJIAppForceUpdateManager = ObjC.classes.DJIAppForceUpdateManager;
 +var hasChecked = DJIAppForceUpdateManager['- hasChecked'];
 +var hasCheckedImpl = hasChecked.implementation;
 +hasChecked.implementation = ObjC.implement(hasChecked, function (handle, selector) {
 +     var originalResult = hasCheckedImpl(handle, selector);
 +     console.log("[*] Disabling App Upgrade Check");
 +     return 1;
 +});
 +</code>
 +
 +===== DJIAppSettings - canUseIllegalChannels =====
 +<code javascript DJIAppForceUpdateManager.hasChecked.js>
 +//Enable Illegal Channels (32 Channels)
 +if (ObjC.available) {
 +     var DJIAppSettings = ObjC.classes.DJIAppSettings;
 +     var canUseIllegalChannels = DJIAppSettings['- canUseIllegalChannels'];
 +     var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation;
 +     canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) {
 +          var originalResult = canUseIllegalChannelsImpl(handle, selector);
 +          console.log('[*] Enabling Illegal Channels (32 Channels)');
 +          return 1;
 +     });
 +     var DJIRadioLogic = ObjC.classes.DJIRadioLogic;
 +     var canUseIllegalChannels = DJIRadioLogic['- canUseIllegalChannels'];
 +     var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation;
 +     canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) {
 +          var originalResult = canUseIllegalChannelsImpl(handle, selector);
 +          console.log('[*] Enabling Illegal Channels (32 Channels)');
 +          return 1;
 +  });
 +}
 </code> </code>
howto/fridahooklibrary.txt ยท Last modified: 2017/11/12 09:45 by czokie