一.目标
- 1.找到内存中调用
setupNotification
方法的位置 - 2.找到调用
setupNotification
的方法funcationA
的位置
- (void)viewDidLoad{
[self funcationA];
}
- (void)funcationA{
self.name = @"lijiachao";
[self setupNotification];
//自定的某个类的某个方法
[LRDocumentPath fetchPath];
}
- (void)setupNotification{
NSLog(@"woshiXXX");
}
在正向开发中,比较简单,都不用找,或者看代码就好了。但是在逆向开中,没有看到代码,那么如何找到那?方法有两种:
- 1.通过Xcode逆向开发
- 2.使用
debugserver+lldb
组合开发
二.基础概念
众所周知,在逆向开发中.
我们如果想知道我调用了谁,去Hopper
或者IDA
中看就好了,
但是怎么看到谁调用了我是个难题。但也有方法:
- 1.如果使用
debugserver+lldb
组合,可以使用po $lr
,打印地址;可以获取到”调用我的位置,然后通过减去偏移量获取基址地址,然后在hopper
中找到,然后就可以看到funcationA
的位置。两个地址都获得了. - 2.使用
Xcode
调试。看右侧的即可。今天主要讲解Xcode调试方法
先去了解Xcode
几个按钮的名称和功能
//
// LRTest1Controller.m
// LLDBTest
//
// Created by 王鑫 on 2017/7/14.
// Copyright © 2017年 王鑫. All rights reserved.
//
#import "LRTest1Controller.h"
@interface LRTest1Controller ()
/** view */
@property(strong,nonatomic) UIView *bgView;
/** money */
@property(assign,nonatomic)CGFloat money;
@end
@implementation LRTest1Controller
- (void)viewDidLoad {
[super viewDidLoad];
[self button:nil];
}
- (IBAction)button:(id)sender {
if (self.person) {
// NSLog(@"有人\n name = %@,age = %ld",self.person.name,self.person.age);
[self setupName];
self.money = 100.;
}else{
LRPerson *per = [[LRPerson alloc] init];
per.name = @"王鑫";
NSLog(@"%@",per.name);
}
}
- (void)setupName{
self.person.name = @"bbb";
[self logSome];
[self createSubViews];
[self removeSomeViews];
}
- (void)logSome{
NSLog(@"有人\n name = %@,age = %ld",self.person.name,self.person.age);
}
- (void)createSubViews{
self.bgView = [[UIView alloc] init];
[self.view addSubview:self.bgView];
self.bgView.frame = CGRectMake(100, 400, 100, 100);
}
- (void)removeSomeViews{
NSLog(@"-------");
}
@end
简介:
- 第四个按钮:单步执行
- 第五个按钮:跟入执行
- 第六个按钮:返回到调用我的位置
三.实际操作
第四个按钮:单步执行
一步一步执行,如果某一步是个方法,我们不进入方法内部,继续往下执行.
第五个按钮:跟入执行,进入到函数的内部.
第六个按钮:返回到调用我的位置
左侧就会一直返回到调用我的位置。
如果这个是Xcode
正向开发,那么很好,可以看到调用我的那个方法名称,但是如果是逆向开发的时候,那么有些方法看不到,我们使用了Hook
勾住,所以切记左侧的都是一些乱东西,我们要将页面拉倒顶部,然后就可以看到调用我的函数,获取到偏移函数的位置
四.查找“调用我的位置”和“谁调用了我那个函数的名称”
查找调用我的位置有三个:
- 1.点击调用栈,然后就可以看到了
- 2.1 逆向环境下:一下一下点击第五个按钮,直到跳转到汇编页面
- 2.2 正向环境下:一下一下点击第五个按钮,就可以跳转到了调用我的地方
- 3.点击第六个按钮即可
查找调用我的那个函数:
当我们在断点出,一下一下点击第五个按钮,直到跳转到汇编页面为止,然后将页面向上拉到顶部,看到的地址就是实际在内存的地址.
获取到“调用我的那个函数”的实际内存地址是0x101208c2c
。
为什么要一下一下的点击,直到汇编页面?
因为我们这个是反汇编,所以看不到他们的源码,所以只能点一下,再点一下,直到获得汇编页面。
正向开发中,我们点击第五个按钮的时候,是一句一句看的见的代码在执行,但是没有源码的情况下,我们只能点一下,点一下的尝试,直到汇编页面.
获取偏移地址
既然我们在Xcode
中调试应用程序,那么我们就在这里不适用debuge+lldb
那个经典的方式去获得应用的偏移量了.
直接在Xcode
中打印获得偏移量0x00000000000ac000
。
(lldb) image list -o -f
[ 0] 0x00000000000ac000 /Users/wangxin/Library/Developer/Xcode/DerivedData/IPAPatch-hcpqapxbshyvjsajulgtoonbuagq/Build/Products/Debug-iphoneos/WeChat.app/WeChat
[ 1] 0x00000000000dc000 /Users/wangxin/Library/Developer/Xcode/iOS DeviceSupport/9.2 (13C75)/Symbols/usr/lib/dyld
...
[327] __lldb_objc_find_implementation_for_selector
[328] __lldb_caller_function
[329] __lldb_apple_objc_v2_get_dynamic_class_info
[336] 0x0000000003b7c000 /Users/wangxin/Library/Developer/Xcode/iOS DeviceSupport/9.2 (13C75)/Symbols/System/Library/Frameworks/Accelerate.framework/Frameworks/vImage.framework/Libraries/libCGInterfaces.dylib
(lldb)
遵循公式 Hopper的地址 = 实际内存地址 - 偏移量
hopper地址 = 0x101208c2c - 0x00000000000ac000 = 000000010115cc2c
在hopper
中找到调用者的地址和名称
将hopper
的地址找到,然后在Hopper
中查找
在这里输入000000010115cc2c
地址
可以获取到方法是
[WebViewA8KeyLogicImpl handleOnGetA8KeyOK:reason:req:]:
ps:
1.之前我在断点处,直接打印lr
的内存地址,试图找到调用者的内存地址,然后减去了偏移地址但是结果不对,现在看来,是我的位置不对
2.hopper
和IDA
他们的地址是相对于偏移地址 = 0而言的