Dyld_Introduction

动态库: 静态库、动态库的区别,编译和注入;导出和隐藏符号表;

Posted by kunnan on August 14, 2018

静态库和动态库的区别

image

  • 动态库的特点

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

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

I 、动态库的编译和注入

  • 编译

  • 动态库注入放入几种方式

    • I 、cycript注入动态库的方式

      在挂载的进程上创建一个挂起的线程, 然后在这个线程里申请一片用于加载动态库的内存,然后恢复线程,动态库就被注入(通过 taskfor_pid函数获取目标进程句柄,然后通过在进程内创建新线程并执行自己的代码。)
          
      
    • II 通过增加load command 的LC_LOAD_DYLIB或者LC_LOAD_WEAK_DYLIB,指定动态库的路径来实现注入

      • optool

      • insert_dylib

        • insert_dylib:# Command line utility for inserting a dylib load command into a Mach-O binary

        • #通过修改可执行文件的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 、通过设置环境变量DYLD_INSERT_LIBRARIES指定要注入的动态库path

      • 利用环境变量 DYLD_INSERT_LIBRARY 来添加动态库dumpdecrypted.dylib

        DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/01ECB9D1-858D-4BC6-90CE-922942460859/KNWeChat.app/KNWeChat
              
        

导出和隐藏符号

  •  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
      
    
  • 控制符号是否导出

使用dlopen 动态的方式调用c++、oc编写的动态库

c++

  • dlopen

    • c++ dylib code
    • 这里的符号是通过c 导出的,所以直接写名字;如果是c++ 导出的,就要指定c++ 的符号, 这点和获取swift类时是一样的。
    //        void *lib_handle = dlopen("/Library/MobileSubstrate/DynamicLibraries/target.dylib", RTLD_LOCAL);
    //        if(!lib_handle){
    //            NSLog(@"Unable to open library: %s",dlerror());
    //            return 0;
    //        }
    //
    //        Person_creator* NewPerson = (Person_creator*)dlsym(lib_handle, "_Z9NewPersonv");
    //        if(!NewPerson){
    //            NSLog(@"Unable to find NewPerson method:%s",dlerror());
    //            return 0;
    //        }
    //
    //        Person_disposer* DeletePerson = (Person_disposer*)dlsym(lib_handle, "_Z12DeletePersonP6Person");
    //        if(!DeletePerson){
    //            NSLog(@"Unable to find DeletePerson method:%s",dlerror());
    //            return 0;
    //        }
    //
    //        Person* person = (Person*)NewPerson();
    //
    //        NSLog(@"person->name() = %s",person->name());
    //
    //        char new_name[] = "AloneMonkey";
    //
    //        person->set_name(new_name);
    //
    //        NSLog(@"person->name() = %s",person->name());
    //
    //        DeletePerson(person);
    //
    //        if(dlclose(lib_handle) != 0){
    //            NSLog(@"Unable to close library: %s",dlerror());
    //        }
      
      
    

oc

  • dlopen

    • oc 的动态库和正常使用动态库没有区别
    • oc dylib code
            // Open the library.
            void* lib_handle = dlopen("/Library/MobileSubstrate/DynamicLibraries/target.dylib", RTLD_LOCAL);
            if (!lib_handle) {
                NSLog(@"[%s] main: Unable to open library: %s\n",
                      __FILE__, dlerror());
                exit(EXIT_FAILURE);
            }
              
            Class PersonClass = objc_getClass("Person");
            if (!PersonClass) {
                NSLog(@"[%s] main: Unable to get Person class", __FILE__);
                exit(EXIT_FAILURE);
            }
              
            NSLog(@"[%s] main: Instantiating PersonClass", __FILE__);
            Person* person = [PersonClass new];
              
            [person setName:@"Alone Monkey"];
            NSLog(@"[%s] main: [person name] = %@", __FILE__, [person name]);
              
            if (dlclose(lib_handle) != 0) {
                NSLog(@"[%s] Unable to close library: %s\n",
                      __FILE__, dlerror());
                exit(EXIT_FAILURE);
            }
      
    

