分类: IOS技术

IOS技术

IOS 微信共享给好友或者朋友圈

用XCode6开发微信共享功能步骤

1.在微信开放平台注册应用程序id

请到 开发者应用登记页面 进行登记,登记并选择移动应用进行设置后,将获得AppID,可立即用于开发。但应用登记完成后还需要提交审核,只有审核通过的应用才能正式发布使用。

2.下载微信终端SDK文件

SDK文件包括 libWeChatSDK.a,WXApi.h,WXApiObject.h 三个。
请前往“资源下载页”下载*新SDK包

3.搭建开发环境

[1] 在XCode中建立你的工程。

[2] 将SDK文件中包含的 libWeChatSDK.a,WXApi.h,WXApiObject.h 三个文件添加到你所建的工程中(如下图所示,建立了一个名为WeiXinTest 的工程,并把以上三个文件添加到Test文件夹下)。

[3]微信开放平台新增了微信模块用户统计功能,便于开发者统计微信功能模块的用户使用和活跃情况。开发者需要在工程中链接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib,libc++.dylib。

[4] 在你的工程文件中选择Build Setting,在Search Paths中添加 libWeChatSDK.a ,WXApi.h,WXApiObject.h 三个文件所在位置(如下图所示)。

[5] 在Xcode中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”为你所注册的应用程序id(如下图所示)。

Xcode设置URL scheme

[5] 在你需要使 用微信终端API的文件中import WXApi.h 头文件,并增加 WXApiDelegate 协议。

4.在代码中使用开发工具包
[1] 要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的id。(如下图所示,在 AppDelegate 的 didFinishLaunchingWithOptions 函数中向微信注册id)。

– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.

[WXApiregisterApp:@”wx28b424d0f0a228fc”];

returnYES;

}

[2] 重写AppDelegate的handleOpenURL和openURL方法:

