TikTok越狱检测之一 <代码模块污染检测>

话说某天在国外论坛闲逛,有一国外小哥,发帖交流TikTok 的相关越狱检测,对TikTok的安全保护极其变态。
好奇心驱使之下,便下载TikTok,注册完账号,竟然什么都做不了,只能浏览视频。
基于逆向的本能,越狱手机应该被检测出来了。
于是便开始了分析该软件。
果然,TikTok的保护极其完善,很多保护都是笔者之前没有接触过的。
把检测的一些函数逆向出来,以后正向开发也有参考价值。
新加坡singpass 政务app也有该相关检测方法
特此记录.

1.<代码模块污染检测>
原理:TikTok加载的内存模块和官方的缓存模块

1

2

3

const char *sharedCachePaths[] = {    "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64",      "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e",

"/System/Library/dyld/dyld_shared_cache_arm64e"

};

进行比较,不一致就说明了TikTok加载的内存模块被篡改了,函数被Hook,或者代码被patch

//根据checkAddress判断该地址所在内存加载模块和 "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64" 官方模块比较
//是否已经被修改过,模块被修改过,返回true,模块没有被修改过返回false

  1. 调用dladdr函数 获取待检测checkAddress内存地址所在的模块
  2. 获取模块名称checkfname,模块代码地址checkTextCommand,模块大小 checkTextVmSize
  3. 映射官方的缓存模块 sharedCachePaths
  4. 从官方的缓存模块中匹配到checkfname模块
  5. 获取匹配模块,代码地址 matchTextCommand
  6. 对待检测的checkTextCommand 和 已经匹配的matchTextCommand进行逐字节比较,一致则说明没有被修改过,不一致则说明被污染了

