글 자체를 통째로 번역해보는 건 처음이네..ㅋㅋ

시디아 지역화 파일 정도 번역같은건 해봤지만.....


오역, 이상한 번역투, 이해 잘못한거, 번역 못한거, 빼먹은 거 등 수정 해주시면 감사합니다~


원문 : http://iphonedevwiki.net/index.php/MobileSubstrate_Pitfalls


#: 번역 주

확장기능(extension) 은 MobileSubstrate Extensions. 즉 트윅을 뜻하는 거임

주황색 : 번역 안됨 혹은 정확한 의미를 모르겠음


===========================================================


일반적인 MobileSubstrate 의 실수들을 막기 위해서 아래 가이드 라인을 따를 것.


1. SpringBoard 를 후킹할 경우 constructor 에서 UIDevice 를 사용하지 말 것

# constructor 는 theos 의 %ctor 나 +(void)load 와 같은걸 의미하는 듯. SpringBoard 가 완전히 로드된 후에는 사용해도 된다.


2. ivar 에 접근할 때는 적절한 property 들을 통해 사용


3. 본래 작업이 동작하지 않게 하는것이 필요하지 않다면 항상 본래 작업을 호출할 것. 또한 원래 작업은 그 메소드 내부에서만 호출해야 함.

# 쉽게 말하자면 꼭 필요한게 아니라면 %orig 를 빼먹지 말고, %orig 는 후킹한 메서드 안에서만 쓰란 얘기


4. MobileLoader 필터를 항상 포함할 것

SpringBoard 를 후킹한다면 com.apple.springboard 를, 모든 UIKit 앱들을 후킹한다면 com.apple.UIKit 필터를 사용하면 됨


5. SpringBoard 안에서 UIAlertView 사용을 피하고 SBAlertItem 을 재정의 해서 쓸 것. system이 경우에 따라 alert 을 무시해도 상관없다면 UIAlertView 를 사용해도 무방.


6. 공개된 SDK 에 기술된 API 들을 쓸 것. Private API 는 Apple이 Public 이전에 테스트 목적으로 넣어둔 경우가 많으며 이 후 버젼에 같거나 비슷한 Api 가 Public 으로 공개된다.


7. Preferences 프레임워크는 iOS 버젼 3.1 과 3.2 사이에 크게 변했다. 간단한 설정엔 PreferenceLoader 와 preferences plist 를 사용하고, 아니라면 PSViewController와 UITableView 를 함께 써라. (PSListController 또한 간단한 설정에 쓰면 좋고 OS 버젼에 따른 큰 차이가 없다. PSViewController 는 훨씬 강력하지만, 3.1->3.2 로 넘어오면서 많은 메서드들이 없어졌다.)

# 나의 경우엔 UIViewController 에 -(void)setRootController:(id)controller, -(void)setParentController:(id)controller, -(void)setSpecifier:(PSSpecifier *)spec, -(PSSpecifier *)specifier, -(void)lazyLoadBundle:(id)bundle 등을 대충 정의해준 뒤 쓴다.


8. 해상도나 기기 방향에 대해 별문제 없도록 autoresizingMask 나 layoutSubviews 를 적절히 써줄 것.


9. OS 나 Cydia 파일을 변경하지 말 것. 런타임 중에 변경되도록 할 것.

# WinterBoard 가 이미지 파일을 런타임으로 변경하는걸 생각하면 이해가 쉬움. 즉 후킹하란 소리


10. 쓸데 없는 작업들은 피할 것. 확장기능의 메서드 들은 타이트한 loop 속에서 실행 된며 디스크 파일 접근이나 property 를 호출하는 것 같은 작업은 많은 일을 하는 것을 고려할 것. 작업이 느려질 수 있음.

# 하지만 경험상 별 상관없음. ctor 나 load 등 최초 실행중에 삽질만 안하면 거의 문제 안남


11. UIImage 를 포함한 UI~~ 메서드들은 반드시 main thread 에서 실행되어야 한다. 백그라운드에서 이미지를 불러와야 한다면 CGImageSource 와 그 계열 함수들을 사용.


12. main thread 를 붙잡고 있지 말 것. 어떤 작업이든 오랜 시간이 걸리는 작업(인터넷 연결을 포함하여)을 main thread 에 두는 것은 좋지 않다.