– (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url

{
return  [WXApihandleOpenURL:urldelegate:self];

}

[3] 现在,你的程序要实现和微信终端交互的具体请求与回应,因此需要实现WXApiDelegate协议的两个方法:

-(void) onReq:(BaseReq*)req
onReq是微信终端向第三方程序发起请求,要求第三方程序响应。第三方程序响应完后必须调用sendRsp返回。在调用sendRsp返回时,会切回到微信终端程序界面。

-(void) onReq:(BaseReq*)req

{
if([reqisKindOfClass:[GetMessageFromWXReqclass]])

{

}

elseif([reqisKindOfClass:[ShowMessageFromWXReqclass]])

{

}

}

-(void) onResp:(BaseResp*)resp
如果第三方程序向微信发送了sendReq的请求,那么onResp会被回调。sendReq请求调用后,会切到微信终端程序界面。

-(void) onResp:(BaseResp*)resp

{
//可以省略

if([respisKindOfClass:[SendMessageToWXRespclass]])

{
}

elseif([respisKindOfClass:[SendAuthRespclass]])

{
}

}

具体在此两方法中所要完成的内容由你定义,具体可参考微信开发工具包中的SDK Sample Demo源码。

[4] 如果你的程序要发消息给微信,那么需要调用WXApi的sendReq函数:

-(BOOL) sendReq:(BaseReq*)req
其中req参数为SendMessageToWXReq类型。

1.要有一个事件触发

– (IBAction)share:(id)sender {

UIActionSheet *acSheet = [[UIActionSheetalloc]initWithTitle:nildelegate:selfcancelButtonTitle:@”取消”destructiveButtonTitle:nilotherButtonTitles:@”分享给微信好友”,@”分享到朋友圈”,nil];

acSheet.tag =1;

acSheet.actionSheetStyle =UIActionSheetStyleBlackTranslucent;

[acSheet showInView:[[UIApplicationsharedApplication]keyWindow]];

}

2.响应选择
– (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

{
if (actionSheet.tag==1){
if (buttonIndex ==0) {
[selfsendMusicContent];

[_delegatechangeScene:WXSceneSession];

}

elseif (buttonIndex ==1) {
[_delegatechangeScene:WXSceneTimeline];

[selfsendVideoContent];

}

}

}

分享实现:

– (void)sendMusicContent

{
//    if (_delegate)

//    {
//        [_delegate sendMusicContent] ;

//    }

if ([WXApiisWXAppInstalled] && [WXApiisWXAppSupportApi]) {

WXMediaMessage *message = [WXMediaMessagemessage];

message.title = @”阴天”;

message.description =@””;

[messagesetThumbImage:[UIImageimageNamed:@”res3.jpg”]];

WXMusicObject *ext = [WXMusicObjectobject];

ext.musicUrl =@””;

message.mediaObject = ext;

SendMessageToWXReq* req = [[SendMessageToWXReqalloc]init];

req.bText =NO;

req.message = message;

req.scene =_scene;

[WXApisendReq:req];

}else{

UIAlertView *alView = [[UIAlertViewalloc]initWithTitle:@””message:@”你的iPhone上还没有安装微信,无法使用此功能,使用微信可以方便的把你喜欢的作品分享给好友。”delegate:selfcancelButtonTitle:@”取消”otherButtonTitles:@”免费下载微信”,nil];

[alViewshow];

}

}

头文件加上协议:
@protocol sendMsgToWeChatViewDelegate <NSObject>

– (void) sendMusicContent ;

– (void) sendVideoContent ;

– (void) changeScene:(NSInteger)scene;

@end

@interface ViewController :UIViewController<UIActionSheetDelegate,WXApiDelegate,sendMsgToWeChatViewDelegate>

{
enumWXScene _scene;

}

@property (nonatomic,assign)id<sendMsgToWeChatViewDelegate> delegate;

– (void)sendVideoContent

{
//    if (_delegate)

//    {
//        [_delegate sendVideoContent] ;

//    }

if ([WXApiisWXAppInstalled] && [WXApiisWXAppSupportApi]) {

WXMediaMessage *message = [WXMediaMessagemessage];

message.title =@””;

message.description =@””;

[messagesetThumbImage:[UIImageimageNamed:@”res2.jpg”]];

WXVideoObject *ext = [WXVideoObjectobject];

ext.videoUrl =@””;

message.mediaObject = ext;

SendMessageToWXReq* req = [[SendMessageToWXReqalloc]init];

req.bText =NO;

req.message = message;

req.scene =WXSceneTimeline;

[WXApisendReq:req];

}else{

UIAlertView *alView = [[UIAlertViewalloc]initWithTitle:@””message:@”你的iPhone上还没有安装微信,无法使用此功能,使用微信可以方便的把你喜欢的作品分享给好友。”delegate:selfcancelButtonTitle:@”取消”otherButtonTitles:@”免费下载微信”,nil];

[alViewshow];

}

}

需要注意的是,SendMessageToWXReq的scene成员,如果scene填WXSceneSession,那么消息会发送至微信的会话内。如果scene填WXSceneTimeline,那么消息会发送至朋友圈。如果scene填WXSceneFavorite,那么消息会发送到“我的收藏”中。scene默认值为WXSceneSession。

IOS下微信好友和朋友圈分享实现

1、IOS分享到微信好友和微信朋友圈

*步,先检测微信客户端是否存在:

[WXApi isWXAppInstalled]; —  这个方法返回一个bool值,来验证微信客户端是否存在

第二步,跳转到微信界面(好友或者朋友圈):

//创建发送对象实例

SendMessageToWXReq *sendReq = [[SendMessageToWXReq alloc] init];

sendReq.bText = NO;//不使用文本信息

//sendReq.scene = 1;//0 = 好友列表 1 = 朋友圈 2 = 收藏

//创建分享内容对象

WXMediaMessage *urlMessage = [WXMediaMessage message];

urlMessage.title = [NSString stringWithUTF8String:“title”];//分享标题

urlMessage.description = [NSString stringWithFormat:@”%s”, “分享描述”];//分享描述

[urlMessage setThumbImage:[UIImage imageNamed:[NSString stringWithUTF8String:“1.png”]];//分享图片,使用SDK的setThumbImage方法可压缩图片大小

//创建多媒体对象

WXWebpageObject *webObj = [WXWebpageObject object];

webObj.webpageUrl = [NSString stringWithFormat:@”%s”, “www.baidu.coom”];//分享链接

 

//完成发送对象实例

urlMessage.mediaObject = webObj;

sendReq.message = urlMessage;

 

//发送分享信息

[WXApi sendReq:sendReq];

第三步:验证分享回调:

在AppController.mm文件中,实现如下方法:

– (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options NS_AVAILABLE_IOS(9_0) // no equiv. notification. return NO if the application can’t open for some reason

{

if([url.host isEqualToString:@”platformId=wechat”])

{

return [WXApi handleOpenURL:url delegate:self];

}

else

{

return true;

}

}

//上面这个方法针对IOS9以上,但是对于IOS8的系统来说, 要实现下边的方法:

– (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation

{

if(url.host isEqualToString:@”platformId=wechat”])

{

return [WXApi handleOpenURL:url delegate:self];

}

else

{

return true;

}

}

实际上这两个方法只是方法名不一致,内容都是一样的。
然后实现微信分享的回调方法:

-(void)onResp:(BaseResp *)resp

{
if([resp isKindOfClass:[SendMessageToWXResp class]]) {

SendMessageToWXResp *sendResp = (SendMessageToWXResp *)resp;

switch (sendResp.errCode) {

case WXSuccess://分享成功

{

printf(“微信朋友圈分享成功\n”);

break;

}

case WXErrCodeUserCancel://分享取消

{

printf(“微信朋友圈分享取消\n”);

break;

}

case WXErrCodeSentFail://分享失败

{

printf(“微信朋友圈分享失败\n”);

break;

}

default://分享失败

{

break;

}

}

}

然后再进行相应的处理即可。

 

iOS逆向-微信自动添加好友

前言

上次完成了 macOS 版微信小助手,现在终于有(xian)时(de)间(huang)来说说 iOS 逆向了。本篇主要实现在微信上自动添加好友(即自动验证新的朋友申请),从而熟悉 iOS 逆向分析的过程,可能总结的有点粗糙,如果有不懂的地方欢迎探讨。

github地址: iOS 版微信小助手(防撤回、修改微信运动、群管理、好友请求管理)

工具

以下工具的详细使用方法可以查看iOS应用逆向工程 第2版 第二部分 工具篇。

macbook 软件

  • theos

    制作 Tweak 的工具

  • hopper disassembler

    用于静态分析

  • usbmuxd

    端口转发,可以让我们通过 usb 连接手机进行 ssh、lldb 调试等。主要使用python-client目录下的文件

  • class-dump

dump 目标对象的 class 信息的工具.

  • lldb

调试神器,用过的都说好。默认自带,在/Applications/Xcode.app/Contents/Developer/usr/bin/lldb 中。

越狱 iPhone 软件

以下软件在 Cydia 中即可下载(debugserver 除外)

  • OpenSSH

实现在越狱手机上远程进行 ssh 服务,通过 ssh,即可以通过终端连接 iPhone 进行控制。

  1. **iOS 工具大部分都需要在 ssh 环境中使用**
  2. 复制代码
  • Cycript

脚本语言,用于 hook 正在运行的进程,并实时注入代码。

  • ondeviceconsole

用于在 Terminal 中查看手机的 log

  • debugserver

用于连接手机进行 lldb 调试的工具。用 Xcode 在手机上进行 app 调试即可在iPhone目录的 /Developer/usr/bin/ 中生成。

使用 debugserver 需要先进行处理。因为缺少task_for_pid权限,所以调试不了其他的 app。 先通过 ssh 拷贝 debugserver

  1. scp root@iOSIP:/Developer/usr/bin/debugserver ~/debugserver // iOSIP 为手机的ip地址
  2. 复制代码

下载 ldid 与 ent,进行

  1. ldid – Sent.xml debugserver
  2. 复制代码

在使用 ssh 拷贝至手机,完成。

分析

思路:想要实现自动验证好友请求,则要拿到获取好友请求的方法,以及通过好友请求的方法。hook 获取好友请求的方法,在接收到好友请求的时候,执行添加好友的方法。 而这些主要逻辑在“新的朋友”界面。

定位好友请求的方法

UI 分析

我们知道,根据 MVC 模式,一般的方法实现都是在 ViewController 中的,所以想要拿到好友请求的方法,要先拿到当前界面的控制器。而这时候可以通过 UI 分析获得。

先打开新的朋友界面。

使用 usbmuxd 进行端口的转发(若手机不卡,可以跳过这步直接使用 ssh 进行 wifi 远程连接)

  1. python tcprelay.py -t 22:2222
  2. 复制代码

再使用 ssh 连接至手机

  1. ssh root@localhost -p 2222
  2. // ssh root@192.168.31.94 如果是wifi连接,请查看当前手机的wifi地址。
  3. 复制代码

查看微信的进程信息

  1. ps -e |grep WeChat
  2. 复制代码

Cycript 注入

  1. cycript -p WeChat // 或者是当前微信的进程号,如下所示
  2. 复制代码

启动Cycript后,使用以下命令查看当前 UI 布局

  1. UIApp.keyWindow.recursiveDescription().toString()
  2. 复制代码

因为知道当前的视图有 tableView,所以找到 tableView 的对象。从上图可以看到该对象的地址为0x18c4be00。 在使用 nextResponder()根据响应者往上找当前的 ViewController。

找到当前的控制器,为 SayHelloViewController

Log 分析

使用class-dump dump 出微信的 class 信息。

  1. class-dump -S -s -H demo.app -o ~/Document/headers/
  2. // dump 微信app的头文件保存在 ~/Document/headers/ 目录中
  3. 复制代码

再使用 theos 的 logify 工具,该工具用来注入NSLog来打印方法的入参和出参。(就是在 hook 某个类的所有的方法,并在里面加 log,并导出xm文件)

  1. logify.pl ~/Document/headers/SayHelloViewController.h > ~/Desktop/Tweak.xm
  2. 复制代码

**注意:**一般该Tweak.xm仍然无法执行,需要进行修改:

  • 去掉 .cxx_destruct 方法
  • 将 HBLogDebug 改为 NSLog
  • 去掉所有的 delegate
  • 将所有的参数对象类型改成 id
  • 去掉所有的 weak

再使用 theos 配置相关文件, 然后进行make package install 安装至手机。

重新启动微信进入新的朋友界面。

在ssh中使用ondeviceconsole打印手机的 log。

这时用另一个微信号添加自己好友。触发好友请求的方法。可以看到以下的 log

说明有好友添加请求的时候,会调用 -[SayHelloViewController OnSayHelloDataChange]

动态分析

既然已经知道了有好友请求的时候会调用OnSayHelloDataChange,那么我们可以在当前方法中进行处理,然而有个弊端,就是当有好友请求时,微信不在新的朋友界面时,是不会调用该方法的。所以我们应该在更底层的类中(假设为消息管理类)中进行处理,而怎么找到消息管理类呢?按照一般的逻辑,消息管理类中一定有方法触发了OnSayHelloDataChange,这时候就要用到 lldb + hopper 神器来找到相应的消息管理类与其处理方法了。

lldb 进行手机端调试,hopper 进行静态分析,分析OnSayHelloDataChange方法的信息,找出突破口。

先用 hopper 打开微信的二进制文件。搜索SayHelloViewController OnSayHelloDataChange方法。 可以看到当前方法在微信中的偏移地址0x14a4824。

启动debugserver 配合lldb调试

先打开微信,并使用 usbmuxd 转换端口

  1. python tcprelay.py -t 1234:1234
  2. 复制代码

再 ssh 到手机上,开启 debugserver 。

  1. debugserver *:1234 -a “WeChat”
  2. 复制代码

使用新的 Terminal 窗口,打开 lldb,连接1234端口,并查看当前微信的进程信息(一般会在所有进程的首行)。 此时会卡住一段时间。

  1. // 打开lldb
  2. /Applications/Xcode.app/Contents/Developer/usr/bin/lldb
  3. // 连接端口调试
  4. (lldb) process connect connect://localhost:1234
  5. // 打印所有进程
  6. (lldb) image list -o -f
  7. 复制代码

找到微信在当前手机上的进程内存基地址为0x000b2000(这个值不是定值)

通过以上可以找到 [SayHelloViewController OnSayHelloDataChange]方法在手机上的内存地址。即

  1. 内存地址 = 进程内存基地址 + 方法偏移地址
  2. 复制代码

使用br打断点查看

  1. br s -a “0x000b2000 + 0x14a4824”
  2. 复制代码

接着输入c继续运行,重新使用另一微信账号添加好友,会触发该断点。

使用bt查看调用栈信息,即哪些方法调用了当前的方法,找到方法的上游。(异步调用的话没办法查看)

*个表示当前的方法,可以看到在调用此方法前,该进程总共调用了3个方法。 分别计算出这三个方法在微信中的偏移量。

将这三个地址在 hopper 中查看(按快捷键g,输入地址),找到了对应的方法为

  1. // 调用的顺序为从下到上
  2. [SayHelloViewController OnSayHelloDataChange]
  3. [SayHelloDataLogic onFriendAssistAddMsg:]
  4. [FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:]
  5. [CMessageMgr MainThreadNotifyToExt:]
  6. 复制代码

从以上方法名可以猜测

  1. [FriendAsistSessionMgr OnAddMsgForSpecialSession:MsgList:]
  2. 复制代码

是用来接收添加好友消息的函数处理,其中MsgList:后面的参数可能为消息的数组,为了证明我们可以在该方法中打个断点查看下。 使用命令register read读取寄存器地址,并使用po打印该对象。

看出r3寄存器确实是个数组,同时也得到了消息的对象为CMessageWrap 证明我们是对的。

ps: 解释下为什么要看r3,因为在 armv7 中,一个方法的调用,一般寄存器都是这么存储的:前四个参数放在r0~r3,剩下的存放在堆栈中。查看堆栈的话使用x/10 $sp 查看前10个堆栈里的对象地址。

然而FriendAsistSessionMgr这个类可能在新的好友界面进行一些初始化,且放在SayHelloViewController中,而我们想要的是不管在哪个控制器里都可以 hook 住上面的消息数组对象。因此我们往上找,[CMessageMgr MainThreadNotifyToExt:],然而里面并没有我们需要的信息。而根据类名我们推测CMessageMgr是用来管理消息的。有可能是在异步执行了消息数组的获取。

因此,重复以上步骤,使用 logify 对CMessageMgr进行 Log 分析。*终锁定了 CMessageMgr MessageReturn:MessageInfo:Event:

定位通过好友请求的方法

动态分析

既然找到了接收好友请求的方法,那么是时候找通过好友请求的方法了。 我们知道,通过好友请求的方法,是在新的朋友界面,点击接受的时候触发的。(可以通过 Log 分析,然而这里还有另一个比较快速的方法)

Cycript 定位

先通过 Cycript 打印出所有的 UI 层级。 找到接受按钮的对象,(有个技巧,我们知道当前按钮是在某个 cell 下面的,所以定位这个)。

再通过cycript将该对象的 hidden 动态修改为 1,看是否隐藏。

  1. #0x186922f0.hidden = 1
  2. 复制代码

发现按钮不见了,证明我们是对的。这时候需要找到点击按钮的事件。

而我们知道 UIButton 是继承 UIControl 的,在 Cycript 中, 可以通过allTargets 与 allControlEvents查看当前UIControl所有的targets与events,再使用actionsForTarget:forControlEvent:从而找到触发的方法。

看出所触发的方法为[ContactsItemView onRightBtnAction]

静态分析

既然拿到了方法名,那我们怎么看他具体的实现呢? 接下来就是大名鼎鼎的 hopper 登场了。 用 hopper 打开微信的二进制文件,并进行汇编与伪代码的转换。 ~~由于汇编读起来比较晦涩,所以还是进行伪代码的转换,这样效率比较快。~~点击该按钮进行转换

可以得到伪代码

上图我们看到了

  1. r10 = self;
  2. r5 = r10 + *0x33befe8;
  3. r4 = objc_loadWeakRetained(r5);
  4. r8 = @selector(onContactsItemViewRightButtonClick:);
  5. r11 = [r4 respondsToSelector:r8];
  6. 复制代码

可以得出,r11 = [r5 onContactsItemViewRightButtonClick:btn],而 r5 我们判断为 self 的代理,这个我们也可以通过在之前用 class-dump 的头文件里面搜索onContactsItemViewRightButtonClick,会发现在ContactsItemViewDelegate中。 也就是[ContactsItemView onRightBtnAction]内部调用了[self.delegate onContactsItemViewRightButtonClick:]. 而 ContactsItemView 的delegate为 SayHelloViewController

再用 hopper 定位onContactsItemViewRightButtonClick

 

看到这里估计会很懵逼不知道从何下手。这时候只要加以推测就可以了。 上图中进行了两个if判断,*个为

  1. r10 = @selector(class);
  2. r2 = loc_1c099bc(@class(CPushContact), r10);
  3. r1 = @selector(isKindOfClass:);
  4. r5 = loc_1c099bc(r4, r1, r2);
  5. loc_1c099d4(r4);
  6. if ((r5 & 0xff) != 0x0) {
  7. 复制代码

可以得出其实是执行了 if([r4 isKindOfClass:[CPushContact class]]); 而r4是什么呢?可以肯定是CPushContact对象,不然下面的代码都不执行了。我们可以根据动态分析,通过 lldb 打断点,并查看r3寄存器的对象类型,可以看到该对象为CPushContact对象。因此r4就是CPushContact对象,根据字面意思可以得到就是联系人对象。

继续看下面的代码,可以看到也进行了一次判断if (((loc_1c099bc(r6, @selector(m_bSuspiciousUser)) & 0xff) != 0x0) && ((loc_1c099bc(r6, @selector(isMMContact)) & 0xff) == 0x0)),看到了MMUIAlertView。推测是弹窗的 view ,推测如果是可疑的用户或者当前申请的好友已经是自己的好友,那就进行弹窗。而另一部分为verifyContactWithOpCode:opcode:,推测该部分为添加好友的方法。 可以通过 Log 分析或者通过 lldb 打断点,会看到都会进入该方法。且参数分别为CPushContact对象与 3。 接着继续分析verifyContactWithOpCode:opcode:方法。主要的部分如下所示。

通过分析,我们可以得到,确认好友申请,显示构造了CContactVerifyLogic对象。再构造了一个CVerifyContactWrap对象,并设置了相关属性,比如m_nsUsrName m_uiScene m_nsTicket.然后通过添加到数组中,通过CContactVerifyLogic对象的startWithVerifyContactWrap:opCode:parentView:fromChatRoom:方法发送。 代码如下:

  1. CContactVerifyLogic *verifyLogic = [[CContactVerifyLogic alloc] init];
  2. CVerifyContactWrap *wrap = [[CVerifyContactWrap alloc] init];
  3. [wrap setM_nsUsrName:contact.m_nsEncodeUserName];
  4. [wrap setM_uiScene:contact.m_uiFriendScene];
  5. [wrap setM_nsTicket:contact.m_nsTicket];
  6. [wrap setM_nsChatRoomUserName:contact.m_nsChatRoomUserName];
  7. wrap.m_oVerifyContact = contact;
  8. AutoSetRemarkMgr *mgr = [[MMServiceCenter defaultCenter] getService:[AutoSetRemarkMgr class]];
  9. id attr = [mgr GetStrangerAttribute:contact AttributeName:1001];
  10. if([attr boolValue]) {
  11. [wrap setM_uiWCFlag:(wrap.m_uiWCFlag | 1)];
  12. }
  13. [verifyLogic startWithVerifyContactWrap:[NSArray arrayWithObject:wrap] opCode:3 parentView:[UIView new] fromChatRoom:NO];
  14. 复制代码

这样我们就得到了 获取好友请求的方法与添加好友的方法。 而这里还有一个问题,就是添加好友的对象是CPushContact,而获得好友请求的对象的CMessageWrap。这里需要进行转换,而转换的方法也在SayHelloViewController中,可以重复上面的分析方法获得。


编写Tweak

通过以上的分析,将代码合并起来

  1. %hook CMessageMgr
  2. – (void)MessageReturn:(unsigned int)arg1 MessageInfo:(NSDictionary *)info Event:(unsigned int)arg3 {
  3. %orig;
  4. if (arg1 == 332) { // 收到添加好友消息
  5. NSString *keyStr = [info objectForKey:@“5”];
  6. if ([keyStr isEqualToString:@“fmessage”]) {
  7. NSArray *wrapArray = [info objectForKey:@“27”];
  8. [self addAutoVerifyWithArray:wrapArray];
  9. }
  10. }
  11. }
  12. %new
  13. – (void)addAutoVerifyWithArray:(NSArray *)ary {
  14. [ary enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  15. CPushContact *contact = [%c(SayHelloDataLogic) getContactFrom:obj];
  16. if (![contact isMyContact] && [contact.m_nsDes isEqualToString:autoVerifyKeyword]) {
  17. CContactVerifyLogic *verifyLogic = [[%c(CContactVerifyLogic) alloc] init];
  18. CVerifyContactWrap *wrap = [[%c(CVerifyContactWrap) alloc] init];
  19. [wrap setM_nsUsrName:contact.m_nsEncodeUserName];
  20. [wrap setM_uiScene:contact.m_uiFriendScene];
  21. [wrap setM_nsTicket:contact.m_nsTicket];
  22. [wrap setM_nsChatRoomUserName:contact.m_nsChatRoomUserName];
  23. wrap.m_oVerifyContact = contact;
  24. AutoSetRemarkMgr *mgr = [[%c(MMServiceCenter) defaultCenter] getService:%c(AutoSetRemarkMgr)];
  25. id attr = [mgr GetStrangerAttribute:contact AttributeName:1001];
  26. if([attr boolValue]) {
  27. [wrap setM_uiWCFlag:(wrap.m_uiWCFlag | 1)];
  28. }
  29. [verifyLogic startWithVerifyContactWrap:[NSArray arrayWithObject:wrap] opCode:3 parentView:[UIView new] fromChatRoom:NO];
  30. }
  31. }];
  32. }
  33. 复制代码

总结

本文为本人根据iOS应用逆向工程 第2版的内容进行分析,由于整个逆向流程有点繁琐,有时候也不是只要分析一次就可以成功的,需要反反复复的进行UI分析、Log分析、lldb 分析。

苹果iOS捷径(快捷指令)自动填写表单

苹果iOS用户可以通过捷径(快捷指令)快速完成表单填写以提高工作效率。本文主要介绍如何通过捷径(快捷指令)调用 JavaScript 在网页运行的方式快速填写表单。

效果展示:

捷径(快捷指令)在网页上运行JavaScript 脚本基本格式:

var result = [];

// JavaScript代码

// 调用 Completion 以完成
completion(result);

以疫情期间在校生出入校园申请表为例:

首先分析表单所需要填写的信息类型,在本例中,类型主要有文本框、单选按钮、时间选择器:

1. 文本框

对于文本框,我们可以通过定位文本框对应id,通过定义value的形式为文本框赋值。

document.getElementById(‘ZY’).value=”需要填写的内容”;

2. 单选按钮

面对单选按钮,改变选择器样式并不能将内容*终插入*后提交的表单中,我们需要用到JavaScript的点击动作。

var event = new MouseEvent(‘click’);

var XQ_click = document.getElementsByClassName(‘van-radio van-radio–horizontal’)[1];

XQ_click.dispatchEvent(event);

基本逻辑为:定义点击事件(MouseEvent继承自UIEvent)——定位选择按钮——实现点击。

关于定位选择按钮,这里再强调一下,对于没有独立id的选择按钮,可以通过其在ClassName中的具体位置序号予以定位。

3. 时间选择器

时间选择器数据的填写,我们可以直接使用捷径(快捷指令)的 当前日期功能:

document.getElementById(‘JTSDJS’).value=”当前日期”;

2 在捷径(快捷指令)中将出发时间的当前日期参数格式设置为 yyyy-MM-dd HH:mm,返校时间的当前日期参数格式设置为 yyyy-MM-dd 23:00,即表示出发时间为填表时间,返校时间为当天的23:00

值得注意的是:

这个表单内的元素全部位于id为formIframe的iframe内,因此在定位表单元素前还需要定位表单:

parent.document.getElementById(“formIframe”)

完整脚本:
var result = [];

parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘ZY’).value=”需要填写的内容”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘NJ’).value=”需要填写的内容”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘BJ’).value=”需要填写的内容”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘LXFS’).value=”需要填写的内容”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘SZSS’).value=”需要填写的内容”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘QJWCSY’).value=”需要填写的内容”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘JTGJD’).value=”步行”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘JKZK’).value=”健康”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘JTSDKS’).value=”当前日期”;
parent.document.getElementById(“formIframe”).contentWindow.document.getElementById(‘JTSDJS’).value=”当前日期”;

