目录

1. 前言   1.1

2. ObjC运行时概览   1.2

3. Runtime基础知识   1.3

4. ObjC函数和对象   1.4

1. NSObject   1.4.1

1. NSObject.h   1.4.1.1

1. 打印类的详情   1.4.1.1.1

2. NSObject-Protocol.h   1.4.1.2

2. CoreFoundation   1.4.2

3. objc系列函数   1.4.3

1. objc_init   1.4.3.1

2. objc_alloc   1.4.3.2

3. objc_alloc_init   1.4.3.3

4. objc_msgSend   1.4.3.4

1. 手动计算参数   1.4.3.4.1

2. 自己组装   1.4.3.4.2

5. objc_getClass   1.4.3.5

1. 应用举例   1.4.3.5.1

6. objc_retain   1.4.3.6

7. objc_retainBlock   1.4.3.7

8. objc_release   1.4.3.8

9. objc_autorelease   1.4.3.9

10. objc_opt_class   1.4.3.10

11. objc_storeStrong   1.4.3.11

4. object系列函数   1.4.4

1. object_getClassName   1.4.4.1

1. 应用举例   1.4.4.1.1

5. 其他心得   1.5

1. ObjC类的常用方法   1.5.1

1. isKindOfClass   1.5.1.1

2. ObjC获取Class类名   1.5.2

1. NSStringFromClass   1.5.2.1

2. class_getName   1.5.2.2

3. className   1.5.2.3

3. 获取ObjC类的父类   1.5.3

1. superclass   1.5.3.1

6. 附录   1.6

1. 参考资料   1.6.1

iOS逆向开发：ObjC运行时

- 最新版本： v0.9.6

- 更新时间： 20241026

简介

介绍iOS逆向期间常会涉及到的ObjC的底层知识Runtime运行时。以及介绍Runtime中的常遇到的各个函数和内容，包括NSObject、objc开头的系列函数，尤其是objc_msgSend函数、object开头的系列函数。

源码+浏览+下载

本书的各种源码、在线浏览地址、多种格式文件下载如下：

HonKit源码

- crifan/ios_re_objc_runtime: iOS逆向开发：ObjC运行时

如何使用此HonKit源码去生成发布为电子书

详见：crifan/honkit_template: demo how to use crifan honkit template and demo

在线浏览

- iOS逆向开发：ObjC运行时 book.crifan.org

- iOS逆向开发：ObjC运行时 crifan.github.io

离线下载阅读

- iOS逆向开发：ObjC运行时 PDF

- iOS逆向开发：ObjC运行时 ePub

- iOS逆向开发：ObjC运行时 Mobi

版权和用途说明

此电子书教程的全部内容，如无特别说明，均为本人原创。其中部分内容参考自网络，均已备注了出处。如发现有侵权，请通过邮箱联系我  admin 艾特 crifan.com ，我会尽快删除。谢谢合作。

各种技术类教程，仅作为学习和研究使用。请勿用于任何非法用途。如有非法用途，均与本人无关。

鸣谢

感谢我的老婆陈雪的包容理解和悉心照料，才使得我 crifan 有更多精力去专注技术专研和整理归纳出这些电子书和技术教程，特此鸣谢。

其他

作者的其他电子书

本人 crifan 还写了其他 150+ 本电子书教程，感兴趣可移步至：

crifan/crifan_ebook_readme: Crifan的电子书的使用说明

关于作者

关于作者更多介绍，详见：

关于CrifanLi李茂 – 在路上

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 15:05:35

ObjC运行时概览

iOS逆向时，常会涉及到一些iOS底层机制，其中就包括， ObjC 的 运行时 = Runtime 。

iOS逆向期间涉及到的很多内容，都和Runtime有关：

- 逆向技术

- Method Swizzling

- 底层就依赖于Objc的Runtime机制

- 导出头文件

- 据说底层机制就依赖于ObjC的Runtime

- 据说，如果代码换成Swift，就无法导出头文件

- 动态调试

- 可以输出类的属性和函数

- 底层就涉及到，Runtime中的 NSObject 、 isa 等内容

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 15:04:50

Runtime基础知识

此处整理iOS的ObjC的Runtime的相关基础知识。

- ObjC Runtime

- 官网文档

- Objective-C Runtime | Apple Developer Documentation

- 概述

- The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps. Objective-C runtime library support functions are implemented in the shared library found at  /usr/lib/libobjc.A.dylib .

- You typically don't need to use the Objective-C runtime library directly when programming in Objective-C. This API is useful primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging

TODO：

- 【整理】iOS运行时iOS Runtime基础知识

- 其他资料：

- Swift & the Objective-C Runtime - NSHipster

- 英文

- 中文

load

TODO：

【未解决】iOS的ObjC基础知识：load方法

objc_classlist 和 objc_nlcatlist

在 objc-file.mm 文件中存有以下定义

// 类似于 C++ 的模板写法，通过宏来处理泛型操作

// 函数内容是从内存数据段的某个区下查询该位置的情况，并回传指针

#define GETSECT(name, type, sectname)                                   \

type *name(const headerType *mhdr, size_t *outCount) {              \

return getDataSection<type>(mhdr, sectname, nil, outCount);     \

}                                                                   \

type *name(const header_info *hi, size_t *outCount) {               \

return getDataSection<type>(hi->mhdr(), sectname, nil, outCount); \

}

// 根据 dyld 对 images 的解析来在特定区域查询内存

GETSECT(_getObjc2ClassList,           classref_t,      "__objc_classlist");

GETSECT(_getObjc2NonlazyCategoryList, category_t *,    "__objc_nlcatlist");

-> 才明白：

+ (void)load

对于每一个 Class 和 Category 来说，必定会调用此方法，而且仅调用一次。当包含 Class 和 Category 的程序库载入系统时，就会执行此方法，并且此过程通常是在程序启动的时候执行

->

- __objc_classlist  ： class = Class类

- __objc_nlcatlist ： nlcat = Non Lazy Catetory = 非懒加载的Category

iOS逆向技术：Method Swizzling

iOS逆向中的一种技术叫： Method Swizzling = 方法交换 ，其底层就是利用了ObjC的Runtime的特性

TODO：

【记录】研究抖音越狱检测逻辑：iOS的ObjC的方法交换Method Swizzling

越狱检测和反越狱检测

TODO：

【已解决】iOS越狱检测和反越狱检测：iOS运行时iOS Runtime

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 14:51:38

ObjC函数和对象

此处整理iOS的ObjC的Runtime相关的函数和对象，和底层机制。

dispatch相关

dispatch_once

TODO：

【已解决】iOS基础知识：dispatch_once

SEL = objc_selector

TODO：

- 【未解决】iOS基础知识：SEL的struct objc_selector结构体的定义

- 【已解决】iOS从SEL的selector得到和打印出函数名

OS_dispatch_queue

TODO：

【已解决】iOS基础知识：OS_dispatch_queue

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 09:58:25

NSObject

TODO：

【整理】iOS逆向心得：Runtime运行时NSObject对象

此处介绍iOS的ObjC中和Runtime有关的： NSObject 类相关的内容。

- NSObject

- 概述

- NSObject是所有ObjC类的根类

- 特点

- NSObject有各个类的通用的属性和函数

NSObject的protocol定义和类本身定义

- 【已解决】iOS逆向：NSObject的定义

- 协议=Protocol

- NSObject-Protocol.h

- iOS-Header/14.5/PrivateFrameworks/CloudDocsDaemon.framework/NSObject-Protocol.h at master · xybp888/iOS-Header · GitHub

- 类=Class

- NSObject.h

- iOS-Runtime-Headers/lib/libobjc.A.dylib/NSObject.h at fbb634c78269b0169efdead80955ba64eaaa2f21 · nst/iOS-Runtime-Headers · GitHub

心得

调试时看到的类的名称和正向开发时所用的类名不一样

比如：

- 正向开发时写的类名是： NSDictionary

- 逆向调试时看到的类名是： __NSDictionaryM

具体解释，详见：

TODO：

【整理】iOS逆向心得：调试时看到的ObjC的底层数据类型和上层类型的对应关系

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 12:02:37

NSObject.h

- NSObject.h

- 源码

- iOS-Runtime-Headers/lib/libobjc.A.dylib/NSObject.h at fbb634c78269b0169efdead80955ba64eaaa2f21 · nst/iOS-Runtime-Headers · GitHub

UIKitCore

- NSObject.h （好像是）所属Framework是

- UIKitCore

- 概述：UIKitCore是iOS中的其中一个Private的Framework

- 详见

- iOS逆向：Framework动态库

- 具体位置： /System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore

NSObject.h 的内容

// Image: /System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore

+ (long long)__accessibilityGuidedAccessRestrictionStateForIdentifier:(id)arg1;

+ (bool)__accessibilityGuidedAccessStateEnabled;

+ (void)__accessibilityRequestGuidedAccessSession:(bool)arg1 completion:(id /* block */)arg2;

+ (void)_installAppearanceSwizzlesForSetter:(id)arg1;

- (id)_NSItemProviderTypeCoercion_coercedUIImageValueFromNSDataValue:(id)arg1 error:(id*)arg2;

- (id)_NSItemProviderTypeCoercion_coercedUIImageValueFromNSURLValue:(id)arg1 error:(id*)arg2;

- (id)__autorotationSanityCheckObjectFromSource:(id)arg1 selector:(SEL)arg2;

- (id)__ivarDescriptionForClass:(Class)arg1;

- (id)__methodDescriptionForClass:(Class)arg1;

- (id)__propertyDescriptionForClass:(Class)arg1;

- (id)__ui_performAsyncSelector:(SEL)arg1 type:(long long)arg2 sender:(id)arg3 completionHandler:(id /* block */)arg4;

- (void)_accessibilityFinalize;

- (void)_applyTraitStorageRecordsForTraitCollection:(id)arg1;

- (void)_connectInterfaceBuilderEventConnection:(id)arg1;

- (id)_internalAccessibilityAttributedHint;

- (id)_internalAccessibilityAttributedLabel;

- (id)_internalAccessibilityAttributedValue;

- (void)_internalSetAccessibilityAttributedHint:(id)arg1;

- (void)_internalSetAccessibilityAttributedLabel:(id)arg1;

- (void)_internalSetAccessibilityAttributedValue:(id)arg1;

- (id)_ivarDescription;

- (id)_methodDescription;

- (id)_propertyDescription;

- (void)_setTraitStorageList:(id)arg1;

- (id)_shortMethodDescription;

- (id)_traitStorageList;

- (id)_ui_descriptionBuilder;

- (void)_uikit_applyValueFromTraitStorage:(id)arg1 forKeyPath:(id)arg2;

- (id)_uikit_valueForTraitCollection:(id)arg1;

- (bool)_uikit_variesByTraitCollections;

- (bool)accessibilityActivate;

- (struct CGPoint { double x1; double x2; })accessibilityActivationPoint;

- (id)accessibilityAssistiveTechnologyFocusedIdentifiers;

- (id)accessibilityAttributedHint;

- (id)accessibilityAttributedLabel;

- (id)accessibilityAttributedValue;

- (id)accessibilityContainer;

- (long long)accessibilityContainerType;

- (id)accessibilityCustomActions;

- (id)accessibilityCustomRotors;

- (void)accessibilityDecrement;

- (id)accessibilityDragSourceDescriptors;

- (id)accessibilityDropPointDescriptors;

- (id)accessibilityElementAtIndex:(long long)arg1;

- (long long)accessibilityElementCount;

- (void)accessibilityElementDidBecomeFocused;

- (void)accessibilityElementDidLoseFocus;

- (bool)accessibilityElementIsFocused;

- (id)accessibilityElements;

- (bool)accessibilityElementsHidden;

- (struct CGRect { struct CGPoint { double x_1_1_1; double x_1_1_2; } x1; struct CGSize { double x_2_1_1; double x_2_1_2; } x2; })accessibilityFrame;

- (id)accessibilityHeaderElements;

- (id)accessibilityHint;

- (id)accessibilityIdentification;

- (id)accessibilityIdentifier;

- (void)accessibilityIncrement;

- (id)accessibilityLabel;

- (id)accessibilityLanguage;

- (id)accessibilityLocalizedStringKey;

- (long long)accessibilityNavigationStyle;

- (id)accessibilityPath;

- (bool)accessibilityPerformEscape;

- (bool)accessibilityPerformMagicTap;

- (bool)accessibilityScroll:(long long)arg1;

- (void)accessibilitySetIdentification:(id)arg1;

- (unsigned long long)accessibilityTraits;

- (id)accessibilityValue;

- (bool)accessibilityViewIsModal;

- (void)awakeFromNib;

- (id)className;

- (unsigned long long)defaultAccessibilityTraits;

- (long long)indexOfAccessibilityElement:(id)arg1;

- (bool)isAccessibilityElement;

- (bool)isAccessibilityElementByDefault;

- (bool)isElementAccessibilityExposedToInterfaceBuilder;

- (void)prepareForInterfaceBuilder;

- (void)setAccessibilityActivationPoint:(struct CGPoint { double x1; double x2; })arg1;

- (void)setAccessibilityAttributedHint:(id)arg1;

- (void)setAccessibilityAttributedLabel:(id)arg1;

- (void)setAccessibilityAttributedValue:(id)arg1;

- (void)setAccessibilityContainer:(id)arg1;

- (void)setAccessibilityContainerType:(long long)arg1;

- (void)setAccessibilityCustomActions:(id)arg1;

- (void)setAccessibilityCustomRotors:(id)arg1;

- (void)setAccessibilityDragSourceDescriptors:(id)arg1;

- (void)setAccessibilityDropPointDescriptors:(id)arg1;

- (void)setAccessibilityElements:(id)arg1;

- (void)setAccessibilityElementsHidden:(bool)arg1;

- (void)setAccessibilityFrame:(struct CGRect { struct CGPoint { double x_1_1_1; double x_1_1_2; } x1; struct CGSize { double x_2_1_1; double x_2_1_2; } x2; })arg1;

- (void)setAccessibilityHeaderElements:(id)arg1;

- (void)setAccessibilityHint:(id)arg1;

- (void)setAccessibilityIdentifier:(id)arg1;

- (void)setAccessibilityLabel:(id)arg1;

- (void)setAccessibilityLanguage:(id)arg1;

- (void)setAccessibilityNavigationStyle:(long long)arg1;

- (void)setAccessibilityPath:(id)arg1;

- (void)setAccessibilityTraits:(unsigned long long)arg1;

- (void)setAccessibilityValue:(id)arg1;

- (void)setAccessibilityViewIsModal:(bool)arg1;

- (void)setIsAccessibilityElement:(bool)arg1;

- (void)setShouldGroupAccessibilityChildren:(bool)arg1;

- (bool)shouldGroupAccessibilityChildren;

- (id)storedAccessibilityActivationPoint;

- (id)storedAccessibilityContainerType;

- (id)storedAccessibilityElementsHidden;

- (id)storedAccessibilityFrame;

- (id)storedAccessibilityNavigationStyle;

- (id)storedAccessibilityTraits;

- (id)storedAccessibilityViewIsModal;

- (id)storedIsAccessibilityElement;

- (id)storedShouldGroupAccessibilityChildren;

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 12:09:55

打印类的详情

前面提到的：NSObject.h中有我们所关注的函数：

- _ivarDescription

- _methodDescription

- _propertyDescription

- _shortMethodDescription

具体应用场景是：

- Xcode调试期间：打印ObjC类的描述详情信息

- 已知的传统手段： Xcode / lldb 中， po 加上对应命令 _ivarDescription 、 _propertyDescription 、 _methodDescription 、 shortMethodDescription

po [xxx _ivarDescription]

po [xxx _propertyDescription]

po [xxx _methodDescription]

po [xxx _shortMethodDescription]

- 新的手段：tweak插件的hook代码中，调用对应命令  _ivarDescription 、 _propertyDescription 、 _methodDescription 、 shortMethodDescription

[classObj _ivarDescription]

[classObj _propertyDescription]

[classObj _methodDescription]

[classObj _shortMethodDescription]

相关完整代码

dynamicDebug/iOSOpenDev/jailAppleAccount/jailAppleAccount/libs/iOS/HookLogiOS.m

// write string to file

