Getting started reverse-engineering OS X? - iphone

What is a good place to learn reverse engineering, specifically as it applies to Mac OS X? Two apps that I admire in terms of this subject:
Hyperspaces – Link
and
Orbit – http://www.steventroughtonsmith.com/orbit/
Thanks guys.

You should grab a copy of Mac OS X Internals which is an awesome book about everything that Apple does not tell you. Not only is this great if you are interested in reverse engineering, it will also make you a better OS X programmer in general.

Use class-dump-x/-z to get the private Objective-C headers for OS X/iPhone OS system frameworks. There are a lot of classes/methods hidden from the public (some rightly so)

Apple releases a ton of the foundation of OS X as open source. See here.
In addition, F-Script Anywhere will help a ton with dissecting the Finder and/or any other closed source application.

For iPhoneOS specifically, class-dump-z is a great way to dump headers. The only problem, of course, is that you can't actually see what is going on inside of each method. IDA Pro and a few scripts make it possible to see the assembly instructions for these system frameworks. (example picture: http://grab.by/1Vn6).
The most handy IDC scripts are fixobjc2 and dyldinfo. You can find each of these linked from this blog post: http://networkpx.blogspot.com/2010/01/two-ida-pro-5x-scripts-for-iphoneos.html
But, what good is this information if you can't use it? iPhone developer saurik has written something called MobileSubstrate that enables hooking onto any method. http://svn.saurik.com/repos/menes/trunk/mobilesubstrate/

Others have already mentioned class-dump, which is an excellent tool for retrieving the class definitions from a compiled executable. On a related note, you should also take a look at otx, which is provides very nice (readable), disassembled output.
If you need a way to quickly test snippets of code, use F-Script (mentioned by others), Nu or MacRuby. Of these, I've mainly used Nu. It has the capability to define bridged functions on the fly, and can handle pointers, both of which are pretty handy if you need to call arbitrary C functions.
Since you mentioned being interesting in Spaces and other screen managers, you should also read A brief tutorial on reverse engineering OS X. It's an old article by Rich Wareham (author of the pre-Spaces multi-desktop app: 'Desktop Manager') on how he figured out the call syntax for few private CoreGraphics methods in order to do nice desktop transitions. The source code for Desktop Manager is also available, which might be useful to you.

