普通视图

发现新文章,点击刷新页面。
昨天以前掘金专栏-iOS逆向

iOS小技能:给debugserver添加task_for_pid权限,以便调试从AppStore中获取的App。

2022年10月27日 09:49

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情

前言

在做iOS开发时,在Mac上输入LLDB的命令就可以控制iOS端的App,是因为在iOS客户端中有一个debugserver服务器。

debugserver专门用来连接Mac端的LLDB客户端,接收LLDB所提供的命令,并且进行相应的执行。

如果你的iOS设备进行过真机调试的话,设备中就会被安装上debugserver, 不过该debugserver只能用来调试你自己的相关应用。

如果想要调试从AppStore中获取的App的话那么我们需要对iOS设备上的debugserver进行处理,那就是给debugserver添加task_for_pid权限

本文的重点是给debugserver添加task_for_pid权限,以便调试从AppStore中获取的App

I 、获取debugserver


iPhone:/Developer/usr/bin root# ls
DTDeviceArbitration  ScreenShotr  XcodeDeviceMonitor  debugserver  iprofiler  xctest

位于/Developer/usr/bin目录下的debugserver。此debugserver只支持调试我们自己的App, 如果需要调试其他人的App的话,需要对此debugserver进行处理

II、对debugserver进行瘦身


进入到到Mac中debugserver所在的目录下执行上述命令即可,-thin后方填写你的测试机相应的ARM架构即可,因为我的测试机是iPhone 6 Plus, 是arm64的架构,所以此处填的参数是arm64, 如果你的是iPhone5的设备,那么就是armv7s了。

devzkndeMacBook-Pro:Downloads devzkn$ scp iphone:/Developer/usr/bin/debugserver ./debugserver

lipo -thin arm64 debugserver -output debugserver

devzkndeMacBook-Pro:Downloads devzkn$ ls -l debugserver
-rwxr-xr-x  1 devzkn  staff  13801968 Oct 17 17:19 debugserver
devzkndeMacBook-Pro:Downloads devzkn$ lipo -thin armv7s debugserver -output debugserver
devzkndeMacBook-Pro:Downloads devzkn$ ls -l debugserver
-rwxr-xr-x  1 devzkn  staff  4582800 Oct 17 17:19 debugserver

III、给debugserver添加task_for_pid权限


给debugserver添加task_for_pid权限后,我们就可以使用LLDB调试其他App了。 此部分我们需要一个存储配置信息的xml文件,该文件的内容如下。你可以将下下方的文本进行拷贝,然后存储成ent.xml即可。

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>com.apple.springboard.debugapplications</key>
        <true/>
        <key>get-task-allow</key>
        <true/>
        <key>task_for_pid-allow</key>
        <true/>
        <key>run-unsigned-code</key>
        <true/>
</dict>
</plist>

在给debugserver符权限时,我们需要使用到ldid命令,如果你的Mac上没有安装ldid命令,那么请用brew进行install 执行下方的命令行就可以给我们的debugserver赋上task_for_pid权限。需要注意的是-S与ent.xml文件名中是没有空格的。

ldid -Sent.xml debugserver


IV、将debugserver拷贝到iOS设备中


最后一步就是将处理好的debugserver拷贝到我们的越狱设备中,并且给debugserver赋上可执行的权限。

chmod +x debugserver


因为/Developer/usr/bin目录下的debugserver是只读的,所以你不能将处理好的debugserver拷贝到上述文件,

你要将处理好的debugserver拷贝到/usr/bin/目录下

devzkndeMacBook-Pro:Downloads devzkn$ scp ./debugserver iphone:/usr/bin/debugserver

Phone:/usr/bin root# ls -l debugserver
-rwxr-xr-x 1 root wheel 4582512 Oct 17 17:31 debugserver
iPhone:/usr/bin root# debugserver
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Usage:
  debugserver host:port [program-name program-arg1 program-arg2 ...]
  debugserver /path/file [program-name program-arg1 program-arg2 ...]
  debugserver host:port --attach=<pid>
  debugserver /path/file --attach=<pid>
  debugserver host:port --attach=<process_name>
  debugserver /path/file --attach=<process_name>

see also

How can you catch a process that is about to be launched, if you don’t know the PID yet?

———————————————— 版权声明:本文为CSDN博主「#公号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 更多内容请关注公号:iOS逆向 原文链接:blog.csdn.net/z929118967/…

iOS小技能:__attribute__的应用

2022年6月19日 06:43

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

引言

LLVM和其他 GCC 特性一样,Clang 支持了 attribute, 还加入了一小部分扩展特性。