//MouseEvent继承自UIEvent
var event = new MouseEvent(‘click’);

var XQ_vant_click = parent.document.getElementById(“formIframe”).contentWindow.document.getElementsByClassName(‘van-radio van-radio–horizontal’)[1];
var ZXTY_vant_click = parent.document.getElementById(“formIframe”).contentWindow.document.getElementsByClassName(‘van-radio van-radio–horizontal’)[2];
var SFLJ_vant_click = parent.document.getElementById(“formIframe”).contentWindow.document.getElementsByClassName(‘van-radio van-radio–horizontal’)[5];

XQ_vant_click.dispatchEvent(event);
ZXTY_vant_click.dispatchEvent(event);
SFLJ_vant_click.dispatchEvent(event);

// 调用 Completion 以完成
completion(result);

至此,本文也就进入尾声了。希望本文能够起到抛砖引玉之效,也欢迎大家的批评交流。

ios 跳转到支付宝_使用iOS快捷指令执行快捷操作之1——每天早起定时打开蚂蚁森林…

写在前面——iOS快捷指令是新版本iOS所具有的功能,图标是下面这个样子:

如果你的iOS设备找不到这个功能,可能这个功能被你屏蔽了,或者iOS版本不够,请升级你的iOS系统。

iOS快捷指令,我个人的感觉,有点类似于微软操作系统中早已存在的批处理文件,它可以执行一系列操作,所以这些日子我在琢磨它的使用方法以充分利用这个功能。于是我琢磨出来两个小快捷指令,分享给大家,抛砖引玉吧,大伙一起享受这个app的便捷之处。

