Hook微信并截取登录密码-真机实测


  • 在上一篇介绍重签名,并真机进行view debug后, 可以试着一些简单的Hook, 以下是主要操作步骤
    • 创建新工程,配置证书啥的,并运行到真机
    • 复制appsign.sh脚本,yololib到工程根目录,在工程下,创建APP目录,并拷贝脱壳的ipa包到APP目录(appsign.sh, yololib 需要可执行权限, chmox +x yololib 加权)
    • 在TARGET下添加 run script ,添加:${SRCROOT}/appsign.sh
    • 运行即可
    • 成功后,添加一个framework, 并创建个类, 在load 方法中,打印下log
    • 在appsign.sh 添加注入的代码${SRCROOT}/yololib framework路径
    • 运行(如果出现image not funded等, 尝试clean后再运行, 成功后,可以看到 load中的打印的log)
  • 准备工作:使用class-dump-z 工具,从微信包导出头文件 (class-dump-z -H /xxx/WeChat.app -o /Users/xxx/Desktop/WCHeads)
  • 上述操作之后,就可以View Debug了
    • 在账号密码登录界面,进行view debug, 可以在xcode 右侧找到密码框,登录按钮的 一些信息,Target , Action onNext (ps: 最新xcode好像只显示类似<__NSDictionaryI: 0x282a71f80>, 那么,可以在 lldb中po出来 )
      #通过po找出target等
      #(lldb)po 0x282a71f80
      {
        className = NSTaggedPointerString;
        memoryAddress = 0x8babeb562c16e467;
      }
      #(lldb)po po 0x8babeb562c16e467
             onNext
      #(lldb)po 0x2807c5d40
      {
        className = WCAccountMainLoginViewController;
        memoryAddress = 0x11e0e9400;
      }
    
    • 通过上面的动态分析,我们可以知道我们要Hook的就是 WCAccountMainLoginViewController 里面的 onNext 方法
    • 接下来,我们分析怎么在onNext获取密码,在微信头文件里,我们可以找到文件:WCAccountMainLoginViewController.h 在里面有找到onNext 方法 及 _textFieldUserPwdItem (猜测应该就是密码,不过类型跟UI view debug中 密码输入框: WCUITextField 不大一致)
    @interface WCAccountMainLoginViewController : WCAccountBaseViewController  {
        id _delegate;
        UIView* _phoneHeaderView;
        WCAccountTextFieldItem* _textFieldCountryCodeSelectItem;
        WCAccountTextFieldItem* _textFieldCountryCodeItem;
        WCAccountTextFieldItem* _textFieldPhoneNumberItem;
        PhoneNumberFormatLogic* _phoneNumFormatter;
        CountryCodeWrap* _curCountryCode;
        UIView* _userHeaderView;
        WCAccountTextFieldItem* _textFieldUserNameItem;
        WCAccountTextFieldItem* _textFieldUserPwdItem;
        //省略部分变量
    }
    //省略部分方法
    -(void)onNext;
    
```
*  _textFieldUserPwdItem 类型为WCAccountTextFieldItem, 通过查找微信头文件找到WCAccountTextFieldItem的父类WCBaseTextFieldItem ,里面有变量:WCUITextField* m_textField,  m_textField 我们就从者获取密码,可以在 lldb在测试动态获取到
```java
    (lldb) po 0x10d961000
    
    (lldb) po [(WCAccountMainLoginViewController *)0x10d961000 valueForKey:@"_textFieldUserPwdItem"]
    
    (lldb) po [(WCAccountTextFieldItem *)0x282251a40 valueForKey:@"m_textField"]
    ; layer = >
    (lldb) po [(WCAccountTextFieldItem *)0x282251a40 valueForKey:@"m_textField"].text
    error: no known method '-valueForKey:'; cast the message send to the method's return type
    (lldb) po [[(WCAccountTextFieldItem *)0x282251a40 valueForKey:@"m_textField"] valueForKey:@"text"]
    ffggggg
```
* 动态分析,就到此结束, 下一步就是写hook代码
  • Hook编写获取密码代码
#import 

#define USE_3 1  //USE_1 USE_2

@implementation TulipObject
+(void)load
{
    NSLog(@"Tulip hook success");
    //总体思路:对WCAccountMainLoginViewController 这个对象的onNext hook,valueForKey获取密码
    //获取要hook的 class
    Class wcClass = objc_getClass("WCAccountMainLoginViewController");
    // “v@:" 可以通过帮助里 查找class_addMethod ,查看Type Encodings相关介绍, 也可以用 ""放空白 ,还可以 method_getTypeEncoding(hook_next)
    //获取要Hook的 旧的实例method,
    //ps: sel_registerName("onNext") == @selector(onNext)
    Method old_onNextMethon = class_getInstanceMethod(wcClass, sel_registerName("onNext"));
#ifdef USE_1
    /** 方法一: 方法交换 method_exchangeImp  */
    //添加一个新的方法,用于交换
    //新添加sel名
    SEL new_onNext = sel_registerName("new_onNext");
    BOOL disAddMethod = class_addMethod(wcClass, new_onNext, (IMP)hook_next, "v@:");
    if (disAddMethod) {
        
        Method newAddMethod = class_getInstanceMethod(wcClass, new_onNext);
        method_exchangeImplementations(old_onNextMethon, newAddMethod);
        NSLog(@"method_exchangeImp 实现.");
    }
#endif
    
#ifdef USE_2
    /** 方法二: replaceMethod  */
    //获取原来的IMP
    old_onNextImp = method_getImplementation(old_onNextMethon);
    //ps: 如果onNext不存在,replace会变成 添加
    class_replaceMethod(wcClass, @selector(onNext),(IMP)hook_next, method_getTypeEncoding(hook_next));
#endif
    
    
#ifdef USE_3
    /** 方法三: GET/SET IMP 实现  */
    //获取原来的IMP
    old_onNextImp = method_getImplementation(old_onNextMethon);
    method_setImplementation(old_onNextMethon, (IMP)hook_next);
#endif
}
IMP (*old_onNextImp)(id self, SEL _cmd); //旧imp 函数指针变量
// [Person alloc] <==> msg_send(Person, alloc)
void hook_next(id self, SEL _cmd)
{
    NSLog(@"Hook %s", __FUNCTION__);
    NSObject *accountTextFieldItem = (NSObject *)[self valueForKey:@"_textFieldUserPwdItem"]; //WCAccountTextFieldItem
    NSObject *wcTextField = (NSObject *)[accountTextFieldItem valueForKey:@"m_textField"];
    NSString *pwd = [wcTextField valueForKey:@"text"];
    NSLog(@"Hook 到的密码: %@", pwd);
    
    //调用原来老方法
//    [self hook_next]; //会崩溃!! 旧方法被交换走了,如果没addMethod
#ifdef USE_1
    [self performSelector:@selector(new_onNext)]; //方法一:addMethon
#else
    old_onNextImp(self, _cmd);
#endif
//    2018-12-08 18:22:30.063485+0800 WeChat[17280:1418288] Hook hook_next
//    2018-12-08 18:22:30.084368+0800 WeChat[17280:1418288] Hook 到的密码: 1231234567
}
@end
  • 编译运行后,可以到打印结果:
    2018-12-08 17:01:38.445077+0800 WeChat[16868:1395486] Hook hook_next
    2018-12-08 17:01:38.495185+0800 WeChat[16868:1395486] Hook 到的密码: passwdisme
  • mark

你可能感兴趣的:(Hook微信并截取登录密码-真机实测)