__attribute__ 语法格式为:__attribute__ ((attribute-list))

constructor(priority), destructor(priority) 分别可以在main() 先后执⾏,可⽤于全局资源初始化和回收。

destructor让系统在main()函数退出或者调用了exit()之后,调用我们的函数。

Function-Attributes: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

I __attribute__的应用案例

1.1 代码注入

  1. ARM (通过汇编调用svc实现用户态到内核态的转换)
// 使用inline方式将函数在调用处强制展开,防止被hook和追踪符号
static __attribute__((always_inline)) void anti_debug()
#ifdef __arm__
    asm volatile(
                 "mov r0,#31\n"
                 "mov r1,#0\n"
                 "mov r2,#0\n"
                 "mov r12,#26\n"
                 "svc #80\n"
                 );
#endif
#ifdef __arm64__
    asm volatile(
                 "mov x0,#26\n"
                 "mov x1,#31\n"
                 "mov x2,#0\n"
                 "mov x3,#0\n"
                 "mov x16,#0\n"
                 "svc #128\n"
                 );
#endif
}
  1. 代码注入: facebook/fishhook符号表替换
/*
 * A structure representing a particular intended rebinding from a symbol
 * name to its replacement
 */
struct rebinding {//rebinding结构体
  const char *name;  //符号名称,C字符串,用来表明我们要hook哪个函数。
  void *replacement; //新函数的地址
  void **replaced;   //原始函数地址的指针!
};

//重新绑定符号
FISHHOOK_VISIBILITY
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);
//rebindings[] 是一个 rebinding类型数组,用来存储需要hook的函数
//rebindings_nel 表示数组的长度


/*
 * Rebinds as above, but only in the specified image. The header should point
 * to the mach-o header, the slide should be the slide offset. Others as above.
 */
FISHHOOK_VISIBILITY
int rebind_symbols_image(void *header,
                         intptr_t slide,
                         struct rebinding rebindings[],
                         size_t rebindings_nel);
//指定镜像的header, slide 表示偏移量


hook ptrace函数,进行反反调试。

PT_DENY_ATTACH is an Apple-specific constant that can prevent debuggers (gdb, DTrace, etc.) from debugging your binary in kernel-level.

ptrace(PT_DENY_ATTACH, 0, 0, 0);

#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif

Rebinding customRebind = {"ptrace", my_ptrace, (void*)&orig_ptrace};
//第一个参数为需要替换的符号
//第二个参数为自己实现的函数名称
//第三个参数为原函数地址,因为fishhook是基于地址进行替换的+ `__attribute__((constructor))`实现注入


rebind_symbols((struct rebinding[1]){customRebind},1);

int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){
    if(_request != PT_DENY_ATTACH){
        return orig_ptrace(_request,_pid,_addr,_data);
    }    
    return 0;
}
  1. 自定义打印方法:用真正的方法替换去拦截 NSLog 的功能(iOS 11 之后这种方法失效了),使用__attribute__((constructor)); 进行实现,extern进行申明公共方法。

#ifdef DEBUG

// iOS 11 之前用真正的方法替换去实现拦截 NSLog 的功能,iOS 11 之后这种方法失效了,所以只能用宏定义的方式覆盖 NSLog。这也就意味着在 iOS 11 下一些如果某些代码编译时机比 QMUI 早,则这些代码里的 NSLog 是无法被替换为 KNLog 的
extern void _NSSetLogCStringFunction(void (*)(const char *string, unsigned length, BOOL withSyslogBanner));
static void PrintNSLogMessage(const char *string, unsigned length, BOOL withSyslogBanner) {
    QMUILog(@"NSLog", @"%s", string);
}

static void HackNSLog(void) __attribute__((constructor));
static void HackNSLog(void) {
    _NSSetLogCStringFunction(PrintNSLogMessage);
}

#define NSLog(...) KNLog(@"NSLog", __VA_ARGS__)// iOS 11 以后真正生效的是这一句
#endif

1.2 对格式化字符串进行类型检查

extern int
my_printf (void *my_object, const char *my_format, ...)
  __attribute__((format(printf, 2, 3)));
 //format 属性用于指定一个函数接收类似 printf, scanf, strftime 和 strfmon 风格的参数,应该按照参数对格式化字符串进行类型检查。

1.3 控制符号的可见性

#define STD_EXPORTS __attribute__ ((visibility("default")))

SymbolVisibility

The -fvisibility=vis compiler option lets you set the visibility for symbols in the current compilation. When set to hidden, symbols not explicitly marked as visible are hidden.