void writeStrToFile(char* filePath, char* outputStr){

FILE *fp = fopen(filePath, "w");

printf("fp=%p", fp);

if(fp != NULL){

fprintf(fp, "%s", outputStr);

fclose(fp);

} else {

printf("Failed to open file %s", filePath);

}

}

// write class description string into file

void dbgWriteClsDescToFile(char* className, id classObj){

NSString* idNSStr = [classObj _ivarDescription];

NSString* pdNSStr = [classObj _propertyDescription];

NSString* mdNSStr = [classObj _methodDescription];

NSString* smdNSStr = [classObj _shortMethodDescription];

const char *idCStr = [idNSStr cStringUsingEncoding:NSUTF8StringEncoding];

const char *pdCStr = [pdNSStr cStringUsingEncoding:NSUTF8StringEncoding];

const char *mdCStr = [mdNSStr cStringUsingEncoding:NSUTF8StringEncoding];

const char *smdCStr = [smdNSStr cStringUsingEncoding:NSUTF8StringEncoding];

//    const char* smdOutputFile = "/var/root/dev/AADeviceInfo_shortMethodDescription.txt";

//    const char* smdOutputFile = "/var/mobile/AADeviceInfo_shortMethodDescription.txt";

//    const char* outputFilePath = "/var/root/dev"; // failed for no write access

const char* outputFilePath = "/var/mobile";

//    iosLogInfo("outputFilePath=%{public}s", outputFilePath);

//    const char* idOutputFile = "AADeviceInfo_ivarDescription.txt";

//    const char* pdOutputFile = "AADeviceInfo_propertyDescription.txt";

//    const char* mdOutputFile = "AADeviceInfo_methodDescription.txt";

//    const char* smdOutputFile = "AADeviceInfo_shortMethodDescription.txt";

char idFullPath[200];

char pdFullPath[200];

char mdFullPath[200];

char smdFullPath[200];

//    snprintf(idFullPath, sizeof(idFullPath), "%s/%s", outputFilePath, idOutputFile);

//    snprintf(pdFullPath, sizeof(pdFullPath), "%s/%s", outputFilePath, pdOutputFile);

//    snprintf(mdFullPath, sizeof(mdFullPath), "%s/%s", outputFilePath, mdOutputFile);

//    snprintf(smdFullPath, sizeof(smdFullPath), "%s/%s", outputFilePath, smdOutputFile);

snprintf(idFullPath, sizeof(idFullPath), "%s/%s_ivarDescription.txt", outputFilePath, className);

snprintf(pdFullPath, sizeof(pdFullPath), "%s/%s_propertyDescription.txt", outputFilePath, className);

snprintf(mdFullPath, sizeof(mdFullPath), "%s/%s_methodDescription.txt", outputFilePath, className);

snprintf(smdFullPath, sizeof(smdFullPath), "%s/%s_shortMethodDescription.txt", outputFilePath, className);

writeStrToFile(idFullPath, (char*)idCStr);

writeStrToFile(pdFullPath, (char*)pdCStr);

writeStrToFile(mdFullPath, (char*)mdCStr);

writeStrToFile(smdFullPath, (char*)smdCStr);

//    iosLogInfo("Written %s description into %s", className, outputFilePath);

}

调用：

dynamicDebug/iOSOpenDev/jailAppleAccount/jailAppleAccount/jailAppleAccount.xm

%hook AADeviceInfo

- (id)udid{

id objUdid = %orig;

iosLogInfo("objUdid=%{public}@, self=%{public}@", objUdid, self);

dbgWriteClsDescToFile("AADeviceInfo", self);

return objUdid;

}

%end

注：最新代码详见：

- HookLogiOS.m

- crifanLib.c

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 12:07:29

NSObject-Protocol.h

- NSObject-Protocol.h

- iOS-Header/14.5/PrivateFrameworks/CloudDocsDaemon.framework/NSObject-Protocol.h at master · xybp888/iOS-Header · GitHub

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 12:05:30

CoreFoundation

CoreFoundation的相关内容

// Image: /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation

+ (id)__allocWithZone_OA:(struct _NSZone { }*)arg1;

+ (id)_copyDescription;

+ (void)dealloc;

+ (id)description;

+ (void)doesNotRecognizeSelector:(SEL)arg1;

+ (id)init;

+ (id)instanceMethodSignatureForSelector:(SEL)arg1;

+ (void)load;

+ (id)methodSignatureForSelector:(SEL)arg1;

- (bool)___tryRetain_OA;

- (id)__autorelease_OA;

- (void)__dealloc_zombie;

- (oneway void)__release_OA;

- (id)__retain_OA;

- (unsigned long long)_cfTypeID;

- (id)_copyDescription;

- (id)description;

- (void)doesNotRecognizeSelector:(SEL)arg1;

- (bool)isNSArray__;

- (bool)isNSCFConstantString__;

- (bool)isNSData__;

- (bool)isNSDate__;

- (bool)isNSDictionary__;

- (bool)isNSNumber__;

- (bool)isNSObject__;

- (bool)isNSOrderedSet__;

- (bool)isNSSet__;

- (bool)isNSString__;

- (bool)isNSTimeZone__;

- (bool)isNSValue__;

- (id)methodSignatureForSelector:(SEL)arg1;

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 12:10:53

objc系列函数

此处介绍iOS的ObjC的Runtime中，常见的，以 objc 开头的一些系列函数。

其中对应官网资料就是：

- Objective-C Automatic Reference Counting (ARC) — Clang 15.0.0git documentation (llvm.org)

对应的 objc 开头的系列函数是：

- id  objc_autorelease (id value);

- void  objc_autoreleasePoolPop (void *pool);

- void * objc_autoreleasePoolPush (void);

- id  objc_autoreleaseReturnValue (id value);

- void  objc_copyWeak (id dest, id src);

- void  objc_destroyWeak (id *object);

- id  objc_initWeak (id *object, id value);

- id  objc_loadWeak (id *object);

- id  objc_loadWeakRetained (id *object);

- void  objc_moveWeak (id dest, id src);

- void  objc_release (id value);

- id  objc_retain (id value);

- id  objc_retainAutorelease (id value);

- id  objc_retainAutoreleaseReturnValue (id value);

- id  objc_retainAutoreleasedReturnValue (id value);

- id  objc_retainBlock (id value);

- void  objc_storeStrong (id *object, id value);

- id  objc_storeWeak (id *object, id value);

- id  objc_unsafeClaimAutoreleasedReturnValue (id value);

下面详细介绍部分函数：

objc_allocWithZone

- 定义

- 精简

id objc_allocWithZone(Class cls)

- 完整

OBJC_EXPORT id objc_allocWithZone(Class cls)

__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);

objc_autoreleaseReturnValue

TODO：

- 【整理】iOS逆向心得：iOS函数objc_autoreleaseReturnValue

- 【已解决】iOS逆向Xcode调试：_objc_autoreleaseReturnValue继续运行导致后续release相关代码运行不到

objc_enumerationMutation

iOS逆向期间，常会看到，伪代码中有个 objc_enumerationMutation ，其实就是表示：代码循环 而已

-》反推：正向代码中，用了 for 、 while 等循环的逻辑。

TODO：

【已解决】iOS底层函数：objc_enumerationMutation

objc_loadWeakRetained

TODO：

【未解决】Xcode的lldb中objc_loadWeakRetained传入的对象是什么类

objc_copyImageNames

TODO：

【无需解决】iOS越狱检测和反越狱检测：objc_copyImageNames

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:10:21

objc_init

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 09:49:50

objc_alloc

- objc_alloc

- 概述

- objc_alloc 是NSObject的类的分配空间，常和 objc_init 搭配使用

- 定义

id objc_alloc(Class cls)

- objc的类的alloc的主要流程

心得

alloc分配后的=新建的空的类：描述为空

IDA伪代码：

newWASignedPrekey = objc_alloc_3808((Class)&OBJC_CLASS___WASignedPrekey);

Xcode汇编代码：

0x10a6b89e4 <+88>:    bl     0x10a73b808              ; symbol stub for: objc_alloc_3808

运行后，返回值：

(lldb) reg r x0

x0 = 0x0000000280a23400

(lldb) po $x0

<object returned empty description>

即：

- alloc空的类， po 返回空的描述信息

- <object returned empty description>

不过，是可以通过class查看具体是什么类的：

(lldb) po [$x0 class]

WASignedPrekey

符合我们的期望。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 14:27:41

objc_alloc_init

- objc_alloc_init

- 函数定义

id objc_alloc_init(Class cls)

- 底层实现过程

- 先 alloc 再 init

[[xxx alloc] init]

- iOS 15 中，调试出的内部主要实现逻辑

- 先： _objc_rootAllocWithZone

- 再： [xxx init]

- 最后再去： [NSMutableArray alloc]

反汇编代码

iOS 15 中 objc_alloc_init 的反汇编代码实现：

