首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用dlopen的IOKit

使用dlopen的IOKit
EN

Stack Overflow用户
提问于 2013-04-28 00:18:49
回答 3查看 1.1K关注 0票数 1

在我的应用程序中,我通过这种方式(通过IOKit)获取电池信息。

代码语言:javascript
复制
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,这样苹果可能就不会发现IOKit在那里了。谢谢。

EN

回答 3

Stack Overflow用户

发布于 2013-04-28 00:27:03

我需要使用dlopen获取IOReturnio_registry_entry_t

这些只是类型。它们是在头文件中声明的,不是编译到IOKit库中的类型。使用dlopen()是无法获得这些的。

,所以苹果可能不会发现IOKit在那里

同样,类型没有在二进制文件中显式表示。如果苹果发现你在使用IOKit,那么的原因就是使用了这些类型。它们是出卖的函数名。

但是,如果您使用dlopen()检索指向这些函数的指针,则表示函数名称的字符串对于苹果的静态分析工具来说仍然是一本打开的书。您可能需要做一些额外的模糊处理,以便二进制文件不会直接公开私有函数名:

代码语言:javascript
复制
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);

等。

票数 2
EN

Stack Overflow用户

发布于 2013-04-30 07:48:48

H2CO3是正确的。#includeing IOKit完全不会影响编译后的代码。当你直接使用IOKit头中定义的函数和IOKit链接时,私有框架才能在你的应用中清晰地显示出来。一种用于隐藏私有框架和使用的符号的混淆形式是简单的密码转换。例如,以H2CO3为例:

代码语言:javascript
复制
// 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中是默认启用的,但我不确定。你需要自己弄清楚这一点。

票数 0
EN

Stack Overflow用户

发布于 2018-10-05 00:42:29

代码语言:javascript
复制
#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中,您只会得到几个值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16254325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档