iOS安全攻防技能总结

Posted by Marco Liu on October 10, 2018

“Security and defense ”

逆向技能清单

1.1 例子
  • 实现App Store的自动下载

  • 反编译团贷网项目,拿到正式环境的加密key

  • hook团贷网app网络请求并成功获取以及修改参数

1.2 逆向知识
  • 通过usb或者wifi连接ssh通道、登录iPhone,通过Cycript命令行调试iPhone

  • 对ipa进行脱壳、使用class-dump生产头文件,使用Reveal工具查看APP布局

  • 使用Hopper或者ida工具分析源码,掌握了常用的逆向工具的原理和部分逆向技术的原理

  • 使用MonkeyDev进行逆向开发,掌握了Logos Tweak语法进行Hook原生方法,对App注入自己的代码

  • 学习了iOS系统底层原理,包括不等于mach-o文件、程序加载、arm64汇编、动态链接、系统文件目录等
  • 安全保护
  • 静态混淆: [Static_obfuscation]
  • 动态保护:反调试(PT_DENY_ATTACH = 31参数用于告诉系统阻止调试器的依附;利用sysctl函数查看当前进程信息,判断是否有此标志位来检测是否处理调试状态)、反反调试、反注入(通过_dyld_get_image_name()获取加载的模块名,判断是否都在白名单中)、hook检测(通过dladdr函数得到imp地址所在的模块info.dli_fname;遍历符号表中的每一个指针,然后判断指针是不是指向__stub_helper或者系统模块; 分析函数的内存前几条指令中有没有跳转)、完整性校验(检查文件load command 的修改,获取内存中运行代码的md5值;是否重签名,从可执行文件的LC_CODE_SIGNATURE 读取信息,拿到当前的签名文件的签名信息和编译前的签名信息比对;bid)
  • 代码混淆:
  • 静态库混淆:混淆带有bitcode的静态
  • 采用LLVM针对源代码混淆
1.4 使用的技术
  • 动态库的注入原理:
    • 一个是基于修改[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 就是以这种方式执行脚本代码。
  • hook 的方式: 一个是通过修改内存中懒加载和非懒加载符号表指针所指向的地址来达到修改方法的目的,作用于主模块懒加载和非懒加载表的符号,在越狱和非越狱环境都可以使用,例如fishhook(符号表替换)。一个是 cydia substrate: 通过inline hook的方式修改目标函数内存中的汇编指令,使其调转到自己的代码块,以达到修改程序的目的;主要是针对c,c++ 函数。同时支持针对oc的method swizzle(替换imp)
    • [hooking-swift-methods 利用MSHookFunction、MSFindSymbol进行实现。]
      • Using nm , we can dump the Swift symbols
      • Using MSFindSymbol we can find the function pointer to the Swift method, and call it
    • hook MGCopyAnswer 使用了 libcapstone + dlopen+ MSHookFunction
      • [使用capstone进行MGCopyAnswer方法地址获取,然后使用MSHookFunction 对方法进行hook]
      • gestalt = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY);
      • size_t CAPSTONE_API cs_disasm(csh handle, const uint8_t *code, size_t code_size, uint64_t address, size_t count, cs_insn **insn);
    • facebook/fishhook符号表替换:: struct rebinding { const char *name; void *replacement; void **replaced;};
      • rebind_symbols((struct rebinding[1])\{\{"ptrace", my_ptrace, (void*)&orig_ptrace}},1); 第一个参数为需要替换的符号,第二个参数为自己实现的函数名称,第三个参数为原函数地址,因为他是基于地址进行替换的)+ __attribute__((constructor))实现注入
    • void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result);
      • MSHookMessageEx(_logos_class$wxHook$CMessageMgr, @selector(UpdateVoiceMessage:MsgWrap:), (IMP)&_logos_method$wxHook$CMessageMgr$UpdateVoiceMessage$MsgWrap$, (IMP*)&_logos_orig$wxHook$CMessageMgr$UpdateVoiceMessage$MsgWrap$);
    • void MSHookFunction(void *symbol, void *replace, void **result); 注入方式和fishhook 一样,都是基于地址进行hook的
      • MSHookFunction(&CNCopyCurrentNetworkInfo, &newCNCopyCurrentNetworkInfo, &oldCNCopyCurrentNetworkInfo);
      • MSHookFunction((void *)MSFindSymbol(NULL,"_ptrace"), (void *)newptrace, (void **)&oldptrace);
  • object-c 的运行时API: 动态新增属性(objc_setAssociatedObject、objc_getAssociatedObject);修改和获取属性(class_getInstanceVariable、object_setIvar、object_getIvar);swizzling交换替换方法的实现(class_getInstanceMethod、class_addMethod、class_replaceMethod、method_exchangeImplementations,想要执行原来的方法就直接调用replaceMethod,因为方法的实现IMP已经被换了)
  • LLDB+chisel
    • 给/usr/bin/debugserver添加task_for_pid权限, 并开启 debugserver host:port --attach=<process_name>(有五种启动方式:auto、posix、fork、backboard 、frontboard),常用backboard 从头开始调试,例如进行[anti ptrace]。
    • 使用symbolic breakpoint 进行条件断点。
  • 开发的ide和分析工具: theos、monkeydev、[lipo]、[cycript]、[hopper] 进行查看交叉引用,修改汇编、[frida-ios-dump]、[mach-oView]、[KNtoggle-pie:changes the MH_PIE flag of the MACH-O header on iOS applications to disable ASLR on applications,只支持app,不支持动态库,因为动态库需要ASLR特性的来保证模块基地址不冲突]、AntiAntiDebug.m

—— Marco 记于 2018.11