libobjc.A.dylib`objc_alloc_init:

->  0x19cbd3c3c <+0>:  stp    x29, x30, [sp, #-0x10]!

0x19cbd3c40 <+4>:  mov    x29, sp

0x19cbd3c44 <+8>:  cbz    x0, 0x19cbd3c5c          ; <+32>

0x19cbd3c48 <+12>: ldr    x8, [x0]

0x19cbd3c4c <+16>: and    x8, x8, #0xffffffff8

0x19cbd3c50 <+20>: ldrb   w8, [x8, #0x1d]

0x19cbd3c54 <+24>: tbz    w8, #0x6, 0x19cbd3c6c     ; <+48>

0x19cbd3c58 <+28>: bl     0x19cbd0134              ; _objc_rootAllocWithZone

0x19cbd3c5c <+32>: adrp   x8, 368761

0x19cbd3c60 <+36>: ldr    x1, [x8, #0x188]

0x19cbd3c64 <+40>: ldp    x29, x30, [sp], #0x10

0x19cbd3c68 <+44>: b      0x19cbcd000              ; objc_msgSend

0x19cbd3c6c <+48>: adrp   x8, 14396

0x19cbd3c70 <+52>: add    x1, x8, #0xeda

0x19cbd3c74 <+56>: bl     0x19cbcd000              ; objc_msgSend

0x19cbd3c78 <+60>: b      0x19cbd3c5c              ; <+32>

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:03:46

objc_msgSend

TODO：

- 【未解决】IDA中如何解析objc_msgSend函数调用

- 【整理】iOS逆向和IDA使用心得：调用objc_msgSend时传递给MLPlayerItemQOEErrorEvent的initWithError:fatal:absoluteTime:的参数不够

- 【整理】iOS逆向开发心得：如何判断ObjC的objc_msgSend的参数个数

- 【已解决】Xcode的lldb调试iOS的ObjC或Swift时如何打印出objc_msgSend第一个参数是什么类的实例

- 【整理】ObjC底层函数：objc_msgSendSuper2、objc_msgSendSuper

- 【未解决】iOS逆向：如何找到objc_msgSendSuper2的第一个参数调用的是什么类

- 【基本解决】Xcode的lldb中动态调试objc_msgSend第一个参数self是哪个类

- 【未解决】研究YouTube逻辑：谁调用了_dispatch_call_block_and_release以及_pthread_wqthread

- 【整理】iOS逆向调试心得：如何找到Block的_pthread_wqthread和_dispatch_call_block_and_release的函数调用最初来源

- 【整理】iOS逆向心得：ObjC函数调用时参数顺序和汇编代码中寄存器传递的参数顺序不一致

iOS逆向中，肯定会涉及到底层的ObjC的Runtime中，最重要的一个函数： objc_msgSend

- objc_msgSend

- 是什么： iOS 的 ObjC 中的 Runtime 中，算是最重要的一个底层实现函数了

- 定义

id objc_msgSend(id self, SEL op, ...);

id objc_msgSend(id self, SEL _cmd, ...);

- 核心逻辑：Objc中所有的类的函数/属性的调用，（经过编译器编译后）底层其实都是转换成objc_msgSend方法的调用

- 核心内容

+[classOrObj someMethod: inputValue];

-[classOrObj someMethod: inputValue];

- 被翻译成：

objc_msgSend(classOrObj, @selector(someMethod:), inputValue);

- 举例

+[NSString stringWithUTF8String: "Hello Crifan"];

- 被翻译成：

objc_msgSend(NSString, @selector(stringWithUTF8String:), "Hello Crifan");

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 14:30:44

手动计算参数

此处，对于iOS逆向中，常见的：

内存中的字符串= objc_msgSend 函数的第二个参数= SEL = selector =汇编中的 x1 寄存器

此处如果是 adrp 的话，可以用如下手动方式计算出来

即：

根据 adrp ，手动计算出当前的：

char*  =  字符串  =  objc_msgSend的SEL = 函数名

举例说明：

对于：

0x1820ba250 <+24>:  adrp   x8, 302695

0x1820ba254 <+28>:  add    x1, x8, #0x99             ; =0x99

0x1820ba258 <+32>:  bl     0x1815b9dc8              ; symbol stub for: objc_msgSend

...

0x1820ba28c <+84>:  adrp   x8, 304011

0x1820ba290 <+88>:  add    x1, x8, #0xc61            ; =0xc61

...

0x1820ba298 <+96>:  bl     0x1815b9dc8              ; symbol stub for: objc_msgSend

其中的：

0x1820ba28c <+84>:  adrp   x8, 304011

-》

- 当前PC地址 = adrp指令所在地址 = 0x1820ba28c

- PC地址去4KB对齐 = PC低12位清零：

- 0x1820ba28c

- 低12位清零=16进制最低3位设置为0 -》 0x1820ba000

- 立即数左移12位：

- 304011 = 0x4A38B

- 左移12位=16进制最低位加3个0 -》 0x4A38B000

- 两者相加 = PC被4KB对齐后的地址 + 立即数左移12位后的值

- 0x1820ba000 + 0x4A38B000

- = 0x1CC445000

- x8 = 0x1CC445000

0x1820ba290 <+88>:  add    x1, x8, #0xc61            ; =0xc61

-》

- x1

- = x8 + 0xc61

- = 0x1CC445000 + 0xc61

- = 0x1CC445C61

对应内存中的字符串的值：

(lldb) po (char*)0x1CC445C61

"_initWithCFURLRequest:"

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 14:29:32

自己组装出objc_msgSend

如果了解 objc_msgSend 底层的机制的话，普通的 objc_msgSend 的函数调用，也可以自己组装=生成出来，比如：

- low-level objc runtime apis (github.com)

...

// Set up a NSString with the contents "Hello World" from a C string

Class nsstring = objc_getClass("NSString");

SEL stringUTF8sel = sel_registerName("stringWithUTF8String:");

id hello = objc_msgSend(nsstring, stringUTF8sel, "Hello World\n");

...

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 14:31:26

objc_getClass

TODO：

- 【无法解决】iOS越狱检测和反越狱检测：objc_getClass *【整理】iOS运行时Runtime：objc_getClass相关函数

hook代码

iOS逆向的动态调试时，底层写hook代码，往往会涉及到这个 objc_getClass

Class NSErrorClass = objc_getClass("NSError");

Class NSDictionaryClass = objc_getClass("NSDictionary");

// 写代码解析传入的变量，是什么类型，然后决定取出对应属性，即request url

//NSURL* getHamErrReqUrl(NSError* curError){

NSURL* getHamErrReqUrl(id erroOrDict){

NSURL* curUrl = NULL;

//    if (curError) {

if (erroOrDict) {

NSDictionary* curUserInfo = NULL;

if ([erroOrDict isKindOfClass: NSErrorClass]){

curUserInfo = [erroOrDict userInfo];

} else if ([erroOrDict isKindOfClass: NSDictionaryClass]) {

curUserInfo = (NSDictionary*)erroOrDict;

}

if (curUserInfo) {

id hamErrUrlReq = curUserInfo[@"HAMErrorURLRequest"];

if (hamErrUrlReq != NULL) {

BOOL isUrlReq = [hamErrUrlReq isKindOfClass: NSMutableURLRequestClass];

if (isUrlReq) {

curUrl = [hamErrUrlReq URL];

}

}

}

}

return curUrl;

}

心得

Xcode的lldb中用objc_getClass如何获取到类名带括号的类

对于iOS的ObjC的定义：

#import <UIKit/UIImage.h>

@interface UIImage (AWEUserRecommend)

+ (id)awe_userRecommendImageNamed:(id)arg1 compatibleWithTraitCollection:(id)arg2;

+ (id)awe_userRecommendImageNamed:(id)arg1;

@end

想要查看类 UIImage(AWEUserRecommend) 的描述（属性、函数等）

不能用：

po [objc_getClass("UIImage(AWEUserRecommend)") _shortMethodDescription]

而是改用：

po [objc_getClass("UIImage") _shortMethodDescription]

因为

类名不是叫： UIImage(AWEUserRecommend)  或  UIImage (AWEUserRecommend)

而是：

此处是 继承自 UIImage的，和AWEUserRecommend相关的类

其真正的类名，还是叫： UIImage

所以直接用：

po [objc_getClass("UIImage") _shortMethodDescription]

即可。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:18:45

应用举例

libobjc.A.dylib

0000000012664BF0        _objc_getClass    /usr/lib/libobjc.A.dylib

获取多个类

Class NSMutableURLRequestClass = objc_getClass("NSMutableURLRequest");

Class NSErrorClass = objc_getClass("NSError");

Class NSDictionaryClass = objc_getClass("NSDictionary");

Class HAMCronetDataLoadTaskClass = objc_getClass("HAMCronetDataLoadTask");

Frida调试时的 Module.findExportByName

var objc_getClass = new NativeFunction(

Module.findExportByName(null, 'objc_getClass'),

'pointer',

['pointer']

)

console.log("objc_getClass=" + objc_getClass)

AKAppleIDAuthSupportProxyImpl

Class AKAppleIDAuthSupportProxyImplClass = objc_getClass("AKAppleIDAuthSupportProxyImpl");

BSObjCBlockArgument

Class BSObjCBlockArgumentClass = objc_getClass("BSObjCBlockArgument");

__NSXPCInterfaceProxy_AKAppleIDAuthenticationDaemonProtocol

id AuthDaemonProtocolProxy = objc_getClass("__NSXPCInterfaceProxy_AKAppleIDAuthenticationDaemonProtocol");

AASignInFlowController

(lldb) po [objc_getClass("AASignInFlowController") _shortMethodDescription]

<AASignInFlowController: 0x1f19cb2e0>:

in AASignInFlowController:

...

ACAccount

(lldb) po [objc_getClass("ACAccount") _shortMethodDescription]

<ACAccount: 0x1f0973718>:

...

@property (copy, nonatomic, setter=aa_setPassword:) NSString* aa_password;

...

- (id) aa_password; (0x192622320)

NSMutableURLRequest

(lldb) po objc_getClass("NSMutableURLRequest")

NSMutableURLRequest

(lldb) po objc_getClass("NSMutableURLRequest(AppleAccount)")

nil

和：

(lldb) po [objc_getClass("NSMutableURLRequest") _shortMethodDescription]

<NSMutableURLRequest: 0x1f0916f10>:

in NSMutableURLRequest:

Class Methods:

+ (int) hashForPlayerID:(id)arg1; (0x1ab494e78)

...

和：

+ (id)HAMErrorWithCode:(long long)arg1 userInfo:(id)arg2{

id hamewc_au = %orig;

iosLogInfo("arg1=%lld,userInfo=%@ -> hamewc_au=%@", arg1, arg2, hamewc_au);

id hamEur = arg2[@"HAMErrorURLRequest"];

if (hamEur != NULL) {

Class urlClass = objc_getClass("NSMutableURLRequest");

BOOL isUrlReq = [hamEur isKindOfClass: urlClass];

if (isUrlReq) {

NSURL *curUrl = [hamEur URL];

if (isYoutubeAdsVideo(curUrl)){

iosLogInfo("is ads video: urlStr=%@", curUrl);

}

}

}

return hamewc_au;

}

UIDevice

(lldb) po [objc_getClass("UIDevice") _shortMethodDescription]

...

+ (id) networkType:(BOOL)arg1; (0x10ebbbc78)

+ (void) clearTid; (0x10ebbc554)

+ (id) tid; (0x10ebbc43c)

+ (id) currentVersion; (0x10ebbc758)

+ (id) networkType; (0x10ebbbbd4)

+ (id) userAgent; (0x10ebbaf34)

+ (id) imsi; (0x10ebbb74c)

+ (id) osVersion; (0x10ebbb830)

+ (id) udid; (0x10ebbc260)

+ (id) imei; (0x10ebbb6e4)

+ (id) clientKey; (0x10ebbb7a4)

+ (id) wifiInterface; (0x10ebbba4c)

和：

(lldb) po [objc_getClass("UIDevice") _shortMethodDescription]

2022-03-28 14:18:09.536479+0800 Aweme[39046:2680735] hook_dyld.xm _NSGetExecutablePath: buf=(null),*bufsize=96 -> extPathCpSize=-1

2022-03-28 14:18:09.536697+0800 Aweme[39046:2680735] hook_dyld.xm _NSGetExecutablePath: buf=/private/var/containers/Bundle/Application/B9FB3ACC-61E5-4030-B89C-C9FF71822F6E/Aweme.app/Aweme,*bufsize=96 -> extPathCpSize=0

[39046:28419:0328/141743.229303:ERROR:ssl_client_socket_impl.cc(1018)] handshake failed; returned -1, SSL error code 1, net_error -100

2022-03-28 14:18:09.604818+0800 Aweme[39046:2680736] hook_misc.xm NSBundle$bundlePath: origBundlePath=/usr/lib

<UIDevice: 0x1dfc62a88>:

in UIDevice:

Class Methods:

+ (void) tspk_preload; (0x11401a864)

+ (BOOL) isPoorthaniPhone6s; (0x113d8d760)

+ (id) deviceMachineModel; (0x113d8d6e0)

...

BSObjCBlockArgument

Class BSObjCBlockArgumentClass = objc_getClass("BSObjCBlockArgument");

%hookf(id, objc_alloc_init, Class cls){

id newObj = %orig;

bool shouldOmit = false;

if (newObj == nil) {

shouldOmit = true;

} else {

shouldOmit = [newObj isKindOfClass: BSObjCBlockArgumentClass];

}

if (shouldOmit) {

iosLogInfo("cls=%{public}@", cls);

} else {

iosLogInfo("cls=%{public}@, newObj=%{public}@", cls, newObj);

}

return newObj;

}

NSURLSessionTask

(lldb) po [objc_getClass("NSURLSessionTask") _shortMethodDescription]

<NSURLSessionTask: 0x1db04c418>:

in NSURLSessionTask:

...

- (void) updateCurrentRequest:(id)arg1; (0xd451b481820be210)

...

(NSObject ...)

__NSCFLocalSessionTask

(lldb) po [objc_getClass("__NSCFLocalSessionTask") _shortMethodDescription]

<__NSCFLocalSessionTask: 0x1db04b130>:

in __NSCFLocalSessionTask:

...

(NSURLSessionTask ...)

(lldb) po [objc_getClass("NSURLSessionTask") _shortMethodDescription]

<NSURLSessionTask: 0x1db04c418>:

in NSURLSessionTask:

...

(NSObject ...)

和：

(lldb) po objc_getClass("__NSCFLocalSessionTask")

__NSCFLocalSessionTask

(lldb) po [objc_getClass("__NSCFLocalSessionTask") _shortMethodDescription]

<__NSCFLocalSessionTask: 0x1db04b130>:

in __NSCFLocalSessionTask:

Properties:

@property (retain) __NSCFURLSessionConnection* cfConn;  (@synthesize cfConn = _cfConn;)

@property (readonly) unsigned long hash;

@property (readonly) Class superclass;

@property (readonly, copy) NSString* description;

@property (readonly, copy) NSString* debugDescription;

Instance Methods:

- (BOOL) _needSendingMetrics; (0xcb62020182126ffc)

- (void) set_timeoutIntervalForResource:(double)arg1; (0x8330f881820edfac)

- (void) _onqueue_needConnectedSocketToHost:(id)arg1 port:(unsigned long)arg2 withCompletion:(^block)arg3; (0xec7a7a81821274d0)

- (void) _didSendMetrics; (0xe7713281820970a8)

- (void) _onqueue_needNewBodyStream:(id)arg1 withCompletion:(^block)arg2; (0x7d19ae0182127aac)

- (void) _askForConnectedSocketLater; (0x464f6f0182127174)

- (void) _onqueue_didSendBodyBytes:(long)arg1 totalBytesSent:(long)arg2 totalBytesExpectedToSend:(long)arg3; (0x46279c8182127440)

- (void) _onqueue_didReceiveResponse:(id)arg1 completion:(^block)arg2; (0x6c56be8182128364)

- (void) _onqueue_willSendRequestForEstablishedConnection:(id)arg1 withCompletion:(^block)arg2; (0x8341b28182127510)

- (void) _onqueue_expectedProgressTargetChanged; (0x739ef01821272cc)

- (void) connection:(id)arg1 didReceiveTCPConnection:(struct shared_ptr<TransportConnection>)arg2 extraBytes:(id)arg3; (0x452b338182126294)

- (void) _onqueue_completeInitialization; (0x40183981820a8368)

- (void) connection:(id)arg1 waitingWithReason:(long)arg2; (0x47404d018209c934)

- (id) _onqueue_strippedMutableRequest; (0xac30cb0182096124)

- (void) _onqueue_connectionWaitingWithReason:(long)arg1; (0x86127501820ef240)

- (void) connection:(id)arg1 challenged:(id)arg2 authCallback:(^block)arg3; (0x3e299f818212697c)

- (void) set_TLSMaximumSupportedProtocolVersion:(unsigned short)arg1; (0x9e501c0182127014)

- (void) _onqueue_cancel_with_error:(id)arg1; (0xa249fa818209c808)

- (id) cfConn; (0x200b80182096b98)

- (void) startResourceTimer; (0x2c288e0182102810)

- (void) dealloc; (0x9f3d55018209f020)

- (void) _task_onqueue_didFinish; (0x8b18df018209b804)

- (void) _onqueue_didReceiveChallenge:(id)arg1 request:(id)arg2 withCompletion:(^block)arg3; (0x2d6fa20182127c80)

- (void) _onqueue_didReceiveResponse:(id)arg1 redirectRequest:(id)arg2 withCompletion:(^block)arg3; (0x7d5f4c0182127d5c)

- (void) setCfConn:(id)arg1; (0x101dc581820a7544)

- (void) connection:(id)arg1 willCacheResponse:(id)arg2 responseCallback:(^block)arg3; (0x4925940182126b64)

- (void) _onqueue_willCacheResponse:(id)arg1 withCompletion:(^block)arg2; (0xa257eb0182127bdc)

- (void) _onqueue_setupNextEffectiveConfigurationWithCompletionHandler:(^block)arg1; (0xb1070201820da7c0)

- (void) _task_onqueue_didReceiveDispatchData:(id)arg1 completionHandler:(^block)arg2; (0x2f187c0182127acc)

- (void) _setConnectionCacheKey:(void*)arg1; (0x90318a81820dfea0)

- (void) _onqueue_conditionalRequirementsChanged:(BOOL)arg1; (0x745cb601821274f4)

- (void) _onqueue_didReceiveDispatchData:(id)arg1 completion:(^block)arg2; (0x403100818210379c)

- (id) .cxx_construct; (0xdf2cb201820ac9a8)

- (void) didReceiveInformationalResponse:(id)arg1; (0x263dad8182127214)

- (void) connection:(id)arg1 wasRedirected:(id)arg2 newRequest:(id)arg3 responseCallback:(^block)arg4; (0x490e8c8182126e6c)

- (id) error:(id)arg1 code:(long)arg2; (0x764ad8818209d410)

- (id) resourceTimeoutError; (0x194506018212716c)

- (void) cancel_with_error:(id)arg1; (0xeb40d781820ebfc0)

- (void) _private_onqueue_didReceiveResponseDisposition:(long)arg1 completion:(^block)arg2; (0x1c5fe301820ee1a8)

- (void) connection:(id)arg1 sentBodyBytes:(id)arg2 totalBytes:(id)arg3 expectedBytes:(id)arg4; (0x8e66eb8182126768)

- (void) connection:(id)arg1 _conditionalRequirementsChanged:(BOOL)arg2; (0x9b6afe81821265dc)

- (void) _onqueue_suspend; (0x696304018212733c)

- (void) connection:(id)arg1 didReceiveSocketInputStream:(id)arg2 outputStream:(id)arg3; (0x13147181821264a8)

- (void) _onqueue_adjustBytesPerSecondLimit:(long)arg1; (0xc642a401820cb594)

- (void) connection:(id)arg1 _willSendRequestForEstablishedConnection:(id)arg2 completion:(^block)arg3; (0xbd707e81821266ac)

- (void) connection:(id)arg1 needConnectedSocketToHost:(id)arg2 port:(unsigned long)arg3 completion:(^block)arg4; (0x121d9a01821261d8)

- (void) _onSessionQueue_disavow; (0x2d108281820b31a8)

- (void) connectionWillFinishLoading:(id)arg1; (0xa4315f81820985ec)

- (void) connection:(id)arg1 didFinishLoadingWithError:(id)arg2; (0x9b13df0182096da4)

- (void) _onqueue_adjustPriorityHint:(float)arg1 incremental:(BOOL)arg2; (0x614e3981821072f0)

- (void) connection:(id)arg1 request:(id)arg2 needsNewBodyStreamCallback:(^block)arg3; (0x5023a80182126a84)

- (void) _onqueue_resume; (0x1a17170182093ee0)

- (id) initWithOriginalRequest:(id)arg1 ident:(unsigned long)arg2 taskGroup:(id)arg3; (0x33449081820d1200)

- (void) connection:(id)arg1 didReceiveResponse:(id)arg2 completion:(^block)arg3; (0xce3ea90182126c20)

- (void) connection:(id)arg1 didReceiveData:(id)arg2 completion:(^block)arg3; (0x6a146c818210aa14)

- (void) _onqueue_didFinishWithError:(id)arg1; (0x8579f2018209b34c)

- (void) set_TLSMinimumSupportedProtocolVersion:(unsigned short)arg1; (0x2a6c6e81820fc554)

- (void) _onqueue_cancel; (0xca661b81821273d4)

- (void) _onqueue_adjustLoadingPoolPriority; (0x76776b0182127330)

- (void) _onqueue_adjustPoolPriority; (0x9a775b01821056f0)

- (void) .cxx_destruct; (0x1673e40182097d60)

- (id) initWithBackgroundTaskInfo:(id)arg1 taskGroup:(id)arg2; (0xfe63a08182128374)

(NSURLSessionTask ...)

NSURLRequest

(lldb) po [objc_getClass("NSURLRequest") _shortMethodDescription]

<NSURLRequest: 0x1db68ffb8>:

in NSURLRequest:

Class Methods:

+ (id) safari_nonAppInitiatedRequestWithURL:(id)arg1; (0x19c71ba04)

+ (id) sl_urlRequestWithToken:(id)arg1 forURLString:(id)arg2; (0x1ba629030)

+ (id) wlk_requestWithURL:(id)arg1 httpMethod:(id)arg2 httpBody:(id)arg3 httpHeaders:(id)arg4 cachePolicy:(unsigned long)arg5 timeout:(double)arg6; (0x1bce5172c)

+ (id) wlk_requestWithURL:(id)arg1 httpMethod:(id)arg2 httpHeaders:(id)arg3 cachePolicy:(unsigned long)arg4 timeout:(double)arg5; (0x1bce5db9c)

+ (void) setAllowsSpecificHTTPSCertificate:(id)arg1 forHost:(id)arg2; (0x1828e4340)

+ (id) requestWithURL:(id)arg1 cachePolicy:(unsigned long)arg2 timeoutInterval:(double)arg3; (0x100d8c344)

+ (BOOL) supportsSecureCoding; (0x182705ee0)

+ (id) allowsSpecificHTTPSCertificateForHost:(id)arg1; (0x18274b6b8)

+ (void) setAllowsAnyHTTPSCertificate:(BOOL)arg1 forHost:(id)arg2; (0x100d8cb08)

+ (BOOL) allowsAnyHTTPSCertificateForHost:(id)arg1; (0x100d8ca2c)

+ (double) defaultTimeoutInterval; (0x1828e3c64)

+ (void) setDefaultTimeoutInterval:(double)arg1; (0x1828e3c74)

+ (id) requestWithURL:(id)arg1; (0x100d8bcb4)

Properties:

@property (readonly, nonatomic) NSDictionary* ams_cookies;

@property (readonly, nonatomic) BOOL ams_requestIsBagLoad;

@property (readonly, copy) NSString* HTTPMethod;

@property (readonly, copy) NSDictionary* allHTTPHeaderFields;

@property (readonly, copy) NSData* HTTPBody;

@property (readonly, retain) NSInputStream* HTTPBodyStream;

@property (readonly) BOOL HTTPShouldHandleCookies;

@property (readonly) BOOL HTTPShouldUsePipelining;

@property (readonly) void* _inner;

@property (readonly, copy) NSURL* URL;

@property (readonly) unsigned long cachePolicy;

@property (readonly) double timeoutInterval;

@property (readonly, copy) NSURL* mainDocumentURL;

@property (readonly) unsigned long networkServiceType;

@property (readonly) BOOL allowsCellularAccess;

@property (readonly) BOOL allowsExpensiveNetworkAccess;

@property (readonly) BOOL allowsConstrainedNetworkAccess;

@property (readonly) BOOL assumesHTTP3Capable;

@property (readonly) unsigned long attribution;

Instance Methods:

- (BOOL) ak_usesHTTPSScheme; (0x1949fef0c)

- (id) aa_HTTPBody; (0x194aea7b4)

- (id) body; (0x18649c274)

- (id) ams_cookies; (0x18649c484)

- (id) ams_valueForHTTPHeader:(id)arg1; (0x1860a5440)

- (BOOL) ams_requestIsBagLoad; (0x1860d5e3c)

- (id) DARequestByApplyingStorageSession:(struct __CFURLStorageSession*)arg1; (0x19fd45d70)

- (id) safari_requestBySettingIsNonAppInitiated:(BOOL)arg1; (0x19c75f0d8)

- (id) initWithXPCEncoding:(id)arg1; (0x194f6d810)

- (id) copyXPCEncoding; (0x194f6d80c)

- (id) ic_valueForHTTPHeaderField:(id)arg1; (0x1994f63e4)

- (id) ic_valuesForCookieWithName:(id)arg1; (0x1994f6178)

- (BOOL) allowsExpensiveNetworkAccess; (0x1828e3b14)

- (const struct __CFURL*) cfURL; (0x18271a284)

- (id) init; (0x182722e14)

- (void) dealloc; (0x1826d8b90)

- (unsigned long) cachePolicy; (0x1826d9420)

- (double) timeoutInterval; (0x1826f430c)

- (id) HTTPMethod; (0x1826edaa8)

- (BOOL) _ignoreHSTS; (0x1826ed60c)

- (id) HTTPBodyStream; (0x18272d438)

- (id) initWithURL:(id)arg1 cachePolicy:(unsigned long)arg2 timeoutInterval:(double)arg3; (0x100d8c6b8)

- (id) mutableCopyWithZone:(struct _NSZone*)arg1; (0x1826d40ec)

- (BOOL) _URLHasScheme:(id)arg1; (0x18273dfac)

- (BOOL) _isIdempotent; (0x1828e3d38)

- (id) HTTPReferrer; (0x1828e3ed4)

- (BOOL) allowsCellularAccess; (0x1826fccc4)

- (id) contentDispositionEncodingFallbackArray; (0x18270ec34)

- (struct _CFURLRequest*) _CFURLRequest; (0x1826ea308)

- (id) HTTPUserAgent; (0x1828e3ec0)

- (id) _initWithInternal:(id)arg1; (0x1826d6b0c)

- (id) _propertyForKey:(id)arg1; (0x1826ff158)

- (id) _startTimeoutDate; (0x182749c38)

- (BOOL) _schemeWasUpgradedDueToDynamicHSTS; (0x1826e4300)

- (BOOL) _isSafeRequestForBackgroundDownload; (0x18270d3dc)

- (id) allHTTPHeaderFields; (0x1826f0d7c)

- (void) _removePropertyForKey:(id)arg1; (0x1828e3b6c)

- (id) _copyReplacingURLWithURL:(id)arg1; (0x1828e3b78)

- (double) _timeWindowDelay; (0x1827299f4)

- (id) _allHTTPHeaderFieldsAsArrays; (0x1828e3f48)

- (id) HTTPContentType; (0x1828e3f34)

- (id) HTTPExtraCookies; (0x1828e3ee8)

- (unsigned long) expectedWorkload; (0x1828e3df0)

- (BOOL) _isNonAppInitiated; (0x1828e3a60)

- (BOOL) allowsConstrainedNetworkAccess; (0x1828e3b40)

- (double) _payloadTransmissionTimeout; (0x1828e3dcc)

- (void) _setProperty:(id)arg1 forKey:(id)arg2; (0x1826f7c20)

- (BOOL) assumesHTTP3Capable; (0x1828e3ae8)

- (BOOL) _preventHSTSStorage; (0x1826face0)

- (id) URL; (0x1826d68d0)

- (BOOL) _needsNetworkTrackingPrevention; (0x1828e3a8c)

- (BOOL) _requiresShortConnectionTimeout; (0x1826f0cb4)

- (BOOL) HTTPShouldHandleCookies; (0x1826fbbd0)

- (BOOL) HTTPShouldUsePipelining; (0x1828e3e14)

- (id) initWithURL:(id)arg1; (0x100d8bffc)

- (unsigned long) attribution; (0x1828e3ac4)

- (void) encodeWithCoder:(id)arg1; (0x1826ff18c)

- (void*) _inner; (0x1826d43a4)

- (BOOL) isEqual:(id)arg1; (0x1828e3c88)

- (id) description; (0x18270bb98)

- (id) copyWithZone:(struct _NSZone*)arg1; (0x1828e3c84)

- (unsigned long) networkServiceType; (0x18270b828)

- (id) initWithCoder:(id)arg1; (0x18272e070)

- (id) mainDocumentURL; (0x182705ef8)

- (id) _initWithCFURLRequest:(struct _CFURLRequest*)arg1; (0x18270f3f4)

- (unsigned long) hash; (0x1828e3cf8)

- (id) valueForHTTPHeaderField:(id)arg1; (0x1826d7e6c)

- (id) _trackerContext; (0x1828e3a3c)

- (BOOL) _isKnownTracker; (0x1828e3a98)

- (id) boundInterfaceIdentifier; (0x182726f54)

- (id) HTTPBody; (0x1826d43d0)

- (double) _timeWindowDuration; (0x182732910)

(NSObject ...)

IBARevealProtocol

def getRevealServerProtocolVersion(self):

expression = "(int)[objc_getClass(\"IBARevealProtocol\") protocolVersion]"

return self.frame.EvaluateExpression(expression, GetCommonExpressionOptions()).signed

YTIAdBreakRequest

(lldb) expr id $adbreakClass = (id)objc_getClass("YTIAdBreakRequest")

(lldb) po $adbreakClass

YTIAdBreakRequest

和：

expr YTIAdBreakRequest* $adbreakObj = (YTIAdBreakRequest*)[objc_getClass("YTIAdBreakRequest") parseFromData: newHttpBodyData]

(lldb) po $adbreakObj

2022-10-17 11:57:55.875251+0800 YouTube[21038:2204921] hook_ youtubeReqResp.xm YTIInnerTubeContext$descriptor: curDesc=<GPBDescriptor: 0x2803e7a40>

<YTIAdBreakRequest 0x28613d960>: {

context {

client {

hl: "zh-CN"

gl: "CN"

carrier_geo: "CN"

device_make: "Apple"

device_model: "iPhone9,1"

client_name: IOS

client_version: "17.08.2"

os_name: "iOS"

os_version: "13.3.1.17D50"

screen_width_points: 375

screen_height_points: 667

screen_pixel_density: 2

client_form_factor: SMALL_FORM_FACTOR

window_width_points: 375

window_height_points: 667

connection_type: CONN_WIFI

...

YTIContentPlaybackContext

(lldb) po [[objc_getClass("YTIContentPlaybackContext") descriptor] fields]

<__NSArrayM 0x280cfd8f0>(

<GPBFieldDescriptor: 0x28392f430>,

<GPBFieldDescriptor: 0x28392f480>,

<GPBFieldDescriptor: 0x28392f4d0>,

<GPBFieldDescriptor: 0x28392f520>,

...

<GPBFieldDescriptor: 0x2839540f0>,

<GPBFieldDescriptor: 0x283954140>,

<GPBFieldDescriptor: 0x283954190>

)

YTIClientInfo

(lldb) po [[objc_getClass("YTIClientInfo") descriptor] fields]

<__NSArrayM 0x2817da910>(

<GPBFieldDescriptor: 0x283b95f90>,

<GPBFieldDescriptor: 0x283b95f40>,

<GPBFieldDescriptor: 0x283b95ef0>,

...

<GPBFieldDescriptor: 0x283b92bc0>,

<GPBFieldDescriptor: 0x283b92c10>,

<GPBFieldDescriptor: 0x283b92c60>

)

GPBMessage

(lldb) po objc_getClass("GPBMessage")

GPBMessage

和：加了临时变量的

expr id $protoClass = (id)objc_getClass("GPBMessage")

(lldb) po $protoClass

GPBMessage

和：继续调用函数 parseFromData

(lldb) po [objc_getClass("GPBMessage") parseFromData: neGpbwData]

<GPBMessage 0x282bc4460>: {

# --- Unknown fields ---

1: "com.google.ssoauth#com.google.ios.youtube"

2: 430166894

4: "com.google.ios.youtube"

5: 1661306181

6: 0x19A3D36E

}

MLServerABRDataLoadTask

%hook HAMCronetDataLoadTask

- (void)startWithDelegate:(id)arg1 delegateQueue:(id)arg2{

iosLogInfo("arg1=%@,delegateQueue=%@", arg1, arg2);

Class MLServerABRDataLoadTaskClass = objc_getClass("MLServerABRDataLoadTask");

BOOL isABRClass = [arg1 isKindOfClass: MLServerABRDataLoadTaskClass];

if(isABRClass) {

iosLogInfo("MLServerABRDataLoadTask: arg1=%@,delegateQueue=%@", arg1, arg2);

}

%orig;

}

%end

和：

Class MLServerABRDataLoadTaskClass = objc_getClass("MLServerABRDataLoadTask");

bool isMLServerABRDataLoadTaskClass(id curObj){

bool isABRClass = [curObj isKindOfClass: MLServerABRDataLoadTaskClass];

return isABRClass;

}

- (void)dataLoadTask:(id)arg1 didReceiveData:(id)arg2{

if(isMLServerABRDataLoadTaskClass(arg1)) {

NSURLRequest* request = [arg1 request];

NSURL* reqUrl = [request URL];

if (isYoutubeAdsVideo_ctier(reqUrl)){

iosLogInfo("isYoutubeAdsVideo_ctier: arg1=%@, didReceiveData=%@", arg1, arg2);

gNoUse = 1;

}

} else{

gNoUse = 1;

}

%orig;

}

IESLiveDeviceInfo

(lldb) po [objc_getClass("IESLiveDeviceInfo") _shortMethodDescription]

<IESLiveDeviceInfo: 0x105fb1bc0>:

in IESLiveDeviceInfo:

Class Methods:

+ (unsigned long) ieslive_defaultSupportOrientation; (0x10d8bffcc)

+ (long) ieslive_defaultPreferredInterfaceOrientation; (0x10d8c0020)

+ (id) carrierMCCMNC; (0x10c9f9060)

+ (BOOL) shouldUseCanOpenURLMethod; (0x10c9f9158)

+ (id) developmentNumber; (0x10c9f91d8)

+ (unsigned long) defaultSupportOrientation; (0x10c9f927c)

+ (long) defaultPreferredInterfaceOrientation; (0x10c9f9284)

+ (long) defaultPreferredInterfaceOrientationForLandscapeMode; (0x10c9f928c)

+ (id) deviceType; (0x10c9f8f0c)

+ (id) MACAddress; (0x10c9f8f20)

(NSObject ...)

AWEAPMManager

(lldb) po [objc_getClass("AWEAPMManager") _shortMethodDescription]

<AWEAPMManager: 0x1061df680>:

in AWEAPMManager:

Class Methods:

+ (void) setPerformanceUploadHost:(id)arg1; (0x10aefa058)

+ (void) attchFilter:(id)arg1 forKey:(id)arg2; (0x113f630b0)

+ (void) attachInfo:(id)arg1 forKey:(id)arg2; (0x10b0ee530)

+ (void) enableInternalNetworkRequest:(BOOL)arg1; (0x10af0d3b8)

+ (void) setupInformationWithCustomHandler:(^block)arg1; (0x10aef40b4)

+ (void) trackerSessionDidChange:(id)arg1; (0x113f631c0)

+ (BOOL) enableToutiaoAPM; (0x10af0506c)

+ (id) signInfo; (0x113f63288)

+ (void) setupInformation; (0x113f62f18)

+ (id) sharedInstance; (0x10aef44f4)

+ (void) start; (0x10af05024)

+ (void) setUserID:(id)arg1; (0x10af00224)

+ (void) setUserName:(id)arg1; (0x10af00274)

Instance Methods:

- (void) bytedSettingDidChange; (0x113f63150)

- (id) init; (0x10aef4568)

- (void) dealloc; (0x113f63044)

(NSObject ...)

和：

(lldb) po [objc_getClass("AWEAPMManager") signInfo]

2022-06-21 15:05:16.241786+0800 Aweme[76410:6169642] hook_misc.xm NSBundle$pathForResource$ofType$: name=embedded, ext=mobileprovision -> resPath=/private/var/containers/Bundle/Application/BE37087C-4861-4FEA-AD61-82FED979134B/Aweme.app/embedded.mobileprovision

AppStore

CheckMethodSwizzle

...

@implementation HookProtect

BOOL CheckMethodSwizzle(const char* className, char *selName) {

Dl_info info;

IMp imp = class_getMethodImplementation(objc_getclass(className), sel_registerName(selName));

...

getHamErrReqUrl

Class NSMutableURLRequestClass = objc_getClass("NSMutableURLRequest");

Class NSErrorClass = objc_getClass("NSError");

Class NSDictionaryClass = objc_getClass("NSDictionary");

//NSURL* getHamErrReqUrl(NSError* curError){

NSURL* getHamErrReqUrl(id erroOrDict){

NSURL* curUrl = NULL;

//    if (curError) {

if (erroOrDict) {

NSDictionary* curUserInfo = NULL;

if ([erroOrDict isKindOfClass: NSErrorClass]){

curUserInfo = [erroOrDict userInfo];

} else if ([erroOrDict isKindOfClass: NSDictionaryClass]) {

curUserInfo = (NSDictionary*)erroOrDict;

}

if (curUserInfo) {

id hamErrUrlReq = curUserInfo[@"HAMErrorURLRequest"];

if (hamErrUrlReq != NULL) {

BOOL isUrlReq = [hamErrUrlReq isKindOfClass: NSMutableURLRequestClass];

if (isUrlReq) {

curUrl = [hamErrUrlReq URL];

}

}

}

}

return curUrl;

}

AWEAppSettings

(lldb) po objc_getClass("AWEAppSettings")

AWEAppSettings

AWEFriendsWidgetsColorSchemeResolutionResult

(lldb) po [objc_getClass("AWEFriendsWidgetsColorSchemeResolutionResult") _shortMethodDescription]

<AWEFriendsWidgetsColorSchemeResolutionResult: 0x10596a158>:

in AWEFriendsWidgetsColorSchemeResolutionResult:

Class Methods:

+ (id) successWithResolvedFriendsWidgetsColorScheme:(long)arg1; (0x11124c3a0)

+ (id) confirmationRequiredWithFriendsWidgetsColorSchemeToConfirm:(long)arg1; (0x11124c3d8)

(INEnumResolutionResult ...)

UIImage

(lldb) po [objc_getClass("UIImage") _shortMethodDescription]

<UIImage: 0x1fc9f33e8>:

in UIImage:

Class Methods:

...

+ (id) awe_userRecommendImageNamed:(id)arg1; (0x114d06fcc)

+ (id) awe_userRecommendImageNamed:(id)arg1 compatibleWithTraitCollection:(id)arg2; (0x114d06fdc)

AWEUserRecommend

(lldb) po objc_getClass("UIImage(AWEUserRecommend)")

nil

(lldb) po [objc_getClass("UIImage(AWEUserRecommend)") _shortMethodDescription]

nil

(lldb) po [objc_getClass("UIImage") _shortMethodDescription]

<UIImage: 0x1fc9f33e8>:

in UIImage:

Class Methods:

+ (id) yy_imageWithColor:(id)arg1; (0x10a74a560)

+ (id) yy_imageWithColor:(id)arg1 size:(struct CGSize)arg2; (0x10aad5334)

...

- (BOOL) isFromStatusBarImageProvider; (0x1b81c15a4)

(NSObject ...)

AWEPlayInteractionFollowSuccessElement

(lldb) po [objc_getClass("AWEPlayInteractionFollowSuccessElement") _shortMethodDescription]

2022-04-02 13:36:53.128548+0800 Aweme[45939:3543378] hook_misc.xm NSBundle$bundlePath: origBundlePath=/usr/lib

<AWEPlayInteractionFollowSuccessElement: 0x10629ab90>:

in AWEPlayInteractionFollowSuccessElement:

Properties:

@property (retain, nonatomic) AWEAntiAddictedNoticeBarView* antiAddictedNoticeBarView;  (@synthesize antiAddictedNoticeBarView = _antiAddictedNoticeBarView;)

...

- (BOOL) appear; (0x10b00f010)

(NSObject ...)

YTAdVideoPlayerOverlayViewController

(lldb) po [objc_getClass("YTAdVideoPlayerOverlayViewController") _shortMethodDescription]

<YTAdVideoPlayerOverlayViewController: 0x10c030f50>:

in YTAdVideoPlayerOverlayViewController:

...

- (void) setMediaTime:(double)arg1; (0x1065e627c)

YTPlaybackData

(lldb) po [objc_getClass("YTPlaybackData") _shortMethodDescription]

<YTPlaybackData: 0x1085737c0>:

in YTPlaybackData:

Class Methods:

+ (id) playbackDataWithPlayerResponse:(id)arg1 CPN:(id)arg2; (0x1032d8060)

+ (id) playbackDataWithAd:(id)arg1; (0x102b2a228)

+ (id) playbackDataWithPlayerResponse:(id)arg1; (0x1032d8050)

Properties:

@property (readonly, nonatomic) YTPlayerResponse* playerResponse;  (@synthesize playerResponse = _playerResponse;)

@property (readonly, nonatomic) YTPlaybackData* trailer;  (@synthesize trailer = _trailer;)

@property (readonly, nonatomic) MLVideo* video;  (@synthesize video = _video;)

@property (readonly, nonatomic, getter=isPlayableInBackground) BOOL playableInBackground;

@property (readonly, nonatomic) YTCPN* CPN;  (@synthesize CPN = _CPN;)

@property (readonly, nonatomic, getter=isPlayable) BOOL playable;

Instance Methods:

- (id) CPN; (0x1032d8724)

- (BOOL) isPlayableInBackground; (0x1032d866c)

- (id) trailer; (0x1032d8714)

- (id) initWithPlayerResponse:(id)arg1 CPN:(id)arg2; (0x1032d80d8)

- (void) .cxx_destruct; (0x1032d872c)

- (BOOL) isPlayable; (0x1032d865c)

- (id) video; (0x1032d871c)

- (id) playerResponse; (0x1032d870c)

(NSObject ...)

IESECSettingRegisterHandler

(lldb) po [objc_getClass("IESECSettingRegisterHandler") _shortMethodDescription]

<IESECSettingRegisterHandler: 0x105f689a8>:

in IESECSettingRegisterHandler:

Properties:

@property (retain, nonatomic) NSValue* handlerPointer;  (@synthesize handlerPointer = _handlerPointer;)

@property (nonatomic) BOOL registed;  (@synthesize registed = _registed;)

Instance Methods:

- (id) handlerPointer; (0x10ad936fc)

- (void) setHandlerPointer:(id)arg1; (0x10ad9364c)

- (BOOL) registed; (0x10ad93704)

- (void) setRegisted:(BOOL)arg1; (0x10ad93644)

- (void) .cxx_destruct; (0x116319b18)

(NSObject ...)

MDXSession

(lldb) po [objc_getClass("MDXSession") _shortMethodDescription]

<MDXSession: 0x10151cb40>:

in MDXSession:

Class Methods:

+ (BOOL) hasExpectedDisconnectReasonFromError:(id)arg1; (0x100d8db6c)

Properties:

@property (nonatomic) long connectionState;  (@synthesize connectionState = _connectionState;)

...

YTWatchController

(lldb) po [objc_getClass("YTWatchController") _shortMethodDescription]

<YTWatchController: 0x10150ba70>:

in YTWatchController:

Class Methods:

+ (id) observerProtocol; (0x100af8960)

Properties:

@property (retain, nonatomic) YTWatchViewController* watchViewController;  (@synthesize watchViewController = _watchViewController;)

CHLoadClass_

CHLoadClass_(0xe0f8, objc_getClass("NSBundle"));

CHLoadClass_(0xe104, objc_getClass("UIDevice"));

CHLoadClass_(0xe110, objc_getClass("NSDictionary"));

CHLoadClass_(0xe11c, objc_getClass("MMCrashReportExtLogMgr"));

CHLoadClass_(0xe128, objc_getClass("JailBreakHelper"));

CHLoadClass_(0xe134, objc_getClass("ASIdentifierManager"));

YTSingleVideoCurrentTimeObserver

(lldb) po [objc_getClass("YTSingleVideoCurrentTimeObserver") _shortMethodDescription]

nil

MDXSingleVideoController

(lldb) po [objc_getClass("MDXSingleVideoController") _shortMethodDescription]

<MDXSingleVideoController: 0x105337920>:

in MDXSingleVideoController:

Properties:

@property (readonly, nonatomic) YTPlayerResponse* playerResponse;  (@synthesize playerResponse = _playerResponse;)

@property (readonly) unsigned long hash;

@property (readonly) Class superclass;

@property (readonly, copy) NSString* description;

@property (readonly, copy) NSString* debugDescription;

@property (readonly, nonatomic) YTPlaybackData* playbackData;

...

MDXPlaybackController

(lldb) po [objc_getClass("MDXPlaybackController") _shortMethodDescription]

<MDXPlaybackController: 0x105337830>:

in MDXPlaybackController:

Properties:

@property (readonly, nonatomic) MDXSingleVideoController* activeVideoController;  (@synthesize activeVideoController = _activeVideoController;)

@property (readonly) unsigned long hash;

...

YTWatchStateController

(lldb) po [objc_getClass("YTWatchStateController") playerTimeEntityUpdateThreshold]

<YTColdConfig: 0x2805644e0>

MoreView

void __cdecl -[MoreView doJailbreakProChange:](MoreView *self, SEL a2, id a3)

{

...

v21 = (void *)objc_getClass(&qword_1004CBB98);

YTAppDelegate

(lldb) po [objc_getClass("YTAppDelegate") _shortMethodDescription]

<YTAppDelegate: 0x1010bf730>:

in YTAppDelegate:

Properties:

@property (readonly, nonatomic) YTQuickActionsController* quickActionsController;  (@synthesize quickActionsController = _quickActionsController;)

@property (readonly, nonatomic) <YTResponderRoot>* responderRoot;  (@synthesize responderRoot = _responderRoot;)

...

AWELaunchTimeTracker

(lldb) po [objc_getClass("AWELaunchTimeTracker") _shortMethodDescription]

<AWELaunchTimeTracker: 0x10394cca8>:

in AWELaunchTimeTracker:

Class Methods:

+ (id) sharedInstance; (0x1088ff5c0)

Properties:

@property (nonatomic) BOOL dylibTrackerEnable;  (@synthesize dylibTrackerEnable = _dylibTrackerEnable;)

@property (copy, nonatomic) ^block shouldShowAwesomeSplashHandler;  (@synthesize shouldShowAwesomeSplashHandler = _shouldShowAwesomeSplashHandler;)

@property (copy, nonatomic) ^block detailAwesomeSplashHandler;  (@synthesize detailAwesomeSplashHandler = _detailAwesomeSplashHandler;)

@property (copy, nonatomic) ^block launchFromHandler;  (@synthesize launchFromHandler = _launchFromHandler;)

@property (copy, nonatomic) ^block isStartUpFirstTimeBlock;  (@synthesize isStartUpFirstTimeBlock = _isStartUpFirstTimeBlock;)

@property (copy, nonatomic) ^block isAppVersionUpdatedBlock;  (@synthesize isAppVersionUpdatedBlock = _isAppVersionUpdatedBlock;)

@property (copy, nonatomic) ^block shouldCollectProcessInfoHandler;  (@synthesize shouldCollectProcessInfoHandler = _shouldCollectProcessInfoHandler;)

@property (copy, nonatomic) ^block extraParamsHandler;  (@synthesize extraParamsHandler = _extraParamsHandler;)

@property (copy, nonatomic) ^block didCollectLaunchDetailHandler;  (@synthesize didCollectLaunchDetailHandler = _didCollectLaunchDetailHandler;)

Instance Methods:

- (void) p_collectDataIfNeeded; (0x1089dc760)

- (BOOL) dylibTrackerEnable; (0x1088ffd88)

- (void) p_collectProcessDetail; (0x1089dc2a8)

...

AWEPremainDelayInitTask

(lldb) po [objc_getClass("AWEPremainDelayInitTask") _ivarDescription]

2022-02-23 14:22:02.644841+0800 Aweme[34024:2559237] XPC connection interrupted

<AWEPremainDelayInitTask: 0x103c80470>:

in AWEPremainDelayInitTask:

in NSObject:

isa (Class): AWEPremainDelayInitTask (isa, 0x103c80498)

和：

(lldb) po [objc_getClass("AWEPremainDelayInitTask") _shortMethodDescription]

<AWEPremainDelayInitTask: 0x103c80470>:

in AWEPremainDelayInitTask:

Class Methods:

+ (void) stubForCheck; (0x110f957fc)

+ (void) execute; (0x1089c6910)

Properties:

@property (readonly) unsigned long hash;

@property (readonly) Class superclass;

@property (readonly, copy) NSString* description;

@property (readonly, copy) NSString* debugDescription;

(NSObject ...)

和：等了很多秒后：

(lldb) po [objc_getClass("AWEPremainDelayInitTask") _methodDescription]

<AWEPremainDelayInitTask: 0x103c80470>:

in AWEPremainDelayInitTask:

Class Methods:

+ (void) stubForCheck; (0x110f957fc)

+ (void) execute; (0x1089c6910)

Properties:

@property (readonly) unsigned long hash;

@property (readonly) Class superclass;

@property (readonly, copy) NSString* description;

@property (readonly, copy) NSString* debugDescription;

in NSObject:

Class Methods:

+ (BOOL) bdp_swizzleClass:(Class)arg1 selector:(SEL)arg2 swizzledClass:(Class)arg3 swizzledSelector:(SEL)arg4; (0x1089af3f4)

+ (BOOL) bdp_swizzleOriginInstanceMethod:(SEL)arg1 withHookInstanceMethod:(SEL)arg2; (0x1143e67f8)

+ (BOOL) bdp_swizzleOriginClassMethod:(SEL)arg1 withHookClassMethod:(SEL)arg2; (0x1143e6814)

+ (BOOL) ts_swizzleInstanceMethod:(SEL)arg1 with:(SEL)arg2; (0x1089c8c40)

+ (id) ts_className; (0x11436fc6c)

...

TTMacroManager

(lldb) po [objc_getClass("TTMacroManager") _shortMethodDescription]

<TTMacroManager: 0x103ed6e48>:

in TTMacroManager:

Class Methods:

+ (BOOL) isBDWEBIMAGE_APP_EXTENSIONS; (0x1144d256c)

+ (BOOL) isDebug; (0x108b03b3c)

(NSObject ...)

MetaSec和appID相关内容

(lldb) po [objc_getClass("CJPayMetaSecService") _shortMethodDescription]

nil

(lldb) po [objc_getClass("CJPayMetaSecManager") _shortMethodDescription]

<CJPayMetaSecManager: 0x105bbda98>:

in CJPayMetaSecManager:

Class Methods:

+ (id) defaultService; (0x10b55a464)

+ (void) registerProtocol; (0x10b55a43c)

Properties:

@property (retain, nonatomic) <CJMetaSecDelegate>* delegate;  (@synthesize delegate = _delegate;)

@property (readonly) unsigned long hash;

@property (readonly) Class superclass;

@property (readonly, copy) NSString* description;

@property (readonly, copy) NSString* debugDescription;

Instance Methods:

- (void) reportForSceneType:(long)arg1; (0x10b55a4dc)

- (void) i_registerMetaSecDelegate:(id)arg1; (0x10b55a644)

- (void) reportForScene:(id)arg1; (0x10b55a58c)

- (id) delegate; (0x10b55a67c)

- (void) setDelegate:(id)arg1; (0x10b55a684)

- (void) .cxx_destruct; (0x10b55a690)

(NSObject ...)

(lldb) po [objc_getClass("PodsDummy_Pods_MetaSecML") _shortMethodDescription]

<PodsDummy_Pods_MetaSecML: 0x105d4a3d0>:

in PodsDummy_Pods_MetaSecML:

(NSObject ...)

(lldb) po [objc_getClass("BytedCertMetaSecDelegate") _shortMethodDescription]

nil

AWECloudJailBreakUtility

(lldb) po [objc_getClass("AWECloudJailBreakUtility") _shortMethodDescription]

<AWECloudJailBreakUtility: 0x103f43000>:

in AWECloudJailBreakUtility:

Class Methods:

+ (int) urlCheck; (0x1093124ac)

+ (int) cydiaCheck; (0x1093124b8)

+ (int) inaccessibleFilesCheck; (0x109312554)

+ (int) plistCheck; (0x1093127f0)

+ (int) processesCheck; (0x109312908)

+ (int) fstabCheck; (0x109312af8)

+ (int) symbolicLinkCheck; (0x109312b5c)

+ (int) filesExistCheck; (0x109312bcc)

+ (id) runningProcesses; (0x109312c7c)

+ (int) jailbroken; (0x1093122f0)

(NSObject ...)

和：

(lldb) po [objc_getClass("AWECloudJailBreakUtility") _methodDescription]

<AWECloudJailBreakUtility: 0x103f43000>:

in AWECloudJailBreakUtility:

Class Methods:

+ (int) urlCheck; (0x1093124ac)

+ (int) cydiaCheck; (0x1093124b8)

+ (int) inaccessibleFilesCheck; (0x109312554)

+ (int) plistCheck; (0x1093127f0)

+ (int) processesCheck; (0x109312908)

+ (int) fstabCheck; (0x109312af8)

+ (int) symbolicLinkCheck; (0x109312b5c)

+ (int) filesExistCheck; (0x109312bcc)

+ (id) runningProcesses; (0x109312c7c)

+ (int) jailbroken; (0x1093122f0)

in NSObject:

Class Methods:

+ (BOOL) bdp_swizzleClass:(Class)arg1 selector:(SEL)arg2 swizzledClass:(Class)arg3 swizzledSelector:(SEL)arg4; (0x108eef3f4)

+ (BOOL) bdp_swizzleOriginInstanceMethod:(SEL)arg1 withHookInstanceMethod:(SEL)arg2; (0x1149267f8)

+ (BOOL) bdp_swizzleOriginClassMethod:(SEL)arg1 withHookClassMethod:(SEL)arg2; (0x114926814)

+ (BOOL) ts_swizzleInstanceMethod:(SEL)arg1 with:(SEL)arg2; (0x108f08c40)

+ (id) ts_className; (0x1148afc6c)

+ (BOOL) ts_swizzleClassMethod:(SEL)arg1 with:(SEL)arg2; (0x1148afb50)

+ (Class) hg_class; (0x11441af44)

+ (id) hg_cast:(id)arg1 warnOnFailure:(BOOL)arg2; (0x11441af50)

+ (BOOL) hg_swizzleClass:(Class)arg1 selector:(SEL)arg2 swizzledClass:(Class)arg3 swizzledSelector:(SEL)arg4; (0x11441a998)

+ (BOOL) hg_swizzleOriginInstanceMethod:(SEL)arg1 withHookInstanceMethod:(SEL)arg2; (0x11441aa64)

+ (BOOL) hg_swizzleOriginClassMethod:(SEL)arg1 withHookClassMethod:(SEL)arg2; (0x11441aa80)

...

- (id) forwardingTargetForSelector:(SEL)arg1; (0x102d28640)

- (id) mutableCopy; (0x1ad73f878)

- (void) finalize; (0x1ad75d700)

和：另外一种写法：

(lldb) expression -l objc -O -- [objc_getClass("AWECloudJailBreakUtility") performSelector:@selector(_methodDescription)]

<AWECloudJailBreakUtility: 0x103f43000>:

in AWECloudJailBreakUtility:

Class Methods:

+ (int) urlCheck; (0x1093124ac)

...

ViewController

...

static __attribute__((constructor)) void myinit() {

Class targetClass = objc_getClass("ViewController");

MSHookMessageEx(targetClass,@selector(clickMe:),(IMP)&newMethodImp,(IMP*)&originMethodImp);

MSHookFunction(open, newopen, &oldopen);

}

SBLockScreenViewControllerBase

...

static __attribute__((constructor)) void _logosLocalInit() {

{Class _logos_class$_ungrouped$SBLockScreenViewControllerBase = objc_getClass("SBLockScreenViewControllerBase"); { MSHookMessageEx(_logos_class$_ungrouped$SBLockScreenViewControllerBase, @selector(viewDidLoad), (IMP)&_logos_method$_ungrouped$SBLockScreenViewControllerBase$viewDidLoad, (IMP*)&_logos_orig$_ungrouped$SBLockScreenViewControllerBase$viewDidLoad);}} }

#line 40 "Tweak.x"

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:48:53

objc_retain

- objc_retain

- 定义

id objc_retain(id obj)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:07:50

objc_retainBlock

- objc_retainBlock

- 概述

- objc_retainBlock 是和ObjC中的 Block 相关的函数

- 和ARC中的引用计数中相关

- 定义

id objc_retainBlock(id value);

- 常用逻辑=常用流程

- Block初始化时，往往都是_NSConcreteStackBlock = Stack=栈 上的，然后被objc_retainBlock，从Stack上，copy拷贝到了 Heap堆上 NSConcreteMallocBlock

- 即：在栈上创建block结构体对象，然后再通过Block_copy复制到堆上，然后把堆上的对象注册到自动释放池autoreleasepool中，同时返回这个堆上的对象

代码和实现

- 底层实现

- 其实往往就是 Block_copy

- 代码

//

// The -fobjc-arr flag causes the compiler to issue calls to objc_{retain/release/autorelease/retain_block}

//

id objc_retainBlock(id x) {

#if ARR_LOGGING

objc_arr_log("objc_retain_block", x);

++CompilerGenerated.blockCopies;

#endif

return (id)_Block_copy(x);

}

- 相关源码

- runtime/objc-arr.mm

- 离线下载

- https://opensource.apple.com/tarballs/objc4/objc4-493.9.tar.gz

- 在线浏览

- https://opensource.apple.com/source/objc4/objc4-493.9/runtime/objc-arr.mm.auto.html

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:13:00

objc_release

- objc_release

- 定义

void objc_release(id obj)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:08:26

objc_autorelease

- objc_autorelease

- 定义

id objc_autorelease(id obj)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:08:55

objc_opt_class

- objc_opt_class

- 概述： iOS 的 ObjC 的（内置 内部）函数， ObjC 中  [somObj class] 的内部具体实现用 objc_opt_class

- 具体实现原理：其实就是获取类，如果参数是对象则返回类，如果是类就返回类

- The compiler translates  [SomeClass class]  method calls into a call to that function (when targeting the new OS). That function has a fast path when +class isn't overridden, improving performance and code size. Other objcopt* functions are similar.

- iOS版本： iOS 13.0+

定义

- objc-internal.h

OBJC_EXPORT Class _Nullable

objc_opt_class(id _Nullable obj)

OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);

具体实现

RetVal/objc-runtime: A debuggable objc runtime (github.com)

// Calls [obj class]

Class

objc_opt_class(id obj)

{

#if __OBJC2__

if (slowpath(!obj)) return nil;

Class cls = obj->getIsa();

if (fastpath(!cls->hasCustomCore())) {

return cls->isMetaClass() ? obj : cls;

}

#endif

return ((Class(*)(id, SEL))objc_msgSend)(obj, @selector(class));

}

可以看出：

在  __OBJC2__  中主要是通过  getIsa()  获取对象所属的 class，然后根据所属 cls 是否是  meta class  返回不同的 class。 如果是元类，则返回类对象本身，否则返回该对象所属的类。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-14 11:01:45

objc_storeStrong

- 定义

void objc_storeStrong(id *object, id value);

- 说明

- Precondition: object is a valid pointer to a __strong object which is adequately aligned for a pointer. value is null or a pointer to a valid object.

- Performs the complete sequence for assigning to a __strong object of non-block type [*]. Equivalent to the following code:

- 代码实现

void objc_storeStrong(id *object, id value) {

id oldValue = *object;

value = [value retain];

*object = value;

[oldValue release];

}

- This does not imply that a __strong object of block type is an invalid argument to this function. Rather it implies that an objc_retain and not an objc_retainBlock operation will be emitted if the argument is a block.

相关理解：

- 在 Objective-C 中，对象的引用关系由引用修饰符来决定，如 __strong 、 __weak 、 __autorelease 等等，编译器会根据不同的修饰符生成不同逻辑的代码来管理内存。

- 在 MRC 时代 Retain 修饰符将会使被引用的对象引用计数 +1

- 在 ARC 中 __strong 修饰符作为其替代者

在正向开发写代码，在给 __strong 变量赋值时

obj = otherObj;

内部其实会调用对应的 runtime 的函数：

// 会变成如下函数调用

objc_storeStrong(&obj, otherObj);

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 09:52:36

object系列函数

此处介绍iOS的ObjC的Runtime中，常见的，以 object 开头的一些系列函数。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 09:55:15

object_getClassName

TODO：

- 【已解决】iOS逆向心得：object_getClassName获取类名__NSDictionaryM是什么意思

iOS逆向的动态调试，有时会用到： object_getClassName

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:20:05

应用举例

MLOnesieRequestContext

- 用lldb调试时，想要查看第一个参数是什么类：

(lldb) reg r x0

x0 = 0x000000028195ccc0

(lldb) po 0x000000028195ccc0

10764012736

(lldb) po (char*)object_getClassName(0x000000028195ccc0)

"MLOnesieRequestContext"

YTGLUILabel

(lldb) reg r x9 x10

x9 = 0x000000010a43a000  (void *)0x000000010a509788: YTGLUILabel

x10 = 0x0000000109375578  @"partid"

(lldb) po 0x000000010a43a000

4467171328

(lldb) po (char*)0x000000010a43a000

"\x88\x97P\n\U00000001"

(lldb) po object_getClassName(0x000000010a43a000)

0x00000001086535b5

(lldb) po (char*)object_getClassName(0x000000010a43a000)

"YTGLUILabel"

MonkeyDev 的 LLDBTools.m

NSString* choose(const char* classname){

NSMutableString* result = [NSMutableString new];

NSArray* results = choose_inner(classname);

[result appendFormat:@"Find %lu instance objects in memory!\n" , (unsigned long)results.count];

for (id item in results) {

[result appendFormat:@"<%s: 0x%llx>\n", object_getClassName(item), (long long)item];

}

return result;

}

__NSDictionaryI

_objc_msgSend(<AWEOnlineABTestManager: 0x283244ce0>, "abTestData”)

查看返回值：

(lldb) reg r x0

x0 = 0x0000000128900000

(lldb) po (char*)object_getClassName(0x0000000128900000)

"__NSDictionaryI"

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:20:42

其他心得

iOS Runtime Header

可以查询和搜索iOS运行时的头文件的网站：

https://developer.limneos.net/

ObjC Runtime源码

- objc4 = Objc = ObjC Runtime

- 下载

- https://opensource.apple.com/tarballs/objc4/

- 在线浏览

- https://opensource.apple.com/source/objc4/

- 常用版本

- https://opensource.apple.com/source/objc4/objc4-750/

- https://opensource.apple.com/source/objc4/objc4-818.2/

具体例子：

- objc_retainAutoreleasedReturnValue + objc_autoreleaseReturnValue

- https://opensource.apple.com/source/objc4/objc4-532.2/runtime/NSObject.mm

- objc_retainBlock

- 相关源码：runtime/objc-arr.mm

- 离线下载

- https://opensource.apple.com/tarballs/objc4/objc4-493.9.tar.gz

- 在线浏览

- https://opensource.apple.com/source/objc4/objc4-493.9/runtime/objc-arr.mm.auto.html

- objc_alloc

- https://opensource.apple.com/source/objc4/objc4-646/runtime/objc-internal.h

OBJC_EXPORT id objc_alloc(Class cls)

__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);

OBJC_EXPORT id objc_allocWithZone(Class cls)

__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);

- objc_loadWeakRetained

- https://opensource.apple.com/source/objc4/objc4-706/runtime/NSObject.mm.auto.html

可调试的objc runtime代码

看到一个经过别人整理，是可以运行和调试的objc runtime的代码：

RetVal/objc-runtime: A debuggable objc runtime (github.com)

如果以后需要，可以去尝试去编译和运行和调试

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:19:01

ObjC类的常用方法

- ObjC类的常用方法

- 获取Class名字=类名

- 概述

- NSStringFromClass(someClass)  =>  NSString*

- class_getName(someClass)  =>  const char*

- [someInstance className]  =>  NSString*

- object_getClassName(someId)  =>  const char*

- 详解

- ObjC获取Class类名

- 获取父类

- 概述

- [xxx superclass]

- class_getSuperclass(xxx)

- 详解

- 获取ObjC类的父类

- 获取Class

- 适用于=输入是： char *

- objc_getClass

- 定义：

id objc_getClass(const char *name);

- 含义

- 传入参数：字符串=类名

- 返回值： Class

- 举例

- 举例1

(lldb) po object_getClass("YTNetworkRequestTrackerImpl")

0x00000004654e5458

- 举例2

(lldb) expr id $protoClass = (id)objc_getClass("GPBMessage")

(lldb) po $protoClass

GPBMessage

- 举例3

(lldb) po [objc_getClass("GPBMessage") parseFromData: newHttpBodyData]

<GPBMessage 0x287b4f4d0>: {

# --- Unknown fields ---

1: "\n\233\022\n\005zh-CN\022\002CNR\002CNb\005Applej\tiPhone9,1\200\001\005\212\001\007

...

- 举例4

Class LSApplicationProxy_class = object_getClass(@"LSApplicationProxy");

- 适用于=输入是：id

- object_getClass

- 定义：

Class object_getClass(id obj);

- 含义

- 传入参数：obj可能是instance对象、class对象、meta-class对象

- 返回值

- 如果是instance对象，返回class对象

- 如果是class对象，返回meta-class对象

- 如果是meta-class对象，返回NSObject（基类）的meta-class对象

- 适用于=输入是：Instance=Object

- class属性

- 用法：

[obj class]

- 返回： Class

- 判断是否是某个类

- 适用于=输入是： Instance = Object

- isKindOfClass

- 定义

- 针对 NSObject 的：

- (BOOL)isKindOfClass:(Class)aClass;

- 用法

BOOL isSameClass = [someObjcInstance isKindOfClass: SomeClass]

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:06:54

isKindOfClass

应用举例

AuthDaemonProtocolProxy

%hook NSXPCConnection

- (id)remoteObjectProxyWithErrorHandler:(void (^)(NSError *error))handler{

id rmtObjPrx = %orig;

iosLogInfo("rmtObjPrx=%{public}@", rmtObjPrx);

BOOL isAuthDaemonProtocol = [rmtObjPrx isKindOfClass: AuthDaemonProtocolProxy];

if (isAuthDaemonProtocol) {

gNoUse = 1;

}

return rmtObjPrx;

}

%end

NSHTTPURLResponse

- (void)_unsafe_provisionAnisetteWithCompletion:(void (^)(BOOL, NSError *))completion {

...

[session beginDataTaskWithRequest:request completionHandler:^(NSData *data, NSHTTPURLResponse *response, NSError *error) {

...

if (![response isKindOfClass:[NSHTTPURLResponse class]]) {

和：

static CFURLResponseRef createCFURLResponseFromResponseData(CFDataRef responseData)

{

...

if (![response isKindOfClass:[NSHTTPURLResponse class]])

_shortMethodDescription

(lldb) po [0x0000000120427c80 _shortMethodDescription]

<__NSCFLocalDataTask: 0x120427c80>:

in __NSCFLocalDataTask:

Instance Methods:

- (void) _onqueue_didReceiveResponse:(id)arg1 completion:(^block)arg2; (0x5c30dd01820f43dc)

- (BOOL) isKindOfClass:(Class)arg1; (0xda4fcc81820974fc)

(__NSCFLocalSessionTask ...)

NSURL

=========== [*] Detected call to: -[NSURL isKindOfClass:]

argSelStr:  isKindOfClass:

argCount:  1

和：

/* TID 0x103 */

5609 ms  -[NSURL _cfTypeID]

5611 ms  -[NSURL path]

5611 ms     | -[NSURL _cfurl]

7203 ms  -[NSURL isEqual:0x2806e07e0]

7203 ms     | -[NSURL isKindOfClass:0x1f2270158]

7203 ms     | -[NSURL _cfurl]

7203 ms     | -[NSURL _cfurl]

7203 ms  -[NSURL _cfTypeID]

YTAdBreakRendererFetcher

void __cdecl -[YTAdBreakRendererFetcher makeAdRequestWithAdBreak:contentPlayerResponse:responseBlock:playbackContext:clientPlaybackNonce:midrollIndex:liveTargetingParams:adBreakLength:autonavSettingState:currentMediaTime:retryEnabled:](YTAdBreakRendererFetcher *self, SEL a2, id a3, id a4, id a5, id a6, id a7, signed __int64 a8, id inputLiveTargetingParams, double inputBreakLength, int a11, double a12, bool retryEnabled)

{

...

if ( objc_msgSend_3E84298(v21, "isKindOfClass:", v27) & 1 )

NSError

id __cdecl +[NSError HAMErrorWithURLResponse:userInfo:request:](NSError_meta *self, SEL a2, id a3, id a4, id a5)

{

...

if ( (unsigned int)objc_msgSend(v8, "isKindOfClass:", v16) )

errorWithDomain

+ (id) errorWithDomain:(id)arg1 code:(long)arg2 userInfo:(id)arg3{

id newError = %orig;

iosLogInfo("errDomain=%@,code=%ld, userInfo=%@ -> newError=%@", arg1, arg2, arg3, newError);

if (arg2 >= 6000) {

iosLogInfo("YouTube related error: %@", newError);

id errUrlReq = arg3[@"HAMErrorURLRequest"];

if (errUrlReq != NULL) {

Class urlReqClass = objc_getClass("NSMutableURLRequest");

BOOL isUrlReq = [errUrlReq isKindOfClass: urlReqClass];

if (isUrlReq) {

NSURL *reqUrl = [errUrlReq URL];

//            if (isYoutubeAdsVideo(reqUrl)){

//                iosLogInfo("is ads video: reqUrl=%@", reqUrl);

if (isYoutubeAdsVideo_ctierA(reqUrl)){

iosLogInfo("is ctier=A ads video: reqUrl=%@", reqUrl);

}

//            }

}

}

}

return newError;

}

HAMErrorWithCode

+ (id)HAMErrorWithCode:(long long)arg1 userInfo:(id)arg2{

id hamewc_au = %orig;

iosLogInfo("arg1=%lld,userInfo=%@ -> hamewc_au=%@", arg1, arg2, hamewc_au);

id hamEur = arg2[@"HAMErrorURLRequest"];

if (hamEur != NULL) {

Class urlClass = objc_getClass("NSMutableURLRequest");

BOOL isUrlReq = [hamEur isKindOfClass: urlClass];

if (isUrlReq) {

NSURL *curUrl = [hamEur URL];

if (isYoutubeAdsVideo(curUrl)){

iosLogInfo("is ads video: urlStr=%@", curUrl);

if (isYoutubeAdsVideo_ctierA(curUrl)){

iosLogInfo("is ctier=A ads video: urlStr=%@", curUrl);

}

}

}

}

return hamewc_au;

}

TTInstallUtil

__text:00000000092EC444 ; id __cdecl +[TTInstallUtil onTheFlyParameter](TTInstallUtil_meta *self, SEL)

__text:00000000092EC444 __TTInstallUtil_onTheFlyParameter_      ; DATA XREF: __objc_const:00000000005F3588↑o

...

__text:00000000092ECD30                 MOV             X2, X0

__text:00000000092ECD34                 ADRP            X8, #isKindOfClass_@PAGE

__text:00000000092ECD38                 LDR             X1, [X8,#isKindOfClass_@PAGEOFF] ; char *

UIStatusBarDataNetworkItemView

-(void)networktype{

NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews];

NSNumber *dataNetworkItemView = nil;

for (id subview in subviews) {

if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {

dataNetworkItemView = subview;

break;

}

}

...

AWEPremainDelayInitTask

(lldb) po [objc_getClass("AWEPremainDelayInitTask") _methodDescription]

<AWEPremainDelayInitTask: 0x103c80470>:

in AWEPremainDelayInitTask:

Class Methods:

+ (void) stubForCheck; (0x110f957fc)

+ (void) execute; (0x1089c6910)

Properties:

@property (readonly) unsigned long hash;

@property (readonly) Class superclass;

@property (readonly, copy) NSString* description;

@property (readonly, copy) NSString* debugDescription;

in NSObject:

Class Methods:

+ (BOOL) bdp_swizzleClass:(Class)arg1 selector:(SEL)arg2 swizzledClass:(Class)arg3 swizzledSelector:(SEL)arg4; (0x1089af3f4)

...

+ (id) performSelector:(SEL)arg1 withObject:(id)arg2 withObject:(id)arg3; (0x1bda92b48)

+ (BOOL) isKindOfClass:(Class)arg1; (0x1bda75df8)

+ (BOOL) isMemberOfClass:(Class)arg1; (0x1bda92a74)

...

UIStatusBar_Modern

NSArray *infoArray = nil;

id statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];

if ([statusBar isKindOfClass:NSClassFromString(@"UIStatusBar_Modern")]) {

infoArray = [[[statusBar valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews];

} else {

infoArray = [[statusBar valueForKey:@"foregroundView"] subviews];

}

UIStatusBarServiceItemView

- (IBAction)statusCarrierBtnClicked:(UIButton *)sender {

NSArray *infoArray = [[[[UIApplication sharedApplication] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];

NSString *serviceString = @"?";

for (id info in infoArray)

{

if ([info isKindOfClass:NSClassFromString(@"UIStatusBarServiceItemView")])

{

serviceString = [info valueForKeyPath:@"serviceString"];

NSLog(@"公司为：%@", serviceString);

}

}

_statusServiceStrLbl.text = serviceString;

}

XCUIApplication.class

+ (int)writeXmlWithRootElement:(id<FBElement>)root

indexPath:(nullable NSString *)indexPath

elementStore:(nullable NSMutableDictionary *)elementStore

includedAttributes:(nullable NSSet<Class> *)includedAttributes

writer:(xmlTextWriterPtr)writer

{

...

XCElementSnapshot *currentSnapshot;

NSArray<XCElementSnapshot *> *children;

if ([root isKindOfClass:XCUIElement.class]) {

XCUIElement *element = (XCUIElement *)root;

NSMutableArray<NSString *> *snapshotAttributes = [NSMutableArray array];

if (nil != includedAttributes) {

for (Class includedAttribute in includedAttributes) {

[snapshotAttributes addObjectsFromArray:[includedAttribute performSelector:@selector(internalNames)]];

}

// Element types should always be there to build XML tree nodes

// Duplicates in this array are OK, since insternally it is anyway

// flattened to a set

[snapshotAttributes addObject:FB_ElementTypeAttributeName];

}

if ([snapshotAttributes containsObject:FB_XCAXAIsVisibleAttributeName]

|| 0 == snapshotAttributes.count) {

// If the app is not idle state while we retrieve the visiblity state

// then the snapshot retrieval operation might freeze and time out

[element.application fb_waitUntilSnapshotIsStable];

}

if ([root isKindOfClass:XCUIApplication.class]) {

currentSnapshot = element.fb_cachedSnapshot ?: element.fb_lastSnapshot;

...

FBClassNameToken.class

- WebDriverAgent/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m

+ (nullable FBClassChain*)compiledQueryWithTokenizedQuery:(NSArray<FBBaseClassChainToken *> *)tokenizedQuery originalQuery:(NSString *)originalQuery error:(NSError **)error

{

...

NSMutableArray<FBAbstractPredicateItem *> *predicates = [NSMutableArray array];

for (FBBaseClassChainToken *token in tokenizedQuery) {

if ([token isKindOfClass:FBClassNameToken.class]) {

if (isTypeSet) {

NSString *description = [NSString stringWithFormat:@"Unexpected token '%@'. The type name can be set only once.", token.asString];

*error = [self.class compilationErrorWithQuery:originalQuery description:description];

return nil;

}

@try {

chainElementType = [FBElementTypeTransformer elementTypeWithTypeName:token.asString];

isTypeSet = YES;

} @catch (NSException *e) {

if ([e.name isEqualToString:FBInvalidArgumentException]) {

NSString *description = [NSString stringWithFormat:@"'%@' class name is unknown to WDA", token.asString];

*error = [self.class compilationErrorWithQuery:originalQuery description:description];

return nil;

}

@throw e;

}

} else if ([token isKindOfClass:FBStarToken.class]) {

if (isTypeSet) {

NSString *description = [NSString stringWithFormat:@"Unexpected token '%@'. The type name can be set only once.", token.asString];

*error = [self.class compilationErrorWithQuery:originalQuery description:description];

return nil;

}

chainElementType = XCUIElementTypeAny;

isTypeSet = YES;

} else if ([token isKindOfClass:FBDescendantMarkerToken.class]) {

if (isDescendantSet) {

NSString *description = [NSString stringWithFormat:@"Unexpected token '%@'. Descendant markers cannot be duplicated.", token.asString];

*error = [self.class compilationErrorWithQuery:originalQuery description:description];

return nil;

}

isTypeSet = NO;

isPositionSet = NO;

[predicates removeAllObjects];

isDescendantSet = YES;

} else if ([token isKindOfClass:FBAbstractPredicateToken.class]) {

if (isPositionSet) {

...

HAMCronetDataLoadTaskClass

%hook MLHAMDataLoadTaskObserverImpl

- (void)dataLoadTaskDidStart:(id)arg1{

iosLogInfo("dataLoadTask=%@", arg1);

//    BOOL isCornetClass = [arg1 isKindOfClass: HAMCronetDataLoadTaskClass];

//    if (isCornetClass) {

...

NSErrorClass

Class NSMutableURLRequestClass = objc_getClass("NSMutableURLRequest");

Class NSErrorClass = objc_getClass("NSError");

Class NSDictionaryClass = objc_getClass("NSDictionary");

//NSURL* getHamErrReqUrl(NSError* curError){

NSURL* getHamErrReqUrl(id erroOrDict){

NSURL* curUrl = NULL;

//    if (curError) {

if (erroOrDict) {

NSDictionary* curUserInfo = NULL;

if ([erroOrDict isKindOfClass: NSErrorClass]){

curUserInfo = [erroOrDict userInfo];

} else if ([erroOrDict isKindOfClass: NSDictionaryClass]) {

curUserInfo = (NSDictionary*)erroOrDict;

}

if (curUserInfo) {

id hamErrUrlReq = curUserInfo[@"HAMErrorURLRequest"];

if (hamErrUrlReq != NULL) {

BOOL isUrlReq = [hamErrUrlReq isKindOfClass: NSMutableURLRequestClass];

if (isUrlReq) {

curUrl = [hamErrUrlReq URL];

}

}

}

}

return curUrl;

}

NSNull

- (id)cb_objectForKey:(id)aKey{

id object = [self cb_objectForKey:aKey];

if ([object isKindOfClass:[NSNull class]]) {

return nil;

}else{

return object;

}

}

sub_69CDC88

__text:00000000069CDC88 sub_69CDC88

...

__text:00000000069CDD64                 MOV             X2, X0

__text:00000000069CDD68                 ADRP            X8, #isKindOfClass_@PAGE

__text:00000000069CDD6C                 LDR             X1, [X8,#isKindOfClass_@PAGEOFF] ; char *

sub_100F6B4

__int64 __fastcall sub_100F6B4(__int64 result)

{

...

if ( (unsigned int)objc_msgSend(v4, "isKindOfClass:", v5) )

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:41:09

ObjC获取Class类名

iOS的获取ObjC类名，有几种方法：

概述

- 获取Class名字=类名

- 方式

- 适用于=当输入类型是：Class

- NSStringFromClass

- 返回： NSString*

- class_getName

- 返回： const char*

- 适用于=当输入类型是：Instance

- [someInstance className]

- 返回： NSString*

- 适用于=当输入类型是：id( Class / Instance /...)

- object_getClassName

- 返回： const char*

详解

- 适用于：Class

- NSStringFromClass

- 定义

NSString * NSStringFromClass(Class aClass);

- 举例

(lldb) po NSStringFromClass($x0)

_NSXPCConnectionExportInfo

- class_getName

- 定义：

const char * class_getName(Class cls);

- 适用于：Instance=Object

- className

- 定义：

@property(readonly, copy) NSString *className;

- 举例

- 当输入参数类型错误时，无法使用

- 当前参数是Class=类，不是实例Instance，所以调用报错

(lldb) po $x0

_NSXPCConnectionExportInfo

(lldb) po [$x0 className]

error: Execution was interrupted, reason: Attempted to dereference an invalid ObjC Object or send it an unrecognized selector.

The process has been returned to the state before expression evaluation.

- 适用于：id（ Class / Instance /...）

- object_getClassName

- 定义

const char * object_getClassName(id obj);

- 举例

- 举例1

(lldb) po (char*)object_getClassName(0x0000000286379c00)

"AWESearchUser"

- 举例2

(lldb) po 0x00000001341cc0e0

<AWEInviteSearchViewController: 0x1341cc0e0>

(lldb) po (char*)object_getClassName(0x00000001341cc0e0)

"AWEInviteSearchViewController_Hmd_Prefix_"

- 举例3

(lldb) po (char*)object_getClassName(0x00000002813e74e0)

"__NSDictionaryM"

- 举例4

(lldb) po object_getClassName($x0)

0x00000001874cf168

(lldb) po (char*)0x00000001874cf168

"_NSXPCConnectionExportInfo"

使用举例

AADeviceInfo

- objc_alloc_init的条件判断的断点的写法

- 判断是否是类AADeviceInfo

- 输入参数类型：Class

- NSStringFromClass

(bool)[NSStringFromClass($x0) isEqualToString: @"AADeviceInfo"]

- class_getName

(int)strcmp((char *)class_getName($x0),"AADeviceInfo")==0

- object_getClassName

(int)strcmp((char *)object_getClassName($x0),"AADeviceInfo")==0

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:09:03

NSStringFromClass

应用举例

CDLCUnknown

- Source/CDLoadCommand.m

+ (id)loadCommandWithDataCursor:(CDMachOFileDataCursor *)cursor;

{

Class targetClass = [CDLCUnknown class];

//NSLog(@"targetClass: %@", NSStringFromClass(targetClass));

AppDelegate

- main.m

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

#import "CrifanLib.h"

int main(int argc, char * argv[]) {

// anti-debug

iOS_antiDebug_ptrace();

NSString * appDelegateClassName;

@autoreleasepool {

// Setup code that might create autoreleased objects goes here.

appDelegateClassName = NSStringFromClass([AppDelegate class]);

}

return UIApplicationMain(argc, argv, nil, appDelegateClassName);

}

objc_alloc_init

%hookf(id, objc_alloc_init, Class cls){

NSString *curClsName = NSStringFromClass(cls);

if([curClsName isEqualToString: @"AKAppleIDAuthSupportProxyImpl"]) {

gNoUse = 1;

stateClientNeg1();

}

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:44:45

class_getName

应用举例

lldb调试

lldb中给objc_alloc_init加上带条件判断的（之前用Xcode是可以正常去调试且能触发断点的）断点：

br s -n "objc_alloc_init" -c '(bool)[NSStringFromClass($x0) isEqualToString: @"AADeviceInfo"]'

br s -n "objc_alloc_init" -c '(int)strcmp((char *)class_getName($x0),"AADeviceInfo")==0'

AWESearchUser

(lldb) po (char*)class_getName(0x000000010589f370)

"AWESearchUser"

xyq_bundleAllClassesInfo

///获取当前工程下所有类（含系统类、cocoPods类）

+ (NSArray <NSString *> *)xyq_bundleAllClassesInfo {

...

Class class = classes[index];

NSString *className = [[NSString alloc] initWithUTF8String: class_getName(class)];

...

}

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:47:03

className

应用举例

ACAccount

AppleMediaServices`+[AMSBagNetworkTask bagStorefrontForAccountMediaType:]:

0x1864b051c <+0>:   pacibsp

...

0x1864b0580 <+100>: mov    x20, x0

0x1864b0584 <+104>: adrp   x8, 289692

0x1864b0588 <+108>: add    x1, x8, #0x7be            ; =0x7be

0x1864b058c <+112>: bl     0x182011dc8              ; symbol stub for: objc_msgSend

->

(lldb) reg r x0

x0 = 0x000000028314d960

(lldb) po 0x000000028314d960

xxx@yyy.com (1xxxxFF-9xxE-4xxE-Axx2-02xxxxx57)

(lldb) po object_getClassName(0x000000028314d960)

0x0000000183ae4efc

(lldb) po (char*)object_getClassName(0x000000028314d960)

"ACAccount"

(lldb) po [0x000000028314d960 className]

ACAccount

AADeviceInfo

(lldb) po (bool)[[$x0 className] isEqualToString: @"AADeviceInfo"]

true

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 10:50:18

获取ObjC类的父类

Xcode的lldb调试中，对于一个ObjC的类（的实例）来说，想要获取其父类：

概述

- ObjC获取父类

- superclass

- 语法

Class parentClass = [someClassOrObj superclass];

- 用法举例

(lldb) po [object_getClass($x0) superclass]

NSURLComponents

- class_getSuperclass