我相信很多人都在玩支付宝的蚂蚁森林,我也在玩,而且我知道有很多人为了不让自己的能量被别人抢走,甚至设置了闹钟来提醒自己收能量球,我也是这么做的。尤其是每天早起7点来钟生成的前一天计步生成的能量,由于是支付宝每天定时定点生成的(每个人的时间都不一样,但是都是集中在7-8点,而且对于一个人来讲时间每天都是一样的),就特别适合定一个每天的闹钟来提醒自己收能量,还能顺便搜刮一下好友的能量,非常的值得。我现在每天能通过收取别人能量,每天就能抢到别人的500克以上的能量(被我天天抢能量的朋友们别生气哈 )!比自己辛辛苦苦走路计步容易多了!

那么iOS快捷指令就可以为你响完闹钟以后自动打开支付宝的蚂蚁森林,具体操作如下:

1、首先弄清楚你的蚂蚁森林能量每天是7点几分成熟,设置一个成熟之前一分钟之内的闹钟,起好名字,比如“蚂蚁森林”,如图:


2、打开iOS快捷指令app,选择底部“自动化”,再选择右上角“+”,新建快捷指令,如图箭头所示:


3、在弹出的窗口中选择“创建个人自动化”


4、新自动化列表里选择“闹钟”-“停止时”-“现有”-找到那个闹钟,比如刚才的名字“蚂蚁森林”-右上角“完成”:


