Initial commit

This commit is contained in:
oscarz
2024-08-12 10:49:20 +08:00
parent 3002510aaf
commit 00fd0adf89
331 changed files with 53210 additions and 130 deletions

21
Pods/TrustDecision/LICENSE generated Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 trustdecision
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

268
Pods/TrustDecision/README.md generated Normal file
View File

@ -0,0 +1,268 @@
<p align="center">
<a href="https://www.trustdecision.com/deviceFingerprint" >
<picture>
<source media="(prefers-color-scheme: dark)" srcset="images/logo_light.png" />
<source media="(prefers-color-scheme: light)" srcset="images/logo_dark.png" />
<img src="images/logo_dark.png" alt="trustdevice logo" width="729px" height="67px"/> </picture>
</a>
</p>
<p align="center">
<img src="images/demoApp.gif" width="195">
</p>
# TrustDevice-iOS
A lightweight library for determining device uniqueness and risk identification.
Create a device identifier based on basic device information.
Will remain the same after uninstalling and reinstalling or clearing app data.
## Quick Start
### 1. Add Dependcy
TrustDecision is available through [CocoaPods](https://cocoapods.org). To install it, simply add the following line to your Podfile:
```ruby
# Podfile
pod 'TrustDecision', '1.4'
```
### 2. Get DeviceInfo
DeviceInfo contains device id, risk information and device details.
#### Objective-C
```objective-c
#import <TrustDecision/TDMobRisk.h>
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
[options setObject:^(NSDictionary *response) {
// Response in sub-thread, do something with the response
// Get DeviceId
NSString *deviceId = response[@"device_id"];
// Get DeviceRiskLabel
NSDictionary *deviceRisk = response[@"device_risk_label"];
// Get DeviceDetail
NSDictionary *deviceDetail = response[@"device_detail"];
} forKey:@"callback"];
manager->initWithOptions(options);
```
#### Swift
```swift
import TrustDecision
var options = [String : NSObject]()
let responseCallback: ([String : Any])-> Void = { response in
// Response in sub-thread, do something with the response
// Get DeviceId
let deviceId = response["device_id"]
// Get DeviceRiskLabel
let deviceRisk = response["device_risk_label"]
// Get DeviceDetail
let deviceDetail = response["device_detail"]
}
options["callback"] = unsafeBitCast(responseCallback as @convention(block) ([String : Any]) -> Void, to: AnyObject.self) as? NSObject
let manager = TDMobRiskManager.sharedManager()
manager?.pointee.initWithOptions(options)
```
## Data Sample
```json
{
"device_id":"4b3491c6bb6a27c6c58a038939a10d4cad97555e517574e7bd0291db96243859",
"device_risk_label":{
"jailbreak":false,
"simulator":false,
"debug":true
},
"device_detail":{
"displayResolution":"828.0x1792.0",
"deviceModel":"N104AP",
"kernelVersion":"Darwin Kernel Version 22.6.0: Wed Jun 28 20:51:23 PDT 2023; root:xnu-8796.142.1~1\/RELEASE_ARM64_T8030",
"debug":true,
"sandboxPath":"3CDAE89E-1D51-4DD2-941C-02B2780021FF",
"mcc":"460",
"batteryState":2,
"teamName":"Hangzhou BoDunXiYan Technology Co., Ltd.",
"cloudid":"316A8157-B4E5-4F40-BE37-8115588CA734",
"bundleId":"com.trustdevice.fingerprint",
"appVersion":"1.0",
"timeZone":"Asia\/Shanghai",
"applicationId":"R3F7G5M76J.com.trustdevice.fingerprint",
"freeDiskSpace":4820676608,
"physicalMemory":"8333852672",
"currentTime":1693451898456090,
"totalDiskSpace":127933894656,
"mnc":"02",
"appInstallTime":1679884827203788.8,
"osVersion":"20G75",
"hostName":"ssd",
"osType":"Darwin",
"deviceType":"iPhone",
"displayScale":2,
"idfv":"E5082421-F447-4B45-B453-22C656B56314",
"osRelease":"22.6.0",
"memorySize":"4038885376",
"deviceName":"iOS",
"cpuCount":"9023060809483288582",
"isiOSAppOnMac":0,
"simulator":false,
"jailbreak":false,
"bootTime":1692954854089697,
"secureKernelStatus":true
}
}
```
## Open Source Features
+ Basic device ID, consistent when uninstalling applications and reinstalling
+ Basic equipment information, which can be used for simple data analysis
+ Basic risk identification ability
| RiskLabel | Risk Description |
| --------- | ------------------------------------------------------------ |
| jailbreak | Attackers will have higher privileges and can install many cheating software to affect the normal development of application business. |
| simulator | The simulator provides many simulation functions, which will affect the normal operation of applications, such as virtual positioning. |
| debug | Applications can be modified by attackers at will, and the program will return unexpected values. |
## Open Source VS Pro
| Ability | Open Source | Pro |
| :---------------------------: | :---------: | :----------------------------------------------------------: |
| 100% open source | Yes | No |
| Device ID | Basic | Extremely stable, even if the device is restored to factory settings, it can still be recognized as the same |
| Device Risk Label | Basic | Extremely rich |
| Device Details | Basic | Extremely rich |
| IP Location | - | ✓ |
| Device Risk Score | - | ✓ |
| Environment Risk Evaluation | - | ✓ |
| Fraud Tools Detection | - | ✓ |
| Behavioral Activity Capturing | - | ✓ |
## Pro Introduction
TrustDecision TrustDevice has the leading device fingerprint technology, which has been integrated by more than 10000 global leading brands, protecting the entire customer journey.
**There are 6 leading core features about TrustDevice Pro:**
### 1. Wide Coverage
Comprehensive coverage of Android, iOS, Web, H5, applets and other device types.
### 2. Stable and Reliable
TrustDevice served more than 10,000 clients, 200 million+ daily active users , and 6 billion+ devices , with excellent product functions and stability.
The fingerprint accuracy of different terminal devices exceeded 99.9%, and the output of risk labels exceeded 70 items.
### 3. Unparalleled Safety
TrustDevice's code virtualization & obfuscation technology make the malware fraudsters suffer from painful cost and imprecision when performing reverse-engineering.
### 4. Core Intellectual Property
Fully independent intellectual property rights, with a number of patented technology.
### 5. Security Compliance
TrustDevice is committed to the highest standards in security and compliance to keep your data safe.
GDPR/CCA/PCI DSS/ISO 27701/ISO 9001 Compliant.
### 6. Easy to Deploy
SaaSSoftware as a Servicedeployment supported, reducing massively your integration cost and enabling rapid access to device fingerprint service.
## Where to Get Support
We are happy to provide technical support for our open-source trustdevice-ios library. We recommend using GitHub Issues to submit bugs or Discussions to ask questions. Using [Issues](https://github.com/trustdecision/trustdevice-ios/issues) and [Discussions](https://github.com/trustdecision/trustdevice-ios/discussions) publicly will help the open-source community and other users with similar issues.
In addition, any idea or interest in using TrustDevice Pro can be found on the [www.trustdecision.com](https://www.trustdecision.com/trustDevice), registered account for a free trial; or via email trustdevice@trustdecision.com contact us directly and quickly open the service.
## Compatibility
| Items | Description |
| :-----------------------: | :------------------: |
| Supported System Versions | iOS9.0+ |
| Supported Architecture | armv7, arm64, x86_64 |
## TrustDevice Pro VS Others
<table>
<tr align="center">
<th>Type</th><th>Scene</th><th>Result</th><th>TrusDevice Pro</th><th>Fingerprint</th><th>Seon</th><th>CredoLab</th><th>Sift</th><th>Shield</th><th>PerimeterX</th>
</tr>
<tr align="center">
<td>Device Fingerprint Compatibility</td><td>iOS 9.0 and above, including iOS 16, etc.</td><td>Able to collect device info and generate device ID</td><td></td><td>✅(ios12 and above)</td><td>✅(ios9 and above)</td><td>✅(ios11 and above)</td><td>✅(ios9.2 and above)</td><td>✅(ios9 and above)</td><td>✅(ios11 and above)</td>
</tr>
<tr align="center">
<td rowspan="2">Device fingerprint uniqueness</td><td>Different apps (with different package names) on the same device</td><td>Device fingerprints/ID matches </td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The same app on two unique devices (including the case of the same device model and the same system version)</td><td>Device fingerprint/ID should not match. Each device to have its own unique device fingeprint/ID</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td rowspan="6">Device Fingerprint Stability</td><td>Uninstall and reinstall</td><td>Device fingerprints/ID are consistent before and after reinstallation</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Clear all app data</td><td>Device fingerprints/ID are consistent before and after clearing all app data</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
</tr>
<tr align="center">
<td>Disable all app permissions except network permissions and clear app data</td><td>Device fingerprints/ID are consistent before and after disabling all permissions</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Modify the common information of the device system (brand, model, IDFA, IDFV, etc.) through the machine modification tool</td><td>Device fingerprint/ID still matches with before modification</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Device system upgrade</td><td>Device fingerprints/ID are consistent before and after system upgrade</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Factory reset (including iOS 14 and above, etc.)</td><td>The device fingerprints/ID are the same before and after the device is restored to factory settings</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td rowspan="12">Device Fingerprint Risk Identification</td><td>Secondary packaging</td><td>Ability to identify secondary packaged unofficial apps</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Replay attack</td><td>Ability to identify replay attacks</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Device location information has been tampered with</td><td>Ability to identify tampering of location information</td><td></td><td></td><td></td><td></td><td></td><td></td><td>-</td>
</tr>
<tr align="center">
<td>No SIM card inserted</td><td>Can identify whether the device is inserted with a SIM card</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The device uses an HTTP proxy</td><td>Can identify HTTP proxy risks</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The device uses a VPN proxy</td><td>Can identify VPN proxy risks</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Jailbreak</td><td>Ability to identify jailbreak risks</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The device is an emulator</td><td>Ability to recognize emulators</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The device uses the machine modification tool to modify the device parameter information</td><td>Ability to identify mainstream modification tools</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The device has scripts and group control tools installed (tools that are used to control multiple devices from single terminal - device farm/device group)</td><td>Can identify mainstream scripting/group control tools</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>The device is equipped with an M chip</td><td>Devices capable of recognizing M-chips</td><td></td><td></td><td></td><td></td><td></td><td></td><td>-</td>
</tr>
<tr align="center">
<td>The device is not logged into the iCloud account</td><td>Able to identify login iCloud account</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td rowspan="6">Security and Stability</td><td>Code Protection</td><td>The device fingerprint SDK and JS have code protection mechanisms (such as VMP), which effectively resist black hat cracking attempts to manipulate code logic and falsify data</td><td>✅ (OLLVM, VMP)</td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Downgrade</td><td>Intercepting and sending collection requests in the iOS environment can still generate device fingerprints normally</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
<tr align="center">
<td>Anti packet capture</td><td>iOS has the ability to prevent packet capture</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
</table>
## License
This library is MIT licensed. Copyright trustdecision, Inc. 2022.

View File

@ -0,0 +1,13 @@
//
// TDMobRiskBaseInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskBaseInfo : NSObject
/// Get current json dictionary of object
- (NSDictionary *)getJsonDict;
@end

View File

@ -0,0 +1,46 @@
//
// TDMobRiskBaseInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
#import <objc/runtime.h>
@implementation TDMobRiskBaseInfo
#pragma mark - Initialization Methods
- (instancetype)init {
if (self = [super init]) {
[self getInfo];
}
return self;
}
#pragma mark - Base Methods
- (void)getInfo {
}
- (NSDictionary *)getJsonDict {
NSMutableDictionary *jsonDict = [[NSMutableDictionary alloc] init];
unsigned int propertyCount = 0;
objc_property_t *propertyList = class_copyPropertyList([self class], &propertyCount);
for (int i = 0; i < propertyCount; i++) {
objc_property_t property = propertyList[i];
const char *propertyCName = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:propertyCName];
id propertyValue = [self valueForKey:propertyName];
if (propertyName && propertyValue) {
[jsonDict setObject:propertyValue forKey:propertyName];
}else {
#ifdef DEBUG
NSLog(@"[%s] - [Error] - propertyName[%@] or propertyValue[%@] is nil",__func__,propertyName,propertyValue);
#endif
}
}
free(propertyList);
return jsonDict;
}
@end

View File

@ -0,0 +1,24 @@
//
// TDMobRiskAppInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskAppInfo : TDMobRiskBaseInfo
/** App Info **/
/// bundleId
@property (nonatomic, copy) NSString *bundleId;
/// appVersion
@property (nonatomic, copy) NSString *appVersion;
/// applicationId
@property (nonatomic, copy) NSString *applicationId;
/// teamName
@property (nonatomic, copy) NSString *teamName;
/// sandboxPath
@property (nonatomic, copy) NSString *sandboxPath;
/// appInstallTime
@property (nonatomic, assign) NSTimeInterval appInstallTime;
@end

View File

@ -0,0 +1,126 @@
//
// TDMobRiskAppInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskAppInfo.h"
#import "TDMobRiskAPIHelper.h"
#import <UIKit/UIKit.h>
@implementation TDMobRiskAppInfo
#pragma mark - Initialization Methods
- (instancetype)init {
if (self = [super init]) {
[self getInfo];
}
return self;
}
#pragma mark - Collect Methods
- (void)getInfo {
// bundleId
{
NSString *bundleId = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
_bundleId = bundleId;
}
// appVersion
{
NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
_appVersion = appVersion;
}
// teamName, applicationId
{
NSString *applicationId = nil;
NSString *teamName = nil;
NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
const char *embeddedPath_c = [embeddedPath UTF8String];
FILE *fp = fopen(embeddedPath_c, "r");
if (fp) {
fseek(fp, 0L, SEEK_END);
uint64_t sz = ftell(fp);
rewind(fp);
char *mobileProvisionContent = malloc(sz);
memset(mobileProvisionContent, 0, sz);
fread(mobileProvisionContent,sz,1, fp);
char *plistBeginTag = "<plist version";
bool isPlistBeginTagMatch = false;
uint64_t plistBeginTagCount = 0;
uint64_t plistBeginTagPos = 0;
char* plistEndTag = "</plist>";
bool isPlistEndTagMatch = false;
uint64_t plistEndTagCount = 0;
uint64_t plistEndTagPos = 0;
for (int i = 0;i < sz;i++) {
if (isPlistBeginTagMatch && isPlistEndTagMatch) {
break;
}
if (!isPlistBeginTagMatch) {
while (plistBeginTag[plistBeginTagCount] && i < sz && plistBeginTag[plistBeginTagCount++] == mobileProvisionContent[i++]);
if (plistBeginTag[plistBeginTagCount] == 0) {
isPlistBeginTagMatch = true;
plistBeginTagPos = i - plistBeginTagCount;
}else {
plistBeginTagCount = 0;
}
}
if (!isPlistEndTagMatch) {
while (plistEndTag[plistEndTagCount] && i < sz && plistEndTag[plistEndTagCount++] == mobileProvisionContent[i++]);
if(plistEndTag[plistEndTagCount] == 0) {
isPlistEndTagMatch = true;
plistEndTagPos = i;
}else{
plistEndTagCount = 0;
}
}
}
mobileProvisionContent[plistEndTagPos] = 0;
char *plistContent = mobileProvisionContent + plistBeginTagPos;
if (plistEndTagPos > plistBeginTagPos) {
uint64_t plistContent_len = plistEndTagPos - plistBeginTagPos;
NSData *data = [NSData dataWithBytes:plistContent length:plistContent_len];
NSError *error;
NSDictionary * plistDic = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListWriteStreamError format:nil error:&error];
if ([plistDic isKindOfClass:[NSDictionary class]]) {
teamName = plistDic[@"TeamName"];
NSDictionary *entitlementsDic = plistDic[@"Entitlements"];
if ([entitlementsDic isKindOfClass:[NSDictionary class]]) {
applicationId = entitlementsDic[@"application-identifier"];
}
}
}
if (mobileProvisionContent) {
free(mobileProvisionContent);
}
if (fp) {
fclose(fp);
}
}
_applicationId = applicationId;
_teamName = teamName;
}
// sandboxPath
{
NSString *sandboxPath = [NSHomeDirectory() lastPathComponent];
_sandboxPath = sandboxPath;
}
// appInstallTime
{
NSString *appDocumentsPath = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] path];
NSDictionary *appDocumentsDict = [[NSFileManager defaultManager] attributesOfItemAtPath:appDocumentsPath error:nil];
NSDate *appDocumentsCreationDate = appDocumentsDict[NSFileCreationDate];
NSTimeInterval appInstallTime = [appDocumentsCreationDate timeIntervalSince1970] * 1000000;
_appInstallTime = appInstallTime;
}
}
@end