This site shows how to patch an existing Objective C program: http://www.culater.net/wiki/moin.cgi/CocoaReverseEngineering
Namely posing:
[[B class] poseAsClass:[A class]];
and method swizzling:
/**
* Renames the selector for a given method.
* Searches for a method with _oldSelector and reassigned _newSelector to that
* implementation.
* #return NO on an error and the methods were not swizzled
*/
BOOL DTRenameSelector(Class _class, SEL _oldSelector, SEL _newSelector)
{
Method method = nil;
// First, look for the methods
method = class_getInstanceMethod(_class, _oldSelector);
if (method == nil)
return NO;
method->method_name = _newSelector;
return YES;
}
// *** Example ***
// never implemented, just here to silence a compiler warning
#interface WebInternalImage (PHWebInternalImageSwizzle)
- (void) _webkit_scheduleFrame;
#end
#implementation WebInternalImage (PHWebInternalImage)
+ (void) initialize
{
DTRenameSelector([self class], #selector(scheduleFrame), #selector (_webkit_scheduleFrame));
DTRenameSelector([self class], #selector(_ph_scheduleFrame), #selector(scheduleFrame));
}
- (void) _ph_scheduleFrame
{
// do something crazy...
...
// call the "super" method - this method doesn't exist until runtime
[self _webkit_scheduleFrame];
}
#end
(code copied from http://www.culater.net/wiki/moin.cgi/CocoaReverseEngineering)

As an addition to the other answers, you are going to want to check out DYLD_INSERT_LIBRARIES to inject your code into a Cocoa program.

You should definitely consider using DTrace. There is an excellent BlackHat presentation on using DTrace for reverse engineering on OS X entitled, "DTRACE: The Reverse Engineer's Unexpected Swiss Army Knife".
You can get a copy and view the video presentation here.
There are also some excellent papers at www.uninformed.org on reverse engineering OS X.

Related

What does this mean? #if !(arch(x86_64) || arch(arm64))

I came across this unusual code in a tutorial I was using.
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
return CGFloat(sqrtf(Float(a)))
}
#endif
It looks nothing like the code I've been learning so far. I know it's a square root function but the hashtag? Something about my computer architecture?
Please explain it to me in simple terms.
#if condition
// Code in here
#endif
This is a conditional compilation directive - it is used to hide blocks of code from the compiler. The code in the block is only compiled if the condition is true.
It's supported in many languages, notably C and C++. It is often used to account for processor architecture and operating system differences - allowing one code-base to compile on many different platforms.
It can also be used to remove debugging/tracing code in a release build.
The condition is evaluated once at compile time, normally in an initial pass over the source code before the main compiler.
You can set those kind of conditional compilation directive for various purpose.
For example you might have an environnement for DEBUG and one for RELEASE, depending on which you wan't to compile your might not use the same functions / values.
In you case, #if !(arch(x86_64) || arch(arm64)) is to determine the architecture of your device (or simulator).
Indeed, some iDevice run 32bits and others 64bits (5S and newer). Float aren't represented the same way.
As #Martin wrote, you might not have to use this code anymore :)

Xcode 4.6, used as the name of the previous parameter rather than as part of the selector [duplicate]

This question already has answers here:
Error after upgrading to xcode 4.6 and iOS 6.1 "used as the name of the previous parameter rather than as part of the selector"
(3 answers)
Closed 10 years ago.
I'm getting the following warning from Xcode 4.6.
.. used as the name of the previous parameter rather than as part of the selector
I know I can disable this warning, but I'd rather fix it.
I have 109 such warnings, so I'm obviously writing methods badly.
Here's a couple of my methods.
+(NSString*)addFormatPrice:(double)dblPrice:(BOOL)booRemoveCurSymbol;
-(void)showHelpChoices:(UIView *)vw:(id)dg;
So, whats the correct way to write these methods ?
Your first method is declaring the selector +addFormatPrice::. With spaces, it looks like
+ (NSString *)addFormatPrice:(double)dblPrice :(BOOL)booRemoveCurSymbol;
This is invoked like [NSString addFormatPrice:0.3 :YES].
What you should do is actually give a name to the previous parameter, such as
+ (NSString *)addFormatPrice:(double)dblPrice removeCurSymbol:(BOOL)booRemoveCurSymbol;
Which would then be invoked like [NSString addFormatPrice:0.3 removeCurSymbol:YES].
Maybe you'll have an easier time understanding if you split these across several lines?
+(NSString*)addFormatPrice:(double)dblPrice
:(BOOL)booRemoveCurSymbol;
-(void)showHelpChoices:(UIView *)vw
:(id)dg;
An Objective-C method name's structure is like this:
- (returntype)firstPartOfMethodWithParameter:(type)nameOfFirstParameter secondPartOfNameWhichDescribesSecondParameter:(type)nameOfSecondParameter;
That is, the full method name is broken up, with the parameter names interspersed. The colons separate each "label" from its parameter; a space separates the parameter name from the next part of the method name.
Your methods are missing the second parts, the bits that describe the second parameters. Right now, the names of your methods are addFormatPrice:: and showHelpChoices::, both of which are legal but un-idiomatic. When you call them, it will look like this:
[Excelsior addFormatPrice:2.0 :YES];
[thumpy showHelpChoices:aView :obj];
which should make it clear that your names aren't quite right. You just need to add the labels for the second parameters:
+(NSString*)addFormatPrice:(double)dblPrice
removingCurrencySymbol:(BOOL)booRemoveCurSymbol;
-(void)showHelpChoices:(UIView *)vw
digeridoo:(id)dg;
For advice on naming Objective-C methods, you should turn to an Objective-C style guide such as Apple's coding guidelines for Cocoa. Any style guide that follows the conventions of the community and Apple's frameworks will suggest that you name your method such that the purpose of each parameter is clearly described within the method name.
+(NSString *)priceStringWithPrice:(double)price removeCurrencySymbol:(BOOL)removeCurrencySymbol
-(void)showHelpChoicesInView:(UIView *)view withSomethingWithAnUndecipherableName:(id)mysteryParameter
Notice the significant change in name to indicate what (I assume) it does in your program and what each parameter does. Your class method doesn't add anything to anything - rather it returns a new string. This makes your code blend naturally with that of other developers, Apple's frameworks, other libraries you may use, and enhances the readability greatly. Not naming your parameters degrades readability and makes maintainability far more difficult.
On a related note, unnecessary abbreviations, including Hungarian notation, are jarring and don't fit the style, and if you follow good naming practices you don't need them and will produce code that is a pleasure to maintain. So don't call it vw, call it view or viewToShowIn. Don't call it strVal call it valueString or somethingSpecificallyDescribingTheNatureOfTheValueString.
This is how you are supposed to do this
+(NSString*)addFormatPrice:(double)dblPrice removeCurSymbol:(BOOL)booRemoveCurSymbol;
-(void)showHelpChoices:(UIView *)vw whatEverThePurposeOf:(id)dg;
try to learn from Apple's example code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
for start, you can try to write your method in a sentence.
like this
applicationdidFinishLaunchingWithOptions
then, add the noun description with parameters like (UIApplication *)application and (NSDictionary *)launchOptions

When making a small open source iOS API, how do I account for ARC and non-arc users

I have seen some libraries use separate branches in their source control. One for ARC one for non-ARC. I dont see this as partical as it requires extra maintaince.
A method I thought was to use the compiler flag: (see this question)
#if __has_feature(objc_arc)
Whenever I need to use retain release etc... That way if the user has it switched on the code will automatically re-factor itself.
Is there a disadvantage of doing this way?
Is there a better way to do it?
While Dave's answer is correct, there is an alternative pattern that avoids having to maintain two memory models in your code.
Namely, compile your code with ARC required and either:
use a static library to distrubute your code; whether that static library is built by a new target in the destination project or you distribute the library itself, ARC can be turned on for the target that builds the library.
turn on ARC for just the files when added to whatever target in the target project. ARC can be turned on per-file.
In any case, mixing ARC and non-ARC code at the per-file level is fully supported and works just fine (as demonstrated by the fact that the system frameworks are almost entirely compiled non-ARC, but work fine from ARC).
That's pretty much how I do it. I also have some macros so that my code stays relatively "clean":
#if __has_feature(objc_arc)
#define DD_HAS_ARC 1
#define DD_RETAIN(_o) (_o)
#define DD_RELEASE(_o)
#define DD_AUTORELEASE(_o) (_o)
#else
#define DD_HAS_ARC 0
#define DD_RETAIN(_o) [(_o) retain]
#define DD_RELEASE(_o) [(_o) release]
#define DD_AUTORELEASE(_o) [(_o) autorelease]
#endif
With these, I can do stuff like:
return DD_AUTORELEASE(DD_RETAIN(_myIvar));
Or:
DD_RELEASE(_myIvar);
_myIvar = DD_RETAIN(newObject);
Or:
- (void)dealloc {
DD_RELEASE(_myIvar);
#if !DD_HAS_ARC
[super dealloc];
#endif
}
And then the macro expands into the correct code depending on whether I'm compiling with ARC or not.
If you are developing a static (compiled) library then you can use what ever approach you want.
Most of the difference is at compile time.
Meaning that the generated output should be the same (if you manage the memory properly in the non-ARC version).
Once you compile it, any project may use it without concerning whether your library was developed with or without ARC.
Bottom line, you may develop an ARC based library and use it in non-ARC project (and visa versa) with no problem.

Making UIBezierPath more like NSBezierPath with elementCount and elementAtIndex

When moving some Cocoa code to Cocoa Touch I was disappointed to find that UIBezierPath is missing the "Accessing Elements of a Path" methods:
– elementCount
– elementAtIndex:
– elementAtIndex:associatedPoints:
– removeAllPoints
– setAssociatedPoints:atIndex:
The only way to get at these elements in Cocoa Touch seems to be through CGPathApply. Before I try to recreate this as a subclass or category of UIBezierPath, I was wondering if this had already been done. Does anyone have an idea if something like this is already available?
I made a port on https://github.com/seivan/UIBezierPathPort but it's with Swift.
Has a test suite and documentation.
Works as of Beta 5.
Technically you should be able to use Swift on a Obj-C project.
Let me know how you like it.
I've bumped into the same problem a couple of months ago and couldn't find anything readily available back then. (Truth be told, since going the CGPathApply route wasn't that bad for my needs, I didn't look very hard to be honest).
The applier function is called for every CGPathElement in the CGPath, such an element consists of a CGPathElementType and a C-array of CGPoints.
Since a CGPathElementType is an enum with only five different values
enum CGPathElementType {
kCGPathElementMoveToPoint,
kCGPathElementAddLineToPoint,
kCGPathElementAddQuadCurveToPoint,
kCGPathElementAddCurveToPoint,
kCGPathElementCloseSubpath
};
You don't need to write that much code to do (control)point manipulation / inspection of a path. Having the same interface available would've been nice though.

Frank: Is it possible to write step definitions in Objective-C

How could I write step definitions in Objective-C? E.g.:
Given(#"^the address book is empty$", ^{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (int i = 0; i < CFArrayGetCount(people); i++) {
ABAddressBookRemoveRecord(addressBook,
CFArrayGetValueAtIndex(people, i), NULL);
}
});
The example above was derived from Rob Holland's blog post "BDD on iPhone: iCuke".
Why would I want to do such a thing? Because, as much as I love Ruby, I prefer to develop iOS apps in Objective-C and to write tests in the same language as that of the app I'm testing. Also, this would allow me to do low-level things, like erasing the address book or editing other data with Core Data.
Can I name the features directory Features with a capital "F"?
I responded to Matt's question on the Frank mailing list here
I agree; test your Objective-C applications in Objective-C. Personally, I use Cedar for this and would do it soup-to-nuts in Objective-C (no cuke), but I realize that might not be a very helpful answer. Not to hijack your thread, but did you find Frank to be any easier than Cedar to set up?
To attempt to answer your second question:
By default I think Cucumber looks for a 'features' directory. I don't know if it is case sensitive, but the fact that your asking means it probably is. You can specify the directory when you run Cucumber.
eg. a cucumber target in my Rakefile with non-standard location
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = ["--format pretty", "FunctionalTests/Frank"]
end