5、返回之后变成这个样子,选择“下一步”:


6、选择“添加操作”-操作列表里找到“来蚂蚁森林收能量”-“下一步”-再“下一步”-关闭“运行前询问”-“完成”:

这样这个快捷指令就会在每天提醒你收能量之后自动打开支付宝,并且直接跳转到蚂蚁森林界面啦!当你看见天天你的蚂蚁森林能量球只有一分钟就成熟,是不是很高兴呢?

注意,在响闹钟的提醒出现以后不要忽略这个提醒,而是点开它,当然如果有锁屏密码和支付宝需要解锁识别身份,还是不能跳过的,但是不会中断运行这个快捷指令!

IOS快捷指令的用法(快捷指令库使用方法)

1、打开快捷指令、找到快捷指令中心,随便添加一个系统给的快捷指令;然后点击我的快捷指令,点击刚加入的快捷指令运行一下。

2、打开设置,搜索快捷指令,勾上允许不信任的快捷指令;

3、用Safari浏览器搜索快捷指令库,从中找到自己想要的加入到快捷指令中心即可(点击获取捷径)。

4、可以使用自动化功能运行此指令,比如NFC,或者打开某个应用时;做法:点击自动化—>创建新的自动化—>下一步—>然后搜索快捷指令—>运行我的快捷指令—>点击框中的快捷指令添加即可。

