飘云 发表于 2019-9-19 20:48:24

[飘云增补篇]《手把手教你破解 MacOS 系列之 Bartender 3 》补遗

原文详见:https://www.chinapyg.com/thread-135989-1-1.html

本文仅对一些细节做修改

0x00 C函数Hook简化


[*]原文

在原文操作实战 3中,tree_fly采用了如下命令来尝试追踪C函数:

~ frida-trace -i "sub_1000627c0" "Bartender 3"

在失败后,又编写了注入器inject.py及js文件进行patch。

[*]简化

其实使用-a选项,“MODULE!OFFSET”方式就可以了,见下图:

本例目标文件存在空格,为调试方便需要先处理一下,飘哥直接一点,修改了文件名,并用下面命令进行追踪:
frida-trace ./Bartender -a "Bartender\!627c0"
Instrumenting functions...
sub_627c0: Loaded handler at "/Users/piao/Downloads/Bartender 3.app/Contents/MacOS/__handlers__/Bartender/sub_627c0.js"
Started tracing 1 function. Press Ctrl+C to stop.
         /* TID 0x407 */
   101 mssub_627c0()
   103 mssub_627c0()
   104 mssub_627c0()
   105 mssub_627c0()
然后就和原文一样修改吧!!!
0x01 DSA签名算法

在原文“分析公钥长度”一节中,tree_fly采用了如下命令来分析PEM文件:
~ openssl rsa -pubin -text -in public.pem
4415460972:error:06FFF07F:digital envelope routines:CRYPTO_internal:expecting an rsa key:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.250.1/libressl-2.6/crypto/evp/p_lib.c:295:
所示的错误,后来tree_fly不断尝试找到1678的秘钥长度恰好吻合!
RSA1678??很怪异吧,飘哥由此断定该分析有误,继续进行二次分析,使用如下命令解析:

openssl asn1parse -in pub.pem


取一个参数放到010 Editor里面,可以确定是(64*8)=512bit,如下图所示。
因此纠正签名算法为DSA-512。
0x02 编写注册机

OpenSSL命令如下:
# 生成DSA参数
openssl dsaparam -out dsa_param.pem 512
# 提取私钥
openssl gendsa -out dsa_private_key.pem dsa_param.pem
# 提取公钥
openssl dsa -in dsa_private_key.pem -pubout -out dsa_public_key.pem
操作过程:
➜Desktop openssl dsaparam -out dsa_param.pem 512
➜Desktop openssl gendsa -out dsa_private_key.pem dsa_param.pem
Generating DSA key, 512 bits
➜Desktop cat dsa_private_key.pem
-----BEGIN DSA PRIVATE KEY-----
MIH4AgEAAkEAraqakqaZAELLKQyPPRUKTlYunqoZqbsrP6A0Y/k10/Fh4hSdqZrn
ajORjFOPUsNIiDCLMqlxqo8aK+R/gY23mQIVAKmoTu5eMxpPc+wNxRCrLL8wfO7Z
AkBcMGr4gMnFxmTRDpQknFOOjebwJ7OkVWpE9ZWMFutWcqpDcAKfjtU1dwNK7IIt
4hgytNXAExOzifrN06rY/zsbAkBdyDX92oQz9KdzyK+QWqc3GA3T4sgBnjQEOL5u
N5wpFdimNDJGtNly2btCRK/MbUWRi2k2P+EUqT8MCdkK4uq8AhUApXG/mJwJMVbC
AEUTY5sz07f2XKA=
-----END DSA PRIVATE KEY-----
➜Desktop openssl dsa -in dsa_private_key.pem -pubout -out dsa_public_key.pem
read DSA key
writing DSA key
➜Desktop cat dsa_public_key.pem
-----BEGIN PUBLIC KEY-----
MIHwMIGoBgcqhkjOOAQBMIGcAkEAraqakqaZAELLKQyPPRUKTlYunqoZqbsrP6A0
Y/k10/Fh4hSdqZrnajORjFOPUsNIiDCLMqlxqo8aK+R/gY23mQIVAKmoTu5eMxpP
c+wNxRCrLL8wfO7ZAkBcMGr4gMnFxmTRDpQknFOOjebwJ7OkVWpE9ZWMFutWcqpD
cAKfjtU1dwNK7IIt4hgytNXAExOzifrN06rY/zsbA0MAAkBdyDX92oQz9KdzyK+Q
Wqc3GA3T4sgBnjQEOL5uN5wpFdimNDJGtNly2btCRK/MbUWRi2k2P+EUqT8MCdkK
4uq8
-----END PUBLIC KEY-----