__attribute__((visibility("default"))) void MyFunction1() {}
__attribute__((visibility("hidden"))) void MyFunction2() {}

1.4 表明一些函数参数应该是非空的指针

extern void *
my_memcpy (void *dest, const void *src, size_t len)
  __attribute__((nonnull (1, 2)));

1.5 确保线程在应用整个生命周期内都能一直运行

AFNetworking 在网络请求线程的入口使用 noreturn 属性,用于网络请求的 NSThread。

github.com/AFNetworkin…

+ (void) __attribute__((noreturn)) networkRequestThreadEntryPoint:(id)__unused object {//确保这个线程在应用整个生命周期内都能一直运行
    do {
        @autoreleasepool {
            [[NSRunLoop currentRunLoop] run];
        }
    } while (YES);
}


+ (NSThread *)networkRequestThread {//专门用于网络请求的 NSThread
    static NSThread *_networkRequestThread = nil;
    static dispatch_once_t oncePredicate;
    
    dispatch_once(&oncePredicate, ^{
        _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
        [_networkRequestThread start];
    });
    
    return _networkRequestThread;
}

1.6 检查能否使用特定的属性

可以用 __has_attribute 这个指令

#ifndef AX_REQUIRES_SUPER
#if __has_attribute(objc_requires_super)
#define AX_REQUIRES_SUPER __attribute__((objc_requires_super))
#else
#define AX_REQUIRES_SUPER

__attribute((objc_requires_super)) was first introduced as work in progress into CLANG in September 2012 and was documented in October 2013. On both OS X and iOS there is now a NS_REQUIRES_SUPER macro that conditionally wraps the objc_requires_super attribute depending on compiler support. Once a method declaration is appended with this macro, the compiler will produce a warning if super is not called by a subclass overriding the method.

II 导出和隐藏符号

2.1 导出符号信息

  • 查看导出符号信息:nm -gm tmp_64.dylib

(__DATA,__data) external (undefined) external _CFDataCreate (from CoreFoundation) (undefined) external _CFNotificationCenterGetDarwinNotifyCenter (from CoreFoundation) (__TEXT,__text) external (undefined) external _IOObjectRelease (from IOKit) (undefined) external _IORegistryEntryCreateCFProperty (from IOKit) 000000010ffa3f97 (__DATA,__objc_data) external OBJC_CLASS_BslyjNwZmPCJkVst 000000010ffa3f97 (__DATA,__objc_data) external _OBJC_CLASS__ChiDDQmRSQpwQJgm

2.2 __attribute__控制符号是否导出

SymbolVisibility :https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html

The -fvisibility=vis compiler option lets you set the visibility for symbols in the current compilation. When set to hidden, symbols not explicitly marked as visible are hidden.

#define EXPORT __attribute__((visibility("default")))

隐藏未明确标记为可见的符号:

  1. 在编译参数中加入-exported_symbols_list export_list

  2. 在编译参数中指定-fvisibility=hidden,对指定符号增加visibility(“default”)来导出符号

__attribute__((visibility("default"))) void MyFunction1() {}
__attribute__((visibility("hidden"))) void MyFunction2() {}

static 参数修饰,不会导出符号信息

static char _person_name[30] = {'\0'};

2.3 Pragmas控制符号是否导出

void f() { }
 
#pragma GCC visibility push(default)
void g() { }
void h() { }
#pragma GCC visibility pop


III ptrace系统调用

为了方便应用软件的开发和调试,unix的早期版本提供了一种对运行中的进程进行跟踪和控制手段:系统调用ptrace;通过ptrace,可以对另一个进程实现调试跟踪,同时ptrace提供了一个PT_DENY_ATTACH = 31参数用于告诉系统阻止调试器的依附

//ptrace系统调用 用于实现断点调试和对进程进行跟踪和控制
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void  *data);
//enum __ptrace_request request:指示了ptrace要执行的命令。
//pid_t pid: 指示ptrace要跟踪的进程。
//void *addr: 指示要监控的内存地址。
//void *data: 存放读取出的或者要写入的数据。

//PT_DENY_ATTACH is an Apple-specific constant that can prevent debuggers (gdb, DTrace, etc.) from debugging your binary in kernel-level.
//ptrace(PT_DENY_ATTACH, 0, 0, 0);

gdb利用ptrace系统调用,在被调试程序和gdb之间建立跟踪关系。然后所有发送给被调试程序的信号(除SIGKILL)都会被gdb截获,gdb根据截获的信号,查看被调试程序相应的内存地址,并控制被调试的程序继续运行。

3.1 syscall

syscall是通过软中断来实现从用户态到内核态,syscall (26,31,0,0)来调用系统函数ptrace(PT_DENY_ATTACH, 0, 0, 0);