View File

@ -0,0 +1,14 @@
//
// TDMobRiskCpuInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskCpuInfo : TDMobRiskBaseInfo
/** Cpu Info **/
/// cpuCount
@property (nonatomic, copy) NSString *cpuCount;
@end

View File

@ -0,0 +1,20 @@
//
// TDMobRiskCpuInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskCpuInfo.h"
#import "TDMobRiskAPIHelper.h"
@implementation TDMobRiskCpuInfo
#pragma mark - Collect Methods
- (void)getInfo {
// cpuCount
{
NSString *cpuCount = [TDMobRiskAPIHelper sysctlByName:"hw.ncpu" isObject:NO];
_cpuCount = cpuCount;
}
}
@end

View File

@ -0,0 +1,32 @@
//
// TDMobRiskDeviceInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskDeviceInfo : TDMobRiskBaseInfo
/** deviceInfo */
/// deviceType
@property (nonatomic, copy) NSString *deviceType;
/// displayResolution
@property (nonatomic, copy) NSString *displayResolution;
/// displayScale
@property (nonatomic, assign) double displayScale;
/// deviceModel
@property (nonatomic, copy) NSString *deviceModel;
/// deviceName
@property (nonatomic, copy) NSString *deviceName;
/// hostName
@property (nonatomic, copy) NSString *hostName;
/// timeZone
@property (nonatomic, copy) NSString *timeZone;
/// batteryState
@property (nonatomic, assign) NSInteger batteryState;
/// Mobile Network Code
@property (nonatomic, copy) NSString *mnc;
/// Mobile Country Code
@property (nonatomic, copy) NSString *mcc;
@end

