Hook实列变量闪退问题

偿试练习hook,显示屏的宽高,查找了一下读取宽高的代码如下:

CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGFloat screenScale = [UIScreen mainScreen].scale;
CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale);

于是找到UIScreen.h文件如下:

@interface UIScreen : NSObject <UICoordinateSpace, UIFocusContainer, UITraitEnvironment, _UIFocusEnvironmentInternal, _UIFocusEnvironmentPrivate, _UIFocusRegionContainer, _UITraitEnvironmentInternal> {
    UIWindow<UIFocusEnvironment> * __focusedWindow;
    NSArray * _availableDisplayModes;
    struct CGRect { 
        struct CGPoint { 
            float x; 
            float y; 
        } origin; 
        struct CGSize { 
            float width; 
            float height; 
        } size; 
    }  _bounds;
+ (void)_FBSDisplayDidPossiblyConnect:(id)arg1;
+ (void)_FBSDisplayDidPossiblyConnect:(id)arg1 withScene:(id)arg2;
+ (void)_FBSDisplayDidPossiblyConnect:(id)arg1 withScene:(id)arg2 andPost:(BOOL)arg3;
+ (void)_FBSDisplayDidPossiblyDisconnect:(id)arg1;
+ (void)_FBSDisplayDidPossiblyDisconnect:(id)arg1 forSceneDestruction:(id)arg2;
+ (id)__availableScenes;
+ (id)__connectedFBSDisplays;
+ (id)__createPlugInScreenForFBSDisplay:(id)arg1;
+ (id)__sceneTrackingQueue;
+ (void)_beginDisableScreenUpdatesForSnapshot;
+ (void)_beginDisableScreenUpdatesForSnapshotUsingSnapshotCover:(BOOL)arg1;
+ (id)_carScreen;
+ (void)_endDisableScreenUpdates;
+ (void)_enumerateScreensWithBlock:(id /* block */)arg1;
+ (void)_prepareCarScreensForResume;
+ (void)_prepareScreensForAppResume;
+ (id)_screenForScene:(id)arg1;
+ (id)_screenWithDisplayID:(id)arg1;
+ (id)_screenWithDisplayName:(id)arg1;
+ (id)_screenWithIntegerDisplayID:(unsigned int)arg1;
+ (BOOL)_shouldDisableJail;
+ (id)_workspaceCapableScreens;
+ (struct CGPoint { float x1; float x2; })convertPoint:(struct CGPoint { float x1; float x2; })arg1 fromView:(id)arg2;
+ (struct CGPoint { float x1; float x2; })convertPoint:(struct CGPoint { float x1; float x2; })arg1 toView:(id)arg2;
+ (struct CGRect { struct CGPoint { float x_1_1_1; float x_1_1_2; } x1; struct CGSize { float x_2_1_1; float x_2_1_2; } x2; })convertRect:(struct CGRect { struct CGPoint { float x_1_1_1; float x_1_1_2; } x1; struct CGSize { float x_2_1_1; float x_2_1_2; } x2; })arg1 fromView:(id)arg2;
+ (struct CGRect { struct CGPoint { float x_1_1_1; float x_1_1_2; } x1; struct CGSize { float x_2_1_1; float x_2_1_2; } x2; })convertRect:(struct CGRect { struct CGPoint { float x_1_1_1; float x_1_1_2; } x1; struct CGSize { float x_2_1_1; float x_2_1_2; } x2; })arg1 toView:(id)arg2;
+ (void)initialize;
+ (id)mainScreen;
+ (id)screens;
%hook   UIScreen
+(id)mainScreen
{
	CGRect * cc = MSHookIvar<CGRect *>(self, "_bounds");
    NSLog(@"=========================debug:[%f]",(cc->size).width);
    return  %orig;
}
%end

编译安装,然后发现,被HOOK的包闪退:

May  2 08:47:18 iPhone diagnosticd[300] <Error>: error evaluating process info - pid: 13338, puniqueid: 13338
May  2 08:47:18 iPhone com.apple.xpc.launchd[1] (UIKitApplication:com.nan.Particle[0x8a2e][13338]) <Notice>: Service exited due to signal: Segmentation fault: 11
May  2 08:47:18 iPhone ReportCrash[13335] <Notice>: Formulating report for corpse[13338] Particle
May  2 08:47:18 iPhone ReportCrash[13335] <Warning>: report not saved because the limit of 25 for 109_Particle logs has been reached.
May  2 08:47:18 iPhone ReportCrash[13335] <Error>: Notice: This report is abbreviated for syslog inclusion because it could not be saved to disk.
	Symbolication may be possible by manually cleaning up and including the Binary Image section of a full report from this same device -- good luck!
May  2 08:47:18 iPhone ReportCrash[13335] <Error>: Process:             Particle [13338]
	Path:                /private/var/mobile/Containers/Bundle/Application/F187E36A-D147-413C-9100-FB6D4E40C8A9/Particle.app/Particle
	OS Version:          iOS 9.2.1 (13D15)
May  2 08:47:18 iPhone ReportCrash[13335] <Error>: Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
	Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
	Triggered by Thread:  0
May  2 08:47:18 iPhone ReportCrash[13335] <Error>: Thread 0 name:  Dispatch queue: com.apple.main-thread

类方法的self指向的是应该是class。class哪来的bounds这个ivar。获取不到所以就空指针解引用了。从

就能看出来

另外请学习markdown语法自己给自己的帖子加上语法高亮不要每次都麻烦我们帮你编辑

重新扫了眼代码。

@interface UIScreen : NSObject {
    struct CGRect { 
        struct CGPoint { 
            float x; 
            float y; 
        } origin; 
        struct CGSize { 
            float width; 
            float height; 
        } size; 
    }  _bounds;

CGRect * cc = MSHookIvar<CGRect *>(self, "_bounds");
第二个问题看出来了吗

还没有看出来,老大,下次发帖,我编辑一下,麻烦老大了

第一个问题

%hook   UIScreen
+ (id)mainScreen
{
	CGRect * cc = MSHookIvar<CGRect *>(self, "_bounds");
    NSLog(@"=========================debug:[%f]",(cc-&gt;size).width);
    return  %orig;
}
%end

+是类方法。self是class本身。你需要修改的bound是这个类的实例里的属性。所以应该是

%hook   UIScreen
+ (id)mainScreen
{
   id foooo=%orig;
   CGRect * cc = MSHookIvar<CGRect *>(foooo, "_bounds");
    NSLog(@"=========================debug:[%f]",(cc-&gt;size).width);
    return   foooo;
}
%end

第二个。
你不觉得头文件里的定义类型 struct CGRect _bounds和你给MSHookIvar这个模版方法传递的类型<CGRect *> 有什么不一样的地方吗

C++/ObjC基础太差了,还是从基础学起吧。

虽然我也没资格说这话就是了

非常感谢老大,我正在补C++,我再试试

感谢老大,改好了

CGRect cc = MSHookIvar<CGRect>(a, "_bounds");

现在,问题,又来了,偿试修改其值,改不了。

UIScreen  *uis=%orig;
CGRect cgr = MSHookIvar<CGRect>(uis, "_bounds");
cgr.size.width=1080.0f;
cgr.size.height=1920.0f;
[uis  bounds]=cgr;
NSLog(@"============:0[%f]",cgr.size.height);

CGRect screenBounds = [uis bounds];
NSLog(@"============:1[%f]",screenBounds.size.height); --调试发现,此处值仍然是旧值

参见 http://www.bbs.iosre.com/t/topic/11751/

感谢老大,搞定了

某种意义上可以