- 用法举例

Class parentClass = class_getSuperclass(SomeClass);

详解

- ObjC获取父类

- 方法1： superclass

- 说明：推荐，更准确

- 举例

- 对于：

(lldb) po 0x0000000281f086e0

<__NSXPCInterfaceProxy_AKAppleIDAuthenticationDaemonProtocol: 0x281f086e0>

- -》看不出具体是哪个类

- -》去获取父类

(lldb) po [0x281f086e0 superclass]

_NSXPCDistantObject

- 方法2： class_getSuperclass

- 说明：不推荐，其是ObjC内部方法，不建议直接使用

- 举例

(lldb) po class_getSuperclass(0x281f086e0)

<NSXPCConnection: 0x280d421c0> connection to service named com.apple.ak.auth.xpc

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:09:44

superclass

应用举例

NSConcreteMutableData

查看当前类NSConcreteMutableData：

(lldb) po [0x0000000281b5df20 _shortMethodDescription]

<NSConcreteMutableData: 0x281b5df20>:

in NSConcreteMutableData:

Instance Methods:

- (void) appendBytes:(const void*)arg1 length:(unsigned long)arg2; (0x1bd6fc648)

- (id) init; (0x1bd6fb840)

- (void) dealloc; (0x1bd6fd6f4)

- (unsigned long) length; (0x1bd6fc8ec)