View File

@ -0,0 +1,95 @@
//
// TDMobRiskDeviceInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskDeviceInfo.h"
#import "TDMobRiskAPIHelper.h"
#import <UIKit/UIKit.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <sys/sysctl.h>
@implementation TDMobRiskDeviceInfo
#pragma mark - Collect Methods
- (void)getInfo {
// deviceType
{
UIDevice *device = [UIDevice currentDevice];
NSString *deviceType = device.model;
_deviceType = deviceType;
}
// displayResolution
{
UIScreen *screen = [UIScreen mainScreen];
CGRect nativeBounds = [screen nativeBounds];
NSString *displayResolution = [NSString stringWithFormat:@"%.1lfx%.1lf",nativeBounds.size.width,nativeBounds.size.height];
_displayResolution = displayResolution;
}
// displayScale
{
UIScreen *screen = [UIScreen mainScreen];
double displayScale = [screen nativeScale];
_displayScale = displayScale;
}
// deviceModel
{
NSString *deviceModel = [TDMobRiskAPIHelper sysctlByName:"hw.model" isObject:YES];
_deviceModel = deviceModel;
}
// deviceName
{
NSString *deviceName = [[UIDevice currentDevice] systemName];
_deviceName = deviceName;
}
// hostName
{
size_t size = 0;
const char *name = "kern.hostname";
sysctlbyname(name , 0LL, &size, 0, 0);
void *buf = malloc(size);
sysctlbyname(name, buf, &size, 0, 0);
NSString *hostName;
if(buf) {
hostName = [NSString stringWithCString:buf encoding:NSUTF8StringEncoding];
free(buf);
}
_hostName = hostName;
}
// timeZone
{
NSString *timeZone = [[NSTimeZone localTimeZone] name];
_timeZone = timeZone;
}
// batteryState
{
UIDevice *currentDevice = [UIDevice currentDevice];
if (!currentDevice.isBatteryMonitoringEnabled) {
currentDevice.batteryMonitoringEnabled = true;
}
_batteryState = [currentDevice batteryState];
}
// mnc
{
CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
_mnc = [[networkInfo subscriberCellularProvider] mobileNetworkCode];
}
// mcc
{
CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
_mcc = [[networkInfo subscriberCellularProvider] mobileCountryCode];
}
}
@end