ptrace的系统调用函数号是26,31是PT_DENY_ATTACH(用于告诉系统阻止调试器的依附)。 int syscall(int, ...); #defineSYS_ptrace 26 在这里插入图片描述

3.2 反调试

iOS动态防护:【Dynamic protection】反调试、反反调试、反注入、hook检测、完整性校验 https://blog.csdn.net/z929118967/article/details/84612698

  1. 运行时期,断点ptrace,直接返回

  2. 分析如何调用的ptrace,hook ptrace

  3. 通过tweak,替换disable_gdb函数

  4. 修改 PT_DENY_ATTACH:在二进制文件中 ,修改 PT_DENY_ATTACH的31,改成 任意一个值,如PT_ATTACH 0。 blog.csdn.net/z929118967/… AlipayWalletTweakF.xm

  5. ARM (通过汇编调用svc实现用户态到内核态的转换)

// 使用inline方式将函数在调用处强制展开,防止被hook和追踪符号
static __attribute__((always_inline)) void anti_debug()
#ifdef __arm__
    asm volatile(
                 "mov r0,#31\n"
                 "mov r1,#0\n"
                 "mov r2,#0\n"
                 "mov r12,#26\n"
                 "svc #80\n"
                 );
#endif
#ifdef __arm64__
    asm volatile(
                 "mov x0,#26\n"
                 "mov x1,#31\n"
                 "mov x2,#0\n"
                 "mov x3,#0\n"
                 "mov x16,#0\n"
                 "svc #128\n"
                 );
#endif
}

see also

小程序:iOS逆向

iOS小技能:动态地给类添加新的方法、实例变量、属性。

2022年6月9日 09:31

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

前言

添加新的实例变量的原理:利用category结合runtime的API实现

动态创建属性的应用场景:利用属性进行传值的时候,我们就可以利用本文的方法进行动态创建属性。尤其在逆向其他app的时候,往已经存在class新增一个属性,用于数据传递,尤其是异步操作的时候。

I 添加新的实例变量

1.1 原理

利用 runtime APIobjc_setAssociatedObjectobjc_getAssociatedObject objc_setAssociatedObject

/** 
 * Sets an associated value for a given object using a given key and association policy.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
 * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
 * 
 * @see objc_setAssociatedObject
 * @see objc_removeAssociatedObjects
 */
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

/** 
 * Returns the value associated with a given object for a given key.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * 
 * @return The value associated with the key \e key for \e object.
 * 
 * @see objc_setAssociatedObject
 */
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

1.2 例子

类别(Category)通过增加新的类和实例方法来扩展现有类的行为。作为惯例,类别被定义在它们自己的.{h,m}文件里。

//  
//  Teacher+Profession.m  
//    
  
#import "Teacher+Profession.h"  
#import <objc/runtime.h>  
  
const char *ProfessionType = "NSString *";  //就是属性的key
@implementation Teacher (Profession)  
  
-(void)setProf:(NSString*)prof  
{  
    objc_setAssociatedObject(self, ProfessionType, prof, OBJC_ASSOCIATION_RETAIN_NONATOMIC);  
}  
  
-(NSString *)prof  
{  
    NSString *pro = objc_getAssociatedObject(self, ProfessionType);  
    return pro;  
}  
  
@end  

II 动态创建属性

使用分类、@dynamic、objc_setAssociatedObject、objc_getAssociatedObject 实现。

2.1 应用场景