13. NSBundle 을 통하여 리소스를 사용할 것. 이것은 WinterBoard 가 theme를 적용시킬 수 있게 해준다.

# 하지만 난 NSBundle 을 한번도 쓴 적이 없지 ㅋ


14. 적절한 의존성을 Debian control 파일 안에 포함할 것. 시디아가 자동으로 설치해 줄 것이며, OS 버젼과 같은 문제가 있을 경우 이를 사용자에게 알려준다.


15. 확장기능이 다른 확장기능이 사용할 수 있는 API 를 포함한다면, 이를 기술할 것.

찾기 쉽게 패키지 안에 헤더파일을 포함해 놔도 좋다.


16. 확장기능이 지역화될 수 있도록 할 것. 일반적인 .lproj 파일을 사용하면 된다. 텍스트를 포함한 이미지 사용은 지양.


17. package 가 .DS_Store / ._* / thumbs.db 같은 파일들을 포함하지 않도록 할 것

# 포함될 경우, 필요 없는 파일이기도 하고 저 파일들이 포함된 또 다른 패키지들이 있을 경우 설치가 안될 수가 있다. make package 가 아니라 직접 dpkg 할 경우 곧잘 포함되서 좀 짜증남;;ㅋㅋ


18. 클래스의 ivar 구조를 추정하지 말 것. 펌웨어 버젼에 따라 달라질 수 있다.

# 말그대로 구조. 구조를 토대로 메모리 주소로 값들을 사용하지 말란 거지 변수이름을 토대로 ivar 을 얻어오는 것과는 다른 얘기인 듯.


19. substrate.h, CaptainHook, Logos 와 같은 인정받은 후킹 메서드들을 사용할 것. 직접 만든것 보다 더 좋으며 당장 사용할 수 있는 자세한 정보들이 많다.


20. low-level 그래픽 하드웨어에 접근할 일이 있다면, 1세대 기기들은 통일된 메모리 모델을 가지고 있지 않음에 주의. (VRam 과 규칙적인 RAM 은 분리되어 있다.)

# 뭔소린지 모르겠지만 우린 1세대 기기와는 상관없으니 무시.


21. iOS의 Memory-Warning 시스템에 참여할 것. 확장기능이 많은 메모리를 사용한다면, 가능한 모든 것들을 해제할 것.


22. 큰 dataset 을 사용할 경우 mmap 을 사용. 커널이 필요에 따라 스왑할 것이다. (하지만 큰 작성은 피할 것, 가상메모리 보다 나은게 없어질 것이다.)

# 뭔소린지 모르겠다..


23. MobileSubstrate의 Safe Mode 를 방해하지 말 것


24. 확장기능이 홈화면의 아이콘을 다룬다면, IconSupport 를 사용함으로써 다른 확장기능의 수정이나 safe-mode layout 을 건드리지 말 것.


25. 가능한 최신의 펌웨어를 지원할 것 - "3.0.1, 3.1 이후 지원" 말고 "3.0 부터 지원" 이렇게 하란 뜻. 필요하다면 버젼을 감지해서 다르게 작동하도록 만들 것.


26. 사용자의 개인정보를 존중할 것.

IMEI, 전화번호, 연락처, 메일은 명백히 개인정보이다.

MAC 주소, Bluetooth MAC 주소, UDID 같은 것이 유저를 식별하기 위한 정보로 사용될 수 있다.


27. 숨겨야 할 것이 있다면, Strip symols 할 것. Objective-C 는 자세한 것까지 보여주니 일반적인 C 나 C++ 을 사용할 것

# 사실 그래도 다 보임. inline 으로 쓰고, ldflags 에 -Xlinker -unexported_symbol -Xlinker "*" 을 넣으면 그나마 덜 보인다고 함.


28. 많은 Private Framework 의 헤더들은 Mac 용 Public Framework 로 공개되어 있으니 그거 쓰면 됨. 혹은 다른 사람들이(kennytm 등) 추출해 놓은 header 들을 사용.


29. 사용하는 Framework 만 링크할 것. 필요없는 프레임워크의 링크는 실행 속도를 저하시킬 수 있음. (앱이 실행된 이후 런타임에서 라이브러리를 로드하기 위해서는 dlopen/dlsym 을 사용)

iOS3.1 이후에는 dyld shared object cache 덕분에 크게 상관 없음. 그래도 필요없으면 뺄 것.


