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
howto:fridahooklibrary [2017/10/19 20:26]
czokie [DJIAppSettings - canUseIllegalChannels]
howto:fridahooklibrary [2017/11/12 09:45] (current)
czokie [Tweak.js]
Line 8: Line 8:
 Our work at the moment is focussed on IOS. As a general rule of thumb, we should where possible use the "swizzle" method of hooking. In the near future, this type of hook method will be able to be run on a modified app launched from Springboard. This is pending a patch from the author, but we know that this is a requirement. Not sure yet what standards if any are required for Android to ensure any protection is not tripped up. Our work at the moment is focussed on IOS. As a general rule of thumb, we should where possible use the "swizzle" method of hooking. In the near future, this type of hook method will be able to be run on a modified app launched from Springboard. This is pending a patch from the author, but we know that this is a requirement. Not sure yet what standards if any are required for Android to ensure any protection is not tripped up.
  
 +===== Configuration =====
 +The config below can be used for stand-alone hooks, allowing you to open DJI GO 4 from springboard.
 +<code java FridaGadget.config>
 +{
 +  "interaction": {
 +    "type": "script",
 +    "path": "Tweak.js",
 +    "on_change": "reload"
 +  },
 +  "code_signing": "required"
 +}
 +</code>
 ===== Template hook ===== ===== Template hook =====
  
Line 16: 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.
  
-So. For now, our template hook is +====== PrettyWoman ====== 
 +As part of this workI 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".
  