替换公钥如下:

注册机如下:
name-->www.chinapyg.com
serial-->GAWAEFAE34G7M6FBGASHIGH5PXRN5JBIZD433HYCCQCGQK5YOCPDB5J3V47MPHEJQTWQ5DPF64======

OC版:

//
//main.m
//KeyGen
//
//Created by piao on 2019/9/19.
//Copyright © 2019 piao. All rights reserved.
//

#import <Foundation/Foundation.h>

#define dsaPrivateKey @"-----BEGIN DSA PRIVATE KEY-----\n" \
"MIH4AgEAAkEAraqakqaZAELLKQyPPRUKTlYunqoZqbsrP6A0Y/k10/Fh4hSdqZrn\n" \
"ajORjFOPUsNIiDCLMqlxqo8aK+R/gY23mQIVAKmoTu5eMxpPc+wNxRCrLL8wfO7Z\n" \
"AkBcMGr4gMnFxmTRDpQknFOOjebwJ7OkVWpE9ZWMFutWcqpDcAKfjtU1dwNK7IIt\n" \
"4hgytNXAExOzifrN06rY/zsbAkBdyDX92oQz9KdzyK+QWqc3GA3T4sgBnjQEOL5u\n" \
"N5wpFdimNDJGtNly2btCRK/MbUWRi2k2P+EUqT8MCdkK4uq8AhUApXG/mJwJMVbC\n" \
"AEUTY5sz07f2XKA=\n" \
"-----END DSA PRIVATE KEY-----"


NSData* sign(NSData* data) {
   
    SecExternalFormat inputFormat = kSecFormatOpenSSL;
    SecExternalItemType itemType = kSecItemTypePrivateKey;
    CFArrayRef outItems = NULL;
   
    NSData *priKey = ;
   
    OSStatus status = SecItemImport((CFDataRef)priKey, NULL, &inputFormat, &itemType, 0, NULL, NULL, &outItems);
    if (status != errSecSuccess || !outItems || CFArrayGetCount(outItems) == 0) {
      if (outItems) CFRelease(outItems);
      return nil;
    }
   
    SecKeyRef privateKey = (SecKeyRef)CFRetain(CFArrayGetValueAtIndex(outItems, 0));
    CFRelease(outItems);
   
    CFErrorRef error;
   
    SecTransformRef signer = SecSignTransformCreate(privateKey, &error);
    if (error) { CFShow(error); exit(-1); }

    SecTransformSetAttribute(signer,
                           kSecDigestTypeAttribute,
                           kSecDigestSHA1,
                           &error);
    if (error) { CFShow(error); exit(-1); }
   
    SecTransformSetAttribute(signer,
                            kSecTransformInputAttributeName,
                            (CFDataRef)data,
                            &error);
    if (error) { CFShow(error); exit(-1); }
   
   
    CFTypeRef signature = SecTransformExecute(signer, &error);
    if (error || !signature) { CFShow(error); exit(-1); }
   
    CFRelease(signer);

    return (__bridge_transfer NSData*)signature;
}

NSString *base32String(NSData *data) {
    NSString *string = nil;
    SecTransformRef encodeTransform = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
    if (encodeTransform) {
      SecTransformSetAttribute(encodeTransform, kSecTransformInputAttributeName, (CFDataRef)data, NULL);
      NSData *encodedData = (__bridge_transfer NSData*)SecTransformExecute(encodeTransform, NULL);
      string = [ initWithData:encodedData encoding:NSASCIIStringEncoding];
      CFRelease(encodeTransform);
    }
   
    return string;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
      // insert code here...
      
      NSString *name = @"www.chinapyg.com";
      NSString *str = ;
      NSData* nsInput = ;

      NSLog(@"\nname-->%@\nserial-->%@", name, base32String(sign(nsInput)));
    }
    return 0;
}



