tree_fly 发表于 2016-2-17 17:51:46

[实践][Level 2]如何优雅破解Mac软件-hook入门教程

本帖最后由 tree_fly 于 2016-2-17 17:51 编辑

2016年让Mac OS/iOS板块活跃起来吧~
今天一起完成一次实践,简单阐述一下如何优雅劫持Mac软件,达到解除软件限制目的。 十一期间论坛发布了不少劫持补丁作品,因为发布时统统延续了为程序名增加“下划线”作为新的文件名风格,故若破文中提到采用下划线优雅破解,希望可以理解采用了劫持思想,而没有去修改原本二进制文件。
授人以鱼不如授人以渔   《老子》

实践目标:AppDelete v4.2.4AppDelete is an uninstaller for Macs that will remove not only Applications but also Widgets, Preference Panes, Plugins, and Screensavers along with their associated files. Without AppDelete these associated items will be left behind to take up space and potentially cause issues. For a proper uninstall don’t just delete but be sure to AppDelete!
分析工具:Hopper 3.11.5, HDS
编码工具:XCode

0x1 分析软件
软件支持中文,打开软件本地中文资源文件 zh_CN.lproj/Localizable.strings,注意到如下信息:
"AppDelete Registration" = "AppDelete 注册";
"Registration Accepted" = "接受注册";
"Registration Rejected" = "拒绝注册";
"Register" = "注册";