利用属性进行传值的时候,我们就可以利用本文的方法进行动态创建属性。尤其在逆向其他app的时候,往已经存在class新增一个属性,用于数据传递,尤其是异步操作的时候。

  //结合@dynamic的 associatedObject例子
  @implementation NSObject (AssociatedObject)
  @dynamic associatedObject;
  - (void)setAssociatedObject:(id)object {
      objc_setAssociatedObject(self,
  @selector(associatedObject), object,
  OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  }
  - (id)associatedObject {
      return objc_getAssociatedObject(self,
  @selector(associatedObject));
  }

2.2 例子:为VC新增一个属性

WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.h


#import "WCNewCommitViewController.h"

@interface NSObject (KNWCNewCommitViewControllerAssociatedObject)
//    isa (Class): NSKVONotifying_WCNewCommitViewController (isa, 0x5a10db2abf7)
@property (nonatomic, strong) id associatedObject;
@end

WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.m

#import "WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.h"

@implementation NSObject (KNWCNewCommitViewControllerAssociatedObject)

@dynamic associatedObject;
- (void)setAssociatedObject:(id)object {
    objc_setAssociatedObject(self,
                             @selector(associatedObject), object,
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)associatedObject {
    return objc_getAssociatedObject(self,
                                    @selector(associatedObject));
}

@end

2.3 效果

  • usage:
  #import "WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.h"

 [WCNewCommit setAssociatedObject:@"sssss"];

  • ret
NSLog(@"associatedObject:%@",[self valueForKey:@"associatedObject"]);//2018-09-06 12:06:06.977711 WeChat[717:226743] associatedObject:sssss

See Also

  • iOS运行时的应用:

1、实现路由(接口控制app跳任意界面 )

2、获取修改对象的成员属性

3、动态添加/交换方法的实现

4、属性关联

blog.csdn.net/z929118967/…

iOS动态库的注入原理

2022年2月6日 11:18

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」。

前言

动态库的注入原理:

  • 一个是基于修改Mach-O 的Load Commands,即通过修改可执行文件的Load Commands来实现的. 在Load Commands中增加一个LC_LOAD_DYLIB , 写入dylib路径。Usage: insert_dylib dylib_path binary_path [new_binary_path]
  • 一个是利用环境变量DYLD_INSERT_LIBRARIES,例如使用它进行dumpdecrypted(补充:Clutch 通过posix_spawnp生成一个新的进程,然后暂停进程并dump内存)
  • 另一个是在挂载的进程上创建一个挂起的线程, 然后在这个线程里申请一片用于加载动态库的内存,然后恢复线程,动态库就被注入(通过 taskfor_pid函数获取目标进程句柄,然后通过在进程内创建新线程并执行自己的代码。) cycript 就是以这种方式执行脚本代码。

I、静态库和动态库的区别

在这里插入图片描述

1.1 动态库的特点

  • 存在形式有 .dylib,.framework 和链接符号 .tdb;
  • 它的好处是可以只保留一份文件和内存空间,从而能够被多个进程使用,例如系统动态库;
  • 可减小可执行文件的体积,不需要链接到目标文件。

1.2 静态库的特点

  • 以.a 或者.framework形式存在的一种共享程序代码的方式,从本质上来讲就是一种可执行文件的二进制形式;常常会将程序的部分功能编译成库,暴露出头文件的形式供开发者调用
  • 静态库以一个或者多个object文件组成;可以将一个静态库拆解成多个object文件(ar -x)
  • 静态库链接的时会直接链接到目标文件,并作为它的一部分存在。

II、动态库的编译和注入

2.1 编译

xcrun --sdk iphoneos clang++ dynamiclib -arch arm64 -framework Foundation Person.mm -o target.dylib -fvisibility=hidden

  • Makefile
CC = xcrun --sdk iphoneos clang++
ARCH = arm64
FRAMEWORK = -framework Foundation
VERSION = -compatibility_version 1 -current_version 1
VISIBLE = -fvisibility=hidden
TARGET = target.dylib

SOURCE = Person.m 

$(TARGET):$(SOURCE)
$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION)

.PHONY:clean
clean:
rm $(TARGET)

2.2 动态库的注入方式

2.2.1 cycript注入动态库的方式

在挂载的进程上创建一个挂起的线程, 然后在这个线程里申请一片用于加载动态库的内存,然后恢复线程,动态库就被注入(通过 taskfor_pid函数获取目标进程句柄,然后通过在进程内创建新线程并执行自己的代码。)

2.2.2 通过环境变量DYLD_INSERT_LIBRARIES 注入

DYLD_INSERT_LIBRARIES=/PathFrom/dumpdecrypted.dylib /PathTo
#New Run Script Phase:
cd ${TARGET_BUILD_DIR}
export DYLD_INSERT_LIBRARIES=./libKNoke.dylib && /Applications/QKNQ.app/Contents/MacOS/QKNQ

2.2.3 通过增加load command 的LC_LOAD_DYLIB或者LC_LOAD_WEAK_DYLIB,指定动态库的路径来实现注入

修改App可执行文件的头部,给它添加这么一个load command,并指定load我们构造的dylib就好

  • 二次打包动态库的注入:避免每次从环境变量注入–偏静态:通过LC_LOAD_DYLIB实现dylib的加载

通过修改可执行文件的Load Commands来实现的. 在Load Commands中增加一个LC_LOAD_DYLIB , 写入dylib路径 Usage: insert_dylib dylib_path binary_path [new_binary_path]

1、现在iOS上的绝大多数以root权限运行的App,都是通过setuid + bash来实现的

2、App运行所需要的信息,一般都存放在其MachO头部43中,其中dylib的信息是由load commands指定的.

这些信息是以静态的方式存放在二进制文件里(不是由DYLD_INSERT_LIBRARIES动态指定),而又是由dyld动态加载的,所以我们给它起了个“偏静态”的名字--在此App得到执行时,dyld会查看其MachO头部中的load commands,并把里面LC_LOAD_DYLIB相关的dylib给加载到进程的内存空间

  • 如果需要修改LC_ID_DYLIDB、、LC_LOAD_DYLIB,可以使用install_name_tool
install_name_toll -id xxx imputfile
install_name_toll -change old new imputfile

  • 通过cydia substrate提高的注入:

配置plist文件,并将对应的plist、dylib文件放入指定目录 /Layout/Library/MobileSubstrate/DynamicLibraries/、/usr/lib/TweakInject其实也是通过DYLD_INSERT_LIBRARIES将自己注入,然后遍历DynamicLibraries目录下的plist文件,再将符合规则的动态库通过dlopen打开

III、导出和隐藏符号

3.1 导出符号

  • 查看导出符号信息
 nm  -gm tmp_64.dylib 

(__DATA,__data) external
(undefined) external _CFDataCreate (from CoreFoundation)
                 (undefined) external _CFNotificationCenterGetDarwinNotifyCenter (from CoreFoundation)
 (__TEXT,__text) external 
                  (undefined) external _IOObjectRelease (from IOKit)
                 (undefined) external _IORegistryEntryCreateCFProperty (from IOKit)
000000010ffa3f97 (__DATA,__objc_data) external _OBJC_CLASS_$_BslyjNwZmPCJkVst
000000010ffa3f97 (__DATA,__objc_data) external _OBJC_CLASS_$_ChiDDQmRSQpwQJgm

3.2 隐藏符号

  • static 参数修饰,不会导出符号信息
static char _person_name[30] = {'\0'};

  • 在编译参数中加入-exported_symbols_list export_list
CC = xcrun --sdk iphoneos clang
ARCH = arm64
FRAMEWORK = -framework Foundation
VERSION = -compatibility_version 1 -current_version 1 
EXPORT = -exported_symbols_list export_list
VISIBLE = -fvisibility=hidden
TARGET = target.dylib

SOURCE = Person.mm

target1:$(SOURCE1)
$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION)