30. Class 이름이나 Category 이름 앞에 Prefix 를 붙여 사용할 것. Objective-C 는 Namespacing capabilities 를 사용하지 않는다. (예를 들어 같은 이름의 클래스가 확장기능과 그 확장기능이 후킹한 앱에서 사용된다면 둘중 하나는 제대로 작동하지 않을 수 있음.)

# 이거 중요함. 이거 때문에 뜬금없이 앱이 오작동하는 일이 많다. UIKit 이나 Foundation 에 카테고리로 메서드를 추가할때도 특히 유의. 예를 들자면(실제 경험) UIView 에 viewController 라는 메서드를 새로 정의해놨는데 이게 앱에서도 똑같은 이름으로 정의해놨지만 앱쪽은 코드가 조금 달랐는지 앱이 제대로 작동 안했었음. 중복될 만한 클래스 명이나 메서드명 앞에는 A_ 같은 식으로 prefix 를 넣어주자. 수정해주기 귀찮으면 define 으로 처리해도 됨.


31. 설정 파일은 /var/mobile/Library/Preferences/ 안에 넣어둘 것. iTunes와 iCloud 가 이것을 백업한다.


32. sandbox 제한을 피해서 데이터를 저장하기 위해서는 필요에 따라 /var/mobile/Library/AddressBook/ 이나 /var/mobile/Library/Keyboard/ 를 사용.

# 샌드박스를 깨주는 라이브러리(혹은 트윅)도 있는 것으로 앎. 필요하다면 알아서 검색~


33. 잠자기에서 폰을 깨우거나 잠자기에 들어가는 것을 방해하지 말 것. 확장기능이 주기적으로 해야할 일이 있다면 Mail 앱의 동기화 부분을 후킹하여 사용. (스케쥴/알람 기능을 가지는 확장기능 들은 이 경고를 무시해도 된다.)


34. 배터리를 위해서 사용자가 예상할 수 없는 CPU, GPU, 디스크 작업은 피할 것


35. NSLog, CFLog, fprintf(stderr, ...) 등을 남용하지 말 것. 이것은 느리고 동기적(?, synchronous)이다.


36. 확장기능이 아이콘을 보여준다면, 29*29와 59*60의 사이즈를 둘다 포함할 것 (more for iPad.)


37. 다른 확장기능이 같은 메서드를 후킹할 것을 염두에 둘 것. 그들은 이 가이드라인을 읽지 않고 미친 짓을 할 수도 있다.


38. Prefer hooking methods over hooking functions--new jailbreaks don't always have kernel patches (although this is not as much of a concern, as jailbreakers understand the need for W^X) and MobileSubstrate may not support newer ARM instructions.

# 뭔소린지 잘 모르겠지만 low-level 의 함수들은 가급적 후킹하지 말란 소리 같음..


39. Public API를 후킹할 경우 return 값의 클래스를 바꾸지 말 것. 일부 AppStore 앱들은 객체의 클래스를 확인하지 않고 문제를 일으킨다.


40. XML 보다 더 빠른 binary plist 를 선호할 것. (OpenSTEP 스타일의 plist 또한 빠르지만 deprecated 된 것으로 보임.)

# binary plist 는 어떻게 만드는건지 모르겠다. 그냥 NSDIctionary 에 있는대로 써도 됨


41. Cocoa 메모리 관리 가이드 라인에 따라 모든 후킹에서 한줄한줄 정확하게 메모리 관리를 할 것.


42. MSHookMessage 대신 MSHookMessageEx 를 사용할 것.

MSHookMessage allows you to specify an optional prefix which gets added to the original method, polluting the class.

우선 반탈 자체가 탈옥 후에 한번 껏다가 just boot 로 켜줘야 제대로 작동하는 짜증나는 점이 존재.


여튼 iOS6 반탈하고 잘 쓰다가 reboot 하니 just boot 을 해도, 다시 jailbreak 를 해도 MobileSubstrate 가 작동안함..

(계속 해봤던 이유는 트윅들이 작동안해서 그냥 탈옥 풀린줄 알았음.)


재탈옥 하면 무한리스프링이니 그냥 껏다가 just boot 다시 해주시고, 터미널 등으로 리스프링 한번 해주면 정상작동함.



그리고 이거 하면서 Mobile Substrate 업데이트 후 재부팅시 볼륨 업 버튼을 꾹 누르고 있으면 Substrate 가 꺼진채로 켜진다는 점도 알았다 ㅋ

