├── Librarys └── .gitkeep ├── Resource └── TargetApp.app │ ├── PkgInfo │ ├── Assets.car │ ├── Info.plist │ ├── TargetApp │ ├── AppIcon60x60@2x.png │ ├── AppIcon60x60@3x.png │ └── Base.lproj │ ├── Main.storyboardc │ ├── Info.plist │ ├── BYZ-38-t0r-view-8bC-Xf-vdC.nib │ └── UIViewController-BYZ-38-t0r.nib │ └── LaunchScreen.storyboardc │ ├── Info.plist │ ├── 01J-lp-oVM-view-Ze5-6b-2t3.nib │ └── UIViewController-01J-lp-oVM.nib ├── bin ├── cycript ├── class-dump ├── monkeyparser ├── createIPA.command ├── md-uninstall ├── md-update └── md-install ├── Frameworks ├── libcycript.db ├── libcycript.dylib ├── libsubstrate.dylib ├── RevealServer.framework │ ├── RevealServer │ ├── Modules │ │ └── module.modulemap │ └── Info.plist └── libcycript.cy ├── MFrameworks └── libsubstitute.dylib ├── Templates ├── MonkeyApp.xctemplate │ ├── icon.png │ ├── TemplateIcon.icns │ ├── Scripts │ │ └── quick-resign.sh │ ├── Config │ │ └── MDConfig.plist │ └── TemplateInfo.plist ├── Base.xctemplate │ ├── TemplateIcon.icns │ └── TemplateInfo.plist ├── MonkeyPod.xctemplate │ ├── TemplateIcon.icns │ ├── ___PACKAGENAMEASIDENTIFIER___.m │ ├── ___PACKAGENAMEASIDENTIFIER___.podspec │ └── TemplateInfo.plist ├── Logos Tweak.xctemplate │ ├── TemplateIcon.icns │ ├── ___PACKAGENAMEASIDENTIFIER___.mm │ ├── ___PACKAGENAMEASIDENTIFIER___.xm │ └── TemplateInfo.plist ├── MonkeyAppMac.xctemplate │ ├── TemplateIcon.png │ ├── TemplateIcon@2x.png │ ├── Cocoa___PACKAGENAMEASIDENTIFIER___.h │ ├── STL___PACKAGENAMEASIDENTIFIER___Priv.hpp │ ├── STL___PACKAGENAMEASIDENTIFIER___.hpp │ ├── STL___PACKAGENAMEASIDENTIFIER___.cpp │ ├── Cocoa___PACKAGENAMEASIDENTIFIER___.m │ ├── fishhook │ │ ├── fishhook.h │ │ └── fishhook.c │ ├── AntiAntiDebug │ │ └── AntiAntiDebug.m │ └── TemplateInfo.plist ├── Debian Package.xctemplate │ ├── TemplateIcon.icns │ └── TemplateInfo.plist ├── MonkeyAppLibrary.xctemplate │ ├── TemplateIcon.icns │ ├── Logos │ │ ├── ___PACKAGENAMEASIDENTIFIER___.mm │ │ └── ___PACKAGENAMEASIDENTIFIER___.xm │ ├── Tools │ │ └── LLDBTools.h │ ├── ___PACKAGENAMEASIDENTIFIER___.h │ ├── Config │ │ ├── MDCycriptManager.h │ │ ├── MDMethodTrace.h │ │ ├── MDConfigManager.m │ │ ├── MDConfigManager.h │ │ └── MDCycriptManager.m │ ├── Trace │ │ ├── OCSelectorTrampolines.h │ │ ├── selectortramps.mac │ │ ├── OCMethodTrace.h │ │ ├── a1a2-selectortramps-arm64.s │ │ ├── a1a2-selectortramps-arm.s │ │ └── a2a3-selectortramps-arm.s │ ├── ___PACKAGENAMEASIDENTIFIER___.m │ ├── fishhook │ │ ├── fishhook.h │ │ └── fishhook.c │ └── AntiAntiDebug │ │ └── AntiAntiDebug.m ├── PreferenceLoader.xctemplate │ ├── TemplateIcon.icns │ ├── ___PACKAGENAMEASIDENTIFIER___Icon.png │ ├── ___PACKAGENAMEASIDENTIFIER___Icon@2x.png │ ├── TemplateInfo.plist │ └── ___PACKAGENAMEASIDENTIFIER___.plist ├── CaptainHook Tweak.xctemplate │ ├── TemplateIcon.icns │ ├── ___PACKAGENAMEASIDENTIFIER___.plist │ ├── ___PACKAGENAMEASIDENTIFIER___.mm │ └── TemplateInfo.plist ├── Command-line Tool.xctemplate │ ├── TemplateIcon.icns │ ├── ___PACKAGENAMEASIDENTIFIER___.xcdatamodeld │ │ ├── .xccurrentversion │ │ └── ___PACKAGENAMEASIDENTIFIER___.xcdatamodel │ │ │ ├── .xccurrentversion │ │ │ └── contents │ ├── monkeydev.entitlements │ └── TemplateInfo.plist ├── README.md └── LICENSE ├── shell └── sshpass.rb ├── Tools ├── mpack.sh └── pack.sh └── README.md /Librarys/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Resource/TargetApp.app/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /bin/cycript: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/bin/cycript -------------------------------------------------------------------------------- /bin/class-dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/bin/class-dump -------------------------------------------------------------------------------- /bin/monkeyparser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/bin/monkeyparser -------------------------------------------------------------------------------- /Frameworks/libcycript.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Frameworks/libcycript.db -------------------------------------------------------------------------------- /Frameworks/libcycript.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Frameworks/libcycript.dylib -------------------------------------------------------------------------------- /Frameworks/libsubstrate.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Frameworks/libsubstrate.dylib -------------------------------------------------------------------------------- /MFrameworks/libsubstitute.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/MFrameworks/libsubstitute.dylib -------------------------------------------------------------------------------- /Resource/TargetApp.app/Assets.car: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Assets.car -------------------------------------------------------------------------------- /Resource/TargetApp.app/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Info.plist -------------------------------------------------------------------------------- /Resource/TargetApp.app/TargetApp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/TargetApp -------------------------------------------------------------------------------- /Templates/MonkeyApp.xctemplate/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/MonkeyApp.xctemplate/icon.png -------------------------------------------------------------------------------- /Resource/TargetApp.app/AppIcon60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/AppIcon60x60@2x.png -------------------------------------------------------------------------------- /Resource/TargetApp.app/AppIcon60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/AppIcon60x60@3x.png -------------------------------------------------------------------------------- /Templates/Base.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/Base.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Frameworks/RevealServer.framework/RevealServer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Frameworks/RevealServer.framework/RevealServer -------------------------------------------------------------------------------- /Templates/MonkeyApp.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/MonkeyApp.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/MonkeyPod.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/MonkeyPod.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/Logos Tweak.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/Logos Tweak.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/TemplateIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/MonkeyAppMac.xctemplate/TemplateIcon.png -------------------------------------------------------------------------------- /Templates/Debian Package.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/Debian Package.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/TemplateIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/MonkeyAppMac.xctemplate/TemplateIcon@2x.png -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/MonkeyAppLibrary.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/PreferenceLoader.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/PreferenceLoader.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/CaptainHook Tweak.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/CaptainHook Tweak.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Templates/Command-line Tool.xctemplate/TemplateIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/Command-line Tool.xctemplate/TemplateIcon.icns -------------------------------------------------------------------------------- /Resource/TargetApp.app/Base.lproj/Main.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Base.lproj/Main.storyboardc/Info.plist -------------------------------------------------------------------------------- /Frameworks/RevealServer.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module RevealServer { 2 | umbrella header "RevealServer.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Resource/TargetApp.app/Base.lproj/LaunchScreen.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Base.lproj/LaunchScreen.storyboardc/Info.plist -------------------------------------------------------------------------------- /Templates/PreferenceLoader.xctemplate/___PACKAGENAMEASIDENTIFIER___Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/PreferenceLoader.xctemplate/___PACKAGENAMEASIDENTIFIER___Icon.png -------------------------------------------------------------------------------- /Templates/PreferenceLoader.xctemplate/___PACKAGENAMEASIDENTIFIER___Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Templates/PreferenceLoader.xctemplate/___PACKAGENAMEASIDENTIFIER___Icon@2x.png -------------------------------------------------------------------------------- /Resource/TargetApp.app/Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib -------------------------------------------------------------------------------- /Resource/TargetApp.app/Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Base.lproj/Main.storyboardc/UIViewController-BYZ-38-t0r.nib -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/Cocoa___PACKAGENAMEASIDENTIFIER___.h: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | //___FILEHEADER___ 5 | 6 | #import 7 | 8 | -------------------------------------------------------------------------------- /Resource/TargetApp.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib -------------------------------------------------------------------------------- /Resource/TargetApp.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XLsnQw/MonkeyTweakDev/HEAD/Resource/TargetApp.app/Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib -------------------------------------------------------------------------------- /Templates/Command-line Tool.xctemplate/___PACKAGENAMEASIDENTIFIER___.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Templates/Logos Tweak.xctemplate/___PACKAGENAMEASIDENTIFIER___.mm: -------------------------------------------------------------------------------- 1 | 2 | // *** DO NOT EDIT THIS FILE! *** 3 | // This file is generated by Logos processing using ___PACKAGENAMEASIDENTIFIER___.xm during each build. 4 | 5 | // Logos by Dustin Howett 6 | // See http://iphonedevwiki.net/index.php/Logos 7 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Logos/___PACKAGENAMEASIDENTIFIER___.mm: -------------------------------------------------------------------------------- 1 | 2 | // *** DO NOT EDIT THIS FILE! *** 3 | // This file is generated by Logos processing using ___PACKAGENAMEASIDENTIFIER___.xm during each build. 4 | 5 | // Logos by Dustin Howett 6 | // See http://iphonedevwiki.net/index.php/Logos 7 | -------------------------------------------------------------------------------- /Templates/Command-line Tool.xctemplate/monkeydev.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/STL___PACKAGENAMEASIDENTIFIER___Priv.hpp: -------------------------------------------------------------------------------- 1 | //___FILEHEADER___ 2 | 3 | /* The classes below are not exported */ 4 | #pragma GCC visibility push(hidden) 5 | 6 | class ___PACKAGENAMEASIDENTIFIER___Priv 7 | { 8 | public: 9 | void HelloWorldPriv(const char *); 10 | }; 11 | 12 | #pragma GCC visibility pop 13 | -------------------------------------------------------------------------------- /Templates/CaptainHook Tweak.xctemplate/___PACKAGENAMEASIDENTIFIER___.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.target.bundleid 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/STL___PACKAGENAMEASIDENTIFIER___.hpp: -------------------------------------------------------------------------------- 1 | //___FILEHEADER___ 2 | 3 | #ifndef ___PACKAGENAMEASIDENTIFIER____ 4 | #define ___PACKAGENAMEASIDENTIFIER____ 5 | 6 | /* The classes below are exported */ 7 | #pragma GCC visibility push(default) 8 | 9 | class ___PACKAGENAMEASIDENTIFIER___ 10 | { 11 | public: 12 | void HelloWorld(const char *); 13 | }; 14 | 15 | #pragma GCC visibility pop 16 | #endif 17 | -------------------------------------------------------------------------------- /Templates/Command-line Tool.xctemplate/___PACKAGENAMEASIDENTIFIER___.xcdatamodeld/___PACKAGENAMEASIDENTIFIER___.xcdatamodel/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | ___PACKAGENAMEASIDENTIFIER___.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Templates/Command-line Tool.xctemplate/___PACKAGENAMEASIDENTIFIER___.xcdatamodeld/___PACKAGENAMEASIDENTIFIER___.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /shell/sshpass.rb: -------------------------------------------------------------------------------- 1 | require 'formula' 2 | 3 | class Sshpass < Formula 4 | url 'http://sourceforge.net/projects/sshpass/files/sshpass/1.06/sshpass-1.06.tar.gz' 5 | homepage 'http://sourceforge.net/projects/sshpass' 6 | sha256 'c6324fcee608b99a58f9870157dfa754837f8c48be3df0f5e2f3accf145dee60' 7 | 8 | def install 9 | system "./configure", "--disable-debug", "--disable-dependency-tracking", 10 | "--prefix=#{prefix}" 11 | system "make install" 12 | end 13 | 14 | def test 15 | system "sshpass" 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/STL___PACKAGENAMEASIDENTIFIER___.cpp: -------------------------------------------------------------------------------- 1 | //___FILEHEADER___ 2 | 3 | #include 4 | #include "___PACKAGENAMEASIDENTIFIER___.hpp" 5 | #include "___PACKAGENAMEASIDENTIFIER___Priv.hpp" 6 | 7 | void ___PACKAGENAMEASIDENTIFIER___::HelloWorld(const char * s) 8 | { 9 | ___PACKAGENAMEASIDENTIFIER___Priv *theObj = new ___PACKAGENAMEASIDENTIFIER___Priv; 10 | theObj->HelloWorldPriv(s); 11 | delete theObj; 12 | }; 13 | 14 | void ___PACKAGENAMEASIDENTIFIER___Priv::HelloWorldPriv(const char * s) 15 | { 16 | std::cout << s << std::endl; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /Templates/MonkeyApp.xctemplate/Scripts/quick-resign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage 4 | # Must be an absolute path 5 | 6 | # ./quick-resign.sh [insert] "origin.ipa path" "resign.ipa path" 7 | 8 | INSERT_DYLIB=NO 9 | INPUT_PATH=$1 10 | OUTPUT_PATH=$2 11 | 12 | if [[ $1 == "insert" ]];then 13 | INSERT_DYLIB=YES 14 | INPUT_PATH=$2 15 | OUTPUT_PATH=$3 16 | fi 17 | 18 | if [[ ! $OUTPUT_PATH ]];then 19 | OUTPUT_PATH=$PWD 20 | fi 21 | 22 | cp -rf $INPUT_PATH ../TargetApp/ 23 | cd ../../ 24 | xcodebuild MONKEYDEV_INSERT_DYLIB=$INSERT_DYLIB | xcpretty 25 | cd LatestBuild 26 | ./createIPA.command 27 | cp -rf Target.ipa $OUTPUT_PATH 28 | exit 0 -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Tools/LLDBTools.h: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // LLDBTools.h 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2018/3/8. 8 | // Copyright © 2018年 AloneMonkey. All rights reserved. 9 | // 10 | 11 | #import 12 | #import 13 | 14 | //(lldb) po pviews() 15 | 16 | NSString* pvc(void); 17 | 18 | NSString* pviews(void); 19 | 20 | NSString* pactions(vm_address_t address); 21 | 22 | NSString* pblock(vm_address_t address); 23 | 24 | NSString* methods(const char * classname); 25 | 26 | NSString* ivars(vm_address_t address); 27 | 28 | NSString* choose(const char* classname); 29 | 30 | NSString* vmmap(); 31 | -------------------------------------------------------------------------------- /Templates/MonkeyPod.xctemplate/___PACKAGENAMEASIDENTIFIER___.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // ___FILENAME___ 5 | // ___PACKAGENAME___ 6 | // 7 | // Created by ___FULLUSERNAME___ on ___DATE___. 8 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 9 | // 10 | 11 | #import "___FILEBASENAME___.h" 12 | #import 13 | #import 14 | 15 | CHDeclareClass(CustomViewController) 16 | 17 | CHOptimizedMethod(0, self, NSString*, CustomViewController,getMyName){ 18 | return @"MonkeyDevPod"; 19 | } 20 | 21 | CHConstructor{ 22 | CHLoadLateClass(CustomViewController); 23 | CHClassHook(0, CustomViewController, getMyName); 24 | } 25 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/___PACKAGENAMEASIDENTIFIER___.h: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // ___FILENAME___ 5 | // ___PACKAGENAME___ 6 | // 7 | // Created by ___FULLUSERNAME___ on ___DATE___. 8 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 9 | // 10 | 11 | #import 12 | 13 | #define INSERT_SUCCESS_WELCOME " 🎉!!!congratulations!!!🎉\n👍----------------insert dylib success----------------👍\n" 14 | 15 | @interface CustomViewController 16 | 17 | @property (nonatomic, copy) NSString* newProperty; 18 | 19 | + (void)classMethod; 20 | 21 | - (NSString*)getMyName; 22 | 23 | - (void)newMethod:(NSString*) output; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /bin/createIPA.command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 | 4 | if [[ ${DIR} = "/opt/MonkeyDev/bin" ]]; then 5 | DIR="$PWD" 6 | fi 7 | 8 | function run { 9 | echo "Executing command: $@" 10 | $@ 11 | if [[ $? != "0" ]]; then 12 | echo "Executing the above command has failed!" 13 | exit 1 14 | fi 15 | } 16 | 17 | function run_at { 18 | pushd $1 19 | shift 20 | run $@ 21 | popd 22 | } 23 | 24 | echo "==================MonkeyDev(create ipa file...)==================" 25 | 26 | run "rm -rf ${DIR}/Target.ipa ${DIR}/Payload" 27 | run "mkdir ${DIR}/Payload" 28 | 29 | APP=$(find ${DIR} -type d | grep ".app$" | head -n 1) 30 | 31 | run "cp -rf ${APP} ${DIR}/Payload" 32 | run_at ${DIR} "zip -qr Target.ipa Payload" 33 | run "rm -rf ${DIR}/Payload" 34 | 35 | echo "==================MonkeyDev(done)==================" 36 | 37 | exit; -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Config/MDCycriptManager.h: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // MDCycriptManager.h 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2018/3/8. 8 | // Copyright © 2018年 AloneMonkey. All rights reserved. 9 | // 10 | 11 | #ifndef __OPTIMIZE__ 12 | 13 | #import 14 | 15 | #define PORT 6666 16 | 17 | @interface MDCycriptManager : NSObject 18 | 19 | + (instancetype)sharedInstance; 20 | 21 | 22 | /** 23 | Download script by config.plist 24 | 25 | @param update Force update of all scripts 26 | */ 27 | -(void)loadCycript:(BOOL) update; 28 | 29 | /** 30 | eval javascript by cycript 31 | 32 | @param cycript javascript string 33 | @param error error happened 34 | @return eval result 35 | */ 36 | -(NSString*)evaluateCycript:(NSString*) cycript error:(NSError **) error; 37 | 38 | @end 39 | 40 | #endif -------------------------------------------------------------------------------- /Templates/Logos Tweak.xctemplate/___PACKAGENAMEASIDENTIFIER___.xm: -------------------------------------------------------------------------------- 1 | // See http://iphonedevwiki.net/index.php/Logos 2 | 3 | #if TARGET_OS_SIMULATOR 4 | #error Do not support the simulator, please use the real iPhone Device. 5 | #endif 6 | 7 | #import 8 | 9 | %hook ClassName 10 | 11 | + (id)sharedInstance 12 | { 13 | %log; 14 | 15 | return %orig; 16 | } 17 | 18 | - (void)messageWithNoReturnAndOneArgument:(id)originalArgument 19 | { 20 | %log; 21 | 22 | %orig(originalArgument); 23 | 24 | // or, for exmaple, you could use a custom value instead of the original argument: %orig(customValue); 25 | } 26 | 27 | - (id)messageWithReturnAndNoArguments 28 | { 29 | %log; 30 | 31 | id originalReturnOfMessage = %orig; 32 | 33 | // for example, you could modify the original return value before returning it: [SomeOtherClass doSomethingToThisObject:originalReturnOfMessage]; 34 | 35 | return originalReturnOfMessage; 36 | } 37 | 38 | %end 39 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Config/MDMethodTrace.h: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // MDMethodTrace.h 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2017/9/7. 8 | // Copyright © 2017年 AloneMonkey. All rights reserved. 9 | // 10 | 11 | #ifndef MethodTrace_h 12 | #define MethodTrace_h 13 | 14 | #define TRACE_README @"\n📚--------------------OCMethodTrace(Usage)-------------------📚\nhttps://github.com/omxcodec/OCMethodTrace/blob/master/README.md\n📚--------------------OCMethodTrace(Usage)-------------------📚" 15 | 16 | #import 17 | 18 | @interface MDMethodTrace : NSObject 19 | 20 | + (instancetype)sharedInstance; 21 | 22 | - (void)addClassTrace:(NSString *) className; 23 | 24 | - (void)addClassTrace:(NSString *)className methodName:(NSString *)methodName; 25 | 26 | - (void)addClassTrace:(NSString *)className methodList:(NSArray *)methodList; 27 | 28 | @end 29 | 30 | #endif /* MethodTrace_h */ 31 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Trace/OCSelectorTrampolines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OCSelectorTrampolines.mm 3 | * OCMethodTrace 4 | * 5 | * https://github.com/omxcodec/OCMethodTrace.git 6 | * 7 | * Copyright (C) 2018 Michael Chen 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #import 23 | 24 | FOUNDATION_EXTERN IMP imp_implementationWithSelector(SEL aSel, const char *signature); 25 | FOUNDATION_EXTERN SEL imp_getSelector(IMP anImp); 26 | FOUNDATION_EXTERN BOOL imp_removeSelector(IMP anImp); 27 | -------------------------------------------------------------------------------- /Templates/README.md: -------------------------------------------------------------------------------- 1 | 工程模块配置: 2 | 3 | * Identifier 4 | 5 | 模板的唯一标示符 6 | * Kind 7 | 8 | Xcode.Xcode3.ProjectTemplateUnitKind 都是这个值 9 | * Concrete 10 | 11 | 设置为YES的模板才可以显示在new project的dialog中,此时这个模板不能被其他模板继承 12 | * Ancestors 13 | 14 | 父模版,从父模版那里继承一些模板的基础属性,可以有多个父类 15 | * Description 16 | 17 | 新建工程时,模版的描述 18 | * Targets 19 | 20 | Target的一些设置,包括编译设置 21 | * Platforms 22 | 23 | 运行平台 24 | * Project 25 | 26 | 项目的一些设置 27 | * Options 28 | 29 | 定义新建工程中的storyboard等 30 | * Nodes 31 | 32 | 定义添加到工程模版中的文件 33 | * Definitions 34 | 35 | 将Nodes中定义的文件添加到项目中 36 | 37 | ### Base模板 38 | 主要是继承一些通过父模板 39 | 40 | * 单元测试 41 | * deb打包 42 | * 设置显示 43 | 44 | Target的编译设置,安装的设备,编译时是否安装等等。 45 | 46 | 项目的设置: 47 | 48 | TARGETED_DEVICE_FAMILY 1,2 Iphone/Ipad 49 | 50 | 文件导入以及pch文件。 51 | 52 | ### Debian Package 53 | Package的一些编译设置。 54 | 55 | 增加文件: 56 | Package/DEBIAN/contrl 57 | 58 | 以及文件里面的内容。 59 | 60 | ### PreferenceLoader 61 | 是否显示在设置里面。 62 | 63 | ### Unit Tests 64 | 单元测试。 65 | 66 | ### CaptainHook Tweak 67 | 类型: 68 | 动态库 69 | 编译设置: 70 | 安装路径 71 | 编译脚本 72 | 73 | 增加修改文件,编译文件,hook的对象,control内容。 74 | 75 | ### Logos Tweak 76 | 同上。 77 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Logos/___PACKAGENAMEASIDENTIFIER___.xm: -------------------------------------------------------------------------------- 1 | // See http://iphonedevwiki.net/index.php/Logos 2 | 3 | #import 4 | 5 | @interface CustomViewController 6 | 7 | @property (nonatomic, copy) NSString* newProperty; 8 | 9 | + (void)classMethod; 10 | 11 | - (NSString*)getMyName; 12 | 13 | - (void)newMethod:(NSString*) output; 14 | 15 | @end 16 | 17 | %hook CustomViewController 18 | 19 | + (void)classMethod 20 | { 21 | %log; 22 | 23 | %orig; 24 | } 25 | 26 | %new 27 | -(void)newMethod:(NSString*) output{ 28 | NSLog(@"This is a new method : %@", output); 29 | } 30 | 31 | %new 32 | - (id)newProperty { 33 | return objc_getAssociatedObject(self, @selector(newProperty)); 34 | } 35 | 36 | %new 37 | - (void)setNewProperty:(id)value { 38 | objc_setAssociatedObject(self, @selector(newProperty), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 39 | } 40 | 41 | - (NSString*)getMyName 42 | { 43 | %log; 44 | 45 | NSString* password = MSHookIvar(self,"_password"); 46 | 47 | NSLog(@"password:%@", password); 48 | 49 | [%c(CustomViewController) classMethod]; 50 | 51 | [self newMethod:@"output"]; 52 | 53 | self.newProperty = @"newProperty"; 54 | 55 | NSLog(@"newProperty : %@", self.newProperty); 56 | 57 | return %orig(); 58 | } 59 | 60 | %end 61 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Config/MDConfigManager.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // MDConfigManager.m 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2018/4/24. 8 | // Copyright © 2018年 AloneMonkey. All rights reserved. 9 | // 10 | 11 | #define CONFIG_FILE_NAME @"MDConfig" 12 | 13 | #import "MDConfigManager.h" 14 | 15 | @implementation MDConfigManager{ 16 | NSString* _filepath; 17 | } 18 | 19 | + (instancetype)sharedInstance{ 20 | static MDConfigManager *sharedInstance = nil; 21 | if (!sharedInstance){ 22 | sharedInstance = [[MDConfigManager alloc] init]; 23 | } 24 | return sharedInstance; 25 | } 26 | 27 | - (BOOL)isActive{ 28 | _filepath = [[NSBundle mainBundle] pathForResource:CONFIG_FILE_NAME ofType:@"plist"]; 29 | if(_filepath == nil){ 30 | return NO; 31 | } 32 | return YES; 33 | } 34 | 35 | - (NSDictionary*) readConfigByKey:(NSString*) key{ 36 | if([self isActive]){ 37 | NSDictionary* contentDict = [NSDictionary dictionaryWithContentsOfFile:_filepath]; 38 | if([contentDict.allKeys containsObject:key]){ 39 | return contentDict[key]; 40 | }else{ 41 | return nil; 42 | } 43 | }else{ 44 | return nil; 45 | } 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/Cocoa___PACKAGENAMEASIDENTIFIER___.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | //___FILEHEADER___ 5 | 6 | #import "___FILEBASENAME___.h" 7 | #import "substrate.h" 8 | 9 | #warning 以下代码只针对QQ,如果是其它应用的话,需要将下面的代码删除 10 | 11 | @class MQAIOChatViewController; 12 | @class QQMessageRevokeEngine; 13 | 14 | static void (*origin_MQAIOChatViewController_revokeMessages)(MQAIOChatViewController*,SEL,id); 15 | static void new_MQAIOChatViewController_revokeMessages(MQAIOChatViewController* self,SEL _cmd,id arrays){ 16 | 17 | } 18 | 19 | static void (*origin_QQMessageRevokeEngine_handleRecallNotify_isOnline)(QQMessageRevokeEngine*,SEL,void*,BOOL); 20 | static void new_QQMessageRevokeEngine_handleRecallNotify_isOnline(QQMessageRevokeEngine* self,SEL _cmd,void* notify,BOOL isOnline){ 21 | 22 | } 23 | 24 | static void __attribute__((constructor)) initialize(void) { 25 | MSHookMessageEx(objc_getClass("MQAIOChatViewController"), @selector(revokeMessages:), (IMP)&new_MQAIOChatViewController_revokeMessages, (IMP*)&origin_MQAIOChatViewController_revokeMessages); 26 | 27 | MSHookMessageEx(objc_getClass("QQMessageRevokeEngine"), @selector(handleRecallNotify:isOnline:), (IMP)&new_QQMessageRevokeEngine_handleRecallNotify_isOnline, (IMP*)&origin_QQMessageRevokeEngine_handleRecallNotify_isOnline); 28 | } 29 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Trace/selectortramps.mac: -------------------------------------------------------------------------------- 1 | /* 2 | * selectortramps.mac 3 | * OCMethodTrace 4 | * 5 | * https://github.com/omxcodec/OCMethodTrace.git 6 | * 7 | * Copyright (C) 2018 Michael Chen 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #ifdef __x86_64__ 23 | #define PRELOAD(x,f) movq x@GOTPCREL(%rip), %r10; 24 | #define LABEL_ADDR(x,f) %r10 25 | #define LABEL_VALUE(x,f) (%r10) 26 | #define INIT_PIC(f) 27 | #define END_PIC(f) 28 | #elif __i386__ 29 | #define PRELOAD(x,f) leal x-L0## f ##$pb(%ebx), %eax; 30 | #define LABEL_ADDR(x,f) %eax 31 | #define LABEL_VALUE(x,f) (%eax) 32 | #define INIT_PIC(x) \ 33 | push %ebx; \ 34 | call L0## x ##$pb; \ 35 | L0## x ##$pb:; \ 36 | pop %ebx; 37 | #define END_PIC(x) pop %ebx 38 | #endif 39 | -------------------------------------------------------------------------------- /Templates/MonkeyPod.xctemplate/___PACKAGENAMEASIDENTIFIER___.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "___PACKAGENAME___" #Pod的名字 3 | spec.version = "1.0.0" #版本号 4 | spec.summary = "A example pod for MonkeyDev" 5 | spec.description = <<-DESC #Pod的描述 6 | - A example pod for MonkeyDev 7 | DESC 8 | 9 | spec.homepage = "https://github.com/AloneMonkey/MonkeyDevPod" #Pod的地址 10 | 11 | spec.license = { :type => "BSD", :file => "LICENSE" } #License 12 | spec.author = { "AloneMonkey" => "liupeiqing1993@163.com" } #作者 13 | spec.social_media_url = "http://weibo.com/xiaoqing28" #weibo 14 | spec.platform = :ios, "8.0" #平台、版本 15 | spec.source = { :git => "https://github.com/AloneMonkey/MonkeyPod.git", :tag => spec.version.to_s } #代码的git地址以及tag 16 | spec.source_files = "___PACKAGENAME___/**/*.{h,m}" #本地验证,表示当前目录以及子目录的所有h或m结尾的文件 如果发布到MonkeyPodSpecs需要填写git clone下来的对应的路径 17 | spec.public_header_files = "___PACKAGENAME___/___PACKAGENAME___.h" #需要对外导出的头文件 此处为本地验证 18 | spec.requires_arc = true #ARC 19 | spec.pod_target_xcconfig = { "ONLY_ACTIVE_ARCH" => "NO", "HEADER_SEARCH_PATHS" => "/opt/MonkeyDev/include" } #这个必须有,不要修改 20 | end -------------------------------------------------------------------------------- /Frameworks/RevealServer.framework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 17E199 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | RevealServer 11 | CFBundleIdentifier 12 | com.ittybittyapps.RevealServer 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | RevealServer 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 14 21 | CFBundleSignature 22 | ???? 23 | CFBundleSupportedPlatforms 24 | 25 | iPhoneOS 26 | 27 | CFBundleVersion 28 | 10107 29 | DTCompiler 30 | com.apple.compilers.llvm.clang.1_0 31 | DTPlatformBuild 32 | 15E217 33 | DTPlatformName 34 | iphoneos 35 | DTPlatformVersion 36 | 11.3 37 | DTSDKBuild 38 | 15E217 39 | DTSDKName 40 | iphoneos11.3 41 | DTXcode 42 | 0930 43 | DTXcodeBuild 44 | 9E145 45 | MinimumOSVersion 46 | 8.0 47 | UIDeviceFamily 48 | 49 | 1 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Tools/mpack.sh: -------------------------------------------------------------------------------- 1 | MONKEYDEV_PATH="/opt/MonkeyDev" 2 | 3 | function panic() # args: exitCode, message... 4 | { 5 | local exitCode=$1 6 | set +e 7 | 8 | shift 9 | [[ "$@" == "" ]] || \ 10 | echo "$@" >&2 11 | 12 | exit $exitCode 13 | } 14 | 15 | echo "packing..." 16 | # environment 17 | monkeyparser="$MONKEYDEV_PATH/bin/monkeyparser" 18 | substrate="$MONKEYDEV_PATH/MFrameworks/libsubstitute.dylib" 19 | 20 | #exename 21 | TARGET_APP_PATH=$(find "$SRCROOT/$TARGET_NAME/TargetApp" -type d | grep ".app$" | head -n 1) 22 | 23 | if [[ "$TARGET_APP_PATH" == "" ]]; then 24 | panic 1 "cannot find target app" 25 | fi 26 | 27 | APP_BINARY_NAME=`plutil -convert xml1 -o - "$TARGET_APP_PATH/Contents/Info.plist" | grep -A1 CFBundleExecutable | tail -n1 | cut -f2 -d\> | cut -f1 -d\<` 28 | APP_BINARY_PATH="$TARGET_APP_PATH/Contents/MacOS/$APP_BINARY_NAME" 29 | 30 | #restoresymbol 31 | if [[ ! -f "$APP_BINARY_PATH".symbol ]]; then 32 | "$monkeyparser" restoresymbol -t "$APP_BINARY_PATH" -o "$APP_BINARY_PATH"_with_symbol 33 | mv "$APP_BINARY_PATH"_with_symbol "$APP_BINARY_PATH" 34 | echo "restoresymbol" >> "$APP_BINARY_PATH".symbol 35 | fi 36 | 37 | #unsign 38 | if [[ ! -f "$APP_BINARY_PATH".unsigned ]]; then 39 | "$monkeyparser" strip -t "$APP_BINARY_PATH" -o "$APP_BINARY_PATH".unsigned 40 | mv "$APP_BINARY_PATH".unsigned "$APP_BINARY_PATH" 41 | echo "unsigned" >> "$APP_BINARY_PATH".unsigned 42 | fi 43 | 44 | #insert dylib 45 | BUILD_DYLIB_PATH="$BUILT_PRODUCTS_DIR/lib$TARGET_NAME.dylib" 46 | 47 | if [[ ! -f "$APP_BINARY_PATH".insert ]]; then 48 | cp -rf "$substrate" "$TARGET_APP_PATH/Contents/MacOS/" 49 | "$monkeyparser" install -c load -p "@executable_path/lib$TARGET_NAME.dylib" -t "$APP_BINARY_PATH" 50 | echo "insert" >> "$APP_BINARY_PATH".insert 51 | fi 52 | 53 | cp -rf "$BUILD_DYLIB_PATH" "$TARGET_APP_PATH/Contents/MacOS/" 54 | 55 | chmod +x "$APP_BINARY_PATH" 56 | 57 | "$APP_BINARY_PATH" 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MonkeyDev修改支持巨魔越狱开发 ----- 公众号XLsnow 2 | 3 | ## 很多人不会theos开发, 只喜欢Xcode开发, 但MonkeyDev已多年没有更新, 4 | ## 故做些许修改, 支持打包编译Tweak开发, 支持iOS15-16的无根越狱Rootless 5 | 6 | 7 | 这是一个为越狱和非越狱开发人员准备的工具,主要包括四个模块: 8 | ## Logos Tweak 9 | 10 | 使用theos提供的logify.pl工具将*.xm文件转成*.mm文件进行编译,集成了CydiaSubstrate,可以使用MSHookMessageEx和MSHookFunction来Hook OC函数和指定地址。 11 | 12 | ## CaptainHook Tweak 13 | 14 | 使用CaptainHook提供的头文件进行OC 函数的Hook以及属性的获取。 15 | 16 | ## Command-line Tool 17 | 18 | 可以直接创建运行于越狱设备的命令行工具 19 | 20 | ## MonkeyApp 21 | 22 | 这是自动给第三方应用集成Reveal、Cycript和注入dylib的模块,支持调试dylib和第三方应用,支持Pod给第三放应用集成SDK,只需要准备一个砸壳后的ipa或者app文件即可。 23 | 24 | 25 | 1. 第一步还是安装Theos, 因为插件都是需要他的, MonkeyDev只是套壳 26 | 27 | 安装最新的theos 28 | sudo git clone --recursive https://github.com/theos/theos.git /opt/theos 29 | 新增Xcode--Build Setting里--MonekDevRootless 为 YES 无根 或 NO 有根 30 | 设置Xcode对应编译的处理器 arm64 A11- |||| arm64e A12+ 31 | 32 | 33 | # 修改MonkeyDev的开发templates 34 | ## 执行以下命令 MonkeyDevRootless=YES CODE_SIGNING_ALLOWED=NO 35 | ``` 36 | sudo /usr/libexec/PlistBuddy -c "Add :Targets:0:SharedSettings:MonkeyDevRootless string YES" ~/Library/Developer/Xcode/Templates/MonkeyDev/Base.xctemplate/TemplateInfo.plist 37 | 38 | sudo /usr/libexec/PlistBuddy -c "Add :Targets:0:SharedSettings:CODE_SIGNING_ALLOWED string NO" ~/Library/Developer/Xcode/Templates/MonkeyDev/Base.xctemplate/TemplateInfo.plist 39 | 40 | sudo /usr/libexec/PlistBuddy -c "Set :Targets:0:SharedSettings:MonkeyDevDeviceIP localhost" ~/Library/Developer/Xcode/Templates/MonkeyDev/Base.xctemplate/TemplateInfo.plist 41 | 42 | sudo /usr/libexec/PlistBuddy -c "Set :Targets:0:SharedSettings:MonkeyDevDevicePassword alpine" ~/Library/Developer/Xcode/Templates/MonkeyDev/Base.xctemplate/TemplateInfo.plist 43 | 44 | sudo /usr/libexec/PlistBuddy -c "Set :Targets:0:SharedSettings:MonkeyDevDevicePort 2222" ~/Library/Developer/Xcode/Templates/MonkeyDev/Base.xctemplate/TemplateInfo.plist 45 | 46 | sudo /usr/libexec/PlistBuddy -c "Set :Targets:0:SharedSettings:MonkeyDevkillProcessOnInstall " ~/Library/Developer/Xcode/Templates/MonkeyDev/Base.xctemplate/TemplateInfo.plist 47 | ``` 48 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/___PACKAGENAMEASIDENTIFIER___.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // ___FILENAME___ 5 | // ___PACKAGENAME___ 6 | // 7 | // Created by ___FULLUSERNAME___ on ___DATE___. 8 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 9 | // 10 | 11 | #import "___FILEBASENAME___.h" 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | CHConstructor{ 18 | printf(INSERT_SUCCESS_WELCOME); 19 | 20 | [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { 21 | 22 | #ifndef __OPTIMIZE__ 23 | CYListenServer(6666); 24 | 25 | MDCycriptManager* manager = [MDCycriptManager sharedInstance]; 26 | [manager loadCycript:NO]; 27 | 28 | NSError* error; 29 | NSString* result = [manager evaluateCycript:@"UIApp" error:&error]; 30 | NSLog(@"result: %@", result); 31 | if(error.code != 0){ 32 | NSLog(@"error: %@", error.localizedDescription); 33 | } 34 | #endif 35 | 36 | }]; 37 | } 38 | 39 | 40 | CHDeclareClass(CustomViewController) 41 | 42 | #pragma clang diagnostic push 43 | #pragma clang diagnostic ignored "-Wstrict-prototypes" 44 | 45 | //add new method 46 | CHDeclareMethod1(void, CustomViewController, newMethod, NSString*, output){ 47 | NSLog(@"This is a new method : %@", output); 48 | } 49 | 50 | #pragma clang diagnostic pop 51 | 52 | CHOptimizedClassMethod0(self, void, CustomViewController, classMethod){ 53 | NSLog(@"hook class method"); 54 | CHSuper0(CustomViewController, classMethod); 55 | } 56 | 57 | CHOptimizedMethod0(self, NSString*, CustomViewController, getMyName){ 58 | //get origin value 59 | NSString* originName = CHSuper(0, CustomViewController, getMyName); 60 | 61 | NSLog(@"origin name is:%@",originName); 62 | 63 | //get property 64 | NSString* password = CHIvar(self,_password,__strong NSString*); 65 | 66 | NSLog(@"password is %@",password); 67 | 68 | [self newMethod:@"output"]; 69 | 70 | //set new property 71 | self.newProperty = @"newProperty"; 72 | 73 | NSLog(@"newProperty : %@", self.newProperty); 74 | 75 | //change the value 76 | return @"___FULLUSERNAME___"; 77 | 78 | } 79 | 80 | //add new property 81 | CHPropertyRetainNonatomic(CustomViewController, NSString*, newProperty, setNewProperty); 82 | 83 | CHConstructor{ 84 | CHLoadLateClass(CustomViewController); 85 | CHClassHook0(CustomViewController, getMyName); 86 | CHClassHook0(CustomViewController, classMethod); 87 | 88 | CHHook0(CustomViewController, newProperty); 89 | CHHook1(CustomViewController, setNewProperty); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /Templates/PreferenceLoader.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.preferenceLoader 9 | Options 10 | 11 | 12 | SortOrder 13 | 2 14 | Default 15 | false 16 | NotPersisted 17 | 18 | Identifier 19 | includePreferenceLoaderSimple 20 | Name 21 | Include Simple PreferenceLoader 22 | Description 23 | Indicates whether a Simple PreferenceLoader (non-bundle) is included. 24 | Type 25 | checkbox 26 | Units 27 | 28 | true 29 | 30 | 31 | Definitions 32 | 33 | Package/Library/PreferenceLoader/Preferences/___PACKAGENAMEASIDENTIFIER___.plist 34 | 35 | Group 36 | 37 | Package 38 | Library 39 | PreferenceLoader 40 | Preferences 41 | 42 | Path 43 | ___PACKAGENAMEASIDENTIFIER___.plist 44 | 45 | Package/Library/PreferenceLoader/Preferences/___PACKAGENAMEASIDENTIFIER___Icon.png 46 | 47 | Group 48 | 49 | Package 50 | Library 51 | PreferenceLoader 52 | Preferences 53 | 54 | Path 55 | ___PACKAGENAMEASIDENTIFIER___Icon.png 56 | 57 | Package/Library/PreferenceLoader/Preferences/___PACKAGENAMEASIDENTIFIER___Icon@2x.png 58 | 59 | Group 60 | 61 | Package 62 | Library 63 | PreferenceLoader 64 | Preferences 65 | 66 | Path 67 | ___PACKAGENAMEASIDENTIFIER___Icon@2x.png 68 | 69 | 70 | Nodes 71 | 72 | Package/Library/PreferenceLoader/Preferences/___PACKAGENAMEASIDENTIFIER___.plist 73 | Package/Library/PreferenceLoader/Preferences/___PACKAGENAMEASIDENTIFIER___Icon.png 74 | Package/Library/PreferenceLoader/Preferences/___PACKAGENAMEASIDENTIFIER___Icon@2x.png 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Trace/OCMethodTrace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OCMethodTrace.h 3 | * OCMethodTrace 4 | * 5 | * https://github.com/omxcodec/OCMethodTrace.git 6 | * 7 | * Copyright (C) 2018 Michael Chen 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #import 23 | 24 | // 方法跟踪条件block 25 | // @param sel 方法名 26 | typedef BOOL (^OMTConditionBlock)(SEL sel); 27 | 28 | // 方法调用前会调用该block 29 | // @param target 跟踪目标对象 30 | // @param cls 调用方法所在的类(可以是target所在的类,也可以是target的父类) 31 | // @param sel 方法名 32 | // @param args 参数列表 33 | // @param deep 调用层次 34 | typedef void (^OMTBeforeBlock)(id target, Class cls, SEL sel, NSArray *args, int deep); 35 | 36 | // 方法调用后会调用该block 37 | // @param target 跟踪目标对象 38 | // @param cls 调用方法所在的类(可以是target所在的类,也可以是target的父类) 39 | // @param sel 方法名 40 | // @param ret 返回值 41 | // @param deep 调用层次 42 | // @param interval 执行方法的ms耗时 43 | typedef void (^OMTAfterBlock)(id target, Class cls, SEL sel, id ret, int deep, NSTimeInterval interval); 44 | 45 | // target位置 46 | typedef NS_ENUM(NSUInteger, OMTTargetPosition) { 47 | OMTTargetPositionBeforeSelf = 0, // before-调用者self 48 | OMTTargetPositionBeforeArgument, // before-参数 49 | OMTTargetPositionAfterSelf, // after-调用者self 50 | OMTTargetPositionAfterReturnValue, // after-返回值 51 | OMTTargetPositionMax, 52 | }; 53 | 54 | // 日志级别 55 | typedef NS_ENUM(NSUInteger, OMTLogLevel) { 56 | OMTLogLevelError = 0, 57 | OMTLogLevelDebug, 58 | OMTLogLevelMax, 59 | }; 60 | 61 | @protocol OCMethodTraceDelegate 62 | 63 | @optional 64 | // 获取target的description回调 65 | - (NSString *)descriptionWithTarget:(id)target class:(Class)cls selector:(SEL)sel targetPosition:(OMTTargetPosition)targetPosition; 66 | // 日志回调 67 | - (void)log:(OMTLogLevel)level format:(NSString *)format, ... NS_FORMAT_FUNCTION(2,3); 68 | 69 | @end 70 | 71 | @interface OCMethodTrace : NSObject 72 | 73 | @property (nonatomic, assign) BOOL disableTrace; // 屏蔽before和after调用,hook完成后默认打开 74 | @property (nonatomic, weak) id delegate; // 回调 75 | @property (nonatomic, assign) OMTLogLevel logLevel; // 日志级别,默认OMTLogLevelDebug 76 | 77 | + (OCMethodTrace *)sharedInstance; 78 | 79 | // 跟踪打印目标(实例或类)方法调用 80 | // @param cls 跟踪打印目标类 81 | // @param condition 判断是否跟踪方法的block 82 | // @param before 被跟踪的方法调用前会调用该block 83 | // @param after 被跟踪的方法调用后会调用该block 84 | - (void)traceMethodWithClass:(Class)cls 85 | condition:(OMTConditionBlock)condition 86 | before:(OMTBeforeBlock)before 87 | after:(OMTAfterBlock)after; 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/fishhook/fishhook.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef fishhook_h 25 | #define fishhook_h 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(FISHHOOK_EXPORT) 31 | #define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) 32 | #else 33 | #define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif //__cplusplus 39 | 40 | /* 41 | * A structure representing a particular intended rebinding from a symbol 42 | * name to its replacement 43 | */ 44 | struct rebinding { 45 | const char *name; 46 | void *replacement; 47 | void **replaced; 48 | }; 49 | 50 | /* 51 | * For each rebinding in rebindings, rebinds references to external, indirect 52 | * symbols with the specified name to instead point at replacement for each 53 | * image in the calling process as well as for all future images that are loaded 54 | * by the process. If rebind_functions is called more than once, the symbols to 55 | * rebind are added to the existing list of rebindings, and if a given symbol 56 | * is rebound more than once, the later rebinding will take precedence. 57 | */ 58 | FISHHOOK_VISIBILITY 59 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); 60 | 61 | /* 62 | * Rebinds as above, but only in the specified image. The header should point 63 | * to the mach-o header, the slide should be the slide offset. Others as above. 64 | */ 65 | FISHHOOK_VISIBILITY 66 | int rebind_symbols_image(void *header, 67 | intptr_t slide, 68 | struct rebinding rebindings[], 69 | size_t rebindings_nel); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif //__cplusplus 74 | 75 | #endif //fishhook_h 76 | 77 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/fishhook/fishhook.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef fishhook_h 25 | #define fishhook_h 26 | 27 | #include 28 | #include 29 | 30 | #if !defined(FISHHOOK_EXPORT) 31 | #define FISHHOOK_VISIBILITY __attribute__((visibility("hidden"))) 32 | #else 33 | #define FISHHOOK_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif //__cplusplus 39 | 40 | /* 41 | * A structure representing a particular intended rebinding from a symbol 42 | * name to its replacement 43 | */ 44 | struct rebinding { 45 | const char *name; 46 | void *replacement; 47 | void **replaced; 48 | }; 49 | 50 | /* 51 | * For each rebinding in rebindings, rebinds references to external, indirect 52 | * symbols with the specified name to instead point at replacement for each 53 | * image in the calling process as well as for all future images that are loaded 54 | * by the process. If rebind_functions is called more than once, the symbols to 55 | * rebind are added to the existing list of rebindings, and if a given symbol 56 | * is rebound more than once, the later rebinding will take precedence. 57 | */ 58 | FISHHOOK_VISIBILITY 59 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); 60 | 61 | /* 62 | * Rebinds as above, but only in the specified image. The header should point 63 | * to the mach-o header, the slide should be the slide offset. Others as above. 64 | */ 65 | FISHHOOK_VISIBILITY 66 | int rebind_symbols_image(void *header, 67 | intptr_t slide, 68 | struct rebinding rebindings[], 69 | size_t rebindings_nel); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif //__cplusplus 74 | 75 | #endif //fishhook_h 76 | 77 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Config/MDConfigManager.h: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // MDConfigManager.h 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2018/4/24. 8 | // Copyright © 2018年 AloneMonkey. All rights reserved. 9 | // 10 | 11 | #import 12 | 13 | #define MDCONFIG_CYCRIPT_KEY @"Cycript" 14 | #define MDCONFIG_LOADATLAUNCH_KEY @"LoadAtLaunch" 15 | 16 | #define MDCONFIG_TRACE_KEY @"MethodTrace" 17 | #define MDCONFIG_LOG_LEVEL_KEY @"LogLevel" 18 | #define MDCONFIG_LOG_WHEN_KEY @"LogWhen" 19 | #define MDCONFIG_LOG_REGEX_STRING_KEY @"LogRegexString" // 仅LogWhen=MDTraceLogWhenRegexString有效 20 | #define MDCONFIG_TRACE_FLAG_KEY @"TraceFlag" 21 | #define MDCONFIG_TRACE_OBJECT_KEY @"TraceObject" 22 | #define MDCONFIG_CLASS_REGEX_STRING_KEY @"ClassRegexString" // 仅TraceObject=MDTraceObjectRegexClass有效 23 | #define MDCONFIG_CORE_CLASS_LIST @"CORE_CLASS_LIST" 24 | #define MDCONFIG_USER_CLASS_LIST @"USER_CLASS_LIST" 25 | #define MDCONFIG_TRACE_MODE_KEY @"TraceMode" 26 | #define MDCONFIG_METHOD_WHITE_LIST_KEY @"MethodWhiteList" 27 | #define MDCONFIG_METHOD_BLACK_LIST_KEY @"MethodBlackList" 28 | 29 | // Trace日志级别 30 | typedef NS_ENUM(NSUInteger, MDTraceLogLevel) { 31 | MDTraceLogLeveError = 0, // 错误 32 | MDTraceLogLeveDebug = 1, // 调试 33 | MDTraceLogLeveMax 34 | }; 35 | 36 | // Trace日志输出时机 37 | typedef NS_ENUM(NSUInteger, MDTraceLogWhen) { 38 | MDTraceLogWhenStartup = 0, // 启动即输出日志 39 | MDTraceLogWhenVolume = 1, // 根据音量键控制输出日志(增加音量:输出日志;降低音量:关闭日志;默认时关闭日志) 40 | MDTraceLogWhenRegexString = 2, // 日志包含指定正则字符串才输出日志 41 | MDTraceLogWhenMax 42 | }; 43 | 44 | // Trace控制位(尽量在该处扩展) 45 | typedef NS_OPTIONS(NSUInteger, MDTraceFlag) { 46 | MDTraceFlagDoesNotUseDescription = 1 << 0, // 跳过调用对象description方法,避免不正规的description实现导致递归 47 | MDTraceFlagDumpClassListInfo = 1 << 1, // 打印类列表信息,便于调试 48 | MDTraceFlagDumpClassMethod = 1 << 2, // 打印某个类的方法(不包括父类方法),便于调试 49 | MDTraceFlagDumpSuperClassMethod = 1 << 3, // 打印某个类的父类方法(包括递归父类的方法),便于调试 50 | MDTraceFlagMask = 0xF, 51 | 52 | MDTraceFlagDefault = 0, 53 | }; 54 | 55 | // Trace对象 56 | typedef NS_ENUM(NSUInteger, MDTraceObject) { 57 | // 屏蔽trace所有类 58 | MDTraceObjectNone = 0, 59 | // trace引擎指定类的方法(仅测试验证使用),仅需要考虑CORE_CLASS_LIST 60 | MDTraceObjectCoreClass = 1, 61 | // trace用户指定类的方法,需要考虑USER_CLASS_LIST + "USER_CLASS_LIST和CORE_CLASS_LIST交集" 62 | MDTraceObjectUserClass = 2, 63 | // trace用户指定类 + 正则匹配类的方法,需要考虑USER_CLASS_LIST + "USER_CLASS_LIST和CORE_CLASS_LIST交集" + 64 | // "匹配ClassRegexString的CLASS_LIST和CORE_CLASS_LIST交集" 65 | MDTraceObjectRegexClass = 3, 66 | 67 | MDTraceObjectMax 68 | }; 69 | 70 | // Trace模式 71 | typedef NS_ENUM(NSUInteger, MDTraceMode) { 72 | MDTraceModeOff = 0, // 屏蔽trace方法 73 | MDTraceModeAll = 1, // trace所有方法 74 | MDTraceModeIncludeWhiteList = 2, // trace包含"白名单方法列表"的方法 75 | MDTraceModeExcludeBlackList = 3, // trace排除"黑名单方法列表"的方法 76 | MDTraceModeMax 77 | }; 78 | 79 | @interface MDConfigManager : NSObject 80 | 81 | + (instancetype)sharedInstance; 82 | 83 | - (NSDictionary*)readConfigByKey:(NSString*) key; 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /Templates/Debian Package.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.debianPackage 9 | Targets 10 | 11 | 12 | SharedSettings 13 | 14 | MonkeyDevBuildPackageOnAnyBuild 15 | NO 16 | 17 | 18 | 19 | Nodes 20 | 21 | Package/DEBIAN/control 22 | Package/DEBIAN/control:debianControl 23 | 24 | Definitions 25 | 26 | Package/DEBIAN/control 27 | 28 | Group 29 | 30 | Package 31 | DEBIAN 32 | 33 | 34 | *:debianControl 35 | 36 | Beginning 37 | Package: ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 38 | Name: ___VARIABLE_productName___ 39 | Version: 0.1-1 40 | Description: 41 | End 42 | Conflicts: 43 | Replaces: 44 | Priority: optional 45 | Architecture: iphoneos-arm 46 | Author: ___FULLUSERNAME___ 47 | dev: 48 | Homepage: 49 | Depiction: 50 | Maintainer: 51 | Icon: 52 | 53 | 54 | Package/DEBIAN/preinst 55 | 56 | Group 57 | 58 | Package 59 | DEBIAN 60 | 61 | Beginning 62 | #!/bin/sh 63 | 64 | # This script is executed BEFORE the Debian package is INSTALLED 65 | # For information about this file, see http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html#s-maintscripts. 66 | 67 | 68 | Package/DEBIAN/postinst 69 | 70 | Group 71 | 72 | Package 73 | DEBIAN 74 | 75 | Beginning 76 | #!/bin/sh 77 | 78 | # This script is executed AFTER the Debian package is INSTALLED 79 | # For information about this file, see http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html#s-maintscripts. 80 | 81 | 82 | Package/DEBIAN/prerm 83 | 84 | Group 85 | 86 | Package 87 | DEBIAN 88 | 89 | Beginning 90 | #!/bin/sh 91 | 92 | # This script is executed BEFORE the Debian package is REMOVED 93 | # For information about this file, see http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html#s-maintscripts. 94 | 95 | 96 | Package/DEBIAN/postrm 97 | 98 | Group 99 | 100 | Package 101 | DEBIAN 102 | 103 | Beginning 104 | #!/bin/sh 105 | 106 | # This script is executed AFTER the Debian package is REMOVED 107 | # For information about this file, see http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html#s-maintscripts. 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /bin/md-uninstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export setCmd="set -eo pipefail" 4 | $setCmd 5 | 6 | export PATH=/opt/MonkeyDev/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH 7 | 8 | export scriptName="${0##*/}" 9 | export scriptVer="2.0" 10 | 11 | export MonkeyDevPath="/opt/MonkeyDev" 12 | export backupFileExt=".MonkeyDev" 13 | 14 | export userName="${SUDO_USER-$USER}" 15 | export userGroup=`id -g $userName` 16 | export userHome=`eval echo ~$userName` 17 | export bashProfileFiles=("$userHome/.zshrc" "$userHome/.bash_profile" "$userHome/.bashrc" "$userHome/.bash_login" "$userHome/.profile") 18 | 19 | export tempDirsFile="`mktemp -d -t $scriptName`/tempdirs" 20 | touch "$tempDirsFile" 21 | 22 | unset LANG 23 | 24 | function cleanup() 25 | { 26 | local exitCode=$? 27 | set +e 28 | trap - $signals 29 | removeTempData 30 | exit $exitCode 31 | } 32 | function panic() 33 | { 34 | local exitCode=$1 35 | set +e 36 | shift 37 | [[ "$@" == "" ]] || echo "$@" >&2 38 | exit $exitCode 39 | } 40 | export signals="0 1 2 3 15" 41 | trap cleanup $signals 42 | 43 | function removeTempData() 44 | { 45 | local tempDirs 46 | if [[ -f "$tempDirsFile" ]]; then 47 | tempDirs=(`cat "$tempDirsFile"`) 48 | for td in "${tempDirs[@]}"; do 49 | rm -rf "$td" || true 50 | done 51 | rm -rf "`dirname $tempDirsFile`" || true 52 | fi 53 | } 54 | 55 | function copyFile() 56 | { 57 | cp -f "$1" "$2" || \ 58 | panic $? "Failed to copy file $1 to $2" 59 | } 60 | 61 | #还原文件 62 | function restoreFile() 63 | { 64 | local filePath="$1" 65 | local backedUpFilePath="${filePath}${backupFileExt}" 66 | 67 | if [[ -f "$backedUpFilePath" ]]; then 68 | copyFile "$backedUpFilePath" "$filePath" 69 | rm -f "$backedUpFilePath" 70 | fi 71 | } 72 | 73 | #获取SDK信息 74 | function getSdkProperty() 75 | { 76 | $setCmd 77 | 78 | local sdk="$1" 79 | local propertyName="$2" 80 | 81 | propertyValue=`xcodebuild -version -sdk $sdk $propertyName` || \ 82 | panic $? "Failed to get $sdk SDK property $propertyName" 83 | 84 | [[ $propertyValue != "" ]] || \ 85 | panic 1 "Value of $sdk SDK property $propertyName cannot be empty" 86 | 87 | # return # 88 | echo "$propertyValue" 89 | } 90 | 91 | echo "Uninstalling MonkeyDev base, Xcode templates and framework header files..." 92 | 93 | #删除文件夹 94 | rm -rf "$MonkeyDevPath" || \ 95 | panic $? "Failed to remove directory: $MonkeyDevPath" 96 | 97 | #移除模块符号链接 98 | userDevDir="$userHome/Library/Developer" 99 | userTemplatesDir="$userDevDir/Xcode/Templates" 100 | symlinkPath="$userTemplatesDir/MonkeyDev" 101 | 102 | rm -f "$symlinkPath" || \ 103 | panic $? "Failed to remove file: $symlinkPath" 104 | 105 | #移除profile环境变量 106 | for f in "${bashProfileFiles[@]}"; do 107 | if [[ -f "$f" ]]; then 108 | userBashProfileFile="$f" 109 | break 110 | fi 111 | done 112 | 113 | if [[ $userBashProfileFile != "" ]]; then 114 | sed -i "" "s/^export MonkeyDevPath=.*$//g" "$userBashProfileFile" 115 | sed -i "" "s/^export MonkeyDevDeviceIP=.*$//g" "$userBashProfileFile" 116 | sed -i "" "s/^export PATH=.*${MonkeyDevPath//\//\\/}\\/bin:.*$//g" "$userBashProfileFile" 117 | sed -i "" "s/^export PATH=.*\$MonkeyDevPath\\/bin:.*$//g" "$userBashProfileFile" 118 | fi 119 | 120 | iosSdkPlatformPath=`getSdkProperty iphoneos PlatformPath` 121 | 122 | specificationFile=$(cd $iosSdkPlatformPath/../../.. && pwd)/PlugIns/IDEiOSSupportCore.ideplugin/Contents/Resources/Embedded-Device.xcspec 123 | 124 | #还原文件 125 | restoreFile "$specificationFile" 126 | 127 | exit 0 -------------------------------------------------------------------------------- /Templates/CaptainHook Tweak.xctemplate/___PACKAGENAMEASIDENTIFIER___.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ___FILENAME___ 3 | // ___PACKAGENAME___ 4 | // 5 | // Created by ___FULLUSERNAME___ on ___DATE___. 6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 7 | // 8 | 9 | // CaptainHook by Ryan Petrich 10 | // see https://github.com/rpetrich/CaptainHook/ 11 | 12 | #if TARGET_OS_SIMULATOR 13 | #error Do not support the simulator, please use the real iPhone Device. 14 | #endif 15 | 16 | #import 17 | #import "CaptainHook/CaptainHook.h" 18 | #include // not required; for examples only 19 | 20 | // Objective-C runtime hooking using CaptainHook: 21 | // 1. declare class using CHDeclareClass() 22 | // 2. load class using CHLoadClass() or CHLoadLateClass() in CHConstructor 23 | // 3. hook method using CHOptimizedMethod() 24 | // 4. register hook using CHHook() in CHConstructor 25 | // 5. (optionally) call old method using CHSuper() 26 | 27 | 28 | @interface ___FILEBASENAMEASIDENTIFIER___ : NSObject 29 | 30 | @end 31 | 32 | @implementation ___FILEBASENAMEASIDENTIFIER___ 33 | 34 | -(id)init 35 | { 36 | if ((self = [super init])) 37 | { 38 | } 39 | 40 | return self; 41 | } 42 | 43 | @end 44 | 45 | 46 | @class ClassToHook; 47 | 48 | CHDeclareClass(ClassToHook); // declare class 49 | 50 | CHOptimizedMethod(0, self, void, ClassToHook, messageName) // hook method (with no arguments and no return value) 51 | { 52 | // write code here ... 53 | 54 | CHSuper(0, ClassToHook, messageName); // call old (original) method 55 | } 56 | 57 | CHOptimizedMethod(2, self, BOOL, ClassToHook, arg1, NSString*, value1, arg2, BOOL, value2) // hook method (with 2 arguments and a return value) 58 | { 59 | // write code here ... 60 | 61 | return CHSuper(2, ClassToHook, arg1, value1, arg2, value2); // call old (original) method and return its return value 62 | } 63 | 64 | static void WillEnterForeground(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 65 | { 66 | // not required; for example only 67 | } 68 | 69 | static void ExternallyPostedNotification(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 70 | { 71 | // not required; for example only 72 | } 73 | 74 | CHConstructor // code block that runs immediately upon load 75 | { 76 | @autoreleasepool 77 | { 78 | // listen for local notification (not required; for example only) 79 | CFNotificationCenterRef center = CFNotificationCenterGetLocalCenter(); 80 | CFNotificationCenterAddObserver(center, NULL, WillEnterForeground, CFSTR("UIApplicationWillEnterForegroundNotification"), NULL, CFNotificationSuspensionBehaviorCoalesce); 81 | 82 | // listen for system-side notification (not required; for example only) 83 | // this would be posted using: notify_post("___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___.eventname"); 84 | CFNotificationCenterRef darwin = CFNotificationCenterGetDarwinNotifyCenter(); 85 | CFNotificationCenterAddObserver(darwin, NULL, ExternallyPostedNotification, CFSTR("___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___.eventname"), NULL, CFNotificationSuspensionBehaviorCoalesce); 86 | 87 | // CHLoadClass(ClassToHook); // load class (that is "available now") 88 | // CHLoadLateClass(ClassToHook); // load class (that will be "available later") 89 | 90 | CHHook(0, ClassToHook, messageName); // register hook 91 | CHHook(2, ClassToHook, arg1, arg2); // register hook 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Templates/CaptainHook Tweak.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.captainHookTweak 9 | Concrete 10 | 11 | Description 12 | This template builds a CaptainHook-based Substrate Tweak. 13 | Ancestors 14 | 15 | com.monkey.monkeydev.base 16 | 17 | Targets 18 | 19 | 20 | ProductType 21 | com.apple.product-type.library.dynamic 22 | SharedSettings 23 | 24 | CLANG_ENABLE_OBJC_ARC 25 | YES 26 | HEADER_SEARCH_PATHS 27 | $(MonkeyDevPath)/include $(MonkeyDevTheosPath)/vendor/include/** 28 | GCC_PRECOMPILE_PREFIX_HEADER 29 | YES 30 | GCC_PREFIX_HEADER 31 | ___PACKAGENAME___/___PACKAGENAME___-Prefix.pch 32 | INSTALL_PATH 33 | /Library/MobileSubstrate/DynamicLibraries 34 | DYLIB_CURRENT_VERSION 35 | 1 36 | DYLIB_COMPATIBILITY_VERSION 37 | 1 38 | 39 | BuildPhases 40 | 41 | 42 | Class 43 | Sources 44 | 45 | 46 | Class 47 | Frameworks 48 | 49 | 50 | Class 51 | Headers 52 | 53 | 54 | ShellScript 55 | /opt/MonkeyDev/bin/md --xcbp 56 | ShellPath 57 | /bin/sh 58 | RunOnlyForDeploymentPostprocessing 59 | 60 | Class 61 | ShellScript 62 | 63 | 64 | Frameworks 65 | 66 | Foundation 67 | 68 | 69 | 70 | Nodes 71 | 72 | ___PACKAGENAME___-Prefix.pch:objC:importFoundation 73 | ___PACKAGENAMEASIDENTIFIER___.mm 74 | Package/DEBIAN/control:debianControl:section 75 | Package/DEBIAN/control:debianControl:depends 76 | Package/Library/MobileSubstrate/DynamicLibraries/___PACKAGENAMEASIDENTIFIER___.plist 77 | 78 | Definitions 79 | 80 | ___PACKAGENAMEASIDENTIFIER___.mm 81 | 82 | Path 83 | ___PACKAGENAMEASIDENTIFIER___.mm 84 | 85 | Package/Library/MobileSubstrate/DynamicLibraries/___PACKAGENAMEASIDENTIFIER___.plist 86 | 87 | Group 88 | 89 | Package 90 | Library 91 | MobileSubstrate 92 | DynamicLibraries 93 | 94 | Path 95 | ___PACKAGENAMEASIDENTIFIER___.plist 96 | 97 | *:debianControl:section 98 | Section: Tweaks 99 | *:debianControl:depends 100 | Depends: firmware (>= 5.0), mobilesubstrate 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/AntiAntiDebug/AntiAntiDebug.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // Created by AloneMonkey on 2016/12/10. 5 | // Copyright © 2017年 Coder. All rights reserved. 6 | // 7 | 8 | #if TARGET_OS_SIMULATOR 9 | #error Do not support the simulator, please use the real iPhone Device. 10 | #endif 11 | 12 | #import "fishhook.h" 13 | #import 14 | #import 15 | 16 | typedef int (*ptrace_ptr_t)(int _request,pid_t _pid, caddr_t _addr,int _data); 17 | typedef void* (*dlsym_ptr_t)(void * __handle, const char* __symbol); 18 | typedef int (*syscall_ptr_t)(int, ...); 19 | typedef int (*sysctl_ptr_t)(int *,u_int, void*, size_t*,void*, size_t); 20 | 21 | 22 | static ptrace_ptr_t orig_ptrace = NULL; 23 | static dlsym_ptr_t orig_dlsym = NULL; 24 | static sysctl_ptr_t orig_sysctl = NULL; 25 | static syscall_ptr_t orig_syscall = NULL; 26 | 27 | int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data); 28 | void* my_dlsym(void* __handle, const char* __symbol); 29 | int my_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize); 30 | int my_syscall(int code, va_list args); 31 | 32 | int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){ 33 | if(_request != 31){ 34 | return orig_ptrace(_request,_pid,_addr,_data); 35 | } 36 | 37 | NSLog(@"[AntiAntiDebug] - ptrace request is PT_DENY_ATTACH"); 38 | 39 | return 0; 40 | } 41 | 42 | void* my_dlsym(void* __handle, const char* __symbol){ 43 | if(strcmp(__symbol, "ptrace") != 0){ 44 | return orig_dlsym(__handle, __symbol); 45 | } 46 | 47 | NSLog(@"[AntiAntiDebug] - dlsym get ptrace symbol"); 48 | 49 | return my_ptrace; 50 | } 51 | 52 | typedef struct kinfo_proc _kinfo_proc; 53 | 54 | int my_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize){ 55 | if(namelen == 4 && name[0] == CTL_KERN && name[1] == KERN_PROC && name[2] == KERN_PROC_PID && info && infosize && ((int)*infosize == sizeof(_kinfo_proc))){ 56 | int ret = orig_sysctl(name, namelen, info, infosize, newinfo, newinfosize); 57 | struct kinfo_proc *info_ptr = (struct kinfo_proc *)info; 58 | if(info_ptr && (info_ptr->kp_proc.p_flag & P_TRACED) != 0){ 59 | NSLog(@"[AntiAntiDebug] - sysctl query trace status."); 60 | info_ptr->kp_proc.p_flag ^= P_TRACED; 61 | if((info_ptr->kp_proc.p_flag & P_TRACED) == 0){ 62 | NSLog(@"trace status reomve success!"); 63 | } 64 | } 65 | return ret; 66 | } 67 | return orig_sysctl(name, namelen, info, infosize, newinfo, newinfosize); 68 | } 69 | 70 | int my_syscall(int code, va_list args){ 71 | int request; 72 | va_list newArgs; 73 | va_copy(newArgs, args); 74 | if(code == 26){ 75 | request = va_arg(args, int); 76 | if(request == 31){ 77 | NSLog(@"[AntiAntiDebug] - syscall call ptrace, and request is PT_DENY_ATTACH"); 78 | return 0; 79 | } 80 | } 81 | return orig_syscall(code, newArgs); 82 | } 83 | 84 | __attribute__((constructor)) static void entry(){ 85 | NSLog(@"[AntiAntiDebug Init]"); 86 | 87 | rebind_symbols((struct rebinding[1]){{"ptrace", my_ptrace, (void*)&orig_ptrace}},1); 88 | 89 | rebind_symbols((struct rebinding[1]){{"dlsym", my_dlsym, (void*)&orig_dlsym}},1); 90 | 91 | //some app will crash with _dyld_debugger_notification 92 | rebind_symbols((struct rebinding[1]){{"sysctl", my_sysctl, (void*)&orig_sysctl}},1); 93 | 94 | // rebind_symbols((struct rebinding[1]){{"syscall", my_syscall, (void*)&orig_syscall}},1); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Trace/a1a2-selectortramps-arm64.s: -------------------------------------------------------------------------------- 1 | /* 2 | * a1a2-selectortramps-arm64.s 3 | * OCMethodTrace 4 | * 5 | * https://github.com/omxcodec/OCMethodTrace.git 6 | * 7 | * Copyright (C) 2018 Michael Chen 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #if __arm64__ 23 | 24 | #include 25 | 26 | .text 27 | 28 | .private_extern __a1a2_selectorTrampHead 29 | .private_extern __a1a2_firstSelectorTramp 30 | .private_extern __a1a2_selectorTrampEnd 31 | 32 | msgSend: 33 | .quad 0 34 | 35 | .align PAGE_MAX_SHIFT 36 | __a1a2_selectorTrampHead: 37 | L_a1a2_selectorTrampHead: 38 | // 1. selector 39 | ldr x1, [x17] // selector -> _cmd 40 | // 2. msgSend 41 | adr x17, L_a1a2_selectorTrampHead 42 | sub x17, x17, #PAGE_MAX_SIZE 43 | ldr x16, [x17] 44 | br x16 // tail call msgSend 45 | 46 | // pad up to TrampolineSelectorPagePair header size 47 | nop 48 | nop 49 | nop 50 | 51 | .macro TrampolineEntry 52 | // load address of trampoline data (one page before this instruction) 53 | adr x17, -PAGE_MAX_SIZE 54 | b L_a1a2_selectorTrampHead 55 | .endmacro 56 | 57 | .macro TrampolineEntryX16 58 | TrampolineEntry 59 | TrampolineEntry 60 | TrampolineEntry 61 | TrampolineEntry 62 | 63 | TrampolineEntry 64 | TrampolineEntry 65 | TrampolineEntry 66 | TrampolineEntry 67 | 68 | TrampolineEntry 69 | TrampolineEntry 70 | TrampolineEntry 71 | TrampolineEntry 72 | 73 | TrampolineEntry 74 | TrampolineEntry 75 | TrampolineEntry 76 | TrampolineEntry 77 | .endmacro 78 | 79 | .macro TrampolineEntryX256 80 | TrampolineEntryX16 81 | TrampolineEntryX16 82 | TrampolineEntryX16 83 | TrampolineEntryX16 84 | 85 | TrampolineEntryX16 86 | TrampolineEntryX16 87 | TrampolineEntryX16 88 | TrampolineEntryX16 89 | 90 | TrampolineEntryX16 91 | TrampolineEntryX16 92 | TrampolineEntryX16 93 | TrampolineEntryX16 94 | 95 | TrampolineEntryX16 96 | TrampolineEntryX16 97 | TrampolineEntryX16 98 | TrampolineEntryX16 99 | .endmacro 100 | 101 | .align 3 102 | .private_extern __a1a2_firstSelectorTramp 103 | __a1a2_firstSelectorTramp: 104 | // 2048-4 trampolines to fill 16K page 105 | TrampolineEntryX256 106 | TrampolineEntryX256 107 | TrampolineEntryX256 108 | TrampolineEntryX256 109 | 110 | TrampolineEntryX256 111 | TrampolineEntryX256 112 | TrampolineEntryX256 113 | 114 | TrampolineEntryX16 115 | TrampolineEntryX16 116 | TrampolineEntryX16 117 | TrampolineEntryX16 118 | 119 | TrampolineEntryX16 120 | TrampolineEntryX16 121 | TrampolineEntryX16 122 | TrampolineEntryX16 123 | 124 | TrampolineEntryX16 125 | TrampolineEntryX16 126 | TrampolineEntryX16 127 | TrampolineEntryX16 128 | 129 | TrampolineEntryX16 130 | TrampolineEntryX16 131 | TrampolineEntryX16 132 | 133 | TrampolineEntry 134 | TrampolineEntry 135 | TrampolineEntry 136 | TrampolineEntry 137 | 138 | TrampolineEntry 139 | TrampolineEntry 140 | TrampolineEntry 141 | TrampolineEntry 142 | 143 | TrampolineEntry 144 | TrampolineEntry 145 | TrampolineEntry 146 | TrampolineEntry 147 | 148 | // TrampolineEntry 149 | // TrampolineEntry 150 | // TrampolineEntry 151 | // TrampolineEntry 152 | 153 | .private_extern __a1a2_selectorTrampEnd 154 | __a1a2_selectorTrampEnd: 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/AntiAntiDebug/AntiAntiDebug.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // AntiAntiDebug.m 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2016/12/10. 8 | // Copyright © 2017年 MonkeyDev. All rights reserved. 9 | // 10 | 11 | #if TARGET_OS_SIMULATOR 12 | #error Do not support the simulator, please use the real iPhone Device. 13 | #endif 14 | 15 | #import "fishhook.h" 16 | #import 17 | #import 18 | 19 | typedef int (*ptrace_ptr_t)(int _request,pid_t _pid, caddr_t _addr,int _data); 20 | typedef void* (*dlsym_ptr_t)(void * __handle, const char* __symbol); 21 | typedef int (*syscall_ptr_t)(int, ...); 22 | typedef int (*sysctl_ptr_t)(int *,u_int, void*, size_t*,void*, size_t); 23 | 24 | 25 | static ptrace_ptr_t orig_ptrace = NULL; 26 | static dlsym_ptr_t orig_dlsym = NULL; 27 | static sysctl_ptr_t orig_sysctl = NULL; 28 | static syscall_ptr_t orig_syscall = NULL; 29 | 30 | int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data); 31 | void* my_dlsym(void* __handle, const char* __symbol); 32 | int my_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize); 33 | int my_syscall(int code, va_list args); 34 | 35 | int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){ 36 | if(_request != 31){ 37 | return orig_ptrace(_request,_pid,_addr,_data); 38 | } 39 | 40 | NSLog(@"[AntiAntiDebug] - ptrace request is PT_DENY_ATTACH"); 41 | 42 | return 0; 43 | } 44 | 45 | void* my_dlsym(void* __handle, const char* __symbol){ 46 | if(strcmp(__symbol, "ptrace") != 0){ 47 | return orig_dlsym(__handle, __symbol); 48 | } 49 | 50 | NSLog(@"[AntiAntiDebug] - dlsym get ptrace symbol"); 51 | 52 | return my_ptrace; 53 | } 54 | 55 | typedef struct kinfo_proc _kinfo_proc; 56 | 57 | int my_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize){ 58 | if(namelen == 4 && name[0] == CTL_KERN && name[1] == KERN_PROC && name[2] == KERN_PROC_PID && info && infosize && ((int)*infosize == sizeof(_kinfo_proc))){ 59 | int ret = orig_sysctl(name, namelen, info, infosize, newinfo, newinfosize); 60 | struct kinfo_proc *info_ptr = (struct kinfo_proc *)info; 61 | if(info_ptr && (info_ptr->kp_proc.p_flag & P_TRACED) != 0){ 62 | NSLog(@"[AntiAntiDebug] - sysctl query trace status."); 63 | info_ptr->kp_proc.p_flag ^= P_TRACED; 64 | if((info_ptr->kp_proc.p_flag & P_TRACED) == 0){ 65 | NSLog(@"trace status reomve success!"); 66 | } 67 | } 68 | return ret; 69 | } 70 | return orig_sysctl(name, namelen, info, infosize, newinfo, newinfosize); 71 | } 72 | 73 | int my_syscall(int code, va_list args){ 74 | int request; 75 | va_list newArgs; 76 | va_copy(newArgs, args); 77 | if(code == 26){ 78 | #ifdef __LP64__ 79 | __asm__( 80 | "ldr %w[result], [fp, #0x10]\n" 81 | : [result] "=r" (request) 82 | : 83 | : 84 | ); 85 | #else 86 | request = va_arg(args, int); 87 | #endif 88 | if(request == 31){ 89 | NSLog(@"[AntiAntiDebug] - syscall call ptrace, and request is PT_DENY_ATTACH"); 90 | return 0; 91 | } 92 | } 93 | return orig_syscall(code, newArgs); 94 | } 95 | 96 | __attribute__((constructor)) static void entry(){ 97 | NSLog(@"[AntiAntiDebug Init]"); 98 | 99 | rebind_symbols((struct rebinding[1]){{"ptrace", my_ptrace, (void*)&orig_ptrace}},1); 100 | 101 | rebind_symbols((struct rebinding[1]){{"dlsym", my_dlsym, (void*)&orig_dlsym}},1); 102 | 103 | //some app will crash with _dyld_debugger_notification 104 | // rebind_symbols((struct rebinding[1]){{"sysctl", my_sysctl, (void*)&orig_sysctl}},1); 105 | 106 | rebind_symbols((struct rebinding[1]){{"syscall", my_syscall, (void*)&orig_syscall}},1); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /Templates/MonkeyPod.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.cocoaTouchFramework 9 | Ancestors 10 | 11 | com.apple.dt.unit.languageChoice 12 | com.apple.dt.unit.frameworkBase 13 | com.apple.dt.unit.iosBase 14 | 15 | Concrete 16 | 17 | Description 18 | This template creates a framework that uses UIKit. 19 | SortOrder 20 | 1 21 | AssociatedTargetSpecification 22 | 23 | PopUpTitle 24 | Embed in Application: 25 | PopUpDescription 26 | The application target that will host this new framework. The application will be set up to link to and embed the new framework. 27 | AllowableProductTypes 28 | 29 | com.apple.product-type.application 30 | com.apple.product-type.application.messages 31 | 32 | AllowablePlatforms 33 | 34 | com.apple.platform.iphoneos 35 | 36 | AssociatedTargetIsDependent 37 | 38 | AssociatedTargetNeedsProductBuildPhaseInjection 39 | 40 | 41 | Options 42 | 43 | 44 | Identifier 45 | hasUnitTests 46 | Name 47 | Include Unit Tests 48 | NotPersisted 49 | 50 | SortOrder 51 | 100 52 | Type 53 | checkbox 54 | Default 55 | true 56 | Units 57 | 58 | true 59 | 60 | Components 61 | 62 | 63 | Identifier 64 | com.apple.dt.unit.cocoaTouchFrameworkUnitTestBundle 65 | Name 66 | ___PACKAGENAME___Tests 67 | 68 | 69 | 70 | 71 | 72 | 73 | Targets 74 | 75 | 76 | TargetIdentifier 77 | com.apple.dt.cocoaTouchLibraryOrFrameworkTarget 78 | SharedSettings 79 | 80 | LD_RUNPATH_SEARCH_PATHS 81 | $(inherited) @executable_path/Frameworks @loader_path/Frameworks 82 | 83 | 84 | 85 | Project 86 | 87 | SharedSettings 88 | 89 | HEADER_SEARCH_PATHS 90 | $(inherited) $(MonkeyDevPath)/include 91 | MonkeyDevPath 92 | /opt/MonkeyDev 93 | IPHONEOS_DEPLOYMENT_TARGET 94 | 8.0 95 | 96 | 97 | Nodes 98 | 99 | ___PACKAGENAMEASIDENTIFIER___.m 100 | ___PACKAGENAMEASIDENTIFIER___.podspec 101 | 102 | Definitions 103 | 104 | ___PACKAGENAMEASIDENTIFIER___.m 105 | 106 | Path 107 | ___PACKAGENAMEASIDENTIFIER___.m 108 | 109 | ___PACKAGENAMEASIDENTIFIER___.podspec 110 | 111 | Path 112 | ___PACKAGENAMEASIDENTIFIER___.podspec 113 | 114 | ___TARGETNAME:c99ExtIdentifier___.h 115 | 116 | TargetIdentifiers 117 | 118 | com.apple.dt.cocoaTouchLibraryOrFrameworkTarget 119 | 120 | BuildAttributes 121 | 122 | Public 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Trace/a1a2-selectortramps-arm.s: -------------------------------------------------------------------------------- 1 | /* 2 | * a1a2-selectortramps-arm.s 3 | * OCMethodTrace 4 | * 5 | * https://github.com/omxcodec/OCMethodTrace.git 6 | * 7 | * Copyright (C) 2018 Michael Chen 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #if __arm__ 23 | 24 | #include 25 | #include 26 | 27 | .syntax unified 28 | 29 | .text 30 | 31 | .private_extern __a1a2_selectorTrampHead 32 | .private_extern __a1a2_firstSelectorTramp 33 | .private_extern __a1a2_selectorTrampEnd 34 | 35 | // Trampoline machinery assumes the trampolines are Thumb function pointers 36 | #if !__thumb2__ 37 | # error sorry 38 | #endif 39 | 40 | .thumb 41 | .thumb_func __a1a2_selectorTrampHead 42 | .thumb_func __a1a2_firstSelectorTramp 43 | .thumb_func __a1a2_selectorTrampEnd 44 | 45 | .align PAGE_MAX_SHIFT 46 | __a1a2_selectorTrampHead: 47 | // Trampoline's data is one page before the trampoline text. 48 | // Also correct PC bias of 4 bytes. 49 | // 1. selector 50 | sub r12, #PAGE_MAX_SIZE 51 | ldr r1, [r12, #-4] // selector -> _cmd 52 | // 2. msgSend 53 | mov r12, pc 54 | sub r12, #PAGE_MAX_SIZE 55 | ldr pc, [r12, #-12] // tail call msgSend 56 | // not reached 57 | nop 58 | 59 | // Align trampolines to 8 bytes 60 | .align 3 61 | 62 | .macro TrampolineEntry 63 | mov r12, pc 64 | b __a1a2_selectorTrampHead 65 | .align 3 66 | .endmacro 67 | 68 | .macro TrampolineEntryX16 69 | TrampolineEntry 70 | TrampolineEntry 71 | TrampolineEntry 72 | TrampolineEntry 73 | 74 | TrampolineEntry 75 | TrampolineEntry 76 | TrampolineEntry 77 | TrampolineEntry 78 | 79 | TrampolineEntry 80 | TrampolineEntry 81 | TrampolineEntry 82 | TrampolineEntry 83 | 84 | TrampolineEntry 85 | TrampolineEntry 86 | TrampolineEntry 87 | TrampolineEntry 88 | .endmacro 89 | 90 | .macro TrampolineEntryX256 91 | TrampolineEntryX16 92 | TrampolineEntryX16 93 | TrampolineEntryX16 94 | TrampolineEntryX16 95 | 96 | TrampolineEntryX16 97 | TrampolineEntryX16 98 | TrampolineEntryX16 99 | TrampolineEntryX16 100 | 101 | TrampolineEntryX16 102 | TrampolineEntryX16 103 | TrampolineEntryX16 104 | TrampolineEntryX16 105 | 106 | TrampolineEntryX16 107 | TrampolineEntryX16 108 | TrampolineEntryX16 109 | TrampolineEntryX16 110 | .endmacro 111 | 112 | .private_extern __a1a2_firstSelectorTramp 113 | __a1a2_firstSelectorTramp: 114 | // 2048-3 trampolines to fill 16K page 115 | TrampolineEntryX256 116 | TrampolineEntryX256 117 | TrampolineEntryX256 118 | TrampolineEntryX256 119 | 120 | TrampolineEntryX256 121 | TrampolineEntryX256 122 | TrampolineEntryX256 123 | 124 | TrampolineEntryX16 125 | TrampolineEntryX16 126 | TrampolineEntryX16 127 | TrampolineEntryX16 128 | 129 | TrampolineEntryX16 130 | TrampolineEntryX16 131 | TrampolineEntryX16 132 | TrampolineEntryX16 133 | 134 | TrampolineEntryX16 135 | TrampolineEntryX16 136 | TrampolineEntryX16 137 | TrampolineEntryX16 138 | 139 | TrampolineEntryX16 140 | TrampolineEntryX16 141 | TrampolineEntryX16 142 | 143 | TrampolineEntry 144 | TrampolineEntry 145 | TrampolineEntry 146 | TrampolineEntry 147 | 148 | TrampolineEntry 149 | TrampolineEntry 150 | TrampolineEntry 151 | TrampolineEntry 152 | 153 | TrampolineEntry 154 | TrampolineEntry 155 | TrampolineEntry 156 | TrampolineEntry 157 | 158 | TrampolineEntry 159 | // TrampolineEntry 160 | // TrampolineEntry 161 | // TrampolineEntry 162 | 163 | .private_extern __a1a2_selectorTrampEnd 164 | __a1a2_selectorTrampEnd: 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /bin/md-update: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #set -e表示一旦脚本中有命令的返回值为非0,则脚本立即退出,后续命令不再执行; 4 | #set -o pipefail表示在管道连接的命令序列中,只要有任何一个命令返回非0值,则整个管道返回非0值,即使最后一个命令返回0. 5 | export setCmd="set -eo pipefail" 6 | $setCmd 7 | 8 | #导出环境变量 9 | export PATH=/opt/MonkeyDev/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH 10 | 11 | #脚本名称和版本 12 | export scriptName="${0##*/}" 13 | export scriptVer="2.0" 14 | 15 | #本地存储文件的目录 16 | export MonkeyDevPath="/opt/MonkeyDev" 17 | 18 | #获取用户名、用户组、用户目录、和profile文件 19 | export userName="${SUDO_USER-$USER}" 20 | export userGroup=`id -g $userName` 21 | export userHome=`eval echo ~$userName` 22 | 23 | #获取临时文件名 24 | export tempDirsFile="`mktemp -d -t $scriptName`/tempdirs" 25 | touch "$tempDirsFile" 26 | 27 | #把LANG变量从当前环境中删除 28 | unset LANG 29 | 30 | #出错退出 31 | function cleanup() 32 | { 33 | local exitCode=$? 34 | set +e 35 | trap - $signals 36 | removeTempData 37 | exit $exitCode 38 | } 39 | 40 | function panic() 41 | { 42 | local exitCode=$1 43 | set +e 44 | shift 45 | [[ "$@" == "" ]] || echo "$@" >&2 46 | exit $exitCode 47 | } 48 | 49 | export signals="0 1 2 3 15" 50 | #当shell接收到signals指定的信号时,执行cleanup命令 51 | trap cleanup $signals 52 | 53 | function removeTempData() 54 | { 55 | local tempDirs 56 | if [[ -f "$tempDirsFile" ]]; then 57 | tempDirs=(`cat "$tempDirsFile"`) 58 | for td in "${tempDirs[@]}"; do 59 | rm -rf "$td" || true 60 | done 61 | rm -rf "`dirname $tempDirsFile`" || true 62 | fi 63 | } 64 | function getTempDir() 65 | { 66 | $setCmd 67 | local tempDir 68 | tempDir=`mktemp -d -t $scriptName` || \ 69 | panic $? "Failed to create temporary directory" 70 | echo "$tempDir" >> "$tempDirsFile" || \ 71 | panic $? "Failed to echo into $tempDirsFile" 72 | echo "$tempDir" 73 | } 74 | 75 | #下载文件 76 | function downloadFile() # args: sourceUrl, targetPath 77 | { 78 | local sourceUrl="$1" 79 | local targetPath="$2" 80 | local curlPath 81 | 82 | mkdir -p "${targetPath%/*}" || \ 83 | panic $? "Failed to make directory: ${targetPath%/*}" 84 | 85 | curlPath=`which curl` || \ 86 | panic $? "Failed to get curl path" 87 | 88 | "$curlPath" --output "$targetPath" "$sourceUrl" || \ 89 | panic $? "Failed to download $sourceUrl to $targetPath" 90 | } 91 | 92 | #解压文件 93 | function extractTar() # args: tarPath, outputPath 94 | { 95 | local tarPath="$1" 96 | local outputPath="$2" 97 | 98 | tar -C "$outputPath" -zxf "$tarPath" || \ 99 | panic $? "Failed to extract $tarPath to $outputPath" 100 | } 101 | 102 | #下载github文件 103 | function downloadGithubTarball() # args: url, outputDir, title 104 | { 105 | $setcmd 106 | 107 | local url="$1" 108 | local outputDir="$2" 109 | local title="$3" 110 | local tempDirForTar 111 | local tempDirForFiles 112 | local untardDir 113 | local tarFile="file.tar.gz" 114 | 115 | echo "Downloading $title from Github..." 116 | 117 | tempDirForTar=`getTempDir` 118 | tempDirForFiles=`getTempDir` 119 | 120 | downloadFile "$url" "$tempDirForTar/$tarFile" 121 | 122 | extractTar "$tempDirForTar/$tarFile" "$tempDirForFiles" 123 | 124 | untardDir=`find "$tempDirForFiles/"* -type d -depth 0` || \ 125 | panic $? "Failed to get untar'ed directory name of $tempDirForTar/$tarFile" 126 | 127 | rm -rf "$outputDir" || \ 128 | panic $? "Failed to remove directory: $outputDir" 129 | 130 | mkdir -p "$outputDir" || \ 131 | panic $? "Failed to make directory: $outputDir" 132 | 133 | cp -fR "$untardDir/"* "$outputDir/" 134 | } 135 | 136 | branch="master" 137 | 138 | if [[ "$1" ]]; then 139 | branch="$1" 140 | fi 141 | 142 | #更新一些基础文件和模板文件 143 | downloadGithubTarball "https://codeload.github.com/AloneMonkey/MonkeyDev/tar.gz/$branch" "$MonkeyDevPath" "MonkeyDev base" 144 | downloadGithubTarball "https://codeload.github.com/AloneMonkey/MonkeyDev-Xcode-Templates/tar.gz/$branch" "$MonkeyDevPath/templates" "Xcode templates" 145 | 146 | #更新frida-ios-dump 147 | echo "Downloading frida-ios-dump from Github..." 148 | downloadFile "https://raw.githubusercontent.com/AloneMonkey/frida-ios-dump/3.x/dump.py" "$MonkeyDevPath/bin/dump.py" 149 | downloadFile "https://raw.githubusercontent.com/AloneMonkey/frida-ios-dump/3.x/dump.js" "$MonkeyDevPath/bin/dump.js" 150 | 151 | chmod +x "$MonkeyDevPath/bin/dump.py" 152 | 153 | exit 0 154 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Trace/a2a3-selectortramps-arm.s: -------------------------------------------------------------------------------- 1 | /* 2 | * a2a3-selectortramps-arm.s 3 | * OCMethodTrace 4 | * 5 | * https://github.com/omxcodec/OCMethodTrace.git 6 | * 7 | * Copyright (C) 2018 Michael Chen 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #if __arm__ 23 | 24 | #include 25 | #include 26 | 27 | .syntax unified 28 | 29 | .text 30 | 31 | .private_extern __a2a3_selectorTrampHead 32 | .private_extern __a2a3_firstSelectorTramp 33 | .private_extern __a2a3_selectorTrampEnd 34 | 35 | // Trampoline machinery assumes the trampolines are Thumb function pointers 36 | #if !__thumb2__ 37 | # error sorry 38 | #endif 39 | 40 | .thumb 41 | .thumb_func __a2a3_selectorTrampHead 42 | .thumb_func __a2a3_firstSelectorTramp 43 | .thumb_func __a2a3_selectorTrampEnd 44 | 45 | .align PAGE_MAX_SHIFT 46 | __a2a3_selectorTrampHead: 47 | // Trampoline's data is one page before the trampoline text. 48 | // Also correct PC bias of 4 bytes. 49 | // 1. selector 50 | sub r12, #PAGE_MAX_SIZE 51 | ldr r2, [r12, #-4] // _cmd = selector 52 | // 2. msgSend. Can't "ldr r12, msgSend", error: out of range pc-relative fixup value 53 | mov r12, pc 54 | sub r12, #PAGE_MAX_SIZE 55 | ldr pc, [r12, #-12] 56 | // not reached 57 | nop 58 | 59 | // Align trampolines to 8 bytes 60 | .align 3 61 | 62 | .macro TrampolineEntry 63 | mov r12, pc 64 | b __a2a3_selectorTrampHead 65 | .align 3 66 | .endmacro 67 | 68 | .macro TrampolineEntryX16 69 | TrampolineEntry 70 | TrampolineEntry 71 | TrampolineEntry 72 | TrampolineEntry 73 | 74 | TrampolineEntry 75 | TrampolineEntry 76 | TrampolineEntry 77 | TrampolineEntry 78 | 79 | TrampolineEntry 80 | TrampolineEntry 81 | TrampolineEntry 82 | TrampolineEntry 83 | 84 | TrampolineEntry 85 | TrampolineEntry 86 | TrampolineEntry 87 | TrampolineEntry 88 | .endmacro 89 | 90 | .macro TrampolineEntryX256 91 | TrampolineEntryX16 92 | TrampolineEntryX16 93 | TrampolineEntryX16 94 | TrampolineEntryX16 95 | 96 | TrampolineEntryX16 97 | TrampolineEntryX16 98 | TrampolineEntryX16 99 | TrampolineEntryX16 100 | 101 | TrampolineEntryX16 102 | TrampolineEntryX16 103 | TrampolineEntryX16 104 | TrampolineEntryX16 105 | 106 | TrampolineEntryX16 107 | TrampolineEntryX16 108 | TrampolineEntryX16 109 | TrampolineEntryX16 110 | .endmacro 111 | 112 | .private_extern __a2a3_firstSelectorTramp 113 | __a2a3_firstSelectorTramp: 114 | // 2048-2 trampolines to fill 16K page 115 | TrampolineEntryX256 116 | TrampolineEntryX256 117 | TrampolineEntryX256 118 | TrampolineEntryX256 119 | 120 | TrampolineEntryX256 121 | TrampolineEntryX256 122 | TrampolineEntryX256 123 | 124 | TrampolineEntryX16 125 | TrampolineEntryX16 126 | TrampolineEntryX16 127 | TrampolineEntryX16 128 | 129 | TrampolineEntryX16 130 | TrampolineEntryX16 131 | TrampolineEntryX16 132 | TrampolineEntryX16 133 | 134 | TrampolineEntryX16 135 | TrampolineEntryX16 136 | TrampolineEntryX16 137 | TrampolineEntryX16 138 | 139 | TrampolineEntryX16 140 | TrampolineEntryX16 141 | TrampolineEntryX16 142 | 143 | TrampolineEntry 144 | TrampolineEntry 145 | TrampolineEntry 146 | TrampolineEntry 147 | 148 | TrampolineEntry 149 | TrampolineEntry 150 | TrampolineEntry 151 | TrampolineEntry 152 | 153 | TrampolineEntry 154 | TrampolineEntry 155 | TrampolineEntry 156 | TrampolineEntry 157 | 158 | TrampolineEntry 159 | // TrampolineEntry 160 | // TrampolineEntry 161 | // TrampolineEntry 162 | 163 | .private_extern __a2a3_selectorTrampEnd 164 | __a2a3_selectorTrampEnd: 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /Templates/Logos Tweak.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.logosTweak 9 | Concrete 10 | 11 | Description 12 | This template builds a Logos-based Substrate Tweak. 13 | Ancestors 14 | 15 | com.monkey.monkeydev.base 16 | 17 | Targets 18 | 19 | 20 | ProductType 21 | com.apple.product-type.library.dynamic 22 | SharedSettings 23 | 24 | CLANG_ENABLE_OBJC_ARC 25 | YES 26 | INSTALL_PATH 27 | /Library/MobileSubstrate/DynamicLibraries 28 | DYLIB_CURRENT_VERSION 29 | 1 30 | DYLIB_COMPATIBILITY_VERSION 31 | 1 32 | GCC_PREFIX_HEADER 33 | ___PACKAGENAME___/___PACKAGENAME___-Prefix.pch 34 | GCC_PRECOMPILE_PREFIX_HEADER 35 | YES 36 | 37 | BuildPhases 38 | 39 | 40 | ShellScript 41 | /opt/MonkeyDev/bin/md --xcbp-logos 42 | ShellPath 43 | /bin/sh 44 | RunOnlyForDeploymentPostprocessing 45 | 46 | Class 47 | ShellScript 48 | 49 | 50 | Class 51 | Sources 52 | 53 | 54 | Class 55 | Frameworks 56 | 57 | 58 | Class 59 | Headers 60 | 61 | 62 | ShellScript 63 | /opt/MonkeyDev/bin/md --xcbp 64 | ShellPath 65 | /bin/sh 66 | RunOnlyForDeploymentPostprocessing 67 | 68 | Class 69 | ShellScript 70 | 71 | 72 | Frameworks 73 | 74 | UIKit 75 | Foundation 76 | CydiaSubstrate 77 | 78 | 79 | 80 | Nodes 81 | 82 | ___PACKAGENAME___-Prefix.pch:objC:importFoundation 83 | ___PACKAGENAME___-Prefix.pch:objC:importTheosPrefix 84 | ___PACKAGENAMEASIDENTIFIER___.xm 85 | ___PACKAGENAMEASIDENTIFIER___.mm 86 | Package/DEBIAN/control:debianControl:section 87 | Package/DEBIAN/control:debianControl:depends 88 | Package/Library/MobileSubstrate/DynamicLibraries/___PACKAGENAMEASIDENTIFIER___.plist 89 | 90 | Definitions 91 | 92 | ___PACKAGENAMEASIDENTIFIER___.xm 93 | 94 | Path 95 | ___PACKAGENAMEASIDENTIFIER___.xm 96 | 97 | ___PACKAGENAMEASIDENTIFIER___.mm 98 | 99 | Path 100 | ___PACKAGENAMEASIDENTIFIER___.mm 101 | 102 | Package/Library/MobileSubstrate/DynamicLibraries/___PACKAGENAMEASIDENTIFIER___.plist 103 | 104 | Group 105 | 106 | Package 107 | Library 108 | MobileSubstrate 109 | DynamicLibraries 110 | 111 | Beginning 112 | <?xml version="1.0" encoding="UTF-8"?> 113 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 114 | <plist version="1.0"> 115 | <dict> 116 | <key>Filter</key> 117 | <dict> 118 | <key>Bundles</key> 119 | <array> 120 | <string>com.apple.springboard</string> 121 | </array> 122 | </dict> 123 | </dict> 124 | </plist> 125 | 126 | *:debianControl:section 127 | Section: System 128 | *:debianControl:depends 129 | Depends: firmware (>= 5.0), mobilesubstrate 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /Templates/MonkeyApp.xctemplate/Config/MDConfig.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MethodTrace 6 | 7 | LogLevel 8 | 0 9 | LogWhen 10 | 0 11 | LogRegexString 12 | 13 | TraceFlag 14 | 2 15 | TraceObject 16 | 0 17 | ClassRegexString 18 | 19 | CORE_CLASS_LIST 20 | 21 | MDConfigManager 22 | 23 | MDMethodTrace 24 | 25 | MDTraceClassInfo 26 | 27 | FastCoder 28 | 29 | NSManagedObject 30 | 31 | NSObject 32 | 33 | NSException 34 | 35 | NSTypesetter 36 | 37 | NSString 38 | 39 | NSCache 40 | 41 | NSPlaceholderString 42 | 43 | __NSCFString 44 | 45 | NSURL 46 | 47 | TraceMode 48 | 0 49 | MethodBlackList 50 | 51 | isKindOfClass: 52 | 53 | 54 | NSFont 55 | 56 | OS_object 57 | 58 | OS_xpc_object 59 | 60 | OS_dispatch_object 61 | 62 | OS_dispatch_queue 63 | 64 | NSSet 65 | 66 | NSOrderedSet 67 | 68 | __NSPlaceholderSet 69 | 70 | __NSPlaceholderOrderedSet 71 | 72 | NSMutableOrderedSet 73 | 74 | NSDictionary 75 | 76 | NSMutableDictionary 77 | 78 | __NSCFDictionary 79 | 80 | __NSDictionaryM 81 | 82 | __NSPlaceholderDictionary 83 | 84 | NSArray 85 | 86 | NSMutableArray 87 | 88 | __NSCFArray 89 | 90 | __NSArrayM 91 | 92 | __NSArrayI 93 | 94 | __NSPlaceholderArray 95 | 96 | NSDate 97 | 98 | __NSDate 99 | 100 | __NSPlaceholderDate 101 | 102 | NSNumber 103 | 104 | NSPlaceholderNumber 105 | 106 | NSPredicate 107 | 108 | NSRecursiveLock 109 | 110 | NSConcreteMapTable 111 | 112 | _UIPointVector 113 | 114 | NSConcreteHashTable 115 | 116 | FBSWorkspace 117 | 118 | FBSSerialQueue 119 | 120 | BSDescriptionBuilder 121 | 122 | FBSSceneImpl 123 | 124 | BSSettings 125 | 126 | FBSWorkspaceClient 127 | 128 | AVAudioSession 129 | 130 | 131 | USER_CLASS_LIST 132 | 133 | BaseMsgContentViewController 134 | 135 | TraceMode 136 | 1 137 | TraceFlag 138 | 0 139 | MethodWhiteList 140 | 141 | MethodBlackList 142 | 143 | 144 | CMessageMgr 145 | 146 | TraceMode 147 | 2 148 | TraceFlag 149 | 0 150 | MethodWhiteList 151 | 152 | AsyncOnAddMsg:MsgWrap: 153 | onRevokeMsg: 154 | 155 | MethodBlackList 156 | 157 | 158 | 159 | 160 | Cycript 161 | 162 | nslog 163 | 164 | LoadAtLaunch 165 | 166 | priority 167 | 0 168 | content 169 | NSLog = function() { var types = 'v', args = [], count = arguments.length; for (var i = 0; i != count; ++i) { types += '@'; args.push(arguments[i]); } new Functor(dlsym(RTLD_DEFAULT, "NSLog"), types).apply(null, args); } 170 | 171 | ms 172 | 173 | LoadAtLaunch 174 | 175 | priority 176 | 1 177 | url 178 | https://raw.githubusercontent.com/AloneMonkey/MDCycript/master/MS.cy 179 | 180 | hook 181 | 182 | LoadAtLaunch 183 | 184 | priority 185 | 2 186 | content 187 | try{ 188 | var oldm = {}; 189 | HookMessage(CustomViewController, @selector(showChangeLog:), function(log) { 190 | NSLog("hooked by cycript!!!"); 191 | return oldm->call(this,log); 192 | }, oldm); 193 | }catch(err){ 194 | NSLog(err.toString()) 195 | } 196 | 197 | md 198 | 199 | LoadAtLaunch 200 | 201 | priority 202 | 3 203 | url 204 | https://raw.githubusercontent.com/AloneMonkey/MDCycript/master/md.cy 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /Templates/MonkeyApp.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.singleViewApplication 9 | Ancestors 10 | 11 | com.apple.dt.unit.bundleBase 12 | com.apple.dt.unit.iosBase 13 | 14 | Concrete 15 | 16 | Description 17 | This template provides a starting point for an application that uses a single view. It provides a view controller to manage the view, and a storyboard or nib file that contains the view. 18 | SortOrder 19 | 1 20 | Nodes 21 | 22 | icon.png 23 | Scripts/quick-resign.sh 24 | Config/MDConfig.plist 25 | Info.plist:PackageType 26 | Info.plist:IconFiles 27 | TargetApp/put ipa or app here 28 | 29 | Definitions 30 | 31 | icon.png 32 | 33 | TargetIndices 34 | 35 | Path 36 | icon.png 37 | 38 | Scripts/quick-resign.sh 39 | 40 | TargetIndices 41 | 42 | Group 43 | 44 | Scripts 45 | 46 | Path 47 | Scripts/quick-resign.sh 48 | 49 | Config/MDConfig.plist 50 | 51 | Group 52 | 53 | Config 54 | 55 | Path 56 | Config/MDConfig.plist 57 | 58 | main.m:main 59 | 60 | Beginning 61 | int main(int argc, const char * argv[]) { 62 | End 63 | } 64 | Indent 65 | 1 66 | 67 | main.m 68 | 69 | SortOrder 70 | 999 71 | 72 | Info.plist:PackageType 73 | <key>CFBundlePackageType</key> 74 | <string>APPL</string> 75 | 76 | Info.plist:IconFiles 77 | <key>CFBundleIconFiles</key> 78 | <array> 79 | <string>___PACKAGENAME___/icon.png</string> 80 | </array> 81 | TargetApp/put ipa or app here 82 | 83 | TargetIndices 84 | 85 | Group 86 | 87 | TargetApp 88 | 89 | 90 | 91 | Targets 92 | 93 | 94 | ProductType 95 | com.apple.product-type.application 96 | SharedSettings 97 | 98 | MONKEYDEV_DEFAULT_BUNDLEID 99 | NO 100 | MONKEYDEV_ADD_SUBSTRATE 101 | YES 102 | MONKEYDEV_TARGET_APP 103 | ___VARIABLE_TargetAppInfo___ 104 | MONKEYDEV_INSERT_DYLIB 105 | YES 106 | PODS_CONFIGURATION_BUILD_DIR 107 | $BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 108 | MONKEYDEV_CLASS_DUMP 109 | NO 110 | MONKEYDEV_RESTORE_SYMBOL 111 | NO 112 | PODS_ROOT 113 | ${SRCROOT}/Pods 114 | ENABLE_BITCODE 115 | NO 116 | 117 | BuildPhases 118 | 119 | 120 | Class 121 | Sources 122 | 123 | 124 | Class 125 | Frameworks 126 | 127 | 128 | RunOnlyForDeploymentPostprocessing 129 | 130 | Class 131 | ShellScript 132 | ShellPath 133 | /bin/sh 134 | ShellScript 135 | /opt/MonkeyDev/Tools/pack.sh 136 | 137 | 138 | Class 139 | Resources 140 | 141 | 142 | RunOnlyForDeploymentPostprocessing 143 | 144 | DstSubfolderSpec 145 | 10 146 | DstPath 147 | 148 | Class 149 | CopyFiles 150 | 151 | 152 | RunOnlyForDeploymentPostprocessing 153 | 154 | Class 155 | ShellScript 156 | ShellPath 157 | /bin/sh 158 | ShellScript 159 | /opt/MonkeyDev/Tools/pack.sh codesign 160 | 161 | 162 | TargetIdentifier 163 | com.monkey.monkeydev.TargetApp 164 | 165 | 166 | Options 167 | 168 | 169 | Identifier 170 | TargetAppInfo 171 | Required 172 | 173 | Name 174 | Target App 175 | NotPersisted 176 | 177 | Description 178 | The displayname or bundle id of the application you debug. 179 | Default 180 | Optional 181 | Type 182 | text 183 | 184 | 185 | Project 186 | 187 | SharedSettings 188 | 189 | IPHONEOS_DEPLOYMENT_TARGET 190 | 8.0 191 | 192 | 193 | Components 194 | 195 | 196 | ProductBuildPhaseInjections 197 | 198 | 199 | TargetIdentifier 200 | com.monkey.monkeydev.TargetApp 201 | 202 | 203 | Identifier 204 | com.monkey.monkeydev.cocoaTouchLibrary 205 | Name 206 | ___PACKAGENAME___Dylib 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /Templates/Base.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Identifier 6 | com.monkey.monkeydev.base 7 | Kind 8 | Xcode.Xcode3.ProjectTemplateUnitKind 9 | Ancestors 10 | 11 | com.apple.dt.unit.iosBase 12 | com.monkey.monkeydev.debianPackage 13 | com.monkey.monkeydev.preferenceLoader 14 | 15 | Targets 16 | 17 | 18 | Name 19 | ___PACKAGENAME___ 20 | SharedSettings 21 | 22 | CODE_SIGNING_ALLOWED 23 | NO 24 | MonkeyDevClearUiCacheOnInstall 25 | NO 26 | MonkeyDevkillProcessOnInstall 27 | 28 | CODE_SIGN_IDENTITY 29 | 30 | PRODUCT_NAME 31 | $(TARGET_NAME) 32 | MonkeyDevRootless 33 | YES 34 | MonkeyDevDeviceIP 35 | localhost 36 | MonkeyDevDevicePort 37 | 2222 38 | MonkeyDevDevicePassword 39 | alpine 40 | MonkeyDevInstallOnProfiling 41 | YES 42 | MonkeyDevCopyOnBuild 43 | NO 44 | MonkeyDevInstallOnAnyBuild 45 | YES 46 | 47 | 48 | 49 | Platforms 50 | 51 | com.apple.platform.iphoneos 52 | 53 | Project 54 | 55 | SharedSettings 56 | 57 | MonkeyDevTheosPath 58 | /opt/theos 59 | TARGETED_DEVICE_FAMILY 60 | 1,2 61 | GCC_WARN_ABOUT_MISSING_PROTOTYPES 62 | YES 63 | GCC_WARN_UNUSED_VARIABLE 64 | YES 65 | GCC_WARN_ABOUT_RETURN_TYPE 66 | YES 67 | GCC_C_LANGUAGE_STANDARD 68 | gnu99 69 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES 70 | *.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj 71 | OTHER_CFLAGS 72 | -DTHEOS_INSTANCE_NAME="\"___PACKAGENAME___\"" 73 | HEADER_SEARCH_PATHS 74 | $(MonkeyDevTheosPath)/vendor/include/** 75 | LIBRARY_SEARCH_PATHS 76 | $(MonkeyDevTheosPath)/vendor/lib/** 77 | MonkeyDevPath 78 | /opt/MonkeyDev 79 | IPHONEOS_DEPLOYMENT_TARGET 80 | 8.0 81 | FRAMEWORK_SEARCH_PATHS 82 | $(MonkeyDevPath)/frameworks/** $(MonkeyDevTheosPath)/vendor/lib 83 | 84 | SDK 85 | iphoneos 86 | Configurations 87 | 88 | Debug 89 | 90 | ONLY_ACTIVE_ARCH 91 | YES 92 | VALIDATE_PRODUCT 93 | NO 94 | GCC_OPTIMIZATION_LEVEL 95 | 0 96 | GCC_PREPROCESSOR_DEFINITIONS 97 | DEBUG=1 $(inherited) 98 | GCC_SYMBOLS_PRIVATE_EXTERN 99 | NO 100 | COPY_PHASE_STRIP 101 | NO 102 | GCC_DYNAMIC_NO_PIC 103 | NO 104 | 105 | Release 106 | 107 | COPY_PHASE_STRIP 108 | YES 109 | VALIDATE_PRODUCT 110 | YES 111 | 112 | 113 | 114 | Options 115 | 116 | 117 | Identifier 118 | productName 119 | Required 120 | 121 | Name 122 | Product Name 123 | NotPersisted 124 | 125 | Description 126 | Your new product's name. 127 | EmptyReplacement 128 | ProductName 129 | Type 130 | text 131 | 132 | 133 | Identifier 134 | bundleIdentifierPrefix 135 | Required 136 | 137 | Name 138 | Company Identifier 139 | Description 140 | Your company's bundle identifier prefix. 141 | EmptyReplacement 142 | com.yourcompany 143 | Type 144 | text 145 | 146 | 147 | Identifier 148 | bundleIdentifier 149 | Name 150 | Bundle Identifier 151 | NotPersisted 152 | 153 | Description 154 | Your new product's bundle identifier. 155 | Default 156 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 157 | Type 158 | static 159 | 160 | 161 | Definitions 162 | 163 | *:*:importTheosPrefix 164 | #import "/opt/theos/Prefix.pch" //path/to/theos/Prefix.pch 165 | *:comments 166 | // 167 | // ___FILENAME___ 168 | // ___PACKAGENAME___ 169 | // 170 | // Created by ___FULLUSERNAME___ on ___DATE___. 171 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved. 172 | // 173 | 174 | *:import:* 175 | #import "___*___" 176 | 177 | *:*:importFoundation 178 | #import <Foundation/Foundation.h> 179 | 180 | ___PACKAGENAME___-Prefix.pch 181 | 182 | Beginning 183 | // 184 | // Prefix header for all source files of the '___PACKAGENAME___' target in the '___PACKAGENAME___' project 185 | // 186 | 187 | Group 188 | Supporting Files 189 | TargetIndices 190 | 191 | 192 | ___PACKAGENAME___-Prefix.pch:objC 193 | 194 | Beginning 195 | #ifdef __OBJC__ 196 | End 197 | #endif 198 | Indent 199 | 1 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /Templates/PreferenceLoader.xctemplate/___PACKAGENAMEASIDENTIFIER___.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | cell 8 | PSLinkCell 9 | icon 10 | ___PACKAGENAMEASIDENTIFIER___Icon.png 11 | label 12 | ___PACKAGENAMEASIDENTIFIER___ 13 | 14 | items 15 | 16 | 17 | cell 18 | PSGroupCell 19 | isStaticText 20 | 21 | label 22 | Text and Secure Cells 23 | 24 | 25 | cell 26 | PSEditTextCell 27 | default 28 | 29 | defaults 30 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 31 | key 32 | EditTextCell1 33 | label 34 | Text 35 | placeholder 36 | Any Text Here 37 | PostNotification 38 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 39 | 40 | 41 | cell 42 | PSSecureEditTextCell 43 | default 44 | 45 | defaults 46 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 47 | key 48 | SecureEditTextCell2 49 | label 50 | Secure 51 | PostNotification 52 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 53 | 54 | 55 | cell 56 | PSGroupCell 57 | footerText 58 | Place text here to provide additional information about the cells above. 59 | 60 | 61 | cell 62 | PSGroupCell 63 | isStaticText 64 | 65 | label 66 | Numeric Cells 67 | 68 | 69 | cell 70 | PSEditTextCell 71 | default 72 | 73 | defaults 74 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 75 | key 76 | EditTextCell3 77 | keyboard 78 | phone 79 | label 80 | Phone 81 | placeholder 82 | Phone Number 83 | PostNotification 84 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 85 | 86 | 87 | cell 88 | PSEditTextCell 89 | default 90 | 91 | defaults 92 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 93 | key 94 | EditTextCel4 95 | keyboard 96 | numbers 97 | label 98 | Numeric 99 | placeholder 100 | Numbers 101 | PostNotification 102 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 103 | 104 | 105 | cell 106 | PSGroupCell 107 | footerText 108 | Place text here to provide additional information about the cells above. 109 | 110 | 111 | cell 112 | PSGroupCell 113 | isStaticText 114 | 115 | label 116 | Switch and Slider Cells 117 | 118 | 119 | cell 120 | PSSwitchCell 121 | default 122 | 123 | defaults 124 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 125 | key 126 | SwitchCell5 127 | label 128 | Switch 129 | PostNotification 130 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 131 | 132 | 133 | cell 134 | PSSliderCell 135 | default 136 | 50 137 | defaults 138 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 139 | key 140 | SliderCell6 141 | min 142 | 1 143 | max 144 | 100 145 | showValue 146 | 147 | PostNotification 148 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 149 | 150 | 151 | cell 152 | PSGroupCell 153 | footerText 154 | Place text here to provide additional information about the cells above. 155 | 156 | 157 | cell 158 | PSGroupCell 159 | isStaticText 160 | 161 | label 162 | List Cell 163 | 164 | 165 | cell 166 | PSLinkListCell 167 | defaults 168 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___ 169 | key 170 | LinkListCell7 171 | label 172 | List 173 | detail 174 | PSListItemsController 175 | validTitles 176 | 177 | Item 1 178 | Item 2 179 | Item 3 180 | 181 | validValues 182 | 183 | 1 184 | 2 185 | 3 186 | 187 | default 188 | 1 189 | PostNotification 190 | ___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.___VARIABLE_productName:RFC1034Identifier___-preferencesChanged 191 | 192 | 193 | 194 | cell 195 | PSGroupCell 196 | isStaticText 197 | 198 | 199 | 200 | cell 201 | PSGroupCell 202 | footerText 203 | © ___YEAR___ ___ORGANIZATIONNAME___ 204 | 205 | 206 | title 207 | ___PACKAGENAME___ 208 | 209 | 210 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.osxLibrary 9 | Ancestors 10 | 11 | com.apple.dt.unit.base 12 | com.apple.dt.unit.osxBase 13 | 14 | Concrete 15 | 16 | Description 17 | This template builds a library that links against the Cocoa framework. 18 | SortOrder 19 | 10 20 | Targets 21 | 22 | 23 | TargetIdentifier 24 | com.apple.dt.cocoaLibraryOrFrameworkTarget 25 | SharedSettings 26 | 27 | INSTALL_PATH 28 | @executable_path/lib___PACKAGENAME___.dylib 29 | OTHER_LDFLAGS 30 | $(inherited) -lsubstitute 31 | EXECUTABLE_PREFIX 32 | lib 33 | 34 | BuildPhases 35 | 36 | 37 | Class 38 | Sources 39 | 40 | 41 | Class 42 | Frameworks 43 | 44 | 45 | Class 46 | Headers 47 | 48 | 49 | ShellScript 50 | /opt/MonkeyDev/Tools/mpack.sh 51 | ShellPath 52 | /bin/sh 53 | RunOnlyForDeploymentPostprocessing 54 | 55 | Class 56 | ShellScript 57 | 58 | 59 | 60 | 61 | Options 62 | 63 | 64 | Identifier 65 | libraryFramework 66 | Name 67 | Framework: 68 | Description 69 | What system framework the library will be based on 70 | Type 71 | popup 72 | Values 73 | 74 | Cocoa 75 | STL (C++ Library) 76 | None (Plain C/C++ Library) 77 | 78 | Default 79 | Cocoa 80 | Units 81 | 82 | Cocoa 83 | 84 | 85 | Nodes 86 | 87 | ___PACKAGENAMEASIDENTIFIER___.h 88 | ___PACKAGENAMEASIDENTIFIER___.m 89 | 90 | Definitions 91 | 92 | ___PACKAGENAMEASIDENTIFIER___.h 93 | 94 | Path 95 | Cocoa___PACKAGENAMEASIDENTIFIER___.h 96 | 97 | ___PACKAGENAMEASIDENTIFIER___.m 98 | 99 | Path 100 | Cocoa___PACKAGENAMEASIDENTIFIER___.m 101 | 102 | 103 | 104 | 105 | STL (C++ Library) 106 | 107 | 108 | Targets 109 | 110 | 111 | SharedSettings 112 | 113 | GCC_ENABLE_CPP_EXCEPTIONS 114 | YES 115 | GCC_ENABLE_CPP_RTTI 116 | YES 117 | 118 | 119 | 120 | Nodes 121 | 122 | ___PACKAGENAMEASIDENTIFIER___.hpp 123 | ___PACKAGENAMEASIDENTIFIER___Priv.hpp 124 | ___PACKAGENAMEASIDENTIFIER___.cpp 125 | 126 | Definitions 127 | 128 | ___PACKAGENAMEASIDENTIFIER___.hpp 129 | 130 | Path 131 | STL___PACKAGENAMEASIDENTIFIER___.hpp 132 | 133 | ___PACKAGENAMEASIDENTIFIER___.cpp 134 | 135 | Path 136 | STL___PACKAGENAMEASIDENTIFIER___.cpp 137 | 138 | ___PACKAGENAMEASIDENTIFIER___Priv.hpp 139 | 140 | Path 141 | STL___PACKAGENAMEASIDENTIFIER___Priv.hpp 142 | 143 | 144 | 145 | 146 | RequiredOptions 147 | 148 | libraryType 149 | Dynamic 150 | 151 | Targets 152 | 153 | 154 | SharedSettings 155 | 156 | GCC_SYMBOLS_PRIVATE_EXTERN 157 | YES 158 | 159 | 160 | 161 | 162 | 163 | None (Plain C/C++ Library) 164 | 165 | 166 | 167 | 168 | 169 | 170 | Identifier 171 | libraryType 172 | Name 173 | Type: 174 | Description 175 | Which type of library to create 176 | Type 177 | popup 178 | Default 179 | Dynamic 180 | Units 181 | 182 | Dynamic 183 | 184 | 185 | Targets 186 | 187 | 188 | ProductType 189 | com.apple.product-type.library.dynamic 190 | SharedSettings 191 | 192 | DYLIB_COMPATIBILITY_VERSION 193 | 1 194 | DYLIB_CURRENT_VERSION 195 | 1 196 | 197 | 198 | 199 | 200 | 201 | Static 202 | 203 | 204 | Targets 205 | 206 | 207 | ProductType 208 | com.apple.product-type.library.static 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | Project 217 | 218 | SharedSettings 219 | 220 | MonkeyDevPath 221 | /opt/MonkeyDev 222 | LIBRARY_SEARCH_PATHS 223 | $(inherited) $(MonkeyDevPath)/MFrameworks 224 | HEADER_SEARCH_PATHS 225 | $(inherited) $(MonkeyDevPath)/MFrameworks 226 | 227 | 228 | Definitions 229 | 230 | fishhook/fishhook.c 231 | 232 | Path 233 | fishhook/fishhook.c 234 | Group 235 | 236 | fishhook 237 | 238 | 239 | fishhook/fishhook.h 240 | 241 | Path 242 | fishhook/fishhook.h 243 | Group 244 | 245 | fishhook 246 | 247 | 248 | AntiAntiDebug/AntiAntiDebug.m 249 | 250 | Group 251 | 252 | AntiAntiDebug 253 | 254 | Path 255 | AntiAntiDebug/AntiAntiDebug.m 256 | 257 | TargetApp/put mac app here 258 | 259 | Group 260 | 261 | TargetApp 262 | 263 | 264 | 265 | Nodes 266 | 267 | AntiAntiDebug/AntiAntiDebug.m 268 | fishhook/fishhook.c 269 | fishhook/fishhook.h 270 | TargetApp/put mac app here 271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /Tools/pack.sh: -------------------------------------------------------------------------------- 1 | MONKEYDEV_PATH="/opt/MonkeyDev" 2 | 3 | # temp path 4 | TEMP_PATH="${SRCROOT}/${TARGET_NAME}/tmp" 5 | 6 | # monkeyparser 7 | MONKEYPARSER="${MONKEYDEV_PATH}/bin/monkeyparser" 8 | 9 | # create ipa script 10 | CREATE_IPA="${MONKEYDEV_PATH}/bin/createIPA.command" 11 | 12 | # build app path 13 | BUILD_APP_PATH="${BUILT_PRODUCTS_DIR}/${TARGET_NAME}.app" 14 | 15 | # default demo app 16 | DEMOTARGET_APP_PATH="${MONKEYDEV_PATH}/Resource/TargetApp.app" 17 | 18 | # link framework path 19 | FRAMEWORKS_TO_INJECT_PATH="${MONKEYDEV_PATH}/Frameworks/" 20 | 21 | # target app placed 22 | TARGET_APP_PUT_PATH="${SRCROOT}/${TARGET_NAME}/TargetApp" 23 | 24 | # Compatiable old version 25 | MONKEYDEV_INSERT_DYLIB=${MONKEYDEV_INSERT_DYLIB:=YES} 26 | MONKEYDEV_TARGET_APP=${MONKEYDEV_TARGET_APP:=Optional} 27 | MONKEYDEV_ADD_SUBSTRATE=${MONKEYDEV_ADD_SUBSTRATE:=YES} 28 | MONKEYDEV_DEFAULT_BUNDLEID=${MONKEYDEV_DEFAULT_BUNDLEID:=NO} 29 | 30 | function isRelease() { 31 | if [[ "${CONFIGURATION}" = "Release" ]]; then 32 | true 33 | else 34 | false 35 | fi 36 | } 37 | 38 | function panic() { # args: exitCode, message... 39 | local exitCode=$1 40 | set +e 41 | 42 | shift 43 | [[ "$@" == "" ]] || \ 44 | echo "$@" >&2 45 | 46 | exit ${exitCode} 47 | } 48 | 49 | function checkApp(){ 50 | local TARGET_APP_PATH="$1" 51 | 52 | # remove Plugin an Watch 53 | rm -rf "${TARGET_APP_PATH}/PlugIns" || true 54 | rm -rf "${TARGET_APP_PATH}/Watch" || true 55 | 56 | /usr/libexec/PlistBuddy -c 'Delete UISupportedDevices' "${TARGET_APP_PATH}/Info.plist" 2>/dev/null 57 | 58 | VERIFY_RESULT=`export MONKEYDEV_CLASS_DUMP=${MONKEYDEV_CLASS_DUMP};MONKEYDEV_RESTORE_SYMBOL=${MONKEYDEV_RESTORE_SYMBOL};"$MONKEYPARSER" verify -t "${TARGET_APP_PATH}" -o "${SRCROOT}/${TARGET_NAME}"` 59 | 60 | if [[ $? -eq 16 ]]; then 61 | panic 1 "${VERIFY_RESULT}" 62 | else 63 | echo "${VERIFY_RESULT}" 64 | fi 65 | } 66 | 67 | function pack(){ 68 | TARGET_INFO_PLIST=${SRCROOT}/${TARGET_NAME}/Info.plist 69 | # environment 70 | CURRENT_EXECUTABLE=$(/usr/libexec/PlistBuddy -c "Print CFBundleExecutable" "${TARGET_INFO_PLIST}" 2>/dev/null) 71 | 72 | # create tmp dir 73 | rm -rf "${TEMP_PATH}" || true 74 | mkdir -p "${TEMP_PATH}" || true 75 | 76 | # latestbuild 77 | ln -fhs "${BUILT_PRODUCTS_DIR}" "${PROJECT_DIR}"/LatestBuild 78 | cp -rf "${CREATE_IPA}" "${PROJECT_DIR}"/LatestBuild/ 79 | 80 | # deal ipa or app 81 | TARGET_APP_PATH=$(find "${SRCROOT}/${TARGET_NAME}" -type d | grep "\.app$" | head -n 1) 82 | TARGET_IPA_PATH=$(find "${SRCROOT}/${TARGET_NAME}" -type f | grep "\.ipa$" | head -n 1) 83 | 84 | if [[ ${TARGET_APP_PATH} ]]; then 85 | cp -rf "${TARGET_APP_PATH}" "${TARGET_APP_PUT_PATH}" 86 | fi 87 | 88 | if [[ ! ${TARGET_APP_PATH} ]] && [[ ! ${TARGET_IPA_PATH} ]] && [[ ${MONKEYDEV_TARGET_APP} != "Optional" ]]; then 89 | echo "pulling decrypted ipa from jailbreak device......." 90 | PYTHONIOENCODING=utf-8 ${MONKEYDEV_PATH}/bin/dump.py ${MONKEYDEV_TARGET_APP} -o "${TARGET_APP_PUT_PATH}/TargetApp.ipa" || panic 1 "dump.py error" 91 | TARGET_IPA_PATH=$(find "${TARGET_APP_PUT_PATH}" -type f | grep "\.ipa$" | head -n 1) 92 | fi 93 | 94 | if [[ ! ${TARGET_APP_PATH} ]] && [[ ${TARGET_IPA_PATH} ]]; then 95 | unzip -oqq "${TARGET_IPA_PATH}" -d "${TEMP_PATH}" 96 | cp -rf "${TEMP_PATH}/Payload/"*.app "${TARGET_APP_PUT_PATH}" 97 | fi 98 | 99 | if [ -f "${BUILD_APP_PATH}/embedded.mobileprovision" ]; then 100 | mv "${BUILD_APP_PATH}/embedded.mobileprovision" "${BUILD_APP_PATH}"/.. 101 | fi 102 | 103 | TARGET_APP_PATH=$(find "${TARGET_APP_PUT_PATH}" -type d | grep "\.app$" | head -n 1) 104 | 105 | if [[ -f "${TARGET_APP_PUT_PATH}"/.current_put_app ]]; then 106 | if [[ $(cat ${TARGET_APP_PUT_PATH}/.current_put_app) != "${TARGET_APP_PATH}" ]]; then 107 | rm -rf "${BUILD_APP_PATH}" || true 108 | mkdir -p "${BUILD_APP_PATH}" || true 109 | rm -rf "${TARGET_APP_PUT_PATH}"/.current_put_app 110 | echo "${TARGET_APP_PATH}" >> "${TARGET_APP_PUT_PATH}"/.current_put_app 111 | fi 112 | fi 113 | 114 | COPY_APP_PATH=${TARGET_APP_PATH} 115 | 116 | if [[ "${TARGET_APP_PATH}" = "" ]]; then 117 | COPY_APP_PATH=${DEMOTARGET_APP_PATH} 118 | cp -rf "${COPY_APP_PATH}/" "${BUILD_APP_PATH}/" 119 | checkApp "${BUILD_APP_PATH}" 120 | else 121 | checkApp "${COPY_APP_PATH}" 122 | cp -rf "${COPY_APP_PATH}/" "${BUILD_APP_PATH}/" 123 | fi 124 | 125 | if [ -f "${BUILD_APP_PATH}/../embedded.mobileprovision" ]; then 126 | mv "${BUILD_APP_PATH}/../embedded.mobileprovision" "${BUILD_APP_PATH}" 127 | fi 128 | 129 | # get target info 130 | ORIGIN_BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" "${COPY_APP_PATH}/Info.plist" 2>/dev/null) 131 | TARGET_EXECUTABLE=$(/usr/libexec/PlistBuddy -c "Print CFBundleExecutable" "${COPY_APP_PATH}/Info.plist" 2>/dev/null) 132 | 133 | if [[ ${CURRENT_EXECUTABLE} != ${TARGET_EXECUTABLE} ]]; then 134 | cp -rf "${COPY_APP_PATH}/Info.plist" "${TARGET_INFO_PLIST}" 135 | fi 136 | 137 | TARGET_DISPLAY_NAME=$(/usr/libexec/PlistBuddy -c "Print CFBundleDisplayName" "${TARGET_INFO_PLIST}" 2>/dev/null) 138 | 139 | # copy default framewrok 140 | TARGET_APP_FRAMEWORKS_PATH="${BUILD_APP_PATH}/Frameworks/" 141 | 142 | if [ ! -d "${TARGET_APP_FRAMEWORKS_PATH}" ]; then 143 | mkdir -p "${TARGET_APP_FRAMEWORKS_PATH}" 144 | fi 145 | 146 | if [[ ${MONKEYDEV_INSERT_DYLIB} == "YES" ]];then 147 | cp -rf "${BUILT_PRODUCTS_DIR}/lib""${TARGET_NAME}""Dylib.dylib" "${TARGET_APP_FRAMEWORKS_PATH}" 148 | cp -rf "${FRAMEWORKS_TO_INJECT_PATH}" "${TARGET_APP_FRAMEWORKS_PATH}" 149 | if [[ ${MONKEYDEV_ADD_SUBSTRATE} != "YES" ]];then 150 | rm -rf "${TARGET_APP_FRAMEWORKS_PATH}/libsubstrate.dylib" 151 | fi 152 | if isRelease; then 153 | rm -rf "${TARGET_APP_FRAMEWORKS_PATH}"/RevealServer.framework 154 | rm -rf "${TARGET_APP_FRAMEWORKS_PATH}"/libcycript* 155 | fi 156 | fi 157 | 158 | if [[ -d "$SRCROOT/${TARGET_NAME}/Resources" ]]; then 159 | for file in "$SRCROOT/${TARGET_NAME}/Resources"/*; do 160 | extension="${file#*.}" 161 | filename="${file##*/}" 162 | if [[ "$extension" == "storyboard" ]]; then 163 | ibtool --compile "${BUILD_APP_PATH}/$filename"c "$file" 164 | else 165 | cp -rf "$file" "${BUILD_APP_PATH}/" 166 | fi 167 | done 168 | fi 169 | 170 | # Inject the Dynamic Lib 171 | APP_BINARY=`plutil -convert xml1 -o - ${BUILD_APP_PATH}/Info.plist | grep -A1 Exec | tail -n1 | cut -f2 -d\> | cut -f1 -d\<` 172 | 173 | if [[ ${MONKEYDEV_INSERT_DYLIB} == "YES" ]];then 174 | "$MONKEYPARSER" install -c load -p "@executable_path/Frameworks/lib""${TARGET_NAME}""Dylib.dylib" -t "${BUILD_APP_PATH}/${APP_BINARY}" 175 | "$MONKEYPARSER" unrestrict -t "${BUILD_APP_PATH}/${APP_BINARY}" 176 | 177 | chmod +x "${BUILD_APP_PATH}/${APP_BINARY}" 178 | fi 179 | 180 | # Update Info.plist for Target App 181 | if [[ "${TARGET_DISPLAY_NAME}" != "" ]]; then 182 | for file in `ls "${BUILD_APP_PATH}"`; 183 | do 184 | extension="${file#*.}" 185 | if [[ -d "${BUILD_APP_PATH}/$file" ]]; then 186 | if [[ "${extension}" == "lproj" ]]; then 187 | if [[ -f "${BUILD_APP_PATH}/${file}/InfoPlist.strings" ]];then 188 | /usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName ${TARGET_DISPLAY_NAME}" "${BUILD_APP_PATH}/${file}/InfoPlist.strings" 189 | fi 190 | fi 191 | fi 192 | done 193 | fi 194 | 195 | if [[ ${MONKEYDEV_DEFAULT_BUNDLEID} = NO ]];then 196 | /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER}" "${TARGET_INFO_PLIST}" 197 | else 198 | /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier ${ORIGIN_BUNDLE_ID}" "${TARGET_INFO_PLIST}" 199 | fi 200 | 201 | /usr/libexec/PlistBuddy -c "Delete :CFBundleIconFiles" "${TARGET_INFO_PLIST}" 202 | /usr/libexec/PlistBuddy -c "Add :CFBundleIconFiles array" "${TARGET_INFO_PLIST}" 203 | /usr/libexec/PlistBuddy -c "Add :CFBundleIconFiles: string ${TARGET_NAME}/icon.png" "${TARGET_INFO_PLIST}" 204 | 205 | cp -rf "${TARGET_INFO_PLIST}" "${BUILD_APP_PATH}/Info.plist" 206 | 207 | #cocoapods 208 | if [[ -f "${SRCROOT}/Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-frameworks.sh" ]]; then 209 | source "${SRCROOT}/Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-frameworks.sh" 210 | fi 211 | 212 | if [[ -f "${SRCROOT}/Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-resources.sh" ]]; then 213 | source "${SRCROOT}/Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-resources.sh" 214 | fi 215 | 216 | if [[ -f "${SRCROOT}/../Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-frameworks.sh" ]]; then 217 | source "${SRCROOT}/../Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-frameworks.sh" 218 | fi 219 | 220 | if [[ -f "${SRCROOT}/../Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-resources.sh" ]]; then 221 | source "${SRCROOT}/../Pods/Target Support Files/Pods-""${TARGET_NAME}""Dylib/Pods-""${TARGET_NAME}""Dylib-resources.sh" 222 | fi 223 | } 224 | 225 | if [[ "$1" == "codesign" ]]; then 226 | ${MONKEYPARSER} codesign -i "${EXPANDED_CODE_SIGN_IDENTITY}" -t "${BUILD_APP_PATH}" 227 | if [[ ${MONKEYDEV_INSERT_DYLIB} == "NO" ]];then 228 | rm -rf "${BUILD_APP_PATH}/Frameworks/lib${TARGET_NAME}Dylib.dylib" 229 | fi 230 | else 231 | pack 232 | fi 233 | -------------------------------------------------------------------------------- /Templates/MonkeyAppMac.xctemplate/fishhook/fishhook.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #import "fishhook.h" 25 | 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | 34 | #ifdef __LP64__ 35 | typedef struct mach_header_64 mach_header_t; 36 | typedef struct segment_command_64 segment_command_t; 37 | typedef struct section_64 section_t; 38 | typedef struct nlist_64 nlist_t; 39 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 40 | #else 41 | typedef struct mach_header mach_header_t; 42 | typedef struct segment_command segment_command_t; 43 | typedef struct section section_t; 44 | typedef struct nlist nlist_t; 45 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT 46 | #endif 47 | 48 | #ifndef SEG_DATA_CONST 49 | #define SEG_DATA_CONST "__DATA_CONST" 50 | #endif 51 | 52 | struct rebindings_entry { 53 | struct rebinding *rebindings; 54 | size_t rebindings_nel; 55 | struct rebindings_entry *next; 56 | }; 57 | 58 | static struct rebindings_entry *_rebindings_head; 59 | 60 | static int prepend_rebindings(struct rebindings_entry **rebindings_head, 61 | struct rebinding rebindings[], 62 | size_t nel) { 63 | struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry)); 64 | if (!new_entry) { 65 | return -1; 66 | } 67 | new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel); 68 | if (!new_entry->rebindings) { 69 | free(new_entry); 70 | return -1; 71 | } 72 | memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); 73 | new_entry->rebindings_nel = nel; 74 | new_entry->next = *rebindings_head; 75 | *rebindings_head = new_entry; 76 | return 0; 77 | } 78 | 79 | static void perform_rebinding_with_section(struct rebindings_entry *rebindings, 80 | section_t *section, 81 | intptr_t slide, 82 | nlist_t *symtab, 83 | char *strtab, 84 | uint32_t *indirect_symtab) { 85 | uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; 86 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); 87 | for (uint i = 0; i < section->size / sizeof(void *); i++) { 88 | uint32_t symtab_index = indirect_symbol_indices[i]; 89 | if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || 90 | symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { 91 | continue; 92 | } 93 | uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; 94 | char *symbol_name = strtab + strtab_offset; 95 | if (strnlen(symbol_name, 2) < 2) { 96 | continue; 97 | } 98 | struct rebindings_entry *cur = rebindings; 99 | while (cur) { 100 | for (uint j = 0; j < cur->rebindings_nel; j++) { 101 | if (strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { 102 | if (cur->rebindings[j].replaced != NULL && 103 | indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { 104 | *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; 105 | } 106 | indirect_symbol_bindings[i] = cur->rebindings[j].replacement; 107 | goto symbol_loop; 108 | } 109 | } 110 | cur = cur->next; 111 | } 112 | symbol_loop:; 113 | } 114 | } 115 | 116 | static void rebind_symbols_for_image(struct rebindings_entry *rebindings, 117 | const struct mach_header *header, 118 | intptr_t slide) { 119 | Dl_info info; 120 | if (dladdr(header, &info) == 0) { 121 | return; 122 | } 123 | 124 | segment_command_t *cur_seg_cmd; 125 | segment_command_t *linkedit_segment = NULL; 126 | struct symtab_command* symtab_cmd = NULL; 127 | struct dysymtab_command* dysymtab_cmd = NULL; 128 | 129 | uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); 130 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 131 | cur_seg_cmd = (segment_command_t *)cur; 132 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 133 | if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { 134 | linkedit_segment = cur_seg_cmd; 135 | } 136 | } else if (cur_seg_cmd->cmd == LC_SYMTAB) { 137 | symtab_cmd = (struct symtab_command*)cur_seg_cmd; 138 | } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { 139 | dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; 140 | } 141 | } 142 | 143 | if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || 144 | !dysymtab_cmd->nindirectsyms) { 145 | return; 146 | } 147 | 148 | // Find base symbol/string table addresses 149 | uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; 150 | nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); 151 | char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); 152 | 153 | // Get indirect symbol table (array of uint32_t indices into symbol table) 154 | uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); 155 | 156 | cur = (uintptr_t)header + sizeof(mach_header_t); 157 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 158 | cur_seg_cmd = (segment_command_t *)cur; 159 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 160 | if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && 161 | strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { 162 | continue; 163 | } 164 | for (uint j = 0; j < cur_seg_cmd->nsects; j++) { 165 | section_t *sect = 166 | (section_t *)(cur + sizeof(segment_command_t)) + j; 167 | if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { 168 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 169 | } 170 | if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { 171 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 172 | } 173 | } 174 | } 175 | } 176 | } 177 | 178 | static void _rebind_symbols_for_image(const struct mach_header *header, 179 | intptr_t slide) { 180 | rebind_symbols_for_image(_rebindings_head, header, slide); 181 | } 182 | 183 | int rebind_symbols_image(void *header, 184 | intptr_t slide, 185 | struct rebinding rebindings[], 186 | size_t rebindings_nel) { 187 | struct rebindings_entry *rebindings_head = NULL; 188 | int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); 189 | rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide); 190 | free(rebindings_head); 191 | return retval; 192 | } 193 | 194 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { 195 | int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); 196 | if (retval < 0) { 197 | return retval; 198 | } 199 | // If this was the first call, register callback for image additions (which is also invoked for 200 | // existing images, otherwise, just run on existing images 201 | if (!_rebindings_head->next) { 202 | _dyld_register_func_for_add_image(_rebind_symbols_for_image); 203 | } else { 204 | uint32_t c = _dyld_image_count(); 205 | for (uint32_t i = 0; i < c; i++) { 206 | _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 207 | } 208 | } 209 | return retval; 210 | } 211 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/fishhook/fishhook.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #import "fishhook.h" 25 | 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | 34 | #ifdef __LP64__ 35 | typedef struct mach_header_64 mach_header_t; 36 | typedef struct segment_command_64 segment_command_t; 37 | typedef struct section_64 section_t; 38 | typedef struct nlist_64 nlist_t; 39 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 40 | #else 41 | typedef struct mach_header mach_header_t; 42 | typedef struct segment_command segment_command_t; 43 | typedef struct section section_t; 44 | typedef struct nlist nlist_t; 45 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT 46 | #endif 47 | 48 | #ifndef SEG_DATA_CONST 49 | #define SEG_DATA_CONST "__DATA_CONST" 50 | #endif 51 | 52 | struct rebindings_entry { 53 | struct rebinding *rebindings; 54 | size_t rebindings_nel; 55 | struct rebindings_entry *next; 56 | }; 57 | 58 | static struct rebindings_entry *_rebindings_head; 59 | 60 | static int prepend_rebindings(struct rebindings_entry **rebindings_head, 61 | struct rebinding rebindings[], 62 | size_t nel) { 63 | struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry)); 64 | if (!new_entry) { 65 | return -1; 66 | } 67 | new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel); 68 | if (!new_entry->rebindings) { 69 | free(new_entry); 70 | return -1; 71 | } 72 | memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); 73 | new_entry->rebindings_nel = nel; 74 | new_entry->next = *rebindings_head; 75 | *rebindings_head = new_entry; 76 | return 0; 77 | } 78 | 79 | static void perform_rebinding_with_section(struct rebindings_entry *rebindings, 80 | section_t *section, 81 | intptr_t slide, 82 | nlist_t *symtab, 83 | char *strtab, 84 | uint32_t *indirect_symtab) { 85 | uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; 86 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); 87 | for (uint i = 0; i < section->size / sizeof(void *); i++) { 88 | uint32_t symtab_index = indirect_symbol_indices[i]; 89 | if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || 90 | symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { 91 | continue; 92 | } 93 | uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; 94 | char *symbol_name = strtab + strtab_offset; 95 | if (strnlen(symbol_name, 2) < 2) { 96 | continue; 97 | } 98 | struct rebindings_entry *cur = rebindings; 99 | while (cur) { 100 | for (uint j = 0; j < cur->rebindings_nel; j++) { 101 | if (strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { 102 | if (cur->rebindings[j].replaced != NULL && 103 | indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { 104 | *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; 105 | } 106 | indirect_symbol_bindings[i] = cur->rebindings[j].replacement; 107 | goto symbol_loop; 108 | } 109 | } 110 | cur = cur->next; 111 | } 112 | symbol_loop:; 113 | } 114 | } 115 | 116 | static void rebind_symbols_for_image(struct rebindings_entry *rebindings, 117 | const struct mach_header *header, 118 | intptr_t slide) { 119 | Dl_info info; 120 | if (dladdr(header, &info) == 0) { 121 | return; 122 | } 123 | 124 | segment_command_t *cur_seg_cmd; 125 | segment_command_t *linkedit_segment = NULL; 126 | struct symtab_command* symtab_cmd = NULL; 127 | struct dysymtab_command* dysymtab_cmd = NULL; 128 | 129 | uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); 130 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 131 | cur_seg_cmd = (segment_command_t *)cur; 132 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 133 | if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { 134 | linkedit_segment = cur_seg_cmd; 135 | } 136 | } else if (cur_seg_cmd->cmd == LC_SYMTAB) { 137 | symtab_cmd = (struct symtab_command*)cur_seg_cmd; 138 | } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { 139 | dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; 140 | } 141 | } 142 | 143 | if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || 144 | !dysymtab_cmd->nindirectsyms) { 145 | return; 146 | } 147 | 148 | // Find base symbol/string table addresses 149 | uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; 150 | nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); 151 | char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); 152 | 153 | // Get indirect symbol table (array of uint32_t indices into symbol table) 154 | uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); 155 | 156 | cur = (uintptr_t)header + sizeof(mach_header_t); 157 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 158 | cur_seg_cmd = (segment_command_t *)cur; 159 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 160 | if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && 161 | strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { 162 | continue; 163 | } 164 | for (uint j = 0; j < cur_seg_cmd->nsects; j++) { 165 | section_t *sect = 166 | (section_t *)(cur + sizeof(segment_command_t)) + j; 167 | if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { 168 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 169 | } 170 | if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { 171 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 172 | } 173 | } 174 | } 175 | } 176 | } 177 | 178 | static void _rebind_symbols_for_image(const struct mach_header *header, 179 | intptr_t slide) { 180 | rebind_symbols_for_image(_rebindings_head, header, slide); 181 | } 182 | 183 | int rebind_symbols_image(void *header, 184 | intptr_t slide, 185 | struct rebinding rebindings[], 186 | size_t rebindings_nel) { 187 | struct rebindings_entry *rebindings_head = NULL; 188 | int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); 189 | rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide); 190 | free(rebindings_head); 191 | return retval; 192 | } 193 | 194 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { 195 | int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); 196 | if (retval < 0) { 197 | return retval; 198 | } 199 | // If this was the first call, register callback for image additions (which is also invoked for 200 | // existing images, otherwise, just run on existing images 201 | if (!_rebindings_head->next) { 202 | _dyld_register_func_for_add_image(_rebind_symbols_for_image); 203 | } else { 204 | uint32_t c = _dyld_image_count(); 205 | for (uint32_t i = 0; i < c; i++) { 206 | _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 207 | } 208 | } 209 | return retval; 210 | } 211 | -------------------------------------------------------------------------------- /Frameworks/libcycript.cy: -------------------------------------------------------------------------------- 1 | /* Cycript - The Truly Universal Scripting Language 2 | * Copyright (C) 2009-2016 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Affero General Public License, Version 3 {{{ */ 6 | /* 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | (function() { 23 | 24 | Number.prototype.__defineGetter__('$cyt', function() { 25 | if (this.$cyt_) 26 | return this.$cyt_; 27 | if ((this|0) == this) 28 | return int; 29 | }); 30 | 31 | this.typeid = function(object) { 32 | return object.$cyt; 33 | }; 34 | 35 | let $cy_set = function(object, properties) { 36 | for (const name in properties) 37 | if ("defineProperty" in Object) 38 | Object.defineProperty(object, name, { 39 | configurable: true, 40 | enumerable: false, 41 | writable: true, 42 | value: properties[name], 43 | }); else object[name] = properties[name]; 44 | }; 45 | 46 | $cy_set(Boolean.prototype, { 47 | toCYON: function() { 48 | return `new Boolean(${this.toString()})`; 49 | }, 50 | }); 51 | 52 | $cy_set(Date.prototype, { 53 | toCYON: function() { 54 | return `new ${this.constructor.name}(${this.toUTCString().toCYON()})`; 55 | }, 56 | }); 57 | 58 | $cy_set(Error.prototype, { 59 | toCYON: function() { 60 | let stack = this.stack; 61 | if (typeof stack == 'undefined') 62 | stack = ''; 63 | else { 64 | stack = stack.split('\n'); 65 | if (stack.slice(-1)[0] == "global code") 66 | stack = stack.slice(0, -1); 67 | for (let i = 0; i != stack.length; ++i) 68 | stack[i] = '\n ' + stack[i]; 69 | if (stack.length == 0) 70 | stack = ''; 71 | else { 72 | stack = stack.join(''); 73 | stack = ` /*${stack} */`; 74 | } 75 | } 76 | return `new ${this.constructor.name}(${this.message.toCYON()})${stack}`; 77 | }, 78 | }); 79 | 80 | $cy_set(Number.prototype, { 81 | toCYON: function() { 82 | if ("$cyt" in this) 83 | //return `${this.$cyt.toCYON()}(${this.toString()})`; 84 | return this.toString(); 85 | return `new Number(${this.toString()})`; 86 | }, 87 | }); 88 | 89 | $cy_set(RegExp.prototype, { 90 | toCYON: function() { 91 | return this.toString(); 92 | }, 93 | }); 94 | 95 | if ("ObjectiveC" in Cycript) { 96 | $cy_set(NSArray.prototype, { 97 | $cyg: function(key) { 98 | return objc_msgSend(this, "objectAtIndex:", key); 99 | }, 100 | 101 | $cys: function(key, value) { 102 | return objc_msgSend(this, "setObject:atIndex:", value, key); 103 | }, 104 | }); 105 | 106 | $cy_set(NSDictionary.prototype, { 107 | $cyg: function(key) { 108 | return objc_msgSend(this, "objectForKey:", key); 109 | }, 110 | 111 | $cys: function(key, value) { 112 | return objc_msgSend(this, "setObject:forKey:", value, key); 113 | }, 114 | }); 115 | } 116 | 117 | let IsFile = function(path) { 118 | // XXX: this doesn't work on symlinks, but I don't want to fix stat :/ 119 | return access(path, F_OK) == 0 && access(path + '/', F_OK) == -1; 120 | }; 121 | 122 | let StartsWith = function(lhs, rhs) { 123 | return lhs.substring(0, rhs.length) == rhs; 124 | }; 125 | 126 | let ResolveFile = function(exact, name) { 127 | if (exact && IsFile(name)) 128 | return name; 129 | for (let suffix of ['.js', '.json']) 130 | if (IsFile(name + suffix)) 131 | return name + suffix; 132 | return null; 133 | }; 134 | 135 | let GetDocumentPath = function() { 136 | return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,1,true)[0]; 137 | }; 138 | 139 | let GetLibraryPath = function() { 140 | let handle = dlopen(NULL, RTLD_NOLOAD); 141 | if (handle == null) 142 | return null; 143 | 144 | try { 145 | let CYListenServer = dlsym(handle, "CYListenServer"); 146 | if (CYListenServer == null) 147 | return null; 148 | 149 | let info = new Dl_info; 150 | if (dladdr(CYListenServer, info) == 0) 151 | return null; 152 | 153 | let path = info->dli_fname; 154 | let slash = path.lastIndexOf('/'); 155 | if (slash == -1) 156 | return null; 157 | 158 | path = path.substr(0, slash); 159 | 160 | GetLibraryPath = function() { 161 | return path; 162 | }; 163 | 164 | return GetLibraryPath(); 165 | } finally { 166 | dlclose(handle); 167 | } 168 | }; 169 | 170 | let ResolveFolder = function(name) { 171 | if (access(name + '/', F_OK) == -1) 172 | return null; 173 | 174 | if (IsFile(name + "/package.json")) { 175 | let package = require(name + "/package.json"); 176 | let path = ResolveFile(true, name + "/" + package.main); 177 | if (path != null) 178 | return path; 179 | } 180 | 181 | return ResolveFile(false, name + "/index"); 182 | }; 183 | 184 | let ResolveEither = function(name) { 185 | let path = null; 186 | if (path == null) 187 | path = ResolveFile(true, name); 188 | if (path == null) 189 | path = ResolveFolder(name); 190 | return path; 191 | }; 192 | 193 | require.resolve = function(name) { 194 | if (StartsWith(name, '/')) { 195 | let path = ResolveEither(name); 196 | if (path != null) 197 | return path; 198 | } else { 199 | let cwd = *new (typedef char[1024]); 200 | cwd = getcwd(cwd, cwd.length).toString(); 201 | cwd = cwd.split('/'); 202 | 203 | if (StartsWith(name, './') || StartsWith(name, '../')) { 204 | let path = ResolveEither(cwd + '/' + name); 205 | if (path != null) 206 | return path; 207 | } else { 208 | 209 | for (let i = cwd.length; i != 0; --i) { 210 | let modules = cwd.slice(0, i).concat("node_modules").join('/'); 211 | let path = ResolveEither(modules + "/" + name); 212 | if (path != null) 213 | return path; 214 | } 215 | 216 | let library = GetLibraryPath(); 217 | let path = ResolveFile(true, library + "/" + name + ".cy"); 218 | if (path != null) 219 | return path; 220 | 221 | let document = GetDocumentPath(); 222 | path = ResolveFile(true, document + "/cycript/" + name + ".cy"); 223 | if (path != null) 224 | return path; 225 | } 226 | } 227 | 228 | throw new Error("Cannot find module '" + name + "'"); 229 | }; 230 | 231 | var _syscall = function(value) { 232 | if (value == -1) 233 | throw new Error(strerror(errno)); 234 | }; 235 | 236 | var info = *new (struct stat); 237 | if (false) { 238 | } else if ("st_atim" in info) { 239 | var st_atime = "st_atim"; 240 | var st_mtime = "st_mtim"; 241 | var st_ctime = "st_ctim"; 242 | } else if ("st_atimespec" in info) { 243 | var st_atime = "st_atimespec"; 244 | var st_mtime = "st_mtimespec"; 245 | var st_ctime = "st_ctimespec"; 246 | } else { 247 | var st_atime = "st_atime"; 248 | var st_mtime = "st_mtime"; 249 | var st_ctime = "st_ctime"; 250 | } 251 | 252 | var toDate = function(timespec) { 253 | return new Date(timespec.tv_sec * 1000 + timespec.tv_nsec / 1000); 254 | }; 255 | 256 | var bindings = {}; 257 | 258 | process.binding = function(name) { 259 | let binding = bindings[name]; 260 | if (typeof binding != 'undefined') 261 | return binding; 262 | 263 | switch (name) { 264 | case 'buffer': binding = { 265 | setupBufferJS() { 266 | }, 267 | }; break; 268 | 269 | case 'cares_wrap': binding = { 270 | }; break; 271 | 272 | case 'constants': binding = { 273 | }; break; 274 | 275 | case 'fs': binding = { 276 | FSInitialize() { 277 | }, 278 | 279 | lstat(path) { 280 | var info = new (struct stat); 281 | _syscall(lstat(path, info)); 282 | 283 | return { 284 | dev: info->st_dev, 285 | mode: info->st_mode, 286 | nlink: info->st_nlink, 287 | uid: info->st_uid, 288 | gid: info->st_gid, 289 | rdev: info->st_rdev, 290 | blksize: info->st_blksize, 291 | ino: info->st_ino, 292 | size: info->st_size, 293 | blocks: info->st_blocks, 294 | 295 | atime: toDate(info->[st_atime]), 296 | mtime: toDate(info->[st_mtime]), 297 | ctime: toDate(info->[st_ctime]), 298 | 299 | isSymbolicLink() { 300 | return S_ISLNK(this.mode); 301 | }, 302 | }; 303 | }, 304 | }; break; 305 | 306 | case 'pipe_wrap': binding = { 307 | }; break; 308 | 309 | case 'smalloc': binding = { 310 | alloc() { 311 | }, 312 | }; break; 313 | 314 | case 'stream_wrap': binding = { 315 | }; break; 316 | 317 | case 'tcp_wrap': binding = { 318 | }; break; 319 | 320 | case 'timer_wrap': binding = { 321 | kOnTimeout: 0, 322 | Timer: { 323 | }, 324 | }; break; 325 | 326 | case 'tty_wrap': binding = { 327 | }; break; 328 | 329 | case 'uv': binding = { 330 | }; break; 331 | 332 | default: 333 | throw new Error('No such module: ' + name); 334 | } 335 | 336 | bindings[name] = binding; 337 | return binding; 338 | }; 339 | 340 | process.env = {}; 341 | 342 | let environ = *(typedef char ***)(dlsym(RTLD_DEFAULT, "environ")); 343 | for (let i = 0; environ[i] != null; ++i) { 344 | let assign = environ[i]; 345 | let equal = assign.indexOf('='); 346 | let name = assign.substr(0, equal); 347 | let value = assign.substr(equal + 1); 348 | process.env[name.toString()] = value; 349 | } 350 | 351 | process.cwd = function() { 352 | let cwd = new (typedef char[1024]); 353 | return getcwd(cwd, cwd.length).toString(); 354 | }; 355 | 356 | process.pid = getpid(); 357 | 358 | })(); 359 | -------------------------------------------------------------------------------- /bin/md-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #set -e表示一旦脚本中有命令的返回值为非0,则脚本立即退出,后续命令不再执行; 4 | #set -o pipefail表示在管道连接的命令序列中,只要有任何一个命令返回非0值,则整个管道返回非0值,即使最后一个命令返回0. 5 | export setCmd="set -eo pipefail" 6 | $setCmd 7 | 8 | #导出环境变量 9 | export PATH=/opt/MonkeyDev/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH 10 | 11 | #脚本名称和版本 12 | export scriptName="${0##*/}" 13 | export scriptVer="2.0" 14 | 15 | #本地存储文件的目录 16 | export MonkeyDevPath="/opt/MonkeyDev" 17 | export backupFileExt=".MonkeyDev" 18 | 19 | #获取用户名、用户组、用户目录、和profile文件 20 | export userName="${SUDO_USER-$USER}" 21 | export userGroup=`id -g $userName` 22 | export userHome=`eval echo ~$userName` 23 | 24 | #用户可能存在的profile文件 25 | export bashProfileFiles=("$userHome/.zshrc" "$userHome/.bash_profile" "$userHome/.bashrc" "$userHome/.bash_login" "$userHome/.profile") 26 | 27 | #获取临时文件名 28 | export tempDirsFile="`mktemp -d -t $scriptName`/tempdirs" 29 | touch "$tempDirsFile" 30 | 31 | #把LANG变量从当前环境中删除 32 | unset LANG 33 | 34 | #出错退出 35 | function cleanup() 36 | { 37 | local exitCode=$? 38 | set +e 39 | trap - $signals 40 | removeTempData 41 | exit $exitCode 42 | } 43 | 44 | function panic() 45 | { 46 | local exitCode=$1 47 | set +e 48 | shift 49 | [[ "$@" == "" ]] || echo "$@" >&2 50 | exit $exitCode 51 | } 52 | 53 | export signals="0 1 2 3 15" 54 | #当shell接收到signals指定的信号时,执行cleanup命令 55 | trap cleanup $signals 56 | 57 | function removeTempData() 58 | { 59 | local tempDirs 60 | if [[ -f "$tempDirsFile" ]]; then 61 | tempDirs=(`cat "$tempDirsFile"`) 62 | for td in "${tempDirs[@]}"; do 63 | rm -rf "$td" || true 64 | done 65 | rm -rf "`dirname $tempDirsFile`" || true 66 | fi 67 | } 68 | function getTempDir() 69 | { 70 | $setCmd 71 | local tempDir 72 | tempDir=`mktemp -d -t $scriptName` || \ 73 | panic $? "Failed to create temporary directory" 74 | echo "$tempDir" >> "$tempDirsFile" || \ 75 | panic $? "Failed to echo into $tempDirsFile" 76 | echo "$tempDir" 77 | } 78 | 79 | function copyFile() 80 | { 81 | cp -f "$1" "$2" || \ 82 | panic $? "Failed to copy file $1 to $2" 83 | } 84 | 85 | #备份原文件 86 | function requireBackup() 87 | { 88 | [[ ! -f "$1" || -f "${1}${backupFileExt}" ]] || \ 89 | copyFile "$1" "${1}${backupFileExt}" 90 | } 91 | 92 | #获取SDK信息 93 | function getSdkProperty() 94 | { 95 | $setCmd 96 | 97 | local sdk="$1" 98 | local propertyName="$2" 99 | 100 | propertyValue=`xcodebuild -version -sdk $sdk $propertyName` || \ 101 | panic $? "Failed to get $sdk SDK property $propertyName" 102 | 103 | [[ $propertyValue != "" ]] || \ 104 | panic 1 "Value of $sdk SDK property $propertyName cannot be empty" 105 | 106 | # return # 107 | echo "$propertyValue" 108 | } 109 | 110 | #下载文件 111 | function downloadFile() # args: sourceUrl, targetPath 112 | { 113 | local sourceUrl="$1" 114 | local targetPath="$2" 115 | local curlPath 116 | 117 | mkdir -p "${targetPath%/*}" || \ 118 | panic $? "Failed to make directory: ${targetPath%/*}" 119 | 120 | curlPath=`which curl` || \ 121 | panic $? "Failed to get curl path" 122 | 123 | "$curlPath" --output "$targetPath" "$sourceUrl" || \ 124 | panic $? "Failed to download $sourceUrl to $targetPath" 125 | } 126 | 127 | #解压文件 128 | function extractTar() # args: tarPath, outputPath 129 | { 130 | local tarPath="$1" 131 | local outputPath="$2" 132 | 133 | tar -C "$outputPath" -zxf "$tarPath" || \ 134 | panic $? "Failed to extract $tarPath to $outputPath" 135 | } 136 | 137 | #下载github文件 138 | function downloadGithubTarball() # args: url, outputDir, title 139 | { 140 | $setcmd 141 | 142 | local url="$1" 143 | local outputDir="$2" 144 | local title="$3" 145 | local tempDirForTar 146 | local tempDirForFiles 147 | local untardDir 148 | local tarFile="file.tar.gz" 149 | 150 | echo "Downloading $title from Github..." 151 | 152 | tempDirForTar=`getTempDir` 153 | tempDirForFiles=`getTempDir` 154 | 155 | downloadFile "$url" "$tempDirForTar/$tarFile" 156 | 157 | extractTar "$tempDirForTar/$tarFile" "$tempDirForFiles" 158 | 159 | untardDir=`find "$tempDirForFiles/"* -type d -depth 0` || \ 160 | panic $? "Failed to get untar'ed directory name of $tempDirForTar/$tarFile" 161 | 162 | mkdir -p "$outputDir" || \ 163 | panic $? "Failed to make directory: $outputDir" 164 | 165 | cp -fR "$untardDir/"* "$outputDir/" 166 | } 167 | 168 | #修改文件权限 169 | function changeMode() 170 | { 171 | local mode="$1" 172 | local target="$2" 173 | local recursive="$3" 174 | local options 175 | 176 | [[ $recursive != "true" ]] || \ 177 | options="-R" 178 | 179 | if [[ -e "$target" ]]; then 180 | chmod $options "$mode" "$target" || \ 181 | panic $? "Failed to change mode to $mode on $target" 182 | fi 183 | } 184 | 185 | #获取用户profile文件 186 | function determineUserBashProfileFile() 187 | { 188 | $setCmd 189 | 190 | local f 191 | local filePath 192 | 193 | for f in "${bashProfileFiles[@]}"; do 194 | if [[ -f "$f" ]]; then 195 | filePath="$f" 196 | echo "" >> "$f" || \ 197 | panic $? "Failed to echo into $f" 198 | break 199 | fi 200 | done 201 | 202 | if [[ $filePath == "" ]]; then 203 | filePath="$bashProfileFiles" 204 | 205 | touch "$filePath" || \ 206 | panic $? "Failed to touch $filePath" 207 | 208 | chown "$userName:$userGroup" "$filePath" || \ 209 | panic $? "Failed to change owner-group of $filePath" 210 | 211 | changeMode 0600 "$filePath" 212 | fi 213 | 214 | # return # 215 | echo "$filePath" 216 | } 217 | 218 | #验证是否存在文件 219 | function requireFile() # args: filePath [, touchFileIfNotFound] 220 | { 221 | local filePath="$1" 222 | local touchFileIfNotFound="$2" 223 | 224 | if [[ ! -f "$filePath" ]]; then 225 | if [[ $touchFileIfNotFound == "true" ]]; then 226 | 227 | touch "$filePath" || \ 228 | panic $? "Failed to touch $filePath" 229 | 230 | else 231 | panic 1 "File $filePath not found" 232 | fi 233 | fi 234 | } 235 | 236 | #增加内容到文件 237 | function addToFileIfMissing() # args: filePath, pattern, value 238 | { 239 | local filePath="$1" 240 | local pattern="$2" 241 | local value="$3" 242 | local doesContain 243 | 244 | doesContain=`doesFileContain "$filePath" "$pattern"` 245 | 246 | [[ $doesContain == "true" ]] || \ 247 | echo "$value" >> "$filePath" || \ 248 | panic $? "Failed to echo into $filePath" 249 | } 250 | 251 | #判断文件是否包含内容 252 | function doesFileContain() # args: filePath, pattern 253 | { 254 | $setCmd 255 | 256 | local filePath="$1" 257 | local pattern="$2" 258 | local perlValue 259 | local funcReturn 260 | 261 | perlValue=`perl -ne 'if (/'"$pattern"'/) { print "true"; exit; }' "$filePath"` || \ 262 | panic $? "Failed to perl" 263 | 264 | if [[ $perlValue == "true" ]]; then 265 | funcReturn="true" 266 | else 267 | funcReturn="false" 268 | fi 269 | 270 | # return # 271 | echo $funcReturn 272 | } 273 | 274 | #从spec读取内容 275 | function readXcodeSpecificationById(){ #args: filePath, id 276 | local filePath="$1" 277 | local id="$2" 278 | content=`/usr/libexec/PlistBuddy -x -c Print "$filePath"` || \ 279 | panic $? "Failed to get $filePath content" 280 | for (( i=0; i<=1; i++)); do 281 | dict=`/usr/libexec/PlistBuddy -x -c "Print $i" "$filePath"` 282 | if echo $dict | grep -qE "$id"; then 283 | echo "$dict" 284 | fi 285 | done 286 | } 287 | 288 | #往spec文件写入内容 289 | function writeDictToSpecification(){ #args: filePath, content 290 | local filePath="$1" 291 | local content="$2" 292 | tempfile=`getTempDir`/dictfile 293 | echo "$content" >> $tempfile 294 | /usr/libexec/PlistBuddy -x -c 'add 0 dict' "$filePath" > /dev/null 295 | /usr/libexec/PlistBuddy -x -c "merge $tempfile 0" "$filePath" > /dev/null 296 | } 297 | 298 | # start it 299 | # 创建/opt/MonkeyDev 300 | mkdir -p "$MonkeyDevPath" || \ 301 | panic $? "Failed to make directory: $MonkeyDevPath" 302 | 303 | branch="master" 304 | 305 | if [[ "$1" ]]; then 306 | branch="$1" 307 | fi 308 | 309 | #下载一些基础文件和模板文件 310 | downloadGithubTarball "https://codeload.github.com/AloneMonkey/MonkeyDev/tar.gz/$branch" "$MonkeyDevPath" "MonkeyDev base" 311 | downloadGithubTarball "https://codeload.github.com/AloneMonkey/MonkeyDev-Xcode-Templates/tar.gz/$branch" "$MonkeyDevPath/templates" "Xcode templates" 312 | 313 | #下载frida-ios-dump 314 | echo "Downloading frida-ios-dump from Github..." 315 | downloadFile "https://raw.githubusercontent.com/AloneMonkey/frida-ios-dump/3.x/dump.py" "$MonkeyDevPath/bin/dump.py" 316 | downloadFile "https://raw.githubusercontent.com/AloneMonkey/frida-ios-dump/3.x/dump.js" "$MonkeyDevPath/bin/dump.js" 317 | 318 | chmod +x "$MonkeyDevPath/bin/dump.py" 319 | 320 | #创建符号链接 321 | echo "Creating symlink to Xcode templates..." 322 | 323 | #$userHome/Library/Developer/Xcode/Templates/MonkeyDev linkto $MonkeyDevPath/templates 324 | userDevDir="$userHome/Library/Developer" 325 | userTemplatesDir="$userDevDir/Xcode/Templates" 326 | 327 | if [[ ! -d "$userTemplatesDir" ]]; then 328 | mkdir -p "$userTemplatesDir" || \ 329 | panic $? "Failed to make directory: $userTemplatesDir" 330 | 331 | chown -R "$userName:$userGroup" "$userDevDir" || \ 332 | panic $? "Failed to change ownership-group of $userDevDir" 333 | fi 334 | 335 | ln -fhs "$MonkeyDevPath/templates" "$userTemplatesDir/MonkeyDev" 336 | 337 | #修改用户profile文件 338 | echo "Modifying Bash personal initialization file..." 339 | 340 | userBashProfileFile=`determineUserBashProfileFile` 341 | 342 | addToFileIfMissing "$userBashProfileFile" "^(export)? *MonkeyDevPath=.*" "export MonkeyDevPath=$MonkeyDevPath" 343 | addToFileIfMissing "$userBashProfileFile" "^(export)? *MonkeyDevDeviceIP=.*" "export MonkeyDevDeviceIP=" 344 | addToFileIfMissing "$userBashProfileFile" "^(export)? *PATH=.*(\\\$MonkeyDevPath\\/bin|${MonkeyDevPath//\//\\/}\\/bin).*" "export PATH=$MonkeyDevPath/bin:\$PATH" 345 | 346 | #支持iphoneos command line tools 347 | iosSdkPlatformPath=`getSdkProperty iphoneos PlatformPath` 348 | macosSdkPlatformPath=`getSdkProperty macosx PlatformPath` 349 | 350 | specificationFile=$(cd $iosSdkPlatformPath/../../.. && pwd)/PlugIns/IDEiOSSupportCore.ideplugin/Contents/Resources/Embedded-Device.xcspec 351 | 352 | requireFile "$specificationFile" false 353 | 354 | #backup 355 | requireBackup "$specificationFile" 356 | 357 | hasPackageTypeForCommandLineTool=`doesFileContain "$specificationFile" 'com.apple.package-type.mach-o-executable'` 358 | hasProductTypeForCommandLineTool=`doesFileContain "$specificationFile" 'com.apple.product-type.tool'` 359 | 360 | macosxSDKSpecificationsPath=$macosSdkPlatformPath/Developer/Library/Xcode/Specifications 361 | packageTypesForMacOSXPath="$macosxSDKSpecificationsPath/MacOSX Package Types.xcspec" 362 | productTypesForMacOSXPath="$macosxSDKSpecificationsPath/MacOSX Product Types.xcspec" 363 | 364 | requireFile "$packageTypesForMacOSXPath" false 365 | requireFile "$productTypesForMacOSXPath" false 366 | 367 | if [[ $hasPackageTypeForCommandLineTool != "true" ]]; then 368 | machoDict=`readXcodeSpecificationById "$packageTypesForMacOSXPath" "com.apple.package-type.mach-o-executable"` 369 | writeDictToSpecification "$specificationFile" "$machoDict" 370 | fi 371 | 372 | if [[ $hasProductTypeForCommandLineTool != "true" ]]; then 373 | toolDict=`readXcodeSpecificationById "$productTypesForMacOSXPath" "com.apple.product-type.tool"` 374 | writeDictToSpecification "$specificationFile" "$toolDict" 375 | fi 376 | 377 | exit 0 378 | -------------------------------------------------------------------------------- /Templates/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Templates/Command-line Tool.xctemplate/TemplateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Kind 6 | Xcode.Xcode3.ProjectTemplateUnitKind 7 | Identifier 8 | com.monkey.monkeydev.commandLineTool 9 | Concrete 10 | 11 | Description 12 | This template builds a command-line tool. 13 | Ancestors 14 | 15 | com.monkey.monkeydev.base 16 | 17 | Targets 18 | 19 | 20 | SharedSettings 21 | 22 | CODE_SIGN_ENTITLEMENTS 23 | ___PACKAGENAME___/monkeydev.entitlements 24 | CLANG_ENABLE_OBJC_ARC 25 | YES 26 | MonkeyDevkillProcessOnInstall 27 | 28 | CODE_SIGN_IDENTITY 29 | iPhone Developer 30 | INSTALL_PATH 31 | /usr/bin 32 | 33 | ProductType 34 | com.apple.product-type.tool 35 | BuildPhases 36 | 37 | 38 | Class 39 | Sources 40 | 41 | 42 | Class 43 | Frameworks 44 | 45 | 46 | ShellScript 47 | /opt/MonkeyDev/bin/md --xcbp 48 | ShellPath 49 | /bin/sh 50 | RunOnlyForDeploymentPostprocessing 51 | 52 | Class 53 | ShellScript 54 | 55 | 56 | 57 | 58 | Options 59 | 60 | 61 | SortOrder 62 | 1 63 | NotPersisted 64 | 65 | Identifier 66 | commandLineType 67 | Name 68 | Type 69 | Description 70 | The type of command-line tool to create. 71 | Default 72 | C 73 | Type 74 | popup 75 | Units 76 | 77 | C 78 | 79 | Nodes 80 | 81 | main.c:comments 82 | main.c:include 83 | main.c:main:content 84 | 85 | Definitions 86 | 87 | main.c:include 88 | #include <stdio.h> 89 | 90 | main.c:main:content 91 | // insert code here... 92 | printf("Hello, World!\n"); 93 | 94 | 95 | 96 | C++ 97 | 98 | Nodes 99 | 100 | main.cpp:comments 101 | main.cpp:include 102 | main.cpp:main:content 103 | 104 | Definitions 105 | 106 | main.cpp:include 107 | #include <iostream> 108 | 109 | main.cpp:main:content 110 | // insert code here... 111 | std::cout << "Hello, World!\n"; 112 | 113 | 114 | 115 | Core Data 116 | 117 | Project 118 | 119 | SharedSettings 120 | 121 | GCC_ENABLE_OBJC_GC 122 | required 123 | 124 | 125 | Targets 126 | 127 | 128 | SharedSettings 129 | 130 | GCC_PRECOMPILE_PREFIX_HEADER 131 | YES 132 | GCC_PREFIX_HEADER 133 | ___PACKAGENAME___/___PACKAGENAME___-Prefix.pch 134 | 135 | Frameworks 136 | 137 | CoreData 138 | Foundation 139 | 140 | 141 | 142 | Nodes 143 | 144 | main.m:comments 145 | main.m:include 146 | main.m:main:content 147 | main.m:coreData 148 | ___PACKAGENAME___-Prefix.pch:objC:importFoundation 149 | ___PACKAGENAME___-Prefix.pch:objC:importCoreData 150 | ___PACKAGENAMEASIDENTIFIER___.xcdatamodeld 151 | 152 | Definitions 153 | 154 | main.m:include 155 | NSManagedObjectModel *managedObjectModel(void); 156 | NSManagedObjectContext *managedObjectContext(void); 157 | 158 | main.m:main:content 159 | @autoreleasepool 160 | { 161 | // Create the managed object context 162 | NSManagedObjectContext *context = managedObjectContext(); 163 | 164 | // Custom code here... 165 | // Save the managed object context 166 | NSError *error = nil; 167 | if (![context save:&error]) { 168 | NSLog(@"Error while saving %@", ([error localizedDescription] != nil) ? [error localizedDescription] : @"Unknown Error"); 169 | exit(1); 170 | } 171 | } 172 | 173 | main.m:coreData 174 | NSManagedObjectModel *managedObjectModel() { 175 | 176 | static NSManagedObjectModel *model = nil; 177 | 178 | if (model != nil) { 179 | return model; 180 | } 181 | 182 | NSString *path = [[[NSProcessInfo processInfo] arguments] objectAtIndex:0]; 183 | path = [path stringByDeletingPathExtension]; 184 | NSURL *modelURL = [NSURL fileURLWithPath:[path stringByAppendingPathExtension:@"momd"]]; 185 | model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 186 | 187 | return model; 188 | } 189 | 190 | NSManagedObjectContext *managedObjectContext() { 191 | 192 | static NSManagedObjectContext *context = nil; 193 | if (context != nil) { 194 | return context; 195 | } 196 | 197 | @autoreleasepool 198 | { 199 | context = [[NSManagedObjectContext alloc] init]; 200 | 201 | NSPersistentStoreCoordinator *coordinator = ___RP___[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel()]___AR___; 202 | [context setPersistentStoreCoordinator:coordinator]; 203 | 204 | NSString *STORE_TYPE = NSSQLiteStoreType; 205 | 206 | NSString *path = [[[NSProcessInfo processInfo] arguments] objectAtIndex:0]; 207 | path = [path stringByDeletingPathExtension]; 208 | NSURL *url = [NSURL fileURLWithPath:[path stringByAppendingPathExtension:@"sqlite"]]; 209 | 210 | NSError *error; 211 | NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE configuration:nil URL:url options:nil error:&error]; 212 | 213 | if (newStore == nil) { 214 | NSLog(@"Store Configuration Failure %@", ([error localizedDescription] != nil) ? [error localizedDescription] : @"Unknown Error"); 215 | } 216 | } 217 | return context; 218 | } 219 | 220 | ___PACKAGENAME___-Prefix.pch:objC:importCoreData 221 | #import <CoreData/CoreData.h> 222 | ___PACKAGENAMEASIDENTIFIER___.xcdatamodeld 223 | 224 | Path 225 | ___PACKAGENAMEASIDENTIFIER___.xcdatamodeld 226 | 227 | 228 | 229 | Core Foundation 230 | 231 | Targets 232 | 233 | 234 | Frameworks 235 | 236 | CoreFoundation 237 | 238 | 239 | 240 | Nodes 241 | 242 | main.c:comments 243 | main.c:include 244 | main.c:main:content 245 | 246 | Definitions 247 | 248 | main.c:include 249 | #include <CoreFoundation/CoreFoundation.h> 250 | 251 | main.c:main:content 252 | // insert code here... 253 | CFShow(CFSTR("Hello, World!\n")); 254 | 255 | 256 | 257 | Core Services 258 | 259 | Targets 260 | 261 | 262 | Frameworks 263 | 264 | CoreServices 265 | 266 | 267 | 268 | Nodes 269 | 270 | main.c:comments 271 | main.c:include 272 | main.c:main:content 273 | 274 | Definitions 275 | 276 | main.c:include 277 | #include <CoreServices/CoreServices.h> 278 | 279 | main.c:main:content 280 | // insert code here... 281 | printf("Hello, World!\n"); 282 | 283 | 284 | 285 | Foundation 286 | 287 | Targets 288 | 289 | 290 | SharedSettings 291 | 292 | GCC_PRECOMPILE_PREFIX_HEADER 293 | YES 294 | GCC_PREFIX_HEADER 295 | ___PACKAGENAME___/___PACKAGENAME___-Prefix.pch 296 | 297 | Frameworks 298 | 299 | Foundation 300 | 301 | 302 | 303 | Nodes 304 | 305 | main.m:comments 306 | main.m:include 307 | main.m:main:content 308 | ___PACKAGENAME___-Prefix.pch:objC:importFoundation 309 | 310 | Definitions 311 | 312 | main.m:include 313 | #import <Foundation/Foundation.h> 314 | 315 | main.m:main:content 316 | @autoreleasepool 317 | { 318 | // insert code here... 319 | NSLog(@"Hello, World!"); 320 | } 321 | 322 | 323 | 324 | 325 | 326 | 327 | Nodes 328 | 329 | monkeydev.entitlements 330 | Package/DEBIAN/control:debianControl:section 331 | Package/DEBIAN/control:debianControl:depends 332 | Package/usr/bin/0xdeadfa11 333 | 334 | Definitions 335 | 336 | monkeydev.entitlements 337 | 338 | Path 339 | monkeydev.entitlements 340 | 341 | Package/usr/bin/0xdeadfa11 342 | 343 | Group 344 | 345 | Package 346 | usr 347 | bin 348 | 349 | Beginning 350 | 351 | This file was created only to help build the project's group structure, and it can now be deleted. 352 | 353 | Why 0xdeadfa11? See http://developer.apple.com/library/ios/#technotes/tn2151/_index.html. 354 | 355 | *:debianControl:section 356 | Section: System 357 | *:debianControl:depends 358 | Depends: firmware (>= 5.0) 359 | *:main 360 | 361 | Beginning 362 | int main (int argc, const char * argv[]) 363 | { 364 | 365 | End 366 | return 0; 367 | } 368 | 369 | Indent 370 | 1 371 | 372 | *:*:importFoundation 373 | #import <Foundation/Foundation.h> 374 | 375 | 376 | 377 | 378 | -------------------------------------------------------------------------------- /Templates/MonkeyAppLibrary.xctemplate/Config/MDCycriptManager.m: -------------------------------------------------------------------------------- 1 | // weibo: http://weibo.com/xiaoqing28 2 | // blog: http://www.alonemonkey.com 3 | // 4 | // MDCycriptManager.m 5 | // MonkeyDev 6 | // 7 | // Created by AloneMonkey on 2018/3/8. 8 | // Copyright © 2018年 AloneMonkey. All rights reserved. 9 | // 10 | 11 | #ifndef __OPTIMIZE__ 12 | 13 | #import "MDCycriptManager.h" 14 | #import "MDConfigManager.h" 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | 21 | #define IOS_CELLULAR @"pdp_ip0" 22 | #define IOS_WIFI @"en0" 23 | #define IP_ADDR_IPv4 @"ipv4" 24 | #define IP_ADDR_IPv6 @"ipv6" 25 | #define MDLog(fmt, ...) NSLog((@"[Cycript] " fmt), ##__VA_ARGS__) 26 | 27 | extern JSGlobalContextRef CYGetJSContext(void); 28 | extern void CydgetMemoryParse(const uint16_t **data, size_t *size); 29 | 30 | NSString * const CYErrorLineKey = @"CYErrorLineKey"; 31 | NSString * const CYErrorNameKey = @"CYErrorNameKey"; 32 | NSString * const CYErrorMessageKey = @"CYErrorMessageKey"; 33 | 34 | @interface MDSettingObject : NSObject 35 | 36 | @property (nonatomic, assign) NSInteger priority; 37 | @property (nonatomic, copy) NSString* url; 38 | @property (nonatomic, copy) NSString* content; 39 | @property (nonatomic, assign) BOOL loadAtLaunch; 40 | 41 | -(instancetype)initWithDicationary:(NSDictionary*) dictionary; 42 | 43 | @end 44 | 45 | @implementation MDSettingObject 46 | 47 | -(instancetype)initWithDicationary:(NSDictionary *)dictionary{ 48 | self = [super init]; 49 | if(self){ 50 | self.priority = [dictionary[@"priority"] integerValue]; 51 | self.url = dictionary[@"url"]; 52 | self.content = dictionary[@"content"]; 53 | self.loadAtLaunch = [dictionary objectForKey:MDCONFIG_LOADATLAUNCH_KEY] && [dictionary[MDCONFIG_LOADATLAUNCH_KEY] boolValue]; 54 | } 55 | return self; 56 | } 57 | 58 | @end 59 | 60 | @interface MDCycriptManager() 61 | 62 | @property (nonatomic, strong) NSDictionary* configItem; 63 | @property (nonatomic, copy) NSString* cycriptDirectory; 64 | @property (nonatomic, strong) NSMutableArray* downloading; 65 | @property (nonatomic, strong) NSMutableDictionary* loadAtLaunchModules; 66 | 67 | @end 68 | 69 | @implementation MDCycriptManager 70 | 71 | + (instancetype)sharedInstance{ 72 | static MDCycriptManager *sharedInstance = nil; 73 | if (!sharedInstance){ 74 | sharedInstance = [[MDCycriptManager alloc] init]; 75 | } 76 | return sharedInstance; 77 | } 78 | 79 | - (instancetype)init 80 | { 81 | self = [super init]; 82 | if (self) { 83 | _loadAtLaunchModules = [NSMutableDictionary dictionary]; 84 | _downloading = [NSMutableArray array]; 85 | [self check]; 86 | [self readConfigFile]; 87 | } 88 | return self; 89 | } 90 | 91 | -(void)check{ 92 | NSString* ip = [self getIPAddress]; 93 | if(ip != nil){ 94 | printf("\nDownload cycript(https://cydia.saurik.com/api/latest/3) then run: ./cycript -r %s:%d\n\n", [ip UTF8String], PORT); 95 | }else{ 96 | printf("\nPlease connect wifi before using cycript!\n\n"); 97 | } 98 | 99 | NSFileManager *fileManager = [NSFileManager defaultManager]; 100 | NSString *documentsPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) firstObject]; 101 | _cycriptDirectory = [documentsPath stringByAppendingPathComponent:@"cycript"]; 102 | [fileManager createDirectoryAtPath:_cycriptDirectory withIntermediateDirectories:YES attributes:nil error:nil]; 103 | } 104 | 105 | -(NSArray*)sortedArray:(NSDictionary*) dictionary{ 106 | NSMutableArray* result = [NSMutableArray arrayWithCapacity:10]; 107 | 108 | NSArray* sortedArray = [dictionary.allKeys sortedArrayUsingComparator:^NSComparisonResult(NSNumber* _Nonnull number1, NSNumber* _Nonnull number2) { 109 | if ([number1 integerValue] > [number2 integerValue]) 110 | return NSOrderedDescending; 111 | return NSOrderedAscending; 112 | }]; 113 | 114 | for (NSNumber* item in sortedArray) { 115 | [result addObject:dictionary[item]]; 116 | } 117 | 118 | return [result copy]; 119 | } 120 | 121 | -(void)readConfigFile{ 122 | MDConfigManager * configManager = [MDConfigManager sharedInstance]; 123 | _configItem = [configManager readConfigByKey:MDCONFIG_CYCRIPT_KEY]; 124 | } 125 | 126 | -(void)loadCycript:(BOOL) update{ 127 | NSFileManager *fileManager = [NSFileManager defaultManager]; 128 | 129 | if(_configItem && _configItem.count > 0){ 130 | 131 | BOOL download = NO; 132 | 133 | for (NSString* moduleName in _configItem.allKeys) { 134 | MDSettingObject * item = [[MDSettingObject alloc] initWithDicationary:_configItem[moduleName]]; 135 | NSString *fullPath = [[_cycriptDirectory stringByAppendingPathComponent:moduleName] stringByAppendingPathExtension:@"cy"]; 136 | 137 | if(item.url){ 138 | if(![fileManager fileExistsAtPath:fullPath] || update){ 139 | download = YES; 140 | [self.downloading addObject:moduleName]; 141 | [self downLoadUrl:item.url saveName:moduleName]; 142 | } 143 | } 144 | 145 | if(item.content){ 146 | if(![fileManager fileExistsAtPath:fullPath] || update){ 147 | NSString* writeContent = [NSString stringWithFormat:@"(function(exports) { %@ })(exports);", item.content]; 148 | [writeContent writeToFile:fullPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 149 | } 150 | } 151 | 152 | if(item.loadAtLaunch){ 153 | [_loadAtLaunchModules setObject:fullPath forKey:@(item.priority)]; 154 | } 155 | } 156 | 157 | if(!download){ 158 | [self finishDownload]; 159 | } 160 | } 161 | } 162 | 163 | -(void)finishDownload{ 164 | MDLog(@"Finish download all script!"); 165 | NSArray* sortedArray = [self sortedArray:_loadAtLaunchModules]; 166 | for (NSString* fullPath in sortedArray) { 167 | NSError* error; 168 | [self evaluateCycript:[NSString stringWithFormat:@"require('%@');",fullPath] error:&error]; 169 | if(error.code != 0){ 170 | MDLog(@"%@", error.localizedDescription); 171 | } 172 | } 173 | } 174 | 175 | -(void)downLoadUrl:(NSString*) urlString saveName:(NSString*) filename{ 176 | __weak typeof(self) weakSelf = self; 177 | NSURLSession *session = [NSURLSession sharedSession]; 178 | NSURL *url = [NSURL URLWithString:urlString]; 179 | NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { 180 | 181 | if(error){ 182 | MDLog(@"Failed download script [%@]: %@", filename, error.localizedDescription); 183 | }else{ 184 | NSString *fullPath = [[weakSelf.cycriptDirectory stringByAppendingPathComponent:filename] stringByAppendingPathExtension:@"cy"]; 185 | [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil]; 186 | 187 | MDLog(@"Successful download script [%@]", filename); 188 | } 189 | 190 | [weakSelf.downloading removeObject:filename]; 191 | 192 | if(!weakSelf.downloading.count){ 193 | [weakSelf finishDownload]; 194 | } 195 | }]; 196 | [downloadTask resume]; 197 | } 198 | 199 | -(NSString *)evaluateCycript:(NSString *)cycript error:(NSError *__autoreleasing *)error{ 200 | NSString *resultString = nil; 201 | 202 | static pthread_mutex_t cycript_metex = PTHREAD_MUTEX_INITIALIZER; 203 | pthread_mutex_lock(&cycript_metex); { 204 | JSGlobalContextRef context = CYGetJSContext(); 205 | 206 | size_t length = cycript.length; 207 | unichar *buffer = malloc(length * sizeof(unichar)); 208 | [cycript getCharacters:buffer range:NSMakeRange(0, length)]; 209 | const uint16_t *characters = buffer; 210 | CydgetMemoryParse(&characters, &length); 211 | JSStringRef expression = JSStringCreateWithCharacters(characters, length); 212 | 213 | // Evaluate the Javascript 214 | JSValueRef exception = NULL; 215 | JSValueRef result = JSEvaluateScript(context, expression, NULL, NULL, 0, &exception); 216 | JSStringRelease(expression); 217 | 218 | // If a result was returned, convert it into an NSString 219 | if (result) { 220 | JSStringRef string = JSValueToStringCopy(context, result, &exception); 221 | if (string) { 222 | resultString = (__bridge_transfer NSString *)JSStringCopyCFString(kCFAllocatorDefault, string); 223 | JSStringRelease(string); 224 | } 225 | } 226 | 227 | // If an exception was thrown, convert it into an NSError 228 | if (exception && error) { 229 | JSObjectRef exceptionObject = JSValueToObject(context, exception, NULL); 230 | 231 | NSInteger line = (NSInteger)JSValueToNumber(context, JSObjectGetProperty(context, exceptionObject, JSStringCreateWithUTF8CString("line"), NULL), NULL); 232 | JSStringRef string = JSValueToStringCopy(context, JSObjectGetProperty(context, exceptionObject, JSStringCreateWithUTF8CString("name"), NULL), NULL); 233 | NSString *name = (__bridge_transfer NSString *)JSStringCopyCFString(kCFAllocatorDefault, string); 234 | JSStringRelease(string); 235 | string = JSValueToStringCopy(context, JSObjectGetProperty(context, exceptionObject, JSStringCreateWithUTF8CString("message"), NULL), NULL); 236 | NSString *message = (__bridge_transfer NSString *)JSStringCopyCFString(kCFAllocatorDefault, string); 237 | JSStringRelease(string); 238 | string = JSValueToStringCopy(context, exception, NULL); 239 | NSString *description = (__bridge_transfer NSString *)JSStringCopyCFString(kCFAllocatorDefault, string); 240 | JSStringRelease(string); 241 | 242 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; 243 | [userInfo setValue:@(line) forKey:CYErrorLineKey]; 244 | [userInfo setValue:name forKey:CYErrorNameKey]; 245 | [userInfo setValue:message forKey:CYErrorMessageKey]; 246 | [userInfo setValue:description forKey:NSLocalizedDescriptionKey]; 247 | *error = [NSError errorWithDomain:@"CYContextDomain" code:0 userInfo:userInfo]; 248 | } 249 | }pthread_mutex_unlock(&cycript_metex); 250 | 251 | return resultString; 252 | } 253 | 254 | - (NSString *)getIPAddress{ 255 | 256 | NSDictionary *addresses = [self getIPAddresses]; 257 | 258 | if([addresses.allKeys containsObject:IOS_WIFI @"/" IP_ADDR_IPv4]){ 259 | return addresses[IOS_WIFI @"/" IP_ADDR_IPv4]; 260 | } 261 | 262 | return nil; 263 | } 264 | 265 | - (NSDictionary *)getIPAddresses{ 266 | NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8]; 267 | 268 | // retrieve the current interfaces - returns 0 on success 269 | struct ifaddrs *interfaces; 270 | if(!getifaddrs(&interfaces)) { 271 | // Loop through linked list of interfaces 272 | struct ifaddrs *interface; 273 | for(interface=interfaces; interface; interface=interface->ifa_next) { 274 | if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) { 275 | continue; // deeply nested code harder to read 276 | } 277 | const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr; 278 | char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ]; 279 | if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) { 280 | NSString *name = [NSString stringWithUTF8String:interface->ifa_name]; 281 | NSString *type; 282 | if(addr->sin_family == AF_INET) { 283 | if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) { 284 | type = IP_ADDR_IPv4; 285 | } 286 | } else { 287 | const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr; 288 | if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) { 289 | type = IP_ADDR_IPv6; 290 | } 291 | } 292 | if(type) { 293 | NSString *key = [NSString stringWithFormat:@"%@/%@", name, type]; 294 | addresses[key] = [NSString stringWithUTF8String:addrBuf]; 295 | } 296 | } 297 | } 298 | // Free memory 299 | freeifaddrs(interfaces); 300 | } 301 | return [addresses count] ? addresses : nil; 302 | } 303 | 304 | @end 305 | 306 | #endif 307 | --------------------------------------------------------------------------------