target2:$(SOURCE1)
$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION) $(EXPORT)


target3:$(SOURCE1)
$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION) $(VISIBLE)

clean:
rm $(TARGET)

  • 在编译参数中指定-fvisibility=hidden,对指定符号增加visibility(“default”)来导出符号
//#define EXPORT __attribute__((visibility("default")))

CC = xcrun --sdk iphoneos clang++
ARCH = arm64
FRAMEWORK = -framework Foundation
VERSION = -compatibility_version 1 -current_version 1
VISIBLE = -fvisibility=hidden
TARGET = target.dylib

SOURCE = Person.m 

$(TARGET):$(SOURCE)
$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION)

.PHONY:clean
clean:
rm $(TARGET)

see also

由于篇幅原因,更多内容请关注 #小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域;更多服务和咨询请关注#公众号:iOS逆向。

🍅 联系作者: iOS逆向(公号:iosrev)


🍅 作者简介:CSDN 博客专家认证🏆丨全站 Top 50、华为云云享专家认证🏆、iOS逆向公号号主


🍅 简历模板、技术互助。关注我,都给你。

iOS逆向小技能:Cydia Substrate的组成部分、编写Tweak的步骤

2022年1月21日 09:08

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。

前言

Cydia Substrate(以前叫做MobileSubstrate)是一个框架,允许第三方的开发者在系统的方法里打一些运行时补丁,扩展一些方法。

Cydia Substrate由3部分组成:

  • MobileHooker
  • MobileLoader
  • safe mode

I Cydia Substrate]

1.1 MobileHooker

MobileHooker用来替换系统函数,这个过程也叫Hooking。有如下的API可以使用:

IMP MSHookMessage(Class class, SEL selector, IMP replacement, const char* prefix); // prefix should be NULL.
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP *result);
void MSHookFunction(void* function, void* replacement, void** p_original);

MSHookMessageEx用来替换Objective-C的函数,MSHookFunction用来替换C/C++函数

1.2 MobileLoader

MobileLoader loads 3rd-party patching code into the running application. MobileLoader will first load itself into the run application using DYLD_INSERT_LIBRARIES environment variable. Then it looks for all dynamic libraries in the directory /Library/MobileSubstrate/DynamicLibraries/, and dlopen them.