이거 언젠가 유용하게 써먹을 듯 ㅋㅋ


iOS open project 이니 뭐니도 나온 상황이고, THEOS 가 훨씬 쓰기 편하다...

아래는 XCode4 나오면서 안되므로 무시하시길.
사실 저거 쓰면서 나도 뭐가 뭔지 몰라서 그냥 복,붙에 불과하다..ㅋㅋ



///////////////////////////////////////////////////////////////////////////////////////////////////

참고 싸이트

modmyi.com http://modmyi.com/forums/iphone-ipod-touch-sdk-development-discussion/728944-tutorial-how-compile-mobile-substrate-extension-xcode.html )

devbug.me http://devbug.me/606?category=2 )



1. XcodeSubstrate.zip 을 받는다. 주소 : http://cl.ly/9b3963d250f4673ccf51

(직접 헤더를 덤프하여 사용하려면 상단 modmyi 의 링크로 따라가서 Ok here we go 하위에 있는 XcodeSubstrateNoHeaders.zip 을 받는다)


그리고 압축풀고 나온 Mobile Substrate Extension 폴더는

/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Project Templates/Application

하위에 집어 넣는다.

템플릿이 4.0 기반이라 XCode에서 프로젝트 생성시 4.0으로 생성된다. 프로젝트 설정에서 바꿔주도록 하자.

버젼 문제는 아래에서 추가 설명


2. class-dump 를 이용하여 springboard 의 헤더파일을 가져온다.

class-dump-3.3.3.dmg (맥용) / apt-get install class-dump (아이폰)


맥-터미널 :

class-dump -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard/

