[飘云增补篇]《手把手教你破解 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,需要的下载吧~
666,大师就是大师,看完后茅塞顿开+++{:biggrin:} 感谢飘总分享奇巧淫技 两位大师传道授业解惑,我等当虚心学习 谢谢飘,认真学习,天天向上 感谢感谢还是更多感谢! 666 RSA算法 增加Go语言版注册机源代码 看不懂,先mark下 感谢飘总分享奇巧淫技
页:
[1]
2