Hopper加载软件后,查找如上字符串,来到注册验证核心:void -(void * self, void * _cmd, void * arg2) {
    var_30 = self;
    r14 = [ retain];
    r15 = [ retain];
    var_38 = ;
    ;
    ;
    r15 = [ retain];
    r14 = [ retain];
    rdx = @"";
    r13 = ;
    ;
    ;
    if (((var_38 & 0xff) != 0x1) && ((r13 & 0xff) != 0x1)) {
            r14 = [ retain];
            rcx = @"";
            rbx = [ retain];
            rdx = rbx;
            r15 = ;//注意这个函数
            rdi = rbx;
            ;
            ;
            if (r15 != 0x0) {
                  r14 = [ retain]; //注册成功
                  r8 = 0x0;
                  r13 = [ retain];
                  var_38 = r13;
                  ;
                  ;
                  ;
                  ;
                  ;
                  ;
                  ;
                  ;
                  r13 = _objc_release;
                  r14 = [ retain];
                  rbx = [ retain];
                  var_40 = [ retain];
                  ;
                  ;
                  r12 = _objc_release;
                  r14 = [ retain];
                  rbx = [ retain];
                  ;
                  ;
                  ;
                  rbx = [ retain];
                  rdx = var_40;
                  ;
                  ;
                  var_30->archiveRun = 0x1;
                  var_30->undoList = 0x0;
                  rbx = var_30;
                  ;
                  ;
            }
            else {
                  r13 = [ retain]; //注册失败
                  rbx = [ retain];
                  NSLog(@"AD Rejected Name ~ %@", rbx);
                  ;
                  ;
                  r13 = [ retain];
                  rbx = [ retain];
                  NSLog(@"AD Rejected Serial Number ~ %@", rbx);
                  ;
                  rdi = r13;
                  r13 = _objc_release;
                  ;
                  rbx = [ retain];
                  r8 = 0x0;
                  r12 = [ retain];
                  ;
                  ;
                  ;
                  ;
                  rdx = @"";
                  ;
                  var_30->archiveRun = 0x0;
                  rbx = var_30;
                  ;
                  r12 = _objc_release;

函数 char -(void * self, void * _cmd, void * arg2)返回非0即可过验证。


那么通过简单地修改代码,就可以了:
mov eax, 1
ret

测试后发现软件重启验证也通过了,注册菜单变灰。
注意,有些很复杂的软件,逆向时候会发现很多暗桩,只有解除了所有的暗桩才能算是完美的破解。
如果你乐意,可以去分析算法,甚至写KG,不在这里细说。



0x2 代码劫持
基础点说,在Windows下,很多时候我们在软件exe同一目录下放置version.dll、lpk.dll等劫持文件,依照规则exe优先加载了当前目录下dll,做很多XX事情。
在Mac OS下,思路是相同的,你可以想尽一切办法让app加载我们的dylib,这里分享一种从飘云、creantan、sagexy诸位大神那里学来的心得:


大家看图和代码,这里以一款截图软件Snagit为例,
首先进入 Snagit.app/Contents/MacOS/目录,
将原本的Snagit文件更名为Snagit_(即添加了下划线),再放入dylib文件,然后创建一个名为Snagit的脚本,贴入如下代码:
#!/bin/bash
Snagit_PATH="`dirname "${0}"`"
Snagit_BIN="`dirname "${0}"`"/Snagit_

export DYLD_FORCE_FLAT_NAMESPACE=1
export DYLD_INSERT_LIBRARIES="${Snagit_PATH}/libSnagitPatch.dylib"
"$Snagit_BIN"

偷梁换柱!这样就可以加载补丁,在运行时态去修改内存数据。问题是如何编写补丁?

这里提供一套模版,大家可以去尝试:
1.创建 Library 工程,贴入如下代码:
#import <objc/runtime.h>

IMP PYSwizzleSelector(Class aClass, SEL selector, IMP newImplementation) {
    // Get the original implementation we are replacing
    Method method = class_getInstanceMethod(aClass, selector);
    IMP origImp = method_getImplementation(method);
    if (! origImp) {
      return NULL;
    }
   
    class_replaceMethod(aClass, selector, newImplementation, method_getTypeEncoding(method));
    return origImp;
}

2.根据劫持函数,设计c劫持代码:
参考实例:
//-:
static NSString* (*pfn_s_ActivationManagerDMG_getInfo)() = NULL;
static NSString* s_ActivationManagerDMG_getInfo(){
    NSLog(@"***** PYG: code by tree_fly/P.Y.G *****");
    NSString* url = @"WwW.ChinaPYG.CoM";
    return url;
}

//-:
static int (*pfn_s_isRegistered)() = NULL;
static int s_isRegistered(){
    return 2015 - 2014;
}


对应的交换代码:

pfn_s_ActivationManagerDMG_getInfo = (NSString* (*)(void))PYSwizzleSelector(objc_getClass("ActivationManagerDMG"), @selector(cachedKeyFromLicenseChecker), (IMP)s_ActivationManagerDMG_getInfo);
   
pfn_s_isRegistered = (int (*)(void))PYSwizzleSelector(objc_getClass("ActivationManagerDMG"), @selector(isSnagitRegistered), (IMP)s_isRegistered);

本文中要劫持的函数是:
char -(void * self, void * _cmd, void * arg2)
尝试如下c代码:
//char -
static char (*pfn_s_orphansArray)(void* _) = NULL;
static char s_orphansArray(void* _){
    NSLog(@"***** PYG: Patch !!! *****");
    return 0x1;
}


3.补丁加载入口:

@implementation AppDeletePatch
+(void)load{
    NSLog(@"***** PYG: WWW. CHINAPYG. COM *****");

    pfn_s_orphansArray = (char (*)(void *))PYSwizzleSelector(objc_getClass("ADController"), @selector(orphansArray:), (IMP)s_orphansArray);
}
@end


记得修改头文件
@interface AppDeletePatch : NSObject
+(void)load;
@end
最终代码如下:




有没有觉得这样写起来真的好复杂,有没有其它方案呢,那就换一种写法吧:

代码:
//
//AppDeletePatch.m
//AppDeletePatch
//
//Created by ftitree_fly on 16/2/17.
//Copyright © 2016年 tree_fly. All rights reserved.
//

#import "AppDeletePatch.h"
#import <objc/runtime.h>

@implementation AppDeletePatch
-(char)orphansArray:(NSString*)data{
    NSLog(@"***** PYG: Patch !!! *****");
    return 0x1;
}


+(void)load{
    NSLog(@"***** PYG: WWW. CHINAPYG .COM *****");
   
    Method origMethod =class_getInstanceMethod
    (NSClassFromString(@"ADController"), NSSelectorFromString(@"orphansArray:"));
   
    Method newMethod = class_getInstanceMethod
    (, @selector(orphansArray:));
   
    method_exchangeImplementations(origMethod, newMethod);
}
@end

有没有看上去更加简洁、优雅,大家可以根据自己的喜好,自由编码~

编译生成最终文件 libAppDeletePatch.dylib。

4.创建bash脚本,如下:
#!/bin/bash
AppDelete_PATH="`dirname "${0}"`"
AppDelete_BIN="`dirname "${0}"`"/AppDelete_

export DYLD_FORCE_FLAT_NAMESPACE=1
export DYLD_INSERT_LIBRARIES="${AppDelete_PATH}/libAppDeletePatch.dylib"
"$AppDelete_BIN"

5.测试

补丁使用说明:

1.安装原版并成功运行一次, 假设安装到 /Applications/AppDelete.app/
2.打开/Applications/AppDelete.app/Contents/MacOS/目录,将 AppDelete 改名为 AppDelete_
3.将补丁libAppDeletePatch.dylib及脚本AppDelete复制到上述目录
4.启动主程序即可!
测试截图:补丁运行Log成功打印,注册菜单栏变灰,功能限制解除。




教程结束,如有问题请跟帖留言,祝大家新年快乐,祝论坛越来越好~


补丁下载:



飘云 发表于 2016-2-17 18:26:11

赞!

…… PYSw*函数还有一半你没看完哟……
http://www.dllhook.com/post/25.html

creantan 发表于 2016-2-17 18:30:29

干货。。。向版主学习

tree_fly 发表于 2016-2-17 18:37:59

飘云 发表于 2016-2-17 18:26
赞!

…… PYSw*函数还有一半你没看完哟……


转载,受教。dllhook.com 果然特多干货

#import <objc/runtime.h>


@interface NSArray(hook)
    -(id)myLastObject;
@end

@implementation NSArray(hook)

-(id)myLastObject
{
    NSLog(@"inject success!!!");
    return ;
}
@end

void HookMethod(Class aClass, SEL oldSEL, SEL newSel)
{
    Method oldMethod = class_getInstanceMethod(aClass, oldSEL);
    assert(oldMethod);
    Method newMethod = class_getInstanceMethod(aClass, newSel);
    assert(newMethod);
    method_exchangeImplementations(oldMethod, newMethod);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
      NSLog(@"Hello, P.Y.G!");
      HookMethod(, @selector(lastObject), @selector(myLastObject));
      NSArray *array = @[@"piaoyun", @"nisy", @"Q", @"GG"];
      NSString *string = ;
      NSLog(@"RET : %@", string);
    }
    return 0;
}

wgz001 发表于 2016-2-17 19:43:10

终于打开了,感谢

ZMLoveLH 发表于 2016-2-17 21:08:12

我是菜鸟,看得头都晕了

zxxiaopi 发表于 2016-2-17 22:08:44

不懂,学下中,膜拜各位大神

2857428593 发表于 2016-2-18 11:14:59

感谢版主这么详细的讲解,可我什么都没学到

overlords 发表于 2017-1-8 23:57:54

感谢版主这么详细的讲解,可我什么都没学到

iNarcissuss 发表于 2017-1-11 22:52:20

学习学习,代码劫持**好啊
页: [1] 2 3
查看完整版本: [实践][Level 2]如何优雅破解Mac软件-hook入门教程