(맥에서 파일,폴더를 드래그 하여 터미널 위로 드랍시킬 경우 커서가 위치한 곳에 파일/폴더의 경로를 뿌려준다.

또한 class-dump 를 설치하고 싶지 않은 사람은 디스크 마운트 상태에서 class-dump를 복사하지 않고 사용이 가능하다.

ex> /Volumes/class-dump-3.3.3/class-dump  -H ~~~

뭐 편한대로 사용하도록 하자.


아이폰-터미널 : class-dump -H /System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/SpringBoard/

(아이폰에서 ssh를 깔아놓고 맥에서 터미널로 접근해서 하는 것을 추천한다.

이 글에서는 컴퓨터에서 추출한 헤더 파일을 사용하므로 일단 방법만을 적어놨을 뿐이고 실제 진행시에는 컴퓨터에서 추출하도록 하자.)


폴더이름은 SpringBoard 그대로 하도록! 뒤에 가서 헷갈린다... 오류 날경우 폴더를 만들어 놓고 실행!

그리고 폴더 채로 /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.0.sdk/usr/include/

하위로 이동하도록 한다


또한 Springboard/SpringBoard.h 파일을 열어서

7번째 줄의
#import "UIApplication.h"

#import "UIKit/UIApplication.h"
로 수정,

54번째 줄의
struct _opaque_pthread_t {
    long _field1;
    struct __darwin_pthread_handler_rec *_field2;
    char _field3[596];
} *_backgroundMIGServerThread;

을 주석 처리 한다.

devbug님이 게시한 방법이며, 이외에도 해줄곳이 많다고 한다. 일단 여기까지-

아이폰에서 class-dump를 했을 경우 파일이 위와 같지 않다. 나도 이런면을 잘아는게 아니라

그냥 다른글을 옮길 뿐이니 그냥 가르쳐주는대로 하도록 하자..ㅠㅠ


3. 1에서 압축을 풀었던 폴더 내에 있는 substrate.h 파일을 2에서 이동한 ~~/include/ 하위로 옮긴다.

SpringBoard 하위로 옮기지 않도록 유의하자.

noheader 버젼을 받은 사람이라면 이 파일이 없을 것이다. 아이폰에서 /Library/Frameworks/CydiaSubstrate.framework/Headers/CydiaSubstrate.h

경로의 파일을 이름을 바꿔서 집어 놓도록 하자.


4. 압축을 푼 폴더 내에 혹은 아이폰 내부(/usr/lib/libsubstrate.dylib) 에 있는 libsubstrate.dylib

/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/ 로 이동한다


이후 Xcode에 가면 새 프로젝트 선택시 MobileSubstrate Extension 이 나타난다.


빌드 시 device모드로 놓고 build and run 이 아닌 그냥 build를 하도록 하자.

개발자 등록을 하지 않았거나 xcode에 code sign 작업을 해놓지 않았을 경우 에러가 뜨게 된다.


빌드 후 프로젝트 폴더 내의 Release-iphoneos / Debug-iphoneos 폴더 아래에 있는 .app 파일을 패키지 보기로 연후

프로젝트 이름의 확장자 없는 실행 화일만 빼내어 .dylib 확장자를 붙인다.

이후 아이폰의 /Library/MobileSubstrate/DynamicLibraries/ 경로에 집어넣고 리스프링 하면 확인할 수 있다.



아래는 modmyi 에서 알려주는 SDK가 4.0 이 아닐경우의 프로젝트 설정이다.

어차피 xcode가 영어니까 그냥 그대로 복사해 오도록 하겠다..

--------------------------

  1. In the menu bar, click Project > Edit Project Settings
  2. Click the "Build" tab at the top
  3. Drop down the Configuration box and change it to Debug
  4. Change the Base SDK to iPhone Device 4.0
  5. Drop down the Configuration box and change it to Release
  6. Change the Base SDK to iPhone Device 4.0
  7. Close the window
  8. Expand the Frameworks folder in the sidebar to reveal the red Foundation and UIKit frameworks, then delete them both
  9. Control-click the Frameworks folder > Add > Existing Frameworks...
  10. Choose Foundation and UIKit from the list
--------------------------
다른 SDK의 경우 특히 8~10 작업을 해주지 않을 경우 컴파일 오류가 날것이다..(아마..)
modmyi에서는 4.0 이 아닌곳에서 쓰는것을 주의하라고는 하지만.. 그냥 무시하자.. 그렇다고 4.1 / 4.2.1 용이 있는것도 아닌것 같다..






가장 좋은건 그냥 modmyi 가서 원문을 읽어보자.. devbug님이 소개한 class-dump 관련한 내용을 제하고는 모두 들어있다.


'개발개발 > Mac, iOS' 카테고리의 다른 글

BundleIdentifier로 앱 정보 구하기  (4) 2011.02.23
앱 설치 여부 구하기  (0) 2011.02.22
DEBIAN PACKAGING (deb) 만들기 (수정)  (1) 2011.01.30
PreferenceLoader 사용법  (0) 2011.01.30
cydia 앱, MobileSubstrate  (0) 2011.01.07

탈옥을 하고 activator 등 트윅들을 설치할 경우 함께 설치 되는것이

MobileSubstrate.


MobileSubstrate 를 이용하는 트윅들을 mobile substrate extension 이라고도 하는 것 같은데 그냥 간단히

트위(Tweak) 이라 하자..ㅋ


MobileSubstrate 는 iOS 기본 앱인 SpringBoard 를 비롯하여 각종 앱, 프레임 워크를 손쉽게 후킹할 수 있게 해준다.


주로 트윅들의 후킹 대상은 SpringBoard 가 되는데 일반적으로는 애플이 제작후 배포되는 SpringBoard 라서 사용중 큰 문제가 없다. 하지만 MobileSubstrate 를 통해 후킹을 할 경우 다른 개발자의 임의의 코드가 들어가면서 SpringBoard 에 에러가 생길 수 있고, 이 에러가 치명적일 경우 사용자가 폰을 사용하기 곤란해 질 것이다.

이를 대비해서 만들어진 것이 Safe Mode. 이 경우, 모든 MobileSubstrate Extension 들은 비활성화 된다.


Tweak 들을 비활성화 하려면 SBSettings 의 More 메뉴에 있는 MobileSubstrate addons 메뉴를 이용하거나

ifile 등을 이용하여 아이폰 내부 /Library/MobileSubstrate/DynamicLibraries/ 폴더에 있는 dylib파일의 확장자를 바꾸면 된다.

'개발개발 > Mac, iOS' 카테고리의 다른 글

BundleIdentifier로 앱 정보 구하기  (4) 2011.02.23
앱 설치 여부 구하기  (0) 2011.02.22
DEBIAN PACKAGING (deb) 만들기 (수정)  (1) 2011.01.30
PreferenceLoader 사용법  (0) 2011.01.30
MobileSubstrate Extension with XCode  (0) 2011.01.07

+ Recent posts