objective-c runtime安全措施之二:反注入

本文介绍了一种通过在类函数调用前进行完整性检测来提高iOS应用程序安全性的方法,并提供了具体的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记

反注入:在类函数被调用前做完整性检测(预防应用自定义函数或apple标准库函数被修改或替换)

原理:调用dladdr()函数检查类方法的基本信息是否合法

例子1:检查Foundation框架类中NSMutableURLRequest基类(用于改变URL请求)的setHTTPBody方法的基本信息

#include <dlfcn.h>

#include <objc/objc.h>

#include <objc/runtime.h>

#include <stdio.h>

#include <string.h>

int main() {

Dl_info info;

IMP imp = class_getMethodImplementation(

objc_getClass("NSMutableURLRequest"),

sel_registerName("setHTTPBody:"));

printf("pointer %p\n", imp);

if (dladdr(imp, &info)) {

printf("dli_fname: %s\n", info.dli_fname);

printf("dli_sname: %s\n", info.dli_sname);

printf("dli_fbase: %p\n", info.dli_fbase);

printf("dli_saddr: %p\n", info.dli_saddr);

} else {

printf("error: can't find that symbol.\n");

}

}

在Mac OS上使用gcc编译

$ gcc -o main main.m -lobjc -framework Foundation

然后运行该程序和观察输出,这些信息(地址空间、文件名、符号名)可以确认该函数来源、是否合法

$ ./main

pointer 0x7fff8e7aba62

dli_fname: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation

dli_sname: -[NSMutableURLRequest(NSMutableHTTPURLRequest) setHTTPBody:]

dli_fbase: 0x7fff8e633000

dli_saddr: 0x7fff8e7aba62

例子2:使用dladdr函数检查类中的所有方法的通用代码

#include <dlfcn.h>

#include <stdio.h>

#include <objc/objc.h>

#include <objc/runtime.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

static inline BOOL validate_methods(const char *, const char *)

__attribute__((always_inline));

BOOL validate_methods(const char *cls, const char *fname) {

Class aClass = objc_getClass(cls);

Method *methods;

unsigned int nMethods;

Dl_info info;

IMP imp;

char buf[128];

Method m;

if (!aClass)

return NO;

methods = class_copyMethodList(aClass, &nMethods);

while(nMethods--) {

m = methods[nMethods];

printf("validating [ %s %s ]\n",

(const char *) class_getName(aClass),

(const char *) method_getName(m));

imp = method_getImplementation(m);

if (!imp) {

printf("error: method_getImplementation(%s) failed\n",

(const char *) method_getName(m));

free(methods);

return NO;

}

if (! dladdr(imp, &info)) {

printf("error: dladdr() failed for %s\n",

(const char *)method_getName(m));

free(methods);

return NO;

}

/* Validate image path */

if (strcmp(info.dli_fname, fname))

goto FAIL;

/* Validate class name in symbol */

snprintf(buf, sizeof(buf), "[%s ",

(const char *) class_getName(aClass));

if (strncmp(info.dli_sname+1, buf, strlen(buf)))

{

snprintf(buf, sizeof(buf), "[%s(",

(const char *) class_getName(aClass));

if (strncmp(info.dli_sname+1, buf, strlen(buf)))

goto FAIL;

}

/* Validate selector in symbol */

snprintf(buf, sizeof(buf), " %s]",

(const char *) method_getName(m));

if (strncmp(info.dli_sname + (strlen(info.dli_sname) - strlen(buf)),

buf, strlen(buf)))

{

goto FAIL;

}

}

return YES;

FAIL:

printf("method %s failed integrity test:\n",

(const char *)method_getName(m));

printf(" dli_fname: %s\n", info.dli_fname);

printf(" dli_sname: %s\n", info.dli_sname);

printf(" dli_fbase: %p\n", info.dli_fbase);

printf(" dli_saddr: %p\n", info.dli_saddr);

free(methods);

return NO;

}

【注意】

1.    重命名检查函数(例如不要用validate_methods这样具有明显意义的名字)

2.    在应用的多处加入检查函数,任何与敏感数据交互的方法在执行前都需要检查

3.    例子中的logging和printf语句只是用来调试,代码正式发布前要移除

4.    验证完整性只是提高了攻击的门槛,不能完全防御黑客,需要综合应用多种技巧,例如思路一中的反调试技巧,及马上要介绍的反汇编技巧

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值