-====== Hooks ====== +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. 
-===== DJITermsNotificationController shouldShowTerms =====+ 
 +===== PrettyWoman.sh ===== 
 +<code bash PrettyWoman.sh> 
 +#!/bin/bash 
 + 
 +function iosheader { 
 +cat <<EOF 
 +// 
 +// DJI GO 4 Frida Tweaks 
 +//
  
-<code javascript DJITermsNotificationController.shouldShowTerms.js> 
 if (ObjC.available) { if (ObjC.available) {
-  var DJITermsNotificationController = ObjC.classes.DJITermsNotificationController; + 
-   +EOF 
-  var shouldShowTerms DJITermsNotificationController['- shouldShowTerms']; +
-  var shouldShowTermsImpl shouldShowTerms.implementation; + 
-  shouldShowTerms.implementation = ObjC.implement(shouldShowTerms, function (handle, selector) { +function iosfooter { 
-    var originalResult = shouldShowTermsImpl(handle, selector); +cat <<EOF 
-    console.log('Original says:', originalResult, 'we say: false'); +
-    return false;+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
 } }
-</code> 
  
-===== DJIAppSettings - sdr_force_fcc ===== +function jsfunction { 
-<code javascript DJIAppSettings.sdr_force_fcc.js> +cat <<EOF 
-if (ObjC.available) { +  var ${1} = ObjC.classes.${1}
-  var DJIAppSettings = ObjC.classes.DJIAppSettings; +  var ${3} ${1}['${2} ${3}']; 
-   +  var ${3}Impl ${3}.implementation; 
-  var sdr_force_fcc DJIAppSettings['- sdr_force_fcc']; +  ${3}.implementation = ObjC.implement(${3}, function (handle, selector) { 
-  var sdr_force_fccImpl sdr_force_fcc.implementation; +    var originalResult = ${3}Impl(handle, selector); 
-  sdr_force_fcc.implementation = ObjC.implement(sdr_force_fcc, function (handle, selector) { +    if ( originalResult != ${4} ) { 
-    var originalResult = sdr_force_fccImpl(handle, selector); +      if ( ${7} == 0 || ${CLASS}${METHOD}SeenReplace == 0 ) { 
-    console.log('DJIAppSettings:sdr_force_fcc  Original says:', originalResult, 'we say: true'); +        console.log("${5}"); 
-    return true;+        ${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> </code>
  
-===== canUseIllegalChannels ===== +===== PrettyWoman.csv ===== 
-<code javascript DJIAppSettings.canUseIllegalChannels.js>+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,
 +jsfunction,DJIAppForceUpdateManager,hasChecked,-,1,[*] Upgrade Check: DISABLED,[*] Upgrade Check: Already checked,0 
 +jsfunction,DJIUpgradeNotifyViewModel,notifyHidden,-,1,[*] Upgrade Notification DISABLLED,[*] Upgrade Notification already disabled,
 +jsfunctioniffcc,DJIProductManager,currentProductCode,+,13,[*] Changed product code to MAVIC,,1 
 +jsfunction,DJILImitDBUpdateLogic,needUpdateType,-,0,[*] Removing NFZ DB Update Message,,
 +</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) { if (ObjC.available) {
-  var DJIAppSettings = ObjC.classes.DJIAppSettings; 
  
 +//
 +// 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 canUseIllegalChannels = DJIAppSettings['- canUseIllegalChannels'];
   var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation;   var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation;
   canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) {   canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) {
     var originalResult = canUseIllegalChannelsImpl(handle, selector);     var originalResult = canUseIllegalChannelsImpl(handle, selector);
-    console.log('DJIAppSettings:canUseIllegalChannels  Original says:', originalResult, 'we say: true'); +    if ( originalResult != 1 ) { 
-    return true;+      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;
   });   });
-} 
  
-var DJIAppSettings = ObjC.classes.DJIAppSettings;+  // 
 +  // DJIRadioLogic canUseIllegalChannels jsfunction 
 +  //
  
-var canUseIllegalChannels = DJIAppSettings['- canUseIllegalChannels']; +  var DJIRadioLogic = ObjC.classes.DJIRadioLogic; 
-var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation; +  var canUseIllegalChannels = DJIRadioLogic['- canUseIllegalChannels']; 
-canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) { +  var canUseIllegalChannelsImpl = canUseIllegalChannels.implementation; 
-  var originalResult = canUseIllegalChannelsImpl(handle, selector); +  canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) { 
-  console.log('DJIAppSettings:canUseIllegalChannels  Original says:', originalResult, 'we say: 1'); +    var originalResult = canUseIllegalChannelsImpl(handle, selector); 
-  return 1; +    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; 
 +  });
  
-var DJIRadioLogic = ObjC.classes.DJIRadioLogic;+  // 
 +  // DJIAppSettings sdr_force_fcc jsfunction 
 +  //
  
-var canUseIllegalChannels DJIRadioLogic['canUseIllegalChannels']; +  var DJIAppSettings ObjC.classes.DJIAppSettings; 
-var canUseIllegalChannelsImpl canUseIllegalChannels.implementation; +  var sdr_force_fcc = DJIAppSettings['sdr_force_fcc']; 
-canUseIllegalChannels.implementation = ObjC.implement(canUseIllegalChannels, function (handle, selector) { +  var sdr_force_fccImpl sdr_force_fcc.implementation; 
-  var originalResult = canUseIllegalChannelsImpl(handle, selector); +  sdr_force_fcc.implementation = ObjC.implement(sdr_force_fcc, function (handle, selector) { 
-  console.log('DJIRadioLogic:canUseIllegalChannels  Original says:', originalResult, 'we say: 1'); +    var originalResult = sdr_force_fccImpl(handle, selector); 
-  return 1; +    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;
 +    }
 +  });
 +
 +  //
 +  // DJILImitDBUpdateLogic needUpdateType jsfunction
 +  //
 +
 +  var DJILImitDBUpdateLogic = ObjC.classes.DJILImitDBUpdateLogic;
 +  var needUpdateType = DJILImitDBUpdateLogic['- needUpdateType'];
 +  var needUpdateTypeImpl = needUpdateType.implementation;
 +  needUpdateType.implementation = ObjC.implement(needUpdateType, function (handle, selector) {
 +    var originalResult = needUpdateTypeImpl(handle, selector);
 +    if ( originalResult != 0 ) {
 +      if ( 00 == 0 || DJILImitDBUpdateLogicneedUpdateTypeSeenReplace == 0 ) {
 +        console.log("[*] Removing NFZ DB Update Message");
 +        DJILImitDBUpdateLogicneedUpdateTypeSeenReplace = 1;
 +      }
 +    } else {
 +      if ( 00 == 0 || DJILImitDBUpdateLogicneedUpdateTypeSeenHit == 0 ) {
 +        console.log("");
 +        DJILImitDBUpdateLogicneedUpdateTypeSeenHit = 1;
 +      }
 +    }
 +    return 0;
 +  });
 +}
 </code> </code>
 +
howto/fridahooklibrary.1508444786.txt.gz · Last modified: 2017/10/19 20:26 by czokie