Objective-C
(Muhtemelen sadece Mac OS X'te clang ile derlenmişse)
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
void unusedFunction(void) {
printf("huh?\n");
exit(0);
}
int main() {
NSString *string;
string = (__bridge id)(void*)0x2A27; // Is this really valid?
NSLog(@"%@", [string stringByAppendingString:@"foo"]);
return 0;
}
@interface MyClass : NSObject
@end
@implementation MyClass
+ (void)load {
Class newClass = objc_allocateClassPair([NSValue class], "MyClass2", 0);
IMP imp = class_getMethodImplementation(self, @selector(unusedMethod));
class_addMethod(object_getClass(newClass), _cmd, imp, "");
objc_registerClassPair(newClass);
[newClass load];
}
- (void)unusedMethod {
Class class = [self superclass];
IMP imp = (IMP)unusedFunction;
class_addMethod(class, @selector(doesNotRecognizeSelector:), imp, "");
}
@end
Bu kod kullanılmayan işleve ulaşmak için birkaç püf noktası kullanır. Birincisi, 0x2A27 değeridir. Bu, bir nesnenin ayrılmasını önlemek için işaretçideki değeri kodlayan tamsayı 42 için etiketli bir işaretçidir .
Sonraki olduğunu MyClass
. Hiçbir zaman kullanılmaz, ancak çalışma zamanı +load
önceden yüklendiğinde yöntemi çağırır main
. Bu dinamik NSValue
olarak, üst sınıfı olarak kullanılan yeni bir sınıf yaratır ve kaydeder . Ayrıca , uygulama olarak 's' +load
kullanarak o sınıf için bir yöntem ekler . Kayıt olduktan sonra, yeni sınıftaki load yöntemini çağırır (nedense otomatik olarak aranmaz).MyClass
-unusedMethod
Yeni sınıfın load metodu unusedMethod
etkin olarak adlandırılan ile aynı uygulamayı kullandığından . Üst unusedFunction
sınıfını alır ve bu sınıfın doesNotRecognizeSelector:
yöntemi için bir uygulama olarak ekler . Bu yöntem başlangıçta bir örnek yöntemdi MyClass
, ancak yeni sınıfta bir sınıf yöntemi olarak adlandırılıyor self
, yeni sınıf nesnesi de öyle. Bu nedenle, süper sınıf NSValue
, bunun için de süper sınıftır NSNumber
.
Sonunda main
koşar. İşaretçi değerini alır ve bir NSString *
değişkene ( ARC ile veya ARC olmadan kullanılmasına izin veren __bridge
ilk döküm) yapışır void *
. Sonra, bu stringByAppendingString:
değişkeni aramaya çalışır . Aslında, bu yöntemi uygulamayan bir sayı olduğu için, doesNotRecognizeSelector:
bunun yerine, yöntem kullanılarak, sınıflandırma hiyerarşisi boyunca NSValue
uygulandığı yere kadar ilerleyen bir yöntem çağrılır unusedFunction
.
Not: Diğer sistemlerle uyumsuzluk, diğer uygulamalar tarafından gerçekleştirildiğine inanmadığım etiketli işaretçi kullanımından kaynaklanmaktadır. Bu normalde oluşturulmuş bir numara ile değiştirilmişse, kodun geri kalanı iyi çalışmalıdır.