View File

@ -0,0 +1,22 @@
//
// TDMobRiskDeviceStatusInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskDeviceStatusInfo : TDMobRiskBaseInfo
/** Device Status Info **/
/// jailbreak
@property (nonatomic, assign) BOOL jailbreak;
/// debug
@property (nonatomic, assign) BOOL debug;
/// simulator
@property (nonatomic, assign) BOOL simulator;
/// secureKernelStatus
@property (nonatomic, assign) BOOL secureKernelStatus;
/// isiOSAppOnMac
@property (nonatomic, assign) int isiOSAppOnMac;
@end

View File

@ -0,0 +1,160 @@
//
// TDMobRiskDeviceStatusInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskDeviceStatusInfo.h"
#import <UIKit/UIKit.h>
#import <assert.h>
#import <stdbool.h>
#import <sys/types.h>
#import <unistd.h>
#import <sys/sysctl.h>
#import <sys/stat.h>
#import <mach-o/dyld.h>
@implementation TDMobRiskDeviceStatusInfo
#pragma mark - Collect Methods
- (void)getInfo {
// jailbreak
{
BOOL jailbreak = [self isJailbreak];
_jailbreak = jailbreak;
}
// debug
{
int debug = [self checkdebug];
_debug = debug;
}
// simulator
{
int simulator = [self isSimulator];
_simulator = simulator;
}
// secureKernelStatus
{
int value = 0;
size_t length = sizeof(value);
if (sysctlbyname("kern.secure_kernel", &value, &length, NULL, 0) == 0) {
_secureKernelStatus = (value != 0);
}
}
// isiOSAppOnMac
{
int isiOSAppOnMac = -1;
if (@available(iOS 14.0, *)) {
isiOSAppOnMac = [[NSProcessInfo processInfo] isiOSAppOnMac];
}
_isiOSAppOnMac =isiOSAppOnMac;
}
}
#pragma mark - Private Collect Methods
- (int)isJailbreak {
NSArray *jailBreakFileList = @[
@"/Applications/Cydia.app",
@"/private/var/lib/apt/",
@"/User/Applications/",
@"/Library/MobileSubstrate/MobileSubstrate.dylib",
@"/bin/bash",
@"/usr/sbin/sshd",
@"/etc/apt",
@"/var/jb"
];
for (NSString *filePath in jailBreakFileList) {
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
return YES;
}
}
char *env = getenv("DYLD_INSERT_LIBRARIES");
if (env != NULL) {
return YES;
}
if (!access("/Library/MobileSubstrate/DynamicLibraries/",R_OK)) {
return YES;
}
//symlink verification check
NSArray *symlinkList = @[
@"/Applications",
@"/var/stash/Library/Ringtones",
@"/var/stash/Library/Wallpaper",
@"/var/stash/usr/include",
@"/var/stash/usr/libexec",
@"/var/stash/usr/share",
@"/var/stash/usr/arm-apple-darwin9",
@"/bin/bash"
];
for (NSString *symlinkPath in symlinkList) {
struct stat sym;
int f = lstat(symlinkPath.UTF8String, &sym);
if (f == 0 && (sym.st_mode & S_IFLNK)) {
return YES;
}
}
return NO;
}
- (int)checkdebug {
int debug = -1;
// check sysctl antidebug
struct kinfo_proc info;
size_t size;
info.kp_proc.p_flag = 0;
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
size = sizeof(info);
int status = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
if (status == 0) {
debug = (info.kp_proc.p_flag & P_TRACED) != 0;
}
// check isatty antidebug
if (debug < 1) {
debug = isatty(1);
}
return debug;
}
- (int)isSimulator {
int simulator = -1;
{
#if TARGET_IPHONE_SIMULATOR
simulator = 1;
#else
simulator = 0;
#endif
}
if (!simulator) {
uint64_t dyld_simulator = 0;
uint32_t dyld_count = _dyld_image_count();
NSString* dyld_sim_str = @"usr/lib/dyld_sim";
NSString* CoreSimulator_str = @"Library/Developer/CoreSimulator";
char* cEmptyString = "";
for (uint32_t i = 0; i < dyld_count; i++) {
@autoreleasepool {
if(i > 10000)
break;
NSString *dyld_image_name = [NSString stringWithCString:_dyld_get_image_name(i) ?: cEmptyString encoding:NSUTF8StringEncoding];
//dyld_simulator
if ([dyld_image_name hasSuffix:dyld_sim_str]) {
dyld_simulator |= 1;
}
if ([dyld_image_name containsString:CoreSimulator_str]) {
dyld_simulator |= 1<<1;
}
}
}
simulator = (dyld_simulator ? 1 : 0);
}
return simulator;
}
@end

View File

@ -0,0 +1,17 @@
//
// TDMobRiskIdentifierInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskIdentifierInfo : TDMobRiskBaseInfo
/** Identifier */
/// idfv
@property (nonatomic, copy) NSString *idfv;
/// cloudid
@property (nonatomic, copy) NSString *cloudid;
@end

View File

@ -0,0 +1,37 @@
//
// TDMobRiskIdentifierInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskIdentifierInfo.h"
#import "TDMobRiskKeychainsHelper.h"
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@implementation TDMobRiskIdentifierInfo
#pragma mark - Collect Methods
- (void)getInfo {
// idfv
{
NSString *idfvCache = [TDMobRiskKeychainsHelper loadValueForKey:@"idfv"];
// Read the keychains cache first. If the cache does not exist, regenerate the IDFV and write it to the keychains cache
if (!idfvCache || idfvCache.length == 0) {
UIDevice *device = [UIDevice currentDevice];
idfvCache = [[device identifierForVendor] UUIDString];
}
_idfv = idfvCache;
}
//cloudid need to iCloud Key-Value storage Capability
NSString *cloudid = [[NSUbiquitousKeyValueStore defaultStore] stringForKey:@"td_cloudid"];
if(!cloudid) {
cloudid = [NSUUID UUID].UUIDString;
[[NSUbiquitousKeyValueStore defaultStore] setString:cloudid forKey:@"td_cloudid"];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
}
_cloudid = cloudid;
}
@end