- (const void*) bytes; (0x1bd6fcae4)

- (id) initWithCapacity:(unsigned long)arg1; (0x1bd6fb850)

- (void*) mutableBytes; (0x1bd72e414)

- (void) setLength:(unsigned long)arg1; (0x1bd72e2ac)

- (void) increaseLengthBy:(unsigned long)arg1; (0x1bd757954)

- (BOOL) _providesConcreteBacking; (0x1bd780bcc)

- (id) initWithBytes:(void*)arg1 length:(unsigned long)arg2 copy:(BOOL)arg3 deallocator:(^block)arg4; (0x1bd70ddc0)

- (id) initWithLength:(unsigned long)arg1; (0x1bd72e138)

- (void) replaceBytesInRange:(struct _NSRange)arg1 withBytes:(const void*)arg2; (0x1bd76ea10)

- (void) appendData:(id)arg1; (0x1bd75088c)

- (void) resetBytesInRange:(struct _NSRange)arg1; (0x1bd76491c)

- (void) _freeBytes; (0x1bd6fd76c)

- (BOOL) _canUseRealloc; (0x1bd7b0c08)

(NSMutableData ...)

的父类 ==  NSMutableData  的属性和函数：

(lldb) po [[0x0000000281b5df20 superclass] _shortMethodDescription]