+(bool)IsRiskModule:(uint64_t)checkAddress {

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

Dl_info checkDlinfo;

if(!dladdr((const void *)checkAddress, &checkDlinfo)){

    return false;

}

const char * checkfname = checkDlinfo.dli_fname;

struct mach_header_64 * checkMachHeader  = (struct mach_header_64 *) checkDlinfo.dli_fbase;

if (checkMachHeader->magic != MH_MAGIC_64)

    return false;

if(checkMachHeader->ncmds == 0)

    return false;

struct segment_command_64 * checkCommand  = (struct segment_command_64 *) ((char *)checkMachHeader + sizeof(struct mach_header_64));

struct segment_command_64 * checkTextCommand  = NULL;

for (int =0; i< checkMachHeader->ncmds; i++) {

    if ((checkCommand->cmd == LC_SEGMENT_64)   && (strcmp(checkCommand->segname, "__TEXT"== 0))

    {

        checkTextCommand = checkCommand;

        break;

    }

    checkCommand =(struct segment_command_64 *) ((uint64_t)checkCommand + checkCommand->cmdsize);

}

if (!checkTextCommand)

    return false;

uint64_t checkTextVmSize = checkTextCommand->vmsize;

kern_return_t kernReturn = KERN_SUCCESS;

const char *sharedCachePaths[] = {

    "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64",

    "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e",

    "/System/Library/dyld/dyld_shared_cache_arm64e",

};

int fd = -1;

for (int = 0;i < sizeof(sharedCachePaths) / sizeof(char *);i++) {

    fd = open(sharedCachePaths[i], O_RDONLY);

    if (fd != -1) {

        break;

    }

}

if (fd == -1)

    return false;

vm_size_t vmPageSize = vm_page_size;

unsigned char* p_map =( unsigned char*) mmap(0, vmPageSize, PROT_READ,MAP_NOCACHE|MAP_PRIVATE, fd, 0);

if (p_map == MAP_FAILED) {

    //映射失败

    close(fd);

    return false;

}

struct dyld_cache_header * cacheHeader = ( struct dyld_cache_header *)p_map;

if(strcmp(cacheHeader->magic, "dyld_v1   arm64") != 0){

    munmap(p_map, vmPageSize);

    close(fd);

    return false;

}

struct dyld_cache_mapping_info* mappings = (struct dyld_cache_mapping_info*)(cacheHeader->mappingOffset + (uintptr_t)cacheHeader);

uintptr_t length =  mappings[0].size;

munmap(p_map, vmPageSize);

vmPageSize = length;

p_map =( unsigned char *) mmap(0, vmPageSize, PROT_READ, MAP_NOCACHE|MAP_PRIVATE|MAP_NORESERVE, fd, 0);

if (p_map == MAP_FAILED) {

    //映射失败

    printf("error:%s\n", strerror(errno));

    close(fd);

    return false;

}

cacheHeader = ( struct dyld_cache_header *)p_map;

mappings = (struct dyld_cache_mapping_info*)(cacheHeader->mappingOffset + (uintptr_t)cacheHeader);

//非越狱系统 imagesCount = 0  越狱系统 imagesCount > 0

uint32_t imagesCount = cacheHeader->imagesCount;

if (imagesCount == 0) {

    munmap(p_map, vmPageSize);

    close(fd);

    return false;

}

struct dyld_cache_image_info* dylibs = (struct dyld_cache_image_info*)((uintptr_t)cacheHeader + cacheHeader->imagesOffset);

struct dyld_cache_image_info * matchDylib = NULL;

for (uint32_t i=0; i < imagesCount; i++) {

    const char* dylibPath  = (char*)cacheHeader + dylibs[i].pathFileOffset;

    if (strcmp(checkfname, dylibPath) == 0) {

        matchDylib = (struct dyld_cache_image_info*)&dylibs[i];

        //NSLog(@"IsRiskModule 函数,匹配到 filename =%s",dylibPath);

        break;

    }

}

if (!matchDylib) {

    NSLog(@"IsRiskModule 函数,找不到 filename =%s",checkfname);

    munmap(p_map, vmPageSize);

    close(fd);

    return false;

}

uint64_t offset = 0;

bool bMatch = false;

for (int = 0 ; i< cacheHeader->mappingCount; i++) {

    uint64_t StartAddress =mappings[i].address;

    if (matchDylib->address >= StartAddress){

        uint64_t EndAddress = mappings[i].address +mappings[i].size;

        if (matchDylib->address <= EndAddress) {

            offset =  matchDylib->address - mappings[i].address + mappings[i].fileOffset ;

            bMatch = true;

            break;;

        }

    }

}

if (!bMatch) {

    munmap(p_map, vmPageSize);

    close(fd);

    return false;

}

struct mach_header_64* matchHeader = (struct mach_header_64*)((uintptr_t)cacheHeader + offset);

if(matchHeader->ncmds == 0)

    return false;

struct segment_command_64 * matchCommand  = (struct segment_command_64 *) ((char *)matchHeader + sizeof(struct mach_header_64));

struct segment_command_64 * matchTextCommand  = NULL;

for (int =0; i< matchHeader->ncmds; i++) {

    if ((matchCommand->cmd == LC_SEGMENT_64)   && (strcmp(matchCommand->segname, "__TEXT"== 0))

    {

        matchTextCommand = matchCommand;

        break;

    }

matchCommand =(struct segment_command_64 *) ((uint64_t)matchCommand + matchCommand->cmdsize);

}

if (!matchTextCommand) {

    munmap(p_map, vmPageSize);

    close(fd);

    return false;

}

if (matchTextCommand->vmsize != checkTextVmSize ) {

    munmap(p_map, vmPageSize);

    close(fd);

    return true;

}

bool bIsRisk = false;

for (int = 0; i< checkTextVmSize ; i++) {

    unsigned char Byte1 = *(unsigned char*) ((uint64_t)matchHeader+i);

    unsigned char Byte2 = *(unsigned char*) ((uint64_t)checkMachHeader+i);

    if (Byte1 != Byte2)

    {

        bIsRisk = true;

        NSLog(@"IsRiskModule 被污染的库,filename =%s,基地址 = 0x%llX,函数地址=0x%llX",checkfname,((uint64_t)checkMachHeader),(uint64_t)i);

        break;

    }

}

munmap(p_map, vmPageSize);

close(fd);

return bIsRisk;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/14336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASO行业面临洗牌,苹果应用商店加搜索广告!

苹果公司全球市场营销高级副总裁菲尔席勒(Phil Schiller),在全球开发者大会开幕前(WWDC)透露了一些应用商店方面的消息。重点包括:1.应用商店搜索中加入广告;2.应用审核加快;3.新的商业模式。 一、 Search Ads搜索广告 这是最令人惊讶的改变,苹果在App Store平台的搜索结果中加…

前端自动将 HTTP 请求升级为 HTTPS 请求

前端将HTTP请求升级为HTTPS请求有两种方式&#xff1a; 一、index.html 中插入meta 直接在首页 index.html 的 head 中加入一条 meta 即可&#xff0c;如下所示&#xff1a; <meta http-equiv"Content-Security-Policy" content"upgrade-insecure-requests&…

广东旅游景点推荐

增城区 增城作为广州市的一个区&#xff0c;拥有丰富的自然景观和人文历史景点&#xff0c;非常适合自驾游。以下是一些推荐的自驾游景点&#xff1a; 白水寨风景区&#xff1a;拥有原始森林、悬崖瀑布和浅滩湿地&#xff0c;是广东罕见的自然生态资源集中地&#xff0c;也是广…

树洞陪聊系统源码/陪聊/陪玩/树洞/陪陪/公众号开发/源码交付/树洞系统源码

独立版本源码交付&#xff0c;自研UI和前后端代码 平台自带店员&#xff0c;无需自主招募&#xff0c;搭建直接运营 支持三方登录&#xff0c;官方支付、虎皮椒、易支付/码支付 支持首单体验、盲盒订单、指定下单等多个模式 支持钱包预充值、店员收藏、订单评价等功能 支持…

AI日报:讯飞星火Lite API永久免费;李开复称大模型疯狂降价是双输;AI特效末日滤镜抖音爆火;AI音乐Suno 融资1.25亿美元

欢迎来到【AI日报】栏目!这里是你每天探索人工智能世界的指南&#xff0c;每天我们为你呈现AI领域的热点内容&#xff0c;聚焦开发者&#xff0c;助你洞悉技术趋势、了解创新AI产品应用。 新鲜AI产品点击了解&#xff1a;AIbase - 智能匹配最适合您的AI产品和网站 1、科大讯飞…

can设备调试 - linux driver

这篇文章主要介绍can设备的调试相关信息&#xff0c;不具体介绍驱动的实现。 如果驱动写完&#xff0c;对can设备进行验证&#xff0c;可能会出现很多不可预见的问题。下面说说验证步骤 验证can设备可以使用工具can-utils。这个工具包中会有cansend candump等程序。可以直接通…

系统架构师考试(十)

SaaS为在线客服 PaaS为二次开发&#xff0c;比如低代码平台 IaaS 硬件开发 B 是基础设施作为服务 软件架构的概念 架构风格 数据流风格 网络报文是在计算机网络中通过网络传输的数据单元&#xff0c;它是网络通信的基本单位。网络报文包含了发送方和接收方之间传输的数据&…

『网络攻防和AI安全之家』星球正式运营及CSDN安全知识汇总,欢迎广大博友加入

“今天是Eastmount的安全星球 —— 『网络攻防和AI安全之家』正式创建和运营的日子&#xff0c;该星球目前主营业务为 安全零基础答疑、安全技术分享、AI安全技术分享、AI安全论文交流、威胁情报每日推送、网络攻防技术总结、系统安全技术实战、面试求职、安全考研考博、简历修…

计算机操作系统核心组件

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天给大家讲讲操作系统。 操作系统核心组件 用户借助于一个或多个应用程序与操作系统进行交互&#xff0c;常常是通过一个称为shell的特殊应用程序进行的&#xff0c;shell也叫作命令解释器。105今天的大多…

Postgresql源码(130)ExecInterpExpr转换为IR的流程

相关 《Postgresql源码&#xff08;127&#xff09;投影ExecProject的表达式执行分析》 《Postgresql源码&#xff08;128&#xff09;深入分析JIT中的函数内联llvm_inline》 《Postgresql源码&#xff08;129&#xff09;JIT函数中如何使用PG的类型llvmjit_types》 表达式计算…

VBA创建文本文件

Sub 创建文本文件()Dim fso As New Scripting.FileSystemObjectDim ostream As Scripting.TextStreamDim sfname As StringDim str1 As Stringsfname Application.InputBox(prompt:"请输入文本文件的名称", _Title:"输入文件名称", Type:2)If sfname &…

Java设计模式 _行为型模式_迭代器模式

一、迭代器模式 1、迭代器模式 迭代器模式&#xff08;Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;用于顺序访问集合对象的元素&#xff0c;不需要关心集合对象的底层表示。如&#xff1a;java中的Iterator接口就是这个工作原理。 2、实现思路 &#xff0…

tomcat jdbc连接池的默认配置配置方案

MySQL 5.0 以后针对超长时间数据库连接做了一个处理&#xff0c;即一个数据库连接在无任何操作情况下过了 8 个小时后(MySQL 服务器默认的超时时间是 8 小时)&#xff0c;MySQL 会自动把这个连接关闭。在数据库连接池中的 connections 如果空闲超过 8 小时&#xff0c;MySQL 将…

国家自然博物馆“云端自然”线上虚拟展厅是如何搭建的?

国家级综合性自然博物馆国家自然博物馆&#xff0c;联手积木易搭打造“云端自然”线上虚拟展览&#xff0c;形成一个集参观游览、科普教育为一体的线上虚拟数字博物馆平台&#xff0c;让数千以至数万年的古生物&#xff0c;栩栩如生地呈现在我们面前。 通过数字化的展示手段&am…

在做题中学习(61):连续数组

525. 连续数组 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;前缀和 哈希表 转化&#xff1a;将 0 ——> -1 转变为&#xff1a;找到和为0的最长子数组 细节&#xff1a; 1.哈希表存什么 前缀和 &#xff0c; 长度 2.什么时候存入哈希表 先处理前一个&…

怎么用二维码看excel表格?生成文件二维码的制作技巧

Excel表格怎么放到二维码中&#xff0c;让其他人通过扫码查看数据呢&#xff1f;现在文件放入二维码中展示在很多的场景中都有应用&#xff0c;比如通知、数据、作品、报告等类型的内容都可以通过扫码的方式在手机上展现&#xff0c;那么如何将文件生成二维码呢&#xff1f; 文…

DVWA登录页面空白问题解决

问题&#xff1a; 创建完成后打开登录页面&#xff0c;发现打不开&#xff0c;一片空白 解决&#xff1a; php版本不对&#xff0c;更换版本即可

Rust Tarui 中的 Scrcpy 客户端,旨在提供控制安卓设备的鼠标和按键映射,类似于游戏模拟器。

Scrcpy-mask 为了实现电脑控制安卓设备&#xff0c;本人使用 Tarui Vue 3 Rust 开发了一款跨平台桌面客户端。该客户端能够提供可视化的鼠标和键盘按键映射配置。通过按键映射实现了实现类似安卓模拟器的多点触控操作&#xff0c;具有毫秒级响应速度。该工具可广泛用于电脑控…

constexpr : 我和const像孪生,我比define更受追捧

一、constexpr constexpr 是 C++11 引入的关键字,用于定义在编译时就能确定值的表达式。这使得编译器能够在编译时执行更多的优化,同时也能用于任何需要常量表达式的场合,如数组大小、整数模板参数等。 二、constexpr 的使用示例 constexpr是C++11引入的关键字,用于声…

YashanDB与慧点科技完成兼容互认证

近日&#xff0c;深圳计算科学研究院崖山数据库系统YashanDB与慧点科技顺利完成兼容性互认证。经严格测试&#xff0c;双方产品完全兼容&#xff0c;稳定运行&#xff0c;共同支撑政府、企业、金融等办公应用场景下的数字化转型升级&#xff0c;为企业的信息技术应用创新提供坚…