View File

@ -0,0 +1,20 @@
//
// TDMobRiskOSInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskOSInfo : TDMobRiskBaseInfo
/** OS Info **/
/// osVersion
@property (nonatomic, copy) NSString *osVersion;
/// osType
@property (nonatomic, copy) NSString *osType;
/// osRelease
@property (nonatomic, copy) NSString *osRelease;
/// kernelVersion
@property (nonatomic, copy) NSString *kernelVersion;
@end

View File

@ -0,0 +1,40 @@
//
// TDMobRiskOSInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskOSInfo.h"
#import "TDMobRiskAPIHelper.h"
#import <UIKit/UIKit.h>
@implementation TDMobRiskOSInfo
#pragma mark - Collect Methods
- (void)getInfo {
// osVersion
{
NSString *osVersion = [TDMobRiskAPIHelper sysctlByName:"kern.osversion" isObject:YES];
_osVersion = osVersion;
}
// osType
{
NSString *osType = [TDMobRiskAPIHelper sysctlByName:"kern.ostype" isObject:YES];
_osType = osType;
}
// osRelease
{
NSString *osRelease = [TDMobRiskAPIHelper sysctlByName:"kern.osrelease" isObject:YES];
_osRelease = osRelease;
}
// kernelVersion
{
NSString *kernelVersion = [TDMobRiskAPIHelper sysctlByName:"kern.version" isObject:YES];
_kernelVersion = kernelVersion;
}
}
@end

View File

@ -0,0 +1,22 @@
//
// TDMobRiskSpaceInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskSpaceInfo : TDMobRiskBaseInfo
/** spaceInfo */
/// freeDiskSpace
@property (nonatomic, assign) long long freeDiskSpace;
/// totalDiskSpace
@property (nonatomic, assign) long long totalDiskSpace;
/// memorySize(ram size)
@property (nonatomic, copy) NSString *memorySize;
/// physicalMemory
@property (nonatomic, copy) NSString *physicalMemory;
@end

View File

@ -0,0 +1,62 @@
//
// TDMobRiskSpaceInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskSpaceInfo.h"
#import "TDMobRiskAPIHelper.h"
#import <UIKit/UIKit.h>
@implementation TDMobRiskSpaceInfo
#pragma mark - Collect Methods
- (void)getInfo {
// totalDiskSpace
{
long long totalDiskSpace = -1;
NSError *error = nil;
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *docDict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[docPaths lastObject] error:&error];
if (docDict) {
NSNumber *systemSize = [docDict objectForKey:NSFileSystemSize];
totalDiskSpace = [systemSize unsignedLongLongValue];
}else {
#ifdef DEBUG
NSLog(@"[%s] - [Error] - %@ ",__func__, error);
#endif
}
_totalDiskSpace = totalDiskSpace;
}
// freeDiskSpace
{
long long freeDiskSpace = -1;
NSError *error = nil;
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *docDict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[docPaths lastObject] error:&error];
if (docDict) {
NSNumber *systemFreeSize = [docDict objectForKey:NSFileSystemFreeSize];
freeDiskSpace = [systemFreeSize unsignedLongLongValue];
}else {
#ifdef DEBUG
NSLog(@"[%s] - [Error] - %@ ",__func__, error);
#endif
}
_freeDiskSpace = freeDiskSpace;
}
// memorySize
{
NSString *memorySize = [TDMobRiskAPIHelper sysctlByName:"hw.memsize" isObject:NO];
_memorySize = memorySize;
}
// physicalMemory
{
NSString *physicalMemory = [TDMobRiskAPIHelper sysctlByName:"hw.physmem" isObject:NO];
_physicalMemory = physicalMemory;
}
}
@end

View File

@ -0,0 +1,16 @@
//
// TDMobRiskTimeInfo.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskBaseInfo.h"
@interface TDMobRiskTimeInfo : TDMobRiskBaseInfo
/** timeInfo */
/// currentTime, unit is microsecond
@property (nonatomic, assign) NSTimeInterval currentTime;
/// bootTime, unit is microsecond
@property (nonatomic, assign) NSTimeInterval bootTime;
@end

View File

@ -0,0 +1,34 @@
//
// TDMobRiskTimeInfo.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskTimeInfo.h"
#import "TDMobRiskAPIHelper.h"
#import <sys/sysctl.h>
@implementation TDMobRiskTimeInfo
#pragma mark - Collect Methods
- (void)getInfo {
// currentTime
{
NSDate *date = [NSDate date];
NSTimeInterval currentTime = [date timeIntervalSince1970] * 1000000;
_currentTime = currentTime;
}
// bootTime
{
struct timeval bootTime_t;
size_t size = sizeof(bootTime_t);
int result = sysctlbyname("kern.boottime", &bootTime_t, &size, NULL, 0);
NSTimeInterval bootTime = 0;
if (result == 0) {
bootTime = bootTime_t.tv_sec *(long long)1000000 + bootTime_t.tv_usec;
}
_bootTime = bootTime;
}
}
@end

View File

@ -0,0 +1,14 @@
//
// TDMobRiskCollector.h
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskCollector : NSObject
/// Get CollectData
+ (NSDictionary *)getCollectInfo;
@end

View File

@ -0,0 +1,62 @@
//
// TDMobRiskCollector.m
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskCollector.h"
#import "TDMobRiskIdentifierInfo.h"
#import "TDMobRiskOSInfo.h"
#import "TDMobRiskCpuInfo.h"
#import "TDMobRiskAppInfo.h"
#import "TDMobRiskDeviceStatusInfo.h"
#import "TDMobRiskSpaceInfo.h"
#import "TDMobRiskDeviceInfo.h"
#import "TDMobRiskTimeInfo.h"
#import "TDMobRiskIdCalculator.h"
#import "TDMobRiskHeader.h"
@implementation TDMobRiskCollector
#pragma mark - Output Methods
/// Get CollectData
+ (NSDictionary *)getCollectInfo {
/** Collect Data */
// IdentifierInfo
TDMobRiskIdentifierInfo *identifierInfo = [[TDMobRiskIdentifierInfo alloc] init];
// OSInfo
TDMobRiskOSInfo *osInfo = [[TDMobRiskOSInfo alloc] init];
// CpuInfo
TDMobRiskCpuInfo *cpuInfo = [[TDMobRiskCpuInfo alloc] init];
// AppInfo
TDMobRiskAppInfo *appInfo = [[TDMobRiskAppInfo alloc] init];
// DeviceStatusInfo
TDMobRiskDeviceStatusInfo *deviceStatusInfo = [[TDMobRiskDeviceStatusInfo alloc] init];
// SpaceInfo
TDMobRiskSpaceInfo *spaceInfo = [[TDMobRiskSpaceInfo alloc] init];
// DeviceInfo
TDMobRiskDeviceInfo *deviceInfo = [[TDMobRiskDeviceInfo alloc] init];
// TimeInfo
TDMobRiskTimeInfo *timeInfo = [[TDMobRiskTimeInfo alloc] init];
/* Transfer the collected data to json **/
NSArray *collectTypeObjArray = @[
identifierInfo,
osInfo,
cpuInfo,
appInfo,
deviceStatusInfo,
spaceInfo,
deviceInfo,
timeInfo
];
NSMutableDictionary *collectDataDict = [[NSMutableDictionary alloc] init];
for (TDMobRiskBaseInfo *info in collectTypeObjArray) {
NSDictionary *infoDict = [info getJsonDict];
if (infoDict && [infoDict isKindOfClass:[NSDictionary class]]) {
[collectDataDict setValuesForKeysWithDictionary:infoDict];
}
}
return collectDataDict;
}
@end