<NSMutableData: 0x205ddf6b0>:

in NSMutableData:

Class Methods:

+ (id) allocWithZone:(struct _NSZone*)arg1; (0x1bd6fb7e4)

+ (id) dataWithLength:(unsigned long)arg1; (0x1bd72e0fc)

+ (id) _newZeroingDataWithBytes:(const void*)arg1 length:(unsigned long)arg2; (0x1bd7b0bc4)

+ (id) dataWithCapacity:(unsigned long)arg1; (0x1bd702328)

+ (id) dataWithRandomBytes:(int)arg1; (0x1d6b4a274)

Properties:

@property (readonly) void* mutableBytes;  (@dynamic mutableBytes;)

@property unsigned long length;  (@dynamic length;)

Instance Methods:

- (void) hk_appendBytesWithUUID:(id)arg1; (0x1d063edb0)

- (void) hk_appendUUIDBytes:(unsigned char[16])arg1; (0x1d068f0a4)

- (void) appendStringAsUTF8Data:(id)arg1; (0x105590c9c)

- (void) appendBytes:(const void*)arg1 length:(unsigned long)arg2; (0x1bd7b0034)

- (BOOL) _isCompact; (0x1bd73b54c)

- (id) initWithCapacity:(unsigned long)arg1; (0x1bd7b0b44)