iOS开发苹果支持中文字体,和使用字体

1.中文字体

转自:https://zhidao.baidu.com/question/1239016138772367339.html

ios7英文字体:Helvetica 下的各种系统,例如Helvetica Neue等,细究起来很烦,不同的地方用不同的系统,但都是Helvetica家族下的
ios7中文字体:STHeitiSC-Light 黑体-简

2.苹果使用字体
转自:http://blog.csdn.net/onlyou930/article/details/7422097
label.font  =  [UIFont fontWithName: @” Arial-BoldItalicMT ”  size: 24 ];

字体名如下:

Font Family: American Typewriter
Font: AmericanTypewriter
Font: AmericanTypewriter-Bold

Font Family: AppleGothic
Font: AppleGothic

Font Family: Arial
Font: ArialMT
Font: Arial-BoldMT
Font: Arial-BoldItalicMT
Font: Arial-ItalicMT

Font Family: Arial Rounded MT Bold
Font: ArialRoundedMTBold

Font Family: Arial Unicode MS
Font: ArialUnicodeMS

Font Family: Courier
Font: Courier
Font: Courier-BoldOblique
Font: Courier-Oblique
Font: Courier-Bold

Font Family: Courier New
Font: CourierNewPS-BoldMT
Font: CourierNewPS-ItalicMT
Font: CourierNewPS-BoldItalicMT
Font: CourierNewPSMT