View File

@ -0,0 +1,12 @@
//
// TDMobRiskSafeDictionary.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskSafeDictionary : NSMutableDictionary
@end

View File

@ -0,0 +1,225 @@
//
// TDMobRiskSafeDictionary.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskSafeDictionary.h"
#define INIT(...) self = super.init; \
if (!self) return nil; \
__VA_ARGS__; \
if (!_dic) return nil; \
_lock = dispatch_semaphore_create(1); \
return self;
#define LOCK(...) dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); \
__VA_ARGS__; \
dispatch_semaphore_signal(_lock);
@implementation TDMobRiskSafeDictionary {
NSMutableDictionary *_dic; //Subclass a class cluster...
dispatch_semaphore_t _lock;
}
#pragma mark - init
- (instancetype)init {
INIT(_dic = [[NSMutableDictionary alloc] init]);
}
- (instancetype)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys {
INIT(_dic = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys]);
}
- (instancetype)initWithCapacity:(NSUInteger)capacity {
INIT(_dic = [[NSMutableDictionary alloc] initWithCapacity:capacity]);
}
- (instancetype)initWithObjects:(const id[])objects forKeys:(const id <NSCopying>[])keys count:(NSUInteger)cnt {
INIT(_dic = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys count:cnt]);
}
- (instancetype)initWithDictionary:(NSDictionary *)otherDictionary {
INIT(_dic = [[NSMutableDictionary alloc] initWithDictionary:otherDictionary]);
}
- (instancetype)initWithDictionary:(NSDictionary *)otherDictionary copyItems:(BOOL)flag {
INIT(_dic = [[NSMutableDictionary alloc] initWithDictionary:otherDictionary copyItems:flag]);
}
#pragma mark - method
- (NSUInteger)count {
LOCK(NSUInteger c = _dic.count); return c;
}
- (id)objectForKey:(id)aKey {
LOCK(id o = [_dic objectForKey:aKey]); return o;
}
- (NSEnumerator *)keyEnumerator {
LOCK(NSEnumerator * e = [_dic keyEnumerator]); return e;
}
- (NSArray *)allKeys {
LOCK(NSArray * a = [_dic allKeys]); return a;
}
- (NSArray *)allKeysForObject:(id)anObject {
LOCK(NSArray * a = [_dic allKeysForObject:anObject]); return a;
}
- (NSArray *)allValues {
LOCK(NSArray * a = [_dic allValues]); return a;
}
- (NSString *)description {
LOCK(NSString * d = [_dic description]); return d;
}
- (NSString *)descriptionInStringsFileFormat {
LOCK(NSString * d = [_dic descriptionInStringsFileFormat]); return d;
}
- (NSString *)descriptionWithLocale:(id)locale {
LOCK(NSString * d = [_dic descriptionWithLocale:locale]); return d;
}
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
LOCK(NSString * d = [_dic descriptionWithLocale:locale indent:level]); return d;
}
- (BOOL)isEqualToDictionary:(NSDictionary *)otherDictionary {
if (otherDictionary == self) return YES;
if ([otherDictionary isKindOfClass:TDMobRiskSafeDictionary.class]) {
TDMobRiskSafeDictionary *other = (id)otherDictionary;
BOOL isEqual;
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(other->_lock, DISPATCH_TIME_FOREVER);
isEqual = [_dic isEqual:other->_dic];
dispatch_semaphore_signal(other->_lock);
dispatch_semaphore_signal(_lock);
return isEqual;
}
return NO;
}
- (NSEnumerator *)objectEnumerator {
LOCK(NSEnumerator * e = [_dic objectEnumerator]); return e;
}
- (NSArray *)objectsForKeys:(NSArray *)keys notFoundMarker:(id)marker {
LOCK(NSArray * a = [_dic objectsForKeys:keys notFoundMarker:marker]); return a;
}
- (NSArray *)keysSortedByValueUsingSelector:(SEL)comparator {
LOCK(NSArray * a = [_dic keysSortedByValueUsingSelector:comparator]); return a;
}
- (void)getObjects:(id __unsafe_unretained[])objects andKeys:(id __unsafe_unretained[])keys {
LOCK([_dic getObjects:objects andKeys:keys]);
}
- (id)objectForKeyedSubscript:(id)key {
LOCK(id o = [_dic objectForKeyedSubscript:key]); return o;
}
- (void)enumerateKeysAndObjectsUsingBlock:(void (NS_NOESCAPE ^)(id key, id obj, BOOL *stop))block {
LOCK([_dic enumerateKeysAndObjectsUsingBlock:block]);
}
- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(id key, id obj, BOOL *stop))block {
LOCK([_dic enumerateKeysAndObjectsWithOptions:opts usingBlock:block]);
}
- (NSArray *)keysSortedByValueUsingComparator:(NSComparator NS_NOESCAPE)cmptr {
LOCK(NSArray * a = [_dic keysSortedByValueUsingComparator:cmptr]); return a;
}
- (NSArray *)keysSortedByValueWithOptions:(NSSortOptions)opts usingComparator:(NSComparator NS_NOESCAPE)cmptr {
LOCK(NSArray * a = [_dic keysSortedByValueWithOptions:opts usingComparator:cmptr]); return a;
}
- (NSSet *)keysOfEntriesPassingTest:(BOOL (NS_NOESCAPE ^)(id key, id obj, BOOL *stop))predicate {
LOCK(NSSet * a = [_dic keysOfEntriesPassingTest:predicate]); return a;
}
- (NSSet *)keysOfEntriesWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (NS_NOESCAPE ^)(id key, id obj, BOOL *stop))predicate {
LOCK(NSSet * a = [_dic keysOfEntriesWithOptions:opts passingTest:predicate]); return a;
}
#pragma mark - mutable
- (void)removeObjectForKey:(id)aKey {
LOCK([_dic removeObjectForKey:aKey]);
}
- (void)setObject:(id)anObject forKey:(id <NSCopying> )aKey {
LOCK([_dic setObject:anObject forKey:aKey]);
}
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary {
LOCK([_dic addEntriesFromDictionary:otherDictionary]);
}
- (void)removeAllObjects {
LOCK([_dic removeAllObjects]);
}
- (void)removeObjectsForKeys:(NSArray *)keyArray {
LOCK([_dic removeObjectsForKeys:keyArray]);
}
- (void)setDictionary:(NSDictionary *)otherDictionary {
LOCK([_dic setDictionary:otherDictionary]);
}
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying> )key {
LOCK([_dic setObject:obj forKeyedSubscript:key]);
}
#pragma mark - protocol
- (id)copyWithZone:(NSZone *)zone {
return [self mutableCopyWithZone:zone];
}
- (id)mutableCopyWithZone:(NSZone *)zone {
LOCK(id copiedDictionary = [[self.class allocWithZone:zone] initWithDictionary:_dic]);
return copiedDictionary;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(id __unsafe_unretained[])stackbuf
count:(NSUInteger)len {
LOCK(NSUInteger count = [_dic countByEnumeratingWithState:state objects:stackbuf count:len]);
return count;
}
- (BOOL)isEqual:(id)object {
if (object == self) return YES;
if ([object isKindOfClass:TDMobRiskSafeDictionary.class]) {
TDMobRiskSafeDictionary *other = object;
BOOL isEqual;
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(other->_lock, DISPATCH_TIME_FOREVER);
isEqual = [_dic isEqual:other->_dic];
dispatch_semaphore_signal(other->_lock);
dispatch_semaphore_signal(_lock);
return isEqual;
}
return NO;
}
- (NSUInteger)hash {
LOCK(NSUInteger hash = [_dic hash]);
return hash;
}
@end

View File

@ -0,0 +1,13 @@
//
// TDMobRiskCalculator.h
// TDMobRisk
//
// Created by zeinber on 2022/12/12.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskCalculator : NSObject
/// Generate risk label according to the collected information
+ (NSDictionary *)generateRiskLabelByInfo:(NSDictionary *)info;
@end

View File

@ -0,0 +1,24 @@
//
// TDMobRiskCalculator.m
// TDMobRisk
//
// Created by zeinber on 2022/12/12.
//
#import "TDMobRiskCalculator.h"
@implementation TDMobRiskCalculator
+ (NSDictionary *)generateRiskLabelByInfo:(NSDictionary *)info {
NSMutableDictionary *riskDict = [[NSMutableDictionary alloc] init];
NSArray *riskArray = @[
@"jailbreak",@"simulator",@"debug"
];
for (id riskLabel in riskArray) {
id riskInfo = info[riskLabel];
if (riskInfo) {
[riskDict setObject:riskInfo forKey:riskLabel];
}
}
return [riskDict copy];
}
@end

View File

@ -0,0 +1,13 @@
//
// TDMobRiskIdCalculator.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskIdCalculator : NSObject
/// Generate ID according to the collected information
+ (NSString *)generateIdByInfo:(NSDictionary *)info;
@end

View File

@ -0,0 +1,21 @@
//
// TDMobRiskIdCalculator.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskIdCalculator.h"
#import "TDMobRiskEncodeHelper.h"
@implementation TDMobRiskIdCalculator
+ (NSString *)generateIdByInfo:(NSDictionary *)info {
// Calculate DeviceId
NSString *idfv = info[@"idfv"];
NSString *deviceId = nil;
if (idfv && [idfv isKindOfClass:[NSString class]]) {
deviceId = [TDMobRiskEncodeHelper sha256WithSrc:idfv];
}
return deviceId;
}
@end

View File

@ -0,0 +1,13 @@
//
// TDMobRiskAPIHelper.h
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskAPIHelper : NSObject
/// get SystemInfo by Name.
+ (NSString *)sysctlByName:(const char *)name isObject:(BOOL)isObject;
@end

View File

@ -0,0 +1,40 @@
//
// TDMobRiskAPIHelper.m
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskAPIHelper.h"
#import <sys/sysctl.h>
@implementation TDMobRiskAPIHelper
+ (NSString *)sysctlByName:(const char *)name isObject:(BOOL)isObject {
NSString *cString = nil;
NSString *unknowDesc = @"unknow";
if (isObject) {
size_t size = 0;
sysctlbyname(name, NULL, &size, NULL, 0);
void *cstr = malloc(size);
memset(cstr, 0, size);
int sysctl_flag = sysctlbyname(name, cstr, &size, NULL, 0);
if (sysctl_flag == 0) {
cString = [[NSString alloc] initWithCString:cstr ?: "" encoding:NSUTF8StringEncoding];
}else {
cString = unknowDesc;
}
free(cstr);
}else {
long long num;
size_t numLen = sizeof(num);
int sysctl_flag = sysctlbyname(name, &num, &numLen, NULL, 0);
if (sysctl_flag == 0) {
cString = [NSString stringWithFormat:@"%lld",num];
}else {
cString = unknowDesc;
}
}
return cString;
}
@end

View File

@ -0,0 +1,13 @@
//
// TDMobRiskEncodeHelper.h
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskEncodeHelper : NSObject
/// sha256 Encode String
+ (NSString *)sha256WithSrc:(NSString *)src;
@end

View File

@ -0,0 +1,30 @@
//
// TDMobRiskEncodeHelper.m
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import "TDMobRiskEncodeHelper.h"
#import <CommonCrypto/CommonCrypto.h>
@implementation TDMobRiskEncodeHelper
#pragma mark - SHA256
+ (NSString *)sha256WithSrc:(NSString *)src {
const char *c = [src UTF8String];
if (!c) {
#ifdef DEBUG
NSLog(@"[%s] - [Error] - src[%@] is nil",__func__,src);
#endif
return nil;
}
unsigned char result[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(c, (CC_LONG)strlen(c), result);
NSMutableString *hash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return [hash lowercaseString];
}
@end

View File

@ -0,0 +1,14 @@
//
// TDMobRiskKeychainsHelper.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import <Foundation/Foundation.h>
@interface TDMobRiskKeychainsHelper : NSObject
+ (OSStatus)deleteValueForKey:(NSString *)key;
+ (OSStatus)saveValueForKey:(NSString *)key value:(id)value;
+ (id)loadValueForKey:(NSString *)key;
@end

View File

@ -0,0 +1,78 @@
//
// TDMobRiskKeychainsHelper.m
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#import "TDMobRiskKeychainsHelper.h"
#import <Security/Security.h>
static NSString *keychainAccount = @"com.td.mobrisk";
@implementation TDMobRiskKeychainsHelper
#pragma mark - function
+ (OSStatus)deleteValueForKey:(NSString *)key {
if (!key) {
return -1;
}
NSDictionary *keychainQuery = @{
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : key,
(__bridge id)kSecAttrAccount : keychainAccount
};
OSStatus result = SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
return result;
}
+ (OSStatus)saveValueForKey:(NSString *)key value:(id)value {
if (!key) {
return -1;
}
if (!value) {
return -2;
}
NSMutableDictionary *keychainQuery = [[NSMutableDictionary alloc] initWithDictionary:@{
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : key,
(__bridge id)kSecAttrAccount : keychainAccount,
(__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
}];
[self deleteValueForKey:key];
NSData *archiverData = [NSKeyedArchiver archivedDataWithRootObject:value];
if (archiverData) {
[keychainQuery setObject:archiverData forKey:(__bridge id)kSecValueData];
}
OSStatus result = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
return result;
}
+ (id)loadValueForKey:(NSString *)key {
id value = nil;
if (!key) {
return value;
}
NSMutableDictionary *keychainQuery = [[NSMutableDictionary alloc] initWithDictionary:@{
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : key,
(__bridge id)kSecAttrAccount : keychainAccount,
(__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue,
(__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne
}];
CFDataRef keyData = NULL;
OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData);
if (result == noErr) {
@try {
value = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
}
@catch (NSException *e) {
value = nil;
}
@finally {}
}
if (keyData) {
CFRelease(keyData);
}
return value;
}
@end

View File

@ -0,0 +1,17 @@
//
// TDMobRisk.h
// TDMobRisk
//
// Created by zeinber on 2022/12/6.
//
#import <Foundation/Foundation.h>
//! Project version number for TDMobRisk.
FOUNDATION_EXPORT double TDMobRiskVersionNumber;
//! Project version string for TDMobRisk.
FOUNDATION_EXPORT const unsigned char TDMobRiskVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <TDMobRisk/PublicHeader.h>
#import <TrustDecision/TDMobRiskManager.h>

View File

@ -0,0 +1,15 @@
//
// TDMobRiskHeader.h
// TDMobRisk
//
// Created by zeinber on 2022/12/7.
//
#ifndef TDMobRiskHeader_h
#define TDMobRiskHeader_h
#pragma mark - Defination List
#define DeviceIdKey @"device_id"
#define DeviceRiskLabelKey @"device_risk_label"
#define DeviceDetailKey @"device_detail"
#endif /* TDMobRiskHeader_h */

View File

@ -0,0 +1,31 @@
//
// TDMobRiskManager.h
// TDMobRisk
//
// Created by zeinber on 2022/12/5.
//
#import <Foundation/Foundation.h>
typedef struct _TDMobRiskVoid {
/**
* Initialization method
* @param options Initialization parametersplease see the document for details.
*/
void (*initWithOptions)(NSDictionary *);
/**
* get device info, you should make sure that method calls after initWithOptions.
*/
NSDictionary *(*getBlackBox)(void);
/**
* get sdkVersioncurrentVersion is 1.1
*/
NSString *(*getSDKVersion)(void);
} TDMobRiskManager_t;
@interface TDMobRiskManager : NSObject
/**
* get a singleton object
*/
+ (TDMobRiskManager_t *)sharedManager;
@end

View File

@ -0,0 +1,102 @@
//
// TDMobRiskManager.m
// TDMobRisk
//
// Created by zeinber on 2022/12/5.
//
#import "TDMobRiskManager.h"
#import "TDMobRiskSafeDictionary.h"
#import "TDMobRiskCollector.h"
#import "TDMobRiskIdCalculator.h"
#import "TDMobRiskCalculator.h"
#import "TDMobRiskHeader.h"
#pragma mark - Static Param
/// SDK Object
static TDMobRiskManager_t *riskManager;
/// SDKVersion
static NSString *sdkVersion = @"1.3";
/// CollectData Dictionary
static TDMobRiskSafeDictionary *infoDict;
/// Global Collect Queue
static dispatch_queue_t collectQueue;
#pragma mark - Output Function Define List
/// Initialization Function
void initWithOptions(NSDictionary *options);
/// Get BlackBox
NSDictionary *getBlackBox(void);
/// Get SDKVersion
NSString *getSDKVersion(void);
#pragma mark - Private Function Define List
/// Assert
static void TDMobRisk_assert(BOOL condition, const char *assertDescription);
@implementation TDMobRiskManager
#pragma mark - public methods
+ (TDMobRiskManager_t *)sharedManager {
static dispatch_once_t deviceManager_once_token;
dispatch_once(&deviceManager_once_token, ^{
riskManager = malloc(sizeof(TDMobRiskManager_t));
riskManager->initWithOptions = initWithOptions;
riskManager->getBlackBox = getBlackBox;
riskManager->getSDKVersion = getSDKVersion;
collectQueue = dispatch_queue_create("com.td.mobrisk.collector", DISPATCH_QUEUE_CONCURRENT);
});
return riskManager;
}
void initWithOptions(NSDictionary *options) {
// protect judge
/// Please use Dictionary
TDMobRisk_assert([options isKindOfClass:[NSDictionary class]], ("[TDMobRiskManager] - [INIT_ERROR] - options is not dictonary type"));
// Async Collect
dispatch_barrier_async(collectQueue, ^{
// Response data
NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] init];
// Collect data
NSDictionary *collectInfo = [TDMobRiskCollector getCollectInfo];
// Calculate and set deviceId
NSString *deviceId = [TDMobRiskIdCalculator generateIdByInfo:collectInfo];
if (deviceId) {
[dataDict setObject:deviceId forKey:DeviceIdKey];
}
// Calculate and set deviceRisk
NSDictionary *deviceRiskLabel = [TDMobRiskCalculator generateRiskLabelByInfo:collectInfo];
if (deviceRiskLabel) {
[dataDict setObject:deviceRiskLabel forKey:DeviceRiskLabelKey];
}
// Calculate and set deviceDetail
if (collectInfo) {
[dataDict setObject:collectInfo forKey:DeviceDetailKey];
}
infoDict = [[TDMobRiskSafeDictionary alloc] initWithDictionary:dataDict];
// Copy Dictionary of infoDict
NSDictionary *responseDict = [[NSDictionary alloc] initWithDictionary:infoDict];
// Set parameters of response
void (^responseCallback)(NSDictionary *blackBox) = [options objectForKey:@"callback"];
// Response callback
if (responseCallback) {
responseCallback(responseDict);
}
});
}
NSDictionary *getBlackBox() {
return [infoDict copy];
}
NSString *getSDKVersion() {
return sdkVersion;
}
#pragma mark - Private Function List
/// Asset Error
static void TDMobRisk_assert(BOOL condition, const char *assertDescription) {
if (!condition) {
__assert_rtn(__func__, ("unknown"), 0, assertDescription);
}
}
@end