最新要闻
- 抄袭、偷票房、成本1千万争端不断!张艺谋:《满江红》是正能量传承
- 网易暴雪游戏退款服务爆火!排队人数超100万 你退了多少?
- 恒大恒驰上海公司被强执409万:累计被执行2.8亿
- 京东PLUS会员与爱奇艺、喜马拉雅联名卡宣布调价:都涨了
- 视焦点讯!能怎样?韩数万用户上诉苹果:故意降低旧款iPhone性能让换新败诉
- 每日观察!马斯克测试推特“仅粉丝可见”遭群嘲:懂的工程师都被裁了?
- 每日消息!董明珠造车路又遭一击!海南三亚67辆格力钛新能源大巴起火被烧
- 焦点简讯:限制480P投屏被7年老粉起诉:律师称爱奇艺大概率会败诉
- 网友囤1000片退烧药全砸手里了被点赞:囤N95口罩血氧仪价格也都惨了
- iPhone反复输错密码 Apple ID锁定怎么办?苹果解答
- 当前播报:比特斯拉还狠!蔚来被曝降价促销 降幅最高超过10万元
- 完胜iPhone 14 Pro Max!一加Ace 2连续滑动10万次:没有1次断触
- 天天快资讯丨河北90后小伙做叶雕月入过万 一张“树叶”售价120元
- 天天微头条丨米哈游起诉《原神》内鬼泄密 获赔15000元
- 世界观天下!小米汽车设计文件意外泄密被疯传!小米通报:供应商被罚100万
- 批判主义的观点是什么?批判主义的代表人物有哪些?
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
每日视讯:IOS逆向--恢复Dyld的内存加载方式
之前我们一直在使用由dyld及其NS Create Object File ImageFrom Memory / NS Link Module API方法所提供的Mach-O捆绑包的内存加载方式。虽然这些方法我们今天仍然还在使用,但是这个工具较以往有一个很大的区别......现在很多模块都被持久化到了硬盘上。
@roguesys 在 2022 年 2 月发布公告称,dyld 的代码已经被更新,传递给 NSLinkModule 的任何模块都将会被写入到一个临时的位置中。
(资料图片)
作为一个红队队员,这对于我们的渗透工作并没有好处。毕竟,NSLinkModule一个非常有用的api函数,这个函数可以使得我们的有效载荷不被蓝队轻易的发现。
因此,在这篇文章中,我们来仔细看看dyld的变化,并看看我们能做些什么来恢复这一功能,让我们的工具在内存中多保存一段时间,防止被蓝队过早的发现。
NS Link Module有何与众不同
由于dyld是开源的,我们可以深入研究一下经常使用的NSLinkModule方法的工作原理。
该函数的签名为:
NSModule APIs::NSLinkModule(NSObjectFileImage ofi, const char* moduleName, uint32_t options) { ... }
该函数的第一个参数是ofi,它是用NS Create Object File Image From Memory创建的,它指向了存放Mach-O包的内存。然后我们还有moduleName参数和options参数,前者只是用于记录语句,后者一般是被忽略不用的。
通过查看代码发现,最新版本的NS Link Module,会将osi所指向的内存写入磁盘。
if ( ofi->memSource != nullptr ) { ... char tempFileName[PATH_MAX]; const char* tmpDir = this->libSystemHelpers->getenv("TMPDIR"); if ( (tmpDir != nullptr) && (strlen(tmpDir) > 2) ) { strlcpy(tempFileName, tmpDir, PATH_MAX); if ( tmpDir[strlen(tmpDir) - 1] != "/" ) strlcat(tempFileName, "/", PATH_MAX); } else strlcpy(tempFileName, "/tmp/", PATH_MAX); strlcat(tempFileName, "NSCreateObjectFileImageFromMemory-XXXXXXXX", PATH_MAX); int fd = this->libSystemHelpers->mkstemp(tempFileName); if ( fd != -1 ) { ssize_t writtenSize = ::pwrite(fd, ofi->memSource, ofi->memLength, 0); } ...}
通过分析可以发现,代码并不是真正的发生了 "新 "的变化。这段代码一直存在于dyld3中,只不过是现在macOS也决定使用这段代码路径。所以我们知道内存会被写入磁盘,并且路径会被传递给dlopen_from。
...ofi->handle = dlopen_from(ofi->path, openMode, callerAddress);...
因此,从本质上讲,这也就使得NS Link Module成为了dlopen的一个封装器。
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
① 网安学习成长路径思维导图 ② 60+网安经典常用工具包 ③ 100+SRC漏洞分析报告 ④ 150+网安攻防实战技术电子书 ⑤ 最权威CISSP 认证考试指南+题库 ⑥ 超1800页CTF实战技巧手册 ⑦ 最新网安大厂面试题合集(含答案) ⑧ APP客户端安全检测指南(安卓+IOS)
那我们能否恢复dyld之前的内存加载特性呢?
我们知道磁盘 I/O 是被用来持久化和读取我们的代码的......那么,如果我们在调用之前拦截它们,会发生什么呢?
使用dyld进行hook
为了拦截 I/O 调用,我们首先需要了解如何对dyld进行hook。
我们研究看看dyld是如何处理mmap调用的。启动 Hopper 并加载 /usr/lib/dyld, 显示mmap 是由 dyld 使用 svc 调用的。
知道了这一点,如果我们找到内存中存放这段代码的位置,我们就应该能够覆盖服务调用并将其重定向到我们控制的地方。但我们该用什么来覆盖它呢?用下面的这段代码就可以。
ldr x8, _valuebr x8_value: .ascii "\x41\x42\x43\x44\x45\x46\x47\x48" ; Update to our br location
在我们进行操作之前,首先我们找到进程地址空间中dyld的基址。这是通过调用task_info完成的,我们可以传入TASK_DYLD_INFO来检索dyld的基址信息。
void *getDyldBase(void) { struct task_dyld_info dyld_info; mach_vm_address_t image_infos; struct dyld_all_image_infos *infos; mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; kern_return_t ret; ret = task_info(mach_task_self_, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); if (ret != KERN_SUCCESS) { return NULL; } image_infos = dyld_info.all_image_info_addr; infos = (struct dyld_all_image_infos *)image_infos; return infos->dyldImageLoadAddress;}
只要我们有了dyld的基址,我们就可以为mmap服务的调用查找签名。
bool searchAndPatch(char *base, char *signature, int length, void *target) { char *patchAddr = NULL; kern_return_t kret; for(int i=0; i < 0x100000; i++) { if (base[i] == signature[0] && memcmp(base+i, signature, length) == 0) { patchAddr = base + i; break; } } ...
当我们找到一个匹配的签名时,我们可以在我们的ARM64的Stub中打补丁。由于我们要处理的是内存的 "Read-Exec"页,我们需要用以下方法来更新内存保护。
kret = vm_protect(mach_task_self(), (vm_address_t)patchAddr, sizeof(patch), false, PROT_READ | PROT_WRITE | VM_PROT_COPY);if (kret != KERN_SUCCESS) { return FALSE;}
注意这里的VM_PROT, 这个是必须要设定的,因为该内存页在其最大内存保护中没有设置写权限。
设置了写权限后,我们可以用我们的补丁覆盖内存,然后将保护重新设定为Read-Exec。
// Copy our pathmemcpy(patchAddr, patch, sizeof(patch));// Set the br address for our hook call*(void **)((char*)patchAddr + 16) = target;// Return exec permissionkret = vm_protect(mach_task_self(), (vm_address_t)patchAddr, sizeof(patch), false, PROT_READ | PROT_EXEC);if (kret != KERN_SUCCESS) { return FALSE;}
现在我们需要思考一下,当我们在试图修改可执行的内存页时,在M1 macs上会发生什么。
由于macOS要确保每一页可执行内存都有签名,这也就意味着我们需要一个com.apple.security.cs.allow-unsigned-executable-memory的权限(com.apple.security.cs.disable-executable-page-protection也适用)来运行我们的代码。
那么,既然如此,我们该如何处理我们的hook程序呢?
API模拟调用
有了所有组件的映射,我们现在就可以开始模拟API的调用。根据dyld的代码,我们需要对mmap、pread、fcntl的内容进行处理。
如果我们这样做是正确的,我们可以在内存指向空白Mach-O文件的情况下对NSLinkModule进行调用,而该文件又将会被写入磁盘。然后当dyld正在从磁盘上读入文件时,我们就可以用内存中的副本动态地交换内容。
首先研究mmap。我们首先检查fd是否指向一个包含NSCreateObjectFileImageFromMemory的文件名,这是dyld写入磁盘的临时文件。
如果是这样的话,我们就不需要从磁盘上映射内存了,只要简单地分配一个新的内存区域,然后复制到我们构造的Mach-O包上。
#define FILENAME_SEARCH "NSCreateObjectFileImageFromMemory-"const void* hookedMmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) { char *alloc; char filePath[PATH_MAX]; int newFlags; memset(filePath, 0, sizeof(filePath)); // Check if the file is our "in-memory" file if (fcntl(fd, F_GETPATH, filePath) != -1) { if (strstr(filePath, FILENAME_SEARCH) > 0) { newFlags = MAP_PRIVATE | MAP_ANONYMOUS; if (addr != 0) { newFlags |= MAP_FIXED; } alloc = mmap(addr, len, PROT_READ | PROT_WRITE, newFlags, 0, 0); memcpy(alloc, memoryLoadedFile+offset, len); vm_protect(mach_task_self(), (vm_address_t)alloc, len, false, prot); return alloc; } } // If for another file, we pass through return mmap(addr, len, prot, flags, fd, offset);}
接下来是pread参数,它会被dyld在加载时用来多次验证Mach-O的UUID。
ssize_t hookedPread(int fd, void *buf, size_t nbyte, int offset) { char filePath[PATH_MAX]; memset(filePath, 0, sizeof(filePath)); // Check if the file is our "in-memory" file if (fcntl(fd, F_GETPATH, filePath) != -1) { if (strstr(filePath, FILENAME_SEARCH) > 0) { memcpy(buf, memoryLoadedFile+offset, nbyte); return nbyte; } } // If for another file, we pass through return pread(fd, buf, nbyte, offset);}
最后我们处理fcntl。它会在很多地方被调用,可以在任何可能会失败的mmap调用之前验证编码的要求。
由于我们已经完成了hook,我们可以使dyld正常运行来绕过这些检查。
int hookedFcntl(int fildes, int cmd, void* param) { char filePath[PATH_MAX]; memset(filePath, 0, sizeof(filePath)); // Check if the file is our "in-memory" file if (fcntl(fildes, F_GETPATH, filePath) != -1) { if (strstr(filePath, FILENAME_SEARCH) > 0) { if (cmd == F_ADDFILESIGS_RETURN) { fsignatures_t *fsig = (fsignatures_t*)param; // called to check that cert covers file.. so we"ll make it cover everything ;) fsig->fs_file_start = 0xFFFFFFFF; return 0; } // Signature sanity check by dyld if (cmd == F_CHECK_LV) { // Just say everything is fine return 0; } } } return fcntl(fildes, cmd, param);}
有了以上这些,然后我们可以把这一切组合起来。
int main(int argc, const char * argv[], const char * argv2[], const char * argv3[]) { @autoreleasepool { char *dyldBase; int fd; int size; void (*function)(void); NSObjectFileImage fileImage; // Read in our dyld we want to memory load... obviously swap this in prod with memory, otherwise we"ve just recreated dlopen :/ size = readFile("/tmp/loadme", &memoryLoadedFile); dyldBase = getDyldBase(); searchAndPatch(dyldBase, mmapSig, sizeof(mmapSig), hookedMmap); searchAndPatch(dyldBase, preadSig, sizeof(preadSig), hookedPread); searchAndPatch(dyldBase, fcntlSig, sizeof(fcntlSig), hookedFcntl); // Set up blank content, same size as our Mach-O char *fakeImage = (char *)malloc(size); memset(fakeImage, 0x41, size); // Small hack to get around NSCreateObjectFileImageFromMemory validating our fake image fileImage = (NSObjectFileImage)malloc(1024); *(void **)(((char*)fileImage+0x8)) = fakeImage; *(void **)(((char*)fileImage+0x10)) = size; void *module = NSLinkModule(fileImage, "test", NSLINKMODULE_OPTION_PRIVATE); void *symbol = NSLookupSymbolInModule(module, "runme"); function = NSAddressOfSymbol(symbol); function(); }}
当我们执行时,可以看到在硬盘上就会创建我们的虚假文件。
但通过在运行时的交换内容来看,我们发现我们的内存模块加载完全正常。
其他
所以,最后一个阶段让我感到很困惑......我们使用了NSLinkModule,它生成了一个临时文件,并且用垃圾字符对它进行了填充。如果我们忽略这一点,而只是使用操作系统中的任意一个库来调用dlopen呢?这样应该就可以避免我们向磁盘中写入任何文件。
事实证明,这个想法是正确的。比如:
void *a = dlopen("/usr/lib/libffi-trampolines.dylib", RTLD_NOW);function = dlsym(a, "runme");function();
而不是只是搜索NSCreateObjectFileImageFromMemory,我们只是在搜索任何加载libffi-trampolines.dylib的引用,并通过我们的代码进行了替换,我们得到了同样的结果。
这里有一些注意事项。首先,我们需要确保库比我们自己要加载的模块大,否则当涉及到pread和mmap时,系统最终会截断我们的Mach-O。
更多靶场实验练习、网安学习资料,请点击这里>>
-
每日视讯:IOS逆向--恢复Dyld的内存加载方式
之前我们一直在使用由dyld及其NSCreateObjectFileImageFromMemory NSLinkModuleAPI方法所提供的Mach-O捆绑包的内存加载方式。虽
来源: 每日视讯:IOS逆向--恢复Dyld的内存加载方式
世界快讯:智能学习灯赛道竞争日趋激烈 火山引擎 VeDI 用数据技术助力打造新优势
全球微资讯!Java里面为什么搞了双重检查锁,写完这篇文章终于真相大白了
抄袭、偷票房、成本1千万争端不断!张艺谋:《满江红》是正能量传承
网易暴雪游戏退款服务爆火!排队人数超100万 你退了多少?
恒大恒驰上海公司被强执409万:累计被执行2.8亿
天天热头条丨微信多开工具,微信消息防撤回、QQ消息防撤回、Tim消息防撤回,不错过每一条消息
京东PLUS会员与爱奇艺、喜马拉雅联名卡宣布调价:都涨了
视焦点讯!能怎样?韩数万用户上诉苹果:故意降低旧款iPhone性能让换新败诉
每日观察!马斯克测试推特“仅粉丝可见”遭群嘲:懂的工程师都被裁了?
每日消息!董明珠造车路又遭一击!海南三亚67辆格力钛新能源大巴起火被烧
焦点简讯:限制480P投屏被7年老粉起诉:律师称爱奇艺大概率会败诉
网友囤1000片退烧药全砸手里了被点赞:囤N95口罩血氧仪价格也都惨了
iPhone反复输错密码 Apple ID锁定怎么办?苹果解答
当前播报:比特斯拉还狠!蔚来被曝降价促销 降幅最高超过10万元
环球新动态:刚上班三天就被裁。。还有谁!!
对话 BitSail Contributor | 梁奋杰:保持耐心,享受创造
当前视点!云原生场景下实现编译加速
【北斗七星】北斗卫星授时之星解读与应用
全球速看:kubernetes 污点(Taint)和容忍度(Toleration)研究
完胜iPhone 14 Pro Max!一加Ace 2连续滑动10万次:没有1次断触
天天快资讯丨河北90后小伙做叶雕月入过万 一张“树叶”售价120元
天天微头条丨米哈游起诉《原神》内鬼泄密 获赔15000元
世界观天下!小米汽车设计文件意外泄密被疯传!小米通报:供应商被罚100万
批判主义的观点是什么?批判主义的代表人物有哪些?
什么是平稳序列?平稳序列的三个条件是什么?
imovie怎么添加音乐?imovie怎么调整视频画面大小?
怎么制作电子图章?图章制作软件有哪些?
罹难怎么读?罹难是什么意思?
平板电视和液晶电视有什么区别?平板电视哪个牌子质量好?
ctrl键无响应是什么原因?ctrl键无响应怎么办?
怎么用电脑打电话?电脑打电话没声音是怎么回事?
手机进水了怎么处理比较好?手机进水了放什么歌可以把水震出来?
csv文件用什么打开?csv文件打开乱码的解决方法
环球快消息!将Windows系统设置为NTP服务器
全球快看:38999元 雷蛇灵刃18游戏本上架:13代i9+RTX 4090
世界球精选!《雷霆沙赞:众神之怒》国内定档3月17日:与北美同步上映
李书福是懂借壳上市的 吉利旗下跑车“路特斯”赴美上市
女子手机不慎落入西湖 “打捞神器”只用30秒捞出
可惜了!《泰坦陨落》还有未公布的单机版游戏 现已被EA砍掉
vmware时间不同步问题
全球热讯:真爱粉!网友凌晨4点花1万多下单三星Galaxy S23 Ultra:直言“早买早享受”
【当前独家】比亚迪元PLUS夺得极寒续航达率成第一 城市高达74.2%
当前短讯!鱼跃血氧仪涨价131%被罚270万!消费者能退差价?客服回应
实时焦点:连点五次才能关:微软全屏通知强推Win11
3D模型 | 回旋火箭弹乐园教程之火箭 有手就会的火箭弹教程,超详细>>
环球快讯:读Java8函数式编程笔记08_测试、调试和重构
世界滚动:18英寸大屏+RTX 40系显卡!ROG枪神7 Plus超竞版图赏
车主注意!明天油价又要调整 加满一箱油可能多花11元
天天新消息丨万元机皇!三星Galaxy S23 Ultra真机图赏
一度濒临破产倒闭!李书福4亿救活的跑车公司:作价364亿上市
Meta搞元宇宙太烧钱 一年亏掉900多亿 CEO被炮轰搞垮公司
三星Galaxy S23/S23+/S23 Ultra有何区别?一文了解
韩国1500年历史的木简刻有生僻汉字引围观:画面让国内网友看尬
世界快资讯丨iPhone 15 Ultra/16 Ultra独占潜望长焦:Pro版本也不香了
环球微动态丨QPython实例02-调用其他app实例
精彩看点:[数据结构] 哈夫曼树
当前最新:路由react-router-dom的使用
ASP.NET Core+Element+SQL Server开发校园图书管理系统(三)
Blazor入门100天 : 身份验证和授权 (3) - DB改Sqlite
天天资讯:卖爆了!特斯拉拟提高上海工厂产量:新一轮大降价要来?
【世界新视野】独占高频版骁龙8 Gen2!三星Galaxy S23/S23+发布:5699元起
世界今热点:顶配1.32万元!三星Galaxy S23 Ultra正式发布:2亿像素无敌
“九转大肠”原综艺:比吃答辩还要抽象10倍
144MB缓存秒所有!AMD锐龙7000X3D上市时间、价格公布
天天热资讯!关于STM32CubeIDE无法正常启动GDB服务端的解决办法
世界要闻:【算法训练营day36】LeetCode435. 无重叠区间 LeetCode763. 划分字母区间 LeetCode56. 合并区间
环球信息:小米年货节终极战报出炉:全渠道支付金额破178亿!
今日快讯:Intel Arc显卡驱动DX9游戏性能累计提升43%!性价比秒杀RTX 3060
每日看点!路虎在中国混不下去了
环球新消息丨【缓存】有关HTTP缓存的总结
如何使用单纯的`WebAssembly`
世界新消息丨国美电器董事长发文“反思”国美失势了:核心要务是活下去
1岁萌娃躺地耍赖父母转身离开 这招对90后不管用:网友点赞
天天速递!谁最靠谱?四大品牌23万块硬盘最新故障率报告公布:希捷让人看不懂
Blazor入门100天 : 身份验证和授权 (1)
2023牛客寒假算法基础集训营5
Spring:AOP
世界观察:试用ChatGPT
骁龙8+性能被榨干了!一加Ace 2散热拉满:极致流畅
【时快讯】《狂飙》大结局!高启强手机穿帮:提前两年用上iPhone 8 Plus
《狂飙》的艺术总监是张译:本人主演电影票房破200亿
环球关注:国内第一大加速器里程碑诞生!面积约合20余个足球场
环球视讯!《流浪地球2》导演郭帆:希望能为科幻电影蹚一条路
玩《原神》最爽的手机!一加Ace 2超10万人预约
环球今日报丨宏碁推出TravelMate B系列笔记本:Intel N系列超低功耗U
游客偷带食物喂兔子致大批死亡:还喂发烂叶子 遭网友疯狂谴责
全球速递!海尔发布博越G43系列笔记本:搭载国产X86 CPU
今日精选:尴尬一幕:近年来论文数量激增 但科技界没有创新 3大原因
环球微资讯!300人研发三年!腾讯自研开放世界生存手游《黎明觉醒:生机》定档
今日聚焦!女子价值近20万元的钻戒丢失在高铁站 后续来了
VS Winform程序制作安装包
【世界聚看点】FluentReader 高颜值的rss阅读器
全球热头条丨易基因|细菌全基因组甲基化纳米孔测序(ONT):技术推介
每日简讯:我在京东做研发 | 揭秘支撑京东万人规模技术人员协作的行云DevOps平台
环球热推荐:再探前端低代码的“野路子”
美国一公司计划复活灭绝的渡渡鸟:还有猛犸象
PC最坏的日子快过去了 苏妈放言:AMD即将触底反弹
环球快讯:500块的产品只要10元 小米商城BUG价遭爆单 后续来了:退单返券
全球微动态丨256G不够了!博主买的小米12S Pro 512G已用掉300多G:光微信就70G