控制是否加载到目标程序,是通过一个plist文件来控制的。如果需要被加载的动态库的名称叫做foo.dylib,那么这个plist文件就叫做foo.plist,这个里面有一个字段叫做filter,里面写明需要hook进的目标程序的bundle id。 比如,如果只想要foo.dylib加载进入SpringBoard,那么对应的plist文件中的filter就应该这样写:

Filter = {
  Bundles = (com.apple.springboard);
};

1.3 Safe mode

When a extension crashed the SpringBoard, MobileLoader will catch that and put the device into safe mode. In safe mode all 3rd-party extensions will be disabled.

The following signals will invoke safe mode:


SIGABRT
SIGILL
SIGBUS
SIGSEGV
SIGSYS

II 编写Tweak的步骤

  • 确定目标:在这个App上编写Tweak实现的特定功能,比如拦截某个具体的应用的特定API调用,获得关键信息。

  • 导出头文件:确定目标之后,就可以利用Clutch先破解App,然后利用class-dump-z导出头文件,找到你感兴趣的类,对它进行分析。

  • 获得类的方法:有时候,头文件没有所有方法调用的信息,这个时候你可以利用cycript,使用之前介绍的trick,打印出所需的方法信息。

  • 编写Tweak:这一步你应该拿到需要Hook的类以及对应的方法,编写并安装与测试。

III SpringBoard 相关的API

  • powerDown