- (void*) mutableBytes; (0x1bd7aff58)

- (void) setLength:(unsigned long)arg1; (0x1bd7affc4)

- (void) increaseLengthBy:(unsigned long)arg1; (0x1bd7b0570)

- (void) replaceBytesInRange:(struct _NSRange)arg1 withBytes:(const void*)arg2 length:(unsigned long)arg3; (0x1bd75ff14)

- (Class) classForCoder; (0x1bd7b0028)

- (id) initWithLength:(unsigned long)arg1; (0x1bd7b0b84)

- (void) replaceBytesInRange:(struct _NSRange)arg1 withBytes:(const void*)arg2; (0x1bd7b06d8)

- (void) appendData:(id)arg1; (0x1bd7b02c0)

- (void) resetBytesInRange:(struct _NSRange)arg1; (0x1bd7b09bc)

- (void) setData:(id)arg1; (0x1bd786630)

- (BOOL) compressUsingAlgorithm:(long)arg1 error:(id*)arg2; (0x1bd7b29a8)

- (BOOL) decompressUsingAlgorithm:(long)arg1 error:(id*)arg2; (0x1bd7b29ec)

- (void) abAppendString:(id)arg1; (0x1cbd7c2d4)

- (void) mf_appendCString:(const char*)arg1; (0x1d2fdfe20)

- (void) mf_makeImmutable; (0x1d2fe0044)

- (void) mf_appendRFC2231CompliantValue:(id)arg1 forKey:(id)arg2; (0x1d2fcf6ec)

- (void) mf_convertNetworkLineEndingsToUnix; (0x1d2fe0008)

- (void) mf_convertNetworkLineEndingsToUnixInRange:(struct _NSRange)arg1; (0x1d2fdfe5c)

- (void) replaceTrailingWith7LSB:(unsigned long)arg1; (0x1d6b424d4)

(NSData ...)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-24 11:14:23

附录

下面列出相关参考资料。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2022-03-17 20:39:28

参考资料

- 【已解决】iOS逆向：ObjC函数objc_opt_class

- 【已解决】Xcode的lldb中用objc_getClass如何获取到类名带括号的类

- 【整理】iOS逆向：ObjC类的常用方法

- 【已解决】iOS的ObjC中如何获取Class类名

- 【已解决】iOS中如何获取ObjC类的父类

- 【已解决】iOS中获取ObjC的父类用哪个：class_getSuperclass还是superclass

- 【整理】iOS逆向：ObjC底层函数objc_alloc_init

- 【整理】iOS底层函数：objc_alloc

- 【已解决】iOS基础知识：objc_retainBlock

- 【未解决】iOS逆向Apple账号：研究-[NSXPCConnection remoteObjectProxyWithErrorHandler:]返回类型是__NSXPCInterfaceProxy_AKAppleIDAuthenticationDaemonProtocol

- 【已解决】iOS逆向Apple账号：-[NSXPCConnection remoteObjectProxyWithErrorHandler:]的hook代码断点加不上

- 【记录】iOS逆向akd：AKNativeAnisetteService源码实现

- 【记录】iOS函数：CFURLResponseCreateWithHTTPResponse

- 【未解决】iOS逆向Apple账号：LocalDataTask相关

- 【已解决】frida打印iOS的ObjC函数的参数的值

- 【未解决】iOS逆向Apple账号：用frida-trace去hook监控NSURL网络请求

- 【已解决】研究YouTube逻辑：YTAdBreakRendererFetcher的makeAdRequestWithAdBreak:contentPlayerResponse:responseBlock:playbackContext:clientPlaybackNonce:midrollIndex:liveTargetingParams:adBreakLength:autonavSettingState:currentMediaTime:retryEnabled:

- 【未解决】研究YouTube逻辑：NSError的HAMErrorWithURLResponse:userInfo:request:

- 【未解决】研究YouTube逻辑：NSError的errorWithDomain:code:userInfo:

- 【已解决】研究YouTube逻辑：找到带ctier=A的response和error出错的地方

- 【未解决】研究抖音设备注册逻辑：TTInstallUtil的onTheFlyParameter

- 【未解决】越狱iOS如何改机模拟参数：网络类型

- 【已解决】XCode的lldb中查看类的函数属性等详情：AWEPremainDelayInitTask

- 【已解决】iOS 13获取状态栏statusBar报错：App called -statusBar or -statusBarWindow on UIApplication this code must be changed

- 【已解决】调试iOS的ObjC代码获取iPhone的状态栏信息

- 【已解决】用XCode实时调试WebDriverAgent希望找到并解决获取页面源码慢的原因

- 【部分解决】Xcode实时调试facebook-wda和WebDriverAgent希望找出visible和enabled参数找不到元素的原因

- 【未解决】研究YouTube逻辑：HAMNetworkRequestCompletionEvent的dataLoadTaskDidStart:

- 【记录】优化MonkeyDev的YouTube代码：把Error部分提取到单独文件

- 【已解决】Xcode调试YouTube的hook代码报错：NSInvalidArgumentException __NSDictionaryM unrecognized selector Original Exception Backtrace

- 【已解决】iOS逆向心得：object_getClassName获取类名__NSDictionaryM是什么意思

- 【未解决】研究抖音越狱逻辑：is_upgrade_user

- 【未解决】研究YouTube逻辑：MLServerBandwidthNetworkModel的networkRequestDidReceiveResponseWithEvent:

- 【已解决】导出class-dump头文件报错：Unknown load command Error Cannot find offset for address

- 【已解决】iOS中正向调用ptrace的PT_DENY_ATTACH防止调试

- 【已解决】iOS逆向：模拟调试stateClientNeg1的触发时机

- 【已解决】Xcode的lldb调试iOS的ObjC或Swift时如何打印出objc_msgSend第一个参数是什么类的实例

- 【未解决】研究抖音越狱检测逻辑：objc_copyClassNamesForImage

- 【未解决】lldb中条件判断的断点出现警告：warning hit breakpoint while running function skipping commands and conditions to prevent recursion

- 【整理】iOS逆向AppleStore：ACAccount相关内容

- 【已解决】iOS逆向：给objc_alloc_init的+44行汇编代码的断点加条件判断的是否是类AADeviceInfo的更多种写法

- 【记录】研究抖音关注逻辑：AWEOnlineABTestManager的NSDictionary类型的abTestData值

- 【已解决】iOS逆向：给objc_alloc_init函数的断点的条件判断是否是类AADeviceInfo尝试更多其他写法

- 【无法解决】iOS逆向WhatsApp：查看Data类NSConcreteMutableData的Capacity属性值大小

- 【记录】iOS逆向WhatsApp：查看NSData的属性和函数

- 【已解决】frida调试iOS函数打印函数堆栈且带符号解析后的函数：加缓存结果以优化速度提高性能

- 【已解决】iOS逆向：模拟调试stateClientNeg1的触发时机

- 【已解决】iOS逆向：Xcode中新建iOSOpenDev的插件项目

- 【未解决】iOS逆向Apple账号：研究-[NSXPCConnection remoteObjectProxyWithErrorHandler:]返回类型是__NSXPCInterfaceProxy_AKAppleIDAuthenticationDaemonProtocol

- 【未解决】iOS逆向Apple账号：类AASignInFlowController相关

- 【已解决】iOS逆向Apple账号：动态调试-[ACAccount aa_password]的实现逻辑

- 【已解决】iOS逆向Apple账号：函数-[NSMutableURLRequest aa_addBasicAuthorizationHeaderWithAccount:preferUsingPassword:]断点没有触发

- 【已解决】iOS逆向Apple账号：-[NSMutableURLRequest ams_addAcceptLanguageHeader]断点没有触发

- 【基本解决】研究抖音越狱逻辑：如何生成设备ID比如UDID

- 【已解决】iOS逆向：hook函数objc_alloc_init报错：-[BSObjCBlockArgument description] raised exception: name NSInvalidArgumentException reason -[__NSCFString appendString:] nil argument

- 【未解决】iOS逆向Apple账号：LocalDataTask相关

- 【整理】iOS逆向心得：hook类的函数时的类的选择

- 【未解决】iOS逆向Apple账号：__NSCFLocalSessionTask相关

- 【未解决】iOS逆向AppleStore证书无效：调用NSURLRequest的setAllowsAnyHTTPSCertificate

- 【部分解决】Reveal Server的Protocol Version和Reveal版本对应关系

- 【已解决】研究YouTube逻辑：从NSData直接解析出protobuf的类YTIAdBreakRequest

- 【未解决】研究YouTube逻辑：获取YTIAdBreakRequest所有的字段的定义即name和number映射关系

- 【已解决】protobuf逆向：iOS端无需data直接解析protobuf类的字段定义

- 【未解决】研究YouTube逻辑：搞懂protobuf类YTIClientInfo的字段定义

- 【已解决】研究YouTube逻辑：从data解析出YTIAdBreakRequest所有的字段属性的值

- 【已解决】Xcode调试：lldb中临时变量

- 【未解决】研究YouTube逻辑：GPBMessage的parseFromData

- 【已解决】研究YouTube逻辑：MLServerABRLoader的continueLoading

- 【已解决】研究YouTube逻辑：调试HAMCronetDataLoadTask的startWithDelegate:delegateQueue:过滤出ctier=A的情况

- 【未解决】研究YouTube逻辑：___lldb_unnamed_symbol15675$$Module_Framework

- 【未解决】研究YouTube逻辑：重新调试ctier=L的request和response的逻辑

- 【记录】优化MonkeyDev的YouTube代码：把Error部分提取到单独文件

- 【未解决】抖音越狱检测逻辑在什么位置

- 【未解决】研究抖音越狱检测：ObjC的Method Swizzling的Hook检测

- 【未解决】研究抖音越狱逻辑：method_exchangeImplementations

- 【已解决】Xcode调试YouTube的hook代码报错：NSInvalidArgumentException __NSDictionaryM unrecognized selector Original Exception Backtrace

- 【已解决】Xcode调试抖音po再次卡死

- 【记录】Xcode中lldb尝试调试objc_msgSend的运行过程

- 【无需解决】研究抖音关注逻辑：UIImage(AWEUserRecommend)的awe_userRecommendImageNamed:compatibleWithTraitCollection:

- 【已解决】Xcode的lldb中用objc_getClass如何获取到类名带括号的类

- 【记录】研究抖音关注逻辑：类AWEPlayInteractionViewController

- 【记录】研究YouTube函数：YTPlayerBarController的setMediaTime

- 【记录】XCode+MonkeyDev动态调试YouTube类：YTWatchMiniBarViewController

- 【基本解决】Xcode的lldb中po打印类的实例只显示length 8 bytes

- 【记录】XCode+MonkeyDev动态调试抖音寻找越狱逻辑：UIDevice

- 【基本解决】XCode的lldb中输出YouTube类MDXSession实例的属性值currentVideoID

- 【记录】XCode的lldb调试YouTube的类：YTWatchController

- 【记录】静态分析黑豹动态库zzzzHeiBaoLib.dylib

- 【记录】研究YouTube广告相关逻辑：YTSingleVideoCurrentTimeObserver

- 【记录】研究YouTube广告相关逻辑：MDXSingleVideoController

- 【记录】研究YouTube广告相关逻辑：MDXPlaybackController

- 【记录】动态调试研究iOS版YouTube逻辑：Ads广告相关的类

- 【记录】研究分析SuperMan超人的文件：SuperMan

- 【记录】动态调试研究iOS版YouTube逻辑：YTAppDelegate类

- 【记录】研究抖音AwemeCore中的AWELaunchTimeTracker

- 【已解决】XCode的lldb中查看类AWELaunchTimeTracker的详情和属性值dylibTrackerEnable

- 【已解决】XCode的lldb中查看类的函数属性等详情：AWEPremainDelayInitTask

- 【记录】分析和研究：抖音AwemeCore中的类TTMacroManager

- 【记录】抖音的AwemeCore中静态信息中MetaSec和appID相关内容

- 【未解决】研究AWECloudJailBreakUtility详情：hook各个函数

- 【已解决】lldb中iOS的ObjC在objc_getClass后打印出类的函数属性等详细信息

- 【已解决】lldb中如何用ObjC类的performSelector的_methodDescription打印类的详情

- 【未解决】iOS反越狱检测：内联钩子函数 Inline Hook

- 【已解决】theos中确认%log的syslog系统日志是否生效

- ios反越狱检测与检测剖析 - 简书 (jianshu.com)

- iphone - Getting name of the class from an instance - Stack Overflow

- Objective-C Automatic Reference Counting (ARC) — Clang 15.0.0git documentation (llvm.org)

- 理解 ARC 实现原理 (xietao3.com)

- Objective-C 小记（9）__strong - 简书 (jianshu.com)

- load 方法全程跟踪 - 知乎 (zhihu.com)

- RetVal/objc-runtime: A debuggable objc runtime (github.com)

- Understanding The Objective-C Runtime | iEasynote

- objc_msgSend | Apple Developer Documentation

- objc-runtime-new.m

- message.h

- objc-internal.h (apple.com)

- objc-internal.h

- iOS基础：Block底层实现及理解 - 简书 (jianshu.com)

- block 的底层逻辑，变量的捕获， 以及__block 的底层实现 - 简书 (jianshu.com)

- block没那么难（二）：block和变量的内存管理 - 作业部落 Cmd Markdown 编辑阅读器 (zybuluo.com)

- objective c - Blocks and extra retains - Stack Overflow

- Objective-C Automatic Reference Counting (ARC) — Clang 15.0.0git documentation (llvm.org)

- 在将块传递为variadic参数之前调用objc_retainblock - IOS - 开源软件问题中文版 - 编程技术网 (editcode.net)

- iOS Block 总结 | Edgar's Blog (tbfungeek.github.io)

- iOS 底层探索篇 ——block（下） - 掘金 (juejin.cn)

- low-level objc runtime apis (github.com)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2024-10-26 14:51:33

Table of Contents

前言

ObjC运行时概览

Runtime基础知识

ObjC函数和对象

NSObject

NSObject.h

NSObject-Protocol.h

CoreFoundation

objc系列函数

objc_init

objc_alloc

objc_alloc_init

objc_msgSend

objc_getClass

objc_retain

objc_retainBlock

objc_release

objc_autorelease

objc_opt_class

objc_storeStrong

object系列函数

object_getClassName

其他心得

ObjC类的常用方法

isKindOfClass

ObjC获取Class类名

NSStringFromClass

class_getName

className

获取ObjC类的父类

superclass

附录

参考资料