当前位置:编程学习 > 网站相关 >>

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

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

 

 

作者  danqingd

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,