+ (void) powerDown {
    id SpringBoard = [UIApplication sharedApplication];//#"<SpringBoard: 0x173d8800>"
    [SpringBoard powerDown];
}

  • relaunchSpringBoard
 @interface SpringBoard : UIApplication
 \t_uiController (SBUIController*): <SBUIController: 0x1809c510>
 - (void)relaunchSpringBoard;  [#0x1617ca00 relaunchSpringBoard]
 - (void)_relaunchSpringBoardNow;
 - (void)powerDown;
 - (void)_powerDownNow;
 - (void)reboot;
 - (void)_rebootNow;
 @end

  • 自动锁屏
    [UIApplication sharedApplication].idleTimerDisabled=YES;//不自动锁屏,放在-(void)viewWillAppear:(BOOL)animated里面的时候,防止失效
  
    [UIApplication sharedApplication].idleTimerDisabled=NO;//自动锁屏

see also

更多内容请关注 #小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域;更多服务和咨询请关注#公众号:iOS逆向。

iOS设备日志查看工具:syslog、socat

2022年1月20日 10:18

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。

前言

本文介绍iOS设备日志查看工具syslog、deviceconsole和socat,如果上述工具都不满意,你也可以使用Mac系统自带的console控制台进行查看。

>

I syslog

1.1 安装syslog

在cydia搜索syslogd to /var/log/syslog安装即可

1.2 syslog用法

syslog是把系统日志写入到/var/log/syslog文件里,用法很简单,执行tail -f /var/log/syslog就能看到了

如果需要过滤某一应用的日志,只需加上grep即可,比如过滤微信

tail -f /var/log/syslog |grep WeChat

II socat

2.1 安装

  • 在iOS设备安装

使用 APT 0.6 Transitional 安装socat 几乎所有流行的黑客工具都可以在 BigBoss Recommendation tools这个包中找到 ( APT 0.6 Transitional, Git, GNU Debugger, less, make, unzip, wget 和 SQLite 3.x)

apt-get install socat

如果找不到安装包的时候,运行一下 apt-get update, 获得最新的包列表.

2.2 连接到系统日志的sock文件

socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock

  • 进入到命令行交互界面,这时可以输入help查看帮助
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock

========================
ASL is here to serve you
> 

2.3 日志的查看

输入watch查看,输入stop停止

2.4 清除日志文件数据

cat /dev/null >/var/log/syslog

III deviceconsole

自从iOS8之后,我就习惯使用Mac系统自带的console ,后来发现有些同事的Mac中console 版本低,没有device 选项;于是乎,就推荐他们使用deviceconsole

  • deviceconsole --help
➜  bin git:(master) ✗ deviceconsole --help
Usage: deviceconsole [options]
Options:
 -d      Include connect/disconnect messages in standard out
 -u <udid>    Show only logs from a specific device
 -p <process name>  Show only logs from a specific process

Control-C to disconnect
Mail bug reports and suggestions to <ryan.petrich@medialets.com>
  • knlog -help

    Usage: knlog [options]
    Options:
    -i | --case-insensitive     Make filters case-insensitive
    -f | --filter <string>      Filter include by single word occurrences (case-sensitive)
    -x | --exclude <string>     Filter exclude by single word occurrences (case-sensitive)
    -p | --process <string>     Filter by process name (case-sensitive)
    -u | --udid <udid>          Show only logs from a specific device
    -s | --simulator <version>  Show logs from iOS Simulator
         --debug                Include connect/disconnect messages in standard out
         --use-separators       Skip a line between each line
         --force-color          Force colored text
         --message-only          Display only level and message
    Control-C to disconnect
    
  • 编译之后的可执行文件 knlog

see also

更多内容请关注 #小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域;更多服务和咨询请关注#公众号:iOS逆向。

iOS逆向小技能:Theos的安装

2022年1月18日 14:15

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

前言

Theos是越狱开发工具包。logos语法简单。,它给我们准备好了一些代码模板、预置一些基本的Makefile脚本,这样我们开发一个tweak就会变得方便的多,

(整合在Xcode的iOSopendev )由于逆向工程很多东西无法自动化,因此推荐Theos

I 安装Thoes

1.1 安装Xcode

安装Xcode,以及command line tools

1.2 下载Thoes

下载Thoes:https://github.com/theos/theos

查看环境变量: 终端中输入命令env

建立环境变量:

 export THEOS=/opt/theos
#在当前终端中起作用了,关闭终端后又得重新设置。

为了避免每次都建立这个环境变量,建立一个永久的环境变量 : 编辑~/.profile文件,在其中添加export THEOS=/opt/theos/,这个环境变量就是永久的了.

记得source

source .profile 

或者使用.bash_profile

 open -e ~/.bash_profile


export THEOS=/opt/theos

 source .bash_profile
devzkndeMacBook-Pro:opt devzkn$ git clone --recursive https://github.com/theos/theos.git $THEOS


fatal: could not create work tree dir '/opt/theos': Permission denied
devzkndeMacBook-Pro:opt devzkn$ sudo git clone --recursive https://github.com/theos/theos.git $THEOS
Password:
Cloning into '/opt/theos'...

新版的theos 已经自带CydiaSubstrate.framework(基本上,tweak都依赖于一个名叫cydia Substrate (以前名字也叫mobile Substrate)的动态库,Mobile Substrate是Cydia的作者Jay Freeman (@saurik)的作品,也叫Cydia Substrate,它的主要功能是hook某个App,修改代码比如替换其中方法的实现,Cydia上的tweak都是基于Mobile Substrate实现的.)


devzkndeMacBook-Pro:lib devzkn$ pwd
/opt/theos/vendor/lib
devzkndeMacBook-Pro:lib devzkn$ ls -lrt
total 72
drwxr-xr-x  3 root  wheel   102 Aug 10 15:19 libswift
lrwxr-xr-x  1 root  wheel    43 Aug 10 15:19 libsubstrate.tbd -> CydiaSubstrate.framework/CydiaSubstrate.tbd
-rw-r--r--  1 root  wheel   635 Aug 10 15:19 librocketbootstrap.tbd
-rw-r--r--  1 root  wheel   392 Aug 10 15:19 libprefs.tbd
-rw-r--r--  1 root  wheel   588 Aug 10 15:19 libflipswitch.tbd
-rw-r--r--  1 root  wheel  1111 Aug 10 15:19 libapplist.tbd
-rw-r--r--  1 root  wheel  5646 Aug 10 15:19 libactivator.tbd
drwxr-xr-x  4 root  wheel   136 Aug 10 15:19 TechSupport.framework
-rw-r--r--  1 root  wheel   432 Aug 10 15:19 README.md
drwxr-xr-x  5 root  wheel   170 Aug 10 15:19 Opener.framework
-rw-r--r--  1 root  wheel  3342 Aug 10 15:19 LICENSE.md
drwxr-xr-x  5 root  wheel   170 Aug 10 15:19 CydiaSubstrate.framework
drwxr-xr-x  4 root  wheel   136 Aug 10 15:19 Cycript.framework
drwxr-xr-x  5 root  wheel   170 Aug 10 15:19 CepheiPrefs.framework
drwxr-xr-x  4 root  wheel   136 Aug 10 15:19 Cephei.framework

1.3 配置ldid

用来专门签名iOS可执行文件的工具,用以在越狱iOS中取代Xcode自带的codesign. 安装这个ldid,推荐的方式是采用brew来安装--

 brew install ldid

ps : 安装brew

1.4 dpkg-deb

deb是越狱开发包的标准格式,dpkg-deb是个用于操作deb文件的工具,有了这个工具,Theos才能正确的把工程打包成deb文件.

brew install dpkg

see also

更多内容请关注 #小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域;更多服务和咨询请关注#公众号:iOS逆向。

❌
❌