Go语言版:


package main

import (
        "bytes"
        "crypto/dsa"
        "crypto/rand"
        "crypto/sha1"
        "encoding/asn1"
        "encoding/base32"
        "fmt"
        "golang.org/x/crypto/ssh"
        "io"
        "log"
        "math/big"
)

var dsaPrivateKey = []byte(`-----BEGIN DSA PRIVATE KEY-----
MIH4AgEAAkEAraqakqaZAELLKQyPPRUKTlYunqoZqbsrP6A0Y/k10/Fh4hSdqZrn
ajORjFOPUsNIiDCLMqlxqo8aK+R/gY23mQIVAKmoTu5eMxpPc+wNxRCrLL8wfO7Z
AkBcMGr4gMnFxmTRDpQknFOOjebwJ7OkVWpE9ZWMFutWcqpDcAKfjtU1dwNK7IIt
4hgytNXAExOzifrN06rY/zsbAkBdyDX92oQz9KdzyK+QWqc3GA3T4sgBnjQEOL5u
N5wpFdimNDJGtNly2btCRK/MbUWRi2k2P+EUqT8MCdkK4uq8AhUApXG/mJwJMVbC
AEUTY5sz07f2XKA=
-----END DSA PRIVATE KEY-----
`)

type dsaSignature struct {
        R, S *big.Int
}

func hashMessage(msg []byte) []byte {
        h := sha1.New()
        _, err := io.WriteString(h, string(msg))
        if err != nil {
                log.Fatalf("failed to hash message: %s", err)
        }
        return h.Sum(nil)
}

func sign(msg []byte) ([]byte, error) {
        privateKey, err := ssh.ParseRawPrivateKey(dsaPrivateKey)
        if err != nil {
                return nil, err
        }

        pk, ok := privateKey.(*dsa.PrivateKey)
        if !ok {
                return nil, fmt.Errorf("private key should be *rsa.PrivateKey")
        }

        r, s, _ := dsa.Sign(rand.Reader, pk, hashMessage(msg))

        signData, _ := asn1.Marshal(dsaSignature{r, s})

        //fmt.Println(hex.Dump(signData))

        return signData, nil
}

func base32Encode(data []byte) string {
        return base32.StdEncoding.EncodeToString(data)
}

func generate(userName string) string {
        // bytes.Buffer效率更高...
        var b bytes.Buffer
        b.Write([]byte("Bartender2,"))
        b.Write([]byte(userName))

        data, err := sign(b.Bytes())
        if err != nil {
                return ""
        }
        return base32Encode(data)
}

func main() {
        name := "www.chinapyg.com"
        fmt.Println("=================================================")
        fmt.Println("「name:」" + name)
        fmt.Println("「serial:」" + generate(name))
        fmt.Println("=================================================")
}



DSA只能用于签名与验签,RSA不但可以进行签名与验签,还可以进行加密与解密。
本例中仅用了签名算法, 而DSA与RSA在数学上是等效的, 所以当做RSA算法来分析也能通过。


src,需要的下载吧~

tree_fly 发表于 2019-9-19 21:13:12

666,大师就是大师,看完后茅塞顿开+++{:biggrin:}

不破不立 发表于 2019-9-20 07:42:11

感谢飘总分享奇巧淫技

Rooking 发表于 2019-9-20 08:41:04

两位大师传道授业解惑,我等当虚心学习

small-q 发表于 2019-9-20 09:12:32

谢谢飘,认真学习,天天向上

yxg888 发表于 2019-9-20 11:16:25

感谢感谢还是更多感谢!

dryzh 发表于 2019-9-20 12:04:16

666 RSA算法

飘云 发表于 2019-9-21 10:13:06

增加Go语言版注册机源代码

bachelor66 发表于 2019-9-23 08:41:44

看不懂,先mark下                                          

zhao_yiyuan 发表于 2019-9-23 14:13:01

感谢飘总分享奇巧淫技
页: [1] 2
查看完整版本: [飘云增补篇]《手把手教你破解 MacOS 系列之 Bartender 3 》补遗