swift

  • getenv

    char * getenv(const char *name) {
      static void *handle;      // 1
      static char * (*real_getenv)(const char *); // 2
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{  // 3
        handle = dlopen("/usr/lib/system/libsystem_c.dylib", RTLD_NOW);
        assert(handle);
        real_getenv = dlsym(handle, "getenv");
    });
      if (strcmp(name, "HOME") == 0) { // 4
    return "/"; }
      return real_getenv(name); // 5
    }
      
    
  • dlopen

    if let handle = dlopen("./Frameworks/HookingSwift.framework/
    HookingSwift", RTLD_NOW) {
    }
          let sym = dlsym(handle, "_TFC12HookingSwift23CopyrightImageGeneratorgP33_71AD57F3ABD678B113CF3AD05D01FF4113originalImageGSqCSo7UIImage_")!
                print("\(sym)")
      
    
 import UIKit
 import HookingSwift
 
 class ViewController: UIViewController {
 
   // MARK: - IBOutlets
   @IBOutlet weak var imageView: UIImageView!
 
   // MARK: - View Life Cycle
   override func viewDidLoad() {
     super.viewDidLoad()
     
     let imageGenerator = CopyrightImageGenerator()
     imageView.image = imageGenerator.watermarkedImage
     
     if let handle = dlopen("./Frameworks/HookingSwift.framework/HookingSwift", RTLD_NOW) {
       let sym = dlsym(handle, "_TFC12HookingSwift23CopyrightImageGeneratorgP33_71AD57F3ABD678B113CF3AD05D01FF4113originalImageGSqCSo7UIImage_")!
       typealias privateMethodAlias = @convention(c) (Any) -> UIImage?
       let originalImageFunction = unsafeBitCast(sym, to: privateMethodAlias.self)
       let originalImage = originalImageFunction(imageGenerator)
       imageView.image = originalImage
     }
   }
 }
 

使用capstone Hook dylib

#import <substrate.h> #import "capstone.h" static CFStringRef (*old_MGCA)(CFStringRef Key);
CFStringRef new_MGCA(CFStringRef Key){
        CFStringRef Ret=old_MGCA(Key);
        NSLog(@"MGHooker:%@\nReturn Value:%@",Key,Ret);
        return Ret;
}
%ctor {
        void * Symbol=MSFindSymbol(MSGetImageByName("/usr/lib/libMobileGestalt.dylib"), "_MGCopyAnswer");
        NSLog(@"MG: %p",Symbol);
        csh handle;
        cs_insn *insn;
        cs_insn BLInstruction;
        size_t count;
        unsigned long realMGAddress=0;
        //MSHookFunction(Symbol,(void*)new_MGCA, (void**)&old_MGCA);
        if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &handle) == CS_ERR_OK) {
          /*cs_disasm(csh handle, const uint8_t *code, size_t code_size, uint64_t address, size_t count, cs_insn **insn);*/
                count=cs_disasm(handle,(const uint8_t *)Symbol,0x1000,(uint64_t)Symbol,0,&insn);
                if (count > 0) {
                        NSLog(@"Found %lu instructions",count);
                        for (size_t j = 0; j < count; j++) {
                              NSLog(@"0x%" PRIx64 ":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic,insn[j].op_str);
                                if(insn[j].id==ARM64_INS_B){
                                  BLInstruction=insn[j];
                                  sscanf(BLInstruction.op_str, "#%lx", &realMGAddress);
                                  break;
                                }
                        }

                        cs_free(insn, count);
                } else{
                  NSLog(@"ERROR: Failed to disassemble given code!%i \n",cs_errno(handle));
                }


                cs_close(&handle);

                //Now perform actual hook
                MSHookFunction((void*)realMGAddress,(void*)new_MGCA, (void**)&old_MGCA);
}
else{
        NSLog(@"MGHooker: CSE Failed");
}
}


See Also

/Users/devzkn/bin//knpost Dyld_Introduction 动态库: 静态库、动态库的区别,编译和注入;导出和银川符号表; -t dyld
#原来""的参数,需要自己加上""

转载请注明: > Dyld_Introduction