在我的应用程序中,我正在使用这种方式获取电池信息(通过IOKit)。
static void print_raw_battery_state(io_registry_entry_t b_reg) {
CFBooleanRef boo;
CFNumberRef n;
int tmp;
int cur_cap = -1;
int max_cap = -1;
CFMutableDictionaryRef prop = NULL;
IOReturn ret;
ret = IORegistryEntryCreateCFProperties(b_reg, &prop, 0, 0);
if( (kIOReturnSuccess != ret) || (NULL == prop) )
{
printf("Couldn't read battery status; error = 0%08x\n", ret);
return;
}
boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSExternalConnectedKey));
printf(" external connected = %s\n",
(kCFBooleanTrue == boo) ? "yes" : "no");
boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSBatteryInstalledKey));
printf(" battery present = %s\n",
(kCFBooleanTrue == boo) ? "yes" : "no");
boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSIsChargingKey));
printf(" battery charging = %s\n",
(kCFBooleanTrue == boo) ? "yes" : "no");
n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCurrentCapacityKey));
if(n) {
CFNumberGetValue(n, kCFNumberIntType, &cur_cap);
}
n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCurrentCapacityKey));
if(n) {
CFNumberGetValue(n, kCFNumberIntType, &max_cap);
}
if( (-1 != cur_cap) && (-1 != max_cap) )
{
printf(" cap = %d/%d\n", cur_cap, max_cap);
gcurCapacity = cur_cap;//hab
gmaxCapacity = max_cap;//hab
}
n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSTimeRemainingKey));
if(n) {
CFNumberGetValue(n, kCFNumberIntType, &tmp);
NSLog(@" time REM = %d:%02d\n", tmp/60, tmp%60);
printf("time cicA = %d:%02d\n", tmp/60, tmp%60);
NSString *stringTimeRem = [NSString stringWithFormat:@"%d:%02d", tmp/60, tmp%60];
[[NSUserDefaults standardUserDefaults] setObject:stringTimeRem forKey:@"stringREM"];
}
n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSAmperageKey));
if(n) {
CFNumberGetValue(n, kCFNumberIntType, &tmp);
gcurrent = tmp;//hab
printf(" current = %d\n", tmp);
}
n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCycleCountKey));
if(n) {
CFNumberGetValue(n, kCFNumberIntType, &tmp);
printf(" cycle count = %d\n", tmp);
gloadcycles = tmp;//hab
}
n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSLocationKey));
if(n) {
CFNumberGetValue(n, kCFNumberIntType, &tmp);
printf(" location = %d\n", tmp);
}
printf("\n");
CFRelease(prop);
return;}
如何使用dlopen访问这些信息?我需要使用dlopen来获取IOReturn和io_registry_entry_t,因此Apple可能不会发现IOKit存在。 感谢。
答案 0 :(得分:2)
我需要使用dlopen
获取IOReturn
和io_registry_entry_t
那些只是类型。它们在头文件中声明,不编译到IOKit库中。你不能使用dlopen()
获得那些。
所以Apple可能不会发现IOKit在那里
同样,类型未在二进制文件中明确表示。如果Apple发现您正在使用IOKit,那么的原因将不会使用这些类型。它们是背叛的功能名称。
但是,如果使用dlopen()
检索指向这些函数的指针,则表示函数名称的字符串仍然是Apple静态分析工具的开放式书籍。您可能必须进行一些额外的混淆,以使二进制文件不直接公开私有函数名称:
NSString *secondPart = @"ateCFProperties";
NSString *firstPart = @"IORegistryEntryCre";
const char *fname = [[firstPart stringByAppendingString:secondPart] UTF8String];
IOReturn (*fptr)(io_registry_entry_t, CFMutableDictionaryRef *, int, int);
fptr = dlsym(dyld_handle, fname);
等
答案 1 :(得分:0)
H2CO3是正确的。只是#include
IOKit根本不会影响编译代码。当您直接使用IOKit头中定义的函数并链接到IOKit时,可以在您的应用中清楚地看到私有框架。隐藏所使用的私有框架和符号的一种混淆形式是简单的密码转换。例如,使用H2CO3的例子:
// Deciphers string in-place and returns a pointer to it
__attribute__((always_inline)) char* decipher(char* str) {
int i, n = strlen(str);
for(i = 0; i < n; i++) str[i]--;
return str;
}
//...
char sym[] = "JPSfhjtuszFouszDsfbufDGQspqfsujft";
char fr[] = "Gsbnfxpslt";
char fmwk[] = "JPLju";
char lib[60];
decipher(fmwk);
sprintf(lib, "/System/Library/%s/%s.framework/Versions/A/%s", fr, fmwk, fmwk);
void* handle = dlopen(lib, RTLD_LAZY);
IOReturn (*fptr)(io_registry_event_t, CFMutableDictionaryRef*,i int, int);
fptr = dlsym(handle, decipher(sym));
// Now just call fptr() as if it were IORegistryEntryCreateCFProperties()
这与H2CO3的版本之间的区别在于,这将阻止人们手动分析应用程序,在没有合理数量的专业知识的情况下完全找到IOKit。当然,无论你试图隐藏它的程度如何,确定的反向器仍然可以找到IOKit的用法。混淆在这里很有用,因为App Store评论员可能不会花费时间将您的应用程序反转几天。另外,在提交之前,请记住strip
您的应用。我认为在Xcode中默认启用剥离,但我不确定。你需要自己解决这个问题。
答案 2 :(得分:0)
#import "ViewController.h"
#import "IOKit/IOKitLib.h"
#import "IOKit/IOPSKeys.h"
#include <dlfcn.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
static mach_port_t *s_kIOMasterPortDefault;
static kern_return_t (*s_IORegistryEntryCreateCFProperties)(mach_port_t entry, CFMutableDictionaryRef *properties, CFAllocatorRef allocator, UInt32 options);
static mach_port_t (*s_IOServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching CF_RELEASES_ARGUMENT);
static CFMutableDictionaryRef (*s_IOServiceMatching)(const char *name);
static CFMutableDictionaryRef g_powerSourceService;
static mach_port_t g_platformExpertDevice;
static BOOL foundSymbols = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
void* handle = dlopen("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_LAZY);
s_IORegistryEntryCreateCFProperties = dlsym(handle, "IORegistryEntryCreateCFProperties");
s_kIOMasterPortDefault = dlsym(handle, "kIOMasterPortDefault");
s_IOServiceMatching = dlsym(handle, "IOServiceMatching");
s_IOServiceGetMatchingService = dlsym(handle, "IOServiceGetMatchingService");
if (s_IORegistryEntryCreateCFProperties && s_IOServiceMatching && s_IOServiceGetMatchingService) {
g_powerSourceService = s_IOServiceMatching("IOPMPowerSource");
g_platformExpertDevice = s_IOServiceGetMatchingService(*s_kIOMasterPortDefault, g_powerSourceService);
foundSymbols = (g_powerSourceService && g_platformExpertDevice);
}
});
if (!foundSymbols) {
return;
}
print_raw_battery_state(g_platformExpertDevice);
}
static void print_raw_battery_state(io_registry_entry_t b_reg) {
CFBooleanRef boo;
CFNumberRef n;
int tmp;
int cur_cap = -1;
int max_cap = -1;
CFMutableDictionaryRef prop = NULL;
IOReturn ret;
ret = IORegistryEntryCreateCFProperties(b_reg, &prop, 0, 0);
if( (kIOReturnSuccess != ret) || (NULL == prop) )
{
printf("Couldn't read battery status; error = 0%08x\n", ret);
return;
}
// battery dictionary
NSLog(@"prop: %@", prop);
printf("\n");
CFRelease(prop);
return;
}
}
@end
在iOS 11和12中,您只会得到一些值。