Font Family: DB LCD Temp
Font: DBLCDTempBlack

Font Family: Georgia
Font: Georgia-Bold
Font: Georgia
Font: Georgia-BoldItalic
Font: Georgia-Italic

Font Family: Helvetica
Font: Helvetica-Oblique
Font: Helvetica-BoldOblique
Font: Helvetica
Font: Helvetica-Bold

Font Family: Helvetica Neue
Font: HelveticaNeue
Font: HelveticaNeue-Bold

Font Family: Hiragino Kaku Gothic **** W3
Font: HiraKakuProN-W3

Font Family: Hiragino Kaku Gothic **** W6
Font: HiraKakuProN-W6

Font Family: Marker Felt
Font: MarkerFelt-Thin

Font Family: STHeiti J
Font: STHeitiJ-Medium
Font: STHeitiJ-Light

Font Family: STHeiti K
Font: STHeitiK-Medium
Font: STHeitiK-Light

Font Family: STHeiti SC
Font: STHeitiSC-Medium
Font: STHeitiSC-Light

Font Family: STHeiti TC
Font: STHeitiTC-Light
Font: STHeitiTC-Medium

Font Family: Times New Roman
Font: TimesNewRomanPSMT
Font: TimesNewRomanPS-BoldMT
Font: TimesNewRomanPS-BoldItalicMT
Font: TimesNewRomanPS-ItalicMT

Font Family: Trebuchet MS
Font: TrebuchetMS-Italic
Font: TrebuchetMS
Font: Trebuchet-BoldItalic
Font: TrebuchetMS-Bold

Font Family: Verdana
Font: Verdana-Bold
Font: Verdana-BoldItalic
Font: Verdana
Font: Verdana-Italic

Font Family: Zapfino
Font: Zapfino

UIFont fontWithName 后不知道字体的名字,看了下面的全解决!


3.打印字体族,和字体名字
转自:http://www.2cto.com/kf/201505/397306.html

ios的提供了很多的字体样式。有时候我们在开发应用的时候可能用到不同的字体,通过此Demo我们可以获取到所有的字体样式供我们选择。 首先获取字体字体族科名字,再通过族科的名字获取到字体的名字。

    NSArray *arr  = [UIFont familyNames];

    for (NSString *str in arr) {

        NSArray *at = [UIFont fontNamesForFamilyName:str];

        for (NSString *fffff in at) {

            NSLog(@”字体名字 %@”,fffff);

        }

    }

然后再使用如下代码就可以修改字符串的字体 。


//    NSString * testStr  = @我随手一打就是漂亮的十五个字了;

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:testStr];

[str addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0,3)];

[str addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(3,4)];

[str addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(7,4)];

[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:_fontArray[indexPath.row] size:30] range:NSMakeRange(0, 15)];

 
?显示中文和英文的效果不是很一致,英文的效果明显一些,如下是部分效果截图。具体在Demo里面有。
\

\

 

\

iOS 修改系统定位(非越狱)

修改系统定位其实是不太可能的(除非越狱)。那么我们今天就通过一个简单方式来修改系统的定位,当然是有一定的限制的。

首先:我们先创建一个项目,名字随意。然后一个文件LocationPosition.gpx如下:

然后打开这个LocationPosition.gpx文件如下:

<?xml version=”1.0″?>
<gpx version=”1.1″ creator=”Xcode”>

<!–
Provide one or more waypoints containing a latitude/longitude pair. If you provide one
waypoint, Xcode will simulate that specific location. If you provide multiple waypoints,
Xcode will simulate a route visiting each waypoint.
–>
<wpt lat=”39.89606702936854″ lon=”116.36890332416854″>

<name>Cupertino</name>

<!–
Optionally provide a time element for each waypoint. Xcode will interpolate movement
at a rate of speed based on the time elapsed between each waypoint. If you do not provide
a time element, then Xcode will use a fixed rate of speed.

Waypoints must be sorted by time in ascending order.
–>
<time>2014-09-24T14:55:37Z</time>
</wpt>

</gpx>
直接修改<wpt lat=”39.89606702936854″ lon=”116.36890332416854″>其中: lat是纬度,lon是经度,然后保存即可,当然也可以添加多个。

*后一步: Product->Scheme->Edit Scheme->Run->Options->Core Location->Default Location 选择:LocationPostion 如下图:

然后运行XCode到真机上,即可以实现系统定位了。

这样有个问题就是,如果我们stop了XCode发现就不管用了,那么怎么解决呢。

这个可以在运行后直接拔掉链接线。那么就可以无忧的实现系统定位了。好了如果还有什么问题可以自己努力了。

iOS系统回退教程

如果你升级了系统之后觉得体验不好或者不习惯怎么办呢?这篇教程就教你回退iOS系统,也就是降级。
1.首先下载iOS固件,访问苹果官方固件下载网站,你会看到4个步骤,分别是:
Choose a product
Choose a platform
Choose a version
Download!
你只需要按照这4个步骤来选择适用你手机的固件,
选择你的产品类型,点击iPhone;

选择手机型号,Global是全网通版本,GSM是移动/联通版本,请确认自己手机的版本,千万不要选错了;

选择固件版本,Signed IPSWs下面的绿色列表是你可以选择的iOS版本,也就是说,这些版本的官方验证通道还没有关闭,是可以正常使用的,选择其中的一个你需要的版本,点击进入下载页面。如果绿色列表中没有你要的版本,说明你要的版本已不支持回退,本文以下内容可以不用再看了;

点击Download按钮下载即可,下载的文件是一个后缀为.ipsw的文件。

2.下载windows PC版本的iTunes(Microsoft下载,点击【获取】按钮即可安装;也可以从Apple官网下载)。
3.安装好iTunes后打开,并将手机通过USB数据线(*好用原装数据线)连接到你的电脑,iTunes检测到后会连接到你的手机,手机上会有弹窗,点击信任即可,连接好后,iTunes左上角会有一个手机的图标出现,点击手机图标(也可能会自动打开与手机相关的页面)打开手机相关页面。
4.数据备份,升级一般数据不会丢失,降级则数据会丢失(这种情况下一定要数据备份),但是为了数据安全性,建议无论是升级还是降级都先备份数据,备份的方式有两种:通过iCloud或者iTunes备份,这里我们选择通过iTunes手动备份(速度快,存储在电脑上),因为只有手动备份才能修改7中说的版本号,备份完毕后再执行下一步操作。
5.升/降级前在设置-顶部头像-iCloud-查找我的iPhone中点击关闭。如果你下载的固件版本低于当前版本选择【恢复iPhone】,如果高于当前版本,则选择【检查更新】,注意点击前先按住【Shift】按键(Mac电脑按住【ALT】按键),然后在弹窗中选择你之前下载好的固件(ipsw文件),然后就是较长一段时间的等待咯。切记中途不要插拔USB数据线。
6.系统升/降级完成后(正常情况下是这样,也有可能中途会报错失败,那样的话你得执行恢复操作,iTunes会有相应的操作提示,也就是还原你之前的系统),下一步就是数据的还原了,升级的话一般数据都还在,降级的话这一步是必须的(降级后相当于拿到了一部新手机,指纹都得重新录入,操作步骤就不说了,其中会提示数据恢复,可以先跳过),降级后的数据恢复请先阅读下面的第7点,现在之前备份的数据就派上用场了,iTunes里面有一个数据恢复,选择你之前备份的数据恢复即可。
7.但是降级后有一个问题就是有可能你之前在高版本系统上备份的数据不能用于低版本的数据恢复,解决办法就是找到你电脑上iTunes的备份目录,我的是在C:\Users\用户名\Apple\MobileSync\Backup下,有一个名字是字母数字混合且很长的文件夹,这就是你备份的数据,打开它,里面有一个文件叫Info.plist,编辑它,修改Product Version下面的版本号,比如你回退的版本号是12.4.1, 注意不要有空格,然后保存即可。
<key>Product Version</key>
<string>12.4.1</string>
1
2
唠嗑:
说一下为啥我会去降级,12.4.1是iOS12的*后一个版本,我的手机是iphone8,一款支持3D touch 的机型,我升级iOS13后发现这个功能变得不伦不类的,iOS13为了照顾那些新的不支持3D touch的机型,搞了一个haptic touch,就是用长按来实现一些类似3D touch的体验,但是经过我的体验过后,发现在已经支持3D touch的机型上存在问题,差不多两个功能同时存在了,反而使3D touch的体验大打折扣,幸运的是我在12*后一个版本关闭验证通道前回退到了12,从此,我的iOS就停留在了12.4.1,直到今天(2020.8)在*新的iOS中依旧没有修复这个问题,我也给苹果发过邮件,希望在已经支持3D touch的机型中不要引入haptic touch, 因为根本不需要,而且haptic touch也代替不了3D touch, 因为3D touch是有不同压感的,不同的压感有不同的反馈,这是硬件支持的,单纯的软件层

iOS开发中点击推送跳转到指定页面

消息推送在现在的App中很常见,但同一个App中推送的消息可能有多种类型,点击推送需要跳转到不同的指定页面。

做法:

我们在接收到推送的时候发送通知,每个页面都接收通知,如果有通知就在当前页面进行页面的跳转跳转到指定页面。

如果在每个页面中都添加接收通知的代码会很麻烦,我们可以将接收通知的代码添加到基类中,这样就简单、方便了许多。可有些项目中的代码中可能没有基类,就像我们公司中的这个项目,那也没问题,我们可以为视图控制器添加一个分类,将接收通知的代码添加到分类中,再在pch文件中导入此分类。

接收推送发送通知的代码:

– (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

{

 

//关闭友盟自带的弹出框

[UMessage setAutoAlert:NO];

 

[UMessage didReceiveRemoteNotification:userInfo];

 

[[NSNotificationCenter defaultCenter] postNotificationName:@”pushNoti” object:nil];

 

}

接收通知进行页面跳转的代码,此代码在视图控制器的分类中:
+ (void)load

{

 

Method m1;

Method m2;

 

// 运行时替换方法

m1 = class_getInstanceMethod(self, @selector(statisticsViewWillAppear:));

m2 = class_getInstanceMethod(self, @selector(viewWillAppear:));

 

method_exchangeImplementations(m1, m2);

 

 

m1 = class_getInstanceMethod(self, @selector(statisticsViewWillDisappear:));

m2 = class_getInstanceMethod(self, @selector(viewWillDisappear:));

 

method_exchangeImplementations(m1, m2);

}

– (void) statisticsViewWillAppear:(BOOL)animated

{

[self statisticsViewWillAppear:animated];

[MobClick beginLogPageView:NSStringFromClass([self class])];

 

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(push) name:@”pushNoti” object:nil];

}

-(void) statisticsViewWillDisappear:(BOOL)animated

{

[self statisticsViewWillDisappear:animated];

[MobClick endLogPageView:NSStringFromClass([self class])];

 

[[NSNotificationCenter defaultCenter] removeObserver:self name:@”pushNoti” object:nil];

}

– (void)push{

 

NotificationVC * notiVC = [[NotificationVC alloc] init];

notiVC.hidesBottomBarWhenPushed = YES;

[self.navigationController pushViewController:notiVC animated:YES];

}

该项目中之前的友盟统计就添加到了该分类中.
好了,本篇博客的主要内容就这些,谢谢阅读。

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速