【随时删除】Xray社区高级版白嫖历史(下)

admin 2022年10月29日14:41:46评论183 views字数 21715阅读72分23秒阅读模式

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。本文只是讲述了菜刀切肉的方法,读者切勿拿菜刀干别的事。

1.8.5破解过程
再次使用证书修改的方式,使用1.8.4的方法破解发现找不到第三处跳转:

【随时删除】Xray社区高级版白嫖历史(下)

运行一段时间后程序结束,需要找到定时器并Nop掉才行。使用IDA查看伪代码:

【随时删除】Xray社区高级版白嫖历史(下)

跟进gunkit_core_assassin_license_LoadLicense函数发现jnz loc_B684D7指令跳转到os_Exit,如图:

【随时删除】Xray社区高级版白嫖历史(下)

查看jnz loc_B684D7指令十六进制值为0F 85 AE 02 00  00:

【随时删除】Xray社区高级版白嫖历史(下)

将指令NOP之后程序依旧在一段时间后结束。继续看下边jz     loc_B684AA,然后执行call os_Exit,如图:

【随时删除】Xray社区高级版白嫖历史(下)

如何找到定时器?有点菜,放弃寻找定时器了,通过修改证书验证逻辑进行破解。跟进gunkit_core_assassin_utils_selfcrypto___ptr_License__IsValid函数,将jl      loc_B5CB83改为ja      loc_B5CB83,即0F 8C 0F 03 00 00改为0F 87 0F 03 00 00:

【随时删除】Xray社区高级版白嫖历史(下)

跟进gunkit_core_assassin_license_LicenseCheck函数,将jnz     loc_B687EC改为jz     loc_B687EC,即0F 85 62 02 00 00 31 C0改为0F 84 62 02 00 00 31 C0:

【随时删除】Xray社区高级版白嫖历史(下)

根据错误提示this license is expired定位,Shift+F12,然后Alt+T搜索字符串:

【随时删除】Xray社区高级版白嫖历史(下)

双击,然后Ctrl+X查看交叉引用列表,双击之后查看gunkit_core_assassin_http_ResponseFromAncestor函数,将jz      loc_BB9D2E改为jmp      loc_BB9D2E,即84  C0 0F 84 CF FE FF FF改为84 C0 E9 D0 FE FF FF FF:

【随时删除】Xray社区高级版白嫖历史(下)

破解代码如下:

package mainimport (  "bytes"  "crypto"  "crypto/aes"  "crypto/cipher"  "crypto/rand"  "crypto/rsa"  "crypto/sha256"  "crypto/x509"  "encoding/base64"  "encoding/hex"  "encoding/json"  "encoding/pem"  "flag"  //"fmt"  "io/ioutil"  "os"  "strings"  "time"  "log")
var ( originPubKeyPem = `-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2K+PRbp/yumhaVnN92JSGuQiwj7df64jHAo8MvXLWjYxU/yvqB4LbGty8ymKQy33qaDNpu9jgE2s8cXrtftm/UcvwDb8sTqWXpDhxYhcvJM30agxz3/8VwNJ4JOvhk9Gn+msYIUz+gXZMBuUFKhiBOd6C2Pro03GYwVTNjfwH/Y9C5EfPKIKNU/5t2cYo+TuOBk5ooP+NTaDzB6rb7fdE5uuNnF21x3rdiI9rZcKPbuU97/0OWNcIUh5wfxPNWwcmjYmFuZcxk/7dOUD65s4pTplCoMLOelacB0l442dM4w2xNpn+Yg7i/ujmg37F+VguCZJWnoyImdhp/raccNG+wIDAQAB-----END PUBLIC KEY-----` newPublicKeyPem = `-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtKvyFB24hIEVwMs4Xi00FCW41tqELGYb7f63A/lAsBPVSOvGrQ5UzuKmttatQF/IDD9UcHqqbi+B80pydiGSeKJOaly0GuX6hfDd51/uo7E44LyzJSSBhTc1vtbL5JbNcapnxo4P6rJ1Uh9V7y8zpRvc1G2da00mQSYoIg/9ty21j4So+Fz/v37qhK50EEIeXGJZb4uz9I9iKCHaazjILf293Gzvp7EFEpZkKrh2VktKaERh+jHmJqEe0z7U/sz0cCa9ohS+TF5nxmkAZBelCwEMXjkjGnCWO3wXJoyrXMn1GY/ilNPDFT7rSZBKLEIi7PrBD1pVLGdq2zTboenV6wIDAQAB-----END PUBLIC KEY-----` newPrivateKeyPem = `-----BEGIN RSA PRIVATE KEY-----MIIEpQIBAAKCAQEAtKvyFB24hIEVwMs4Xi00FCW41tqELGYb7f63A/lAsBPVSOvGrQ5UzuKmttatQF/IDD9UcHqqbi+B80pydiGSeKJOaly0GuX6hfDd51/uo7E44LyzJSSBhTc1vtbL5JbNcapnxo4P6rJ1Uh9V7y8zpRvc1G2da00mQSYoIg/9ty21j4So+Fz/v37qhK50EEIeXGJZb4uz9I9iKCHaazjILf293Gzvp7EFEpZkKrh2VktKaERh+jHmJqEe0z7U/sz0cCa9ohS+TF5nxmkAZBelCwEMXjkjGnCWO3wXJoyrXMn1GY/ilNPDFT7rSZBKLEIi7PrBD1pVLGdq2zTboenV6wIDAQABAoIBAQCu3PSxr4pVBLLPJGFsFQggr9nUaS4f4rwJfswXlnibcratmzVxbTt7+TYuJF0OvyVZZToOm0q01lpJ5LYfy6J+C2kl3I+csRXl6Rh8xgase+x252vj+Q86phLon/A7UBGLf8htDjYti4etchK0KtUramozV9xSbBsoVwvk2+FOFdiLsc+B3PyuydB0Lvov5EDBtZJ1GbnyWk/3c++aL+lkjQbIs11A4Nwp7hUdPmM/Va8VK+DqWxbFCIr6rli5d9VOE//EHJ7S7aPp+fxV9gyv1d0WBRNktH2t8O2JVn90379/EgWuonSlRG+HrhqZKrXIKuIFJEUmGUjs8qJNzoERAoGBAOLjiGbXuOQHkshDqdB4xF1b4rvCBrr881dBAOnYqSyEUWuUD3et4qX/7GaxWlSU2IteB+r5FyfEpmqUNmKVsgLkGh3lgeTU0Mss2+2xIAODNXvba8MVUIawpvDFnLN2HEY/d+LYycBjWDk+6B1+dGlPZIxXF+8HqGnlqyBNFjP/AoGBAMvaWVB02FK4oXa8APTtvuQ2MP67Q95WdhZXdy8CEWnwJaknSTE3dXJ9nZZmFgHt54loKjbGfIOSCLeCqXm3ZGs5HQr2kY/xJXDJga6uNh71w66/q/W2z+30FFzta6BjYE/83pB+P4vUUsp/vb3SkNfRKdcNrtoL29UYdXM7QG4VAoGAQqLw/MN+2fofchHtXf0aLxE9lkd2EpUYIxhEXGn1xc1W3HGv2UaIuphfpgmQribJMqV7Tde6pUNsXQEKuAmfLpov0XgGnl6itAmIzlanQGDY5HedPr6T1/sqDKz9SPf3depOG6HwH0EOOEHxijgJmKRos48gyGNHY1LA38vEKaECgYEAmu8fRsknyOdOwMFvMLiphyWw40pM8OVh5uUfTnkR5ySAWynitSdjelsCtNZuD5VTjtm+i9cbt5v8SA1k5X9/MQc9jaGNTIuJW0mr6Km7tJgx29UNyzjgnAgQmfhQ/pvJDcIxHjz16z66lfG0slshfwYX+L0LkenFcRaf3a7A72kCgYEAhSSGHVkCTGteSyKxhbMVqTlxQQQWZKv4b+usqss00CKgs3CAKL8HCrds7fq96xVDVCvxJGYMKQzG61MBa+e1f8YSdhl5EY1IltlHkZstgts7avG6MP6AxMNjyLp1b84s2VVXTpSFA7i6KEUhl4NjqhZTslJht5Dfiy2Mmvfk2so=-----END RSA PRIVATE KEY-----` licenseVersion2Byte = []byte{0x02} pre2Bytes = []byte{0x00, 0x01} aesKeyNew, _ = hex.DecodeString("B293C506E0C7F60353C604961837B810"))
var ( licenseName string originLicense string xrayFilePath string xrayArchitecture string)
func main() { flag.StringVar(&licenseName, "g", "", "生成一个永久license,需要指定用户名") flag.StringVar(&originLicense, "p", "", "解析官方证书,需要指定证书路径") flag.StringVar(&xrayFilePath, "c", "", "patch xray,需要指定xray程序文件路径") flag.StringVar(&xrayArchitecture,"a","exe64","xray平台和架构[exe64|elf64],默认为exe64")
flag.Parse()
if originLicense != "" { parseAlready(originLicense) }
if licenseName != "" { genNew(licenseName) }
if xrayFilePath != "" { patch(xrayFilePath) }
}
func parseAlready(licenseFile string) { // 加载公钥 pubKey := importPublicKey(originPubKeyPem)
// 解析 xray-license.lic 文件 licenseFileData, err := ioutil.ReadFile(licenseFile) if err != nil { log.Panic("[!]",err) } licenseString := string(licenseFileData) tmpStrings := strings.Split(licenseString, "n") licenseString = "" for _, line := range tmpStrings { if !strings.HasPrefix(line, "#") && line != "" { licenseString += line } } //fmt.Println("your license:", licenseString)
base64DecodeData, err := base64.StdEncoding.DecodeString(licenseString) if err != nil { log.Panic("[!]",err) }
//fmt.Println("base64 decode data:", hex.EncodeToString(base64DecodeData))
licenseVersion := base64DecodeData[0] if licenseVersion == 2 { log.Println("[*] Version OK: 2") }
//解密前有一个简单的变换处理 right := len(base64DecodeData) - 1 for l := 1; l < right; l++ { r := right - l if l >= r { break } base64DecodeData[l], base64DecodeData[r] = base64DecodeData[r], base64DecodeData[l] } //fmt.Println("trans bytes:", hex.EncodeToString(base64DecodeData))
// aes解密license // | 1B : version | 16B : aes iv | 480B : cipher | aesDecData, err := Decrypt(base64DecodeData[17:], base64DecodeData[1:17]) if err != nil { log.Panic("[!]",err) } //fmt.Printf("AES DEC: %xn", aesDecData) //fmt.Println(string(aesDecData))
//另一个异或变换 for i := 0; i < len(aesDecData); i++ { aesDecData[i] = aesDecData[i] ^ 0x44 } //fmt.Println("trans 2 :", hex.EncodeToString(aesDecData)) //fmt.Println("trans 2 string:", string(aesDecData))
// 后半部分是明文的json licensePlainJsonBytes := aesDecData[0x102:] //fmt.Println("license info json:", string(licensePlainJsonBytes)) //fmt.Println("pre2bytes:", hex.EncodeToString(aesDecData[:0x2]))
license := License{} err = json.Unmarshal([]byte(licensePlainJsonBytes), &license) if err != nil { log.Panic("[!]",err) } log.Println("[*] License Parsed:", license)
// rsa 验证签名 pss sum := sha256.Sum256(licensePlainJsonBytes) //fmt.Println(sum)
// rsa使用 sha256算法,对 aes解密后的数据第三个字节开始,到后面json明文前面为止是签名 //fmt.Println("解析出来的签名:", aesDecData[2:0x102])
err = rsa.VerifyPSS(pubKey, crypto.SHA256, sum[:], aesDecData[2:0x102], nil) if err != nil { log.Println("[!]",err) } else { log.Println("[+] Varify Success!") }}
func genNew(name string) { validTime, err := time.Parse("2006-01-02 15:04:05", "9999-09-09 00:00:00")
license := License{ LicenseId: "88888888888888888888888888888888", UserId: "88888888888888888888888888888888", UserName: name, Distribution: "ADVANCED-Infiltrator", NotValidBefore: 1591891200, NotValidAfter: validTime.Unix(), }
licensePlainJsonBytes, _ := json.Marshal(license) //licensePlainJson := string(licensePlainJsonBytes) //fmt.Println("明文license信息:", licensePlainJson)
// rsa sign priKey := importPrivateKey(newPrivateKeyPem)
//sha256sum sum := sha256.Sum256(licensePlainJsonBytes) signature, err := rsa.SignPSS(rand.Reader, priKey, crypto.SHA256, sum[:], nil) if err != nil { log.Panic("[!]",err) }
licenseInfoWithSign := append(signature, licensePlainJsonBytes...) data2Enc := append(pre2Bytes, licenseInfoWithSign...)
// 加密前一次异或 for i := 0; i < len(data2Enc); i++ { data2Enc[i] = data2Enc[i] ^ 0x44 }
// session iv iv := make([]byte, 16) _, _ = rand.Read(iv) log.Println("[*] Temp AES IV:", hex.EncodeToString(iv)) aesEnc, err := Encrypt(data2Enc, iv) if err != nil { log.Panic("[!]",err) } //fmt.Println(aesEnc)
allBytes := append(iv, aesEnc...) allBytes = append(licenseVersion2Byte, allBytes...)
// 左右交换 right := len(allBytes) - 1 for l := 1; l < right; l++ { r := right - l if l >= r { break } allBytes[l], allBytes[r] = allBytes[r], allBytes[l] }
licenseText := base64.StdEncoding.EncodeToString(allBytes)
fileText := `# xray license# 需要重命名为 xray-license.lic 和 xray 可执行程序放在同一个文件夹中# user_name: Chinese# distribution: COMMUNITY-ADVANCED# 仅对修改后的xray有效

` + licenseText + ``
err = ioutil.WriteFile("xray-license.lic", []byte(fileText), os.ModePerm) if err == nil { log.Println("[+] 证书已写入文件:xray-license.lic") }}
func Decrypt(decodeData []byte, iv []byte) ([]byte, error) { block, _ := aes.NewCipher(aesKeyNew) blockMode := cipher.NewCBCDecrypter(block, iv) origin_data := make([]byte, len(decodeData)) blockMode.CryptBlocks(origin_data, decodeData) return unpad(origin_data), nil}
func unpad(ciphertext []byte) []byte { length := len(ciphertext) unpadding := int(ciphertext[length-1]) return ciphertext[:(length - unpadding)]}
func Encrypt(text []byte, iv []byte) ([]byte, error) { block, _ := aes.NewCipher(aesKeyNew) blockSize := block.BlockSize() originData := pad(text, blockSize) blockMode := cipher.NewCBCEncrypter(block, iv) crypted := make([]byte, len(originData)) blockMode.CryptBlocks(crypted, originData) //fmt.Println(len(originData)) return crypted, nil}
func pad(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...)}
type License struct { LicenseId string `json:"license_id"` UserId string `json:"user_id"` UserName string `json:"user_name"` Distribution string `json:"distribution"` NotValidBefore int64 `json:"not_valid_before"` NotValidAfter int64 `json:"not_valid_after"`}
func importPublicKey(key string) *rsa.PublicKey { block, _ := pem.Decode([]byte(key)) if block == nil { log.Panic("[!] Unable To Decode PublicKey To Request!") }
pub, _ := x509.ParsePKIXPublicKey(block.Bytes) return pub.(*rsa.PublicKey)}
func importPrivateKey(key string) *rsa.PrivateKey { block, _ := pem.Decode([]byte(key)) privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { log.Panic("[!]",err) } return privateKey}
func patch(filePath string) { amd64Bytes := make(map[string]string) if xrayArchitecture == "exe64"{ // jl loc_B5CB83 改为 ja loc_B5CB83 amd64Bytes["48394B380F8C0F030000"] = "48394B380F870F030000" // jnz loc_B687EC 改为 jz loc_B687EC amd64Bytes["0F856202000031C0"] = "0F846202000031C0" // jz loc_BB9D2E 改为 jmp loc_BB9D2E amd64Bytes["84C00F84CFFEFFFF"] = "84C0E9D0FEFFFFFF" } // Linux amd64 //cmp qword ptr [rsp+2F8h+var_2F8+8], 0 改为 1 //jz short loc_1434748 -> call os_Exit if xrayArchitecture == "elf64"{ //jl loc_B40BE3 amd64Bytes["0F8CF9020000"] = "0F87F9020000" //jnz loc_B4C78C amd64Bytes["0F8566020000"] = "0F8466020000" //jz loc_B9CC27 amd64Bytes["84C00F84C8FEFFFF"] = "84C0E9C9FEFFFFFF" } for originBytes, newBytes := range amd64Bytes { origin, err := ioutil.ReadFile(filePath) originTmpBytes, _ := hex.DecodeString(originBytes) newTmpBytes, _ := hex.DecodeString(newBytes) loc := bytes.LastIndex(origin, originTmpBytes) if loc > 0 { log.Printf("[*] Signature Index: %#xn", loc) newFile := replace(origin, newTmpBytes, loc) err = ioutil.WriteFile(filePath, newFile, os.ModePerm) if err == nil { log.Println("[+] Patch Success:", filePath) } } else { log.Println("[!] Can't Find Signature!",originBytes) } }
}
func replace(origin, new []byte, index int) []byte { n := make([]byte, len(origin)) copy(n[:index], origin[:index]) copy(n[index:index+len(new)], new) copy(n[index+len(new):], origin[index+len(new):]) return n}
使用该方法需要一个合法证书xray-license.lic,如下:
# xray license# user_name: xray team# user_id: c2a60b56f75189a74fe684ec0cb65add# license_id: 1b76efc317ac09ececdf1f1338f5b4d6# distribution: COMMUNITY-ADVANCED# not_valid_before: 2021-01-10# not_valid_after: 2021-04-10
AsFUXefZmgucJvUeivLDC8bCsyQjUxkEFm5Z8aZ29ujjXKBjUevNqQUhYlLwDAEcO+UarCjYqTsy6VTi9ewHLeEqPx4NI8ese/ALO0Oa6JBucvKNN+V0CphEGQw6vfr60KT0OKc7mcnnK+azYihSXRbHW98EZgyRr3vzLb9TWITZJwzZDPhoR4kDMHq86CLhpdfV6wDoOjvWdcxmRuDrbdRkWKkuXSrYiZpfsMsrhq4dDLfdvgT4LjnHJjlOdQBhfablZKeRlEx/6DWhJ/5AwgIFzkf9o5sumCkK+gvmK3w0zkmzTM2Sd2ydqSveRrfnl2apS+t5xwM/BMSWdnYQvIzH9KrpwE+rsNDUMUDMnurSqTr652rMZrzqmg+ckloka7uhHsj2TCLopzv9N62fFPf9/akSox+unvXhdluUI9TRYFVecXqJ9YJzDDGJKcjXGgxIDWfmYoXvgfAutSuIzi5qkEvEjFs6yGmZNJTvuorqKL82AO4DqQI3Axi6FjbFRvnmapIWHFtWZZbd0/mcUrhmwQ9fjXamiXm+IyVh7t38CqLXahupGili1WV2oVGy84tPZZQFTZVmoXlSSwCW4qRcYwOHk7OhQA9RLsx8DLkfahf2upzkdIgXdq7GAOm+bmp5dmJtOHRJTW5MNTg5eZU=


1.9.0破解过程

在1.8.5的基础上修改证书验证逻辑,将jl      loc_BD3DAF改为ja      loc_BD3DAF,即48 39 4B 38 0F 8C 25 02  00 00改为48 39 4B 38 0F 87 25 02  00 00即可:

if xrayArchitecture == "elf64"{    //jl      loc_B40BE3    amd64Bytes["48394B380F8C25020000"] = "48394B380F8725020000"    //jnz     loc_B4C78C    amd64Bytes["0F8566020000"] = "0F8466020000"    //jz      loc_B9CC27    amd64Bytes["84C00F84C8FEFFFF"] = "84C0E9C9FEFFFFFF"  }

破解结果如下:

【随时删除】Xray社区高级版白嫖历史(下)

1.9.1破解过程

跟进gunkit_core_assassin_http_ResponseFromAncestor函数,将jl指令改为ja:

【随时删除】Xray社区高级版白嫖历史(下)

跟进gunkit_ext_nmap.UnquoteCStyleString函数,将jnz指令改为jz:

【随时删除】Xray社区高级版白嫖历史(下)

破解结果:

【随时删除】Xray社区高级版白嫖历史(下)

【随时删除】Xray社区高级版白嫖历史(下)

破解代码如下:

package mainimport (  "bytes"  "crypto"  "crypto/aes"  "crypto/cipher"  "crypto/rand"  "crypto/rsa"  "crypto/sha256"  "crypto/x509"  "encoding/base64"  "encoding/hex"  "encoding/json"  "encoding/pem"  "flag"  //"fmt"  "io/ioutil"  "os"  "strings"  "time"  "log")
var ( originPubKeyPem = `-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2K+PRbp/yumhaVnN92JSGuQiwj7df64jHAo8MvXLWjYxU/yvqB4LbGty8ymKQy33qaDNpu9jgE2s8cXrtftm/UcvwDb8sTqWXpDhxYhcvJM30agxz3/8VwNJ4JOvhk9Gn+msYIUz+gXZMBuUFKhiBOd6C2Pro03GYwVTNjfwH/Y9C5EfPKIKNU/5t2cYo+TuOBk5ooP+NTaDzB6rb7fdE5uuNnF21x3rdiI9rZcKPbuU97/0OWNcIUh5wfxPNWwcmjYmFuZcxk/7dOUD65s4pTplCoMLOelacB0l442dM4w2xNpn+Yg7i/ujmg37F+VguCZJWnoyImdhp/raccNG+wIDAQAB-----END PUBLIC KEY-----` newPublicKeyPem = `-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtKvyFB24hIEVwMs4Xi00FCW41tqELGYb7f63A/lAsBPVSOvGrQ5UzuKmttatQF/IDD9UcHqqbi+B80pydiGSeKJOaly0GuX6hfDd51/uo7E44LyzJSSBhTc1vtbL5JbNcapnxo4P6rJ1Uh9V7y8zpRvc1G2da00mQSYoIg/9ty21j4So+Fz/v37qhK50EEIeXGJZb4uz9I9iKCHaazjILf293Gzvp7EFEpZkKrh2VktKaERh+jHmJqEe0z7U/sz0cCa9ohS+TF5nxmkAZBelCwEMXjkjGnCWO3wXJoyrXMn1GY/ilNPDFT7rSZBKLEIi7PrBD1pVLGdq2zTboenV6wIDAQAB-----END PUBLIC KEY-----` newPrivateKeyPem = `-----BEGIN RSA PRIVATE KEY-----MIIEpQIBAAKCAQEAtKvyFB24hIEVwMs4Xi00FCW41tqELGYb7f63A/lAsBPVSOvGrQ5UzuKmttatQF/IDD9UcHqqbi+B80pydiGSeKJOaly0GuX6hfDd51/uo7E44LyzJSSBhTc1vtbL5JbNcapnxo4P6rJ1Uh9V7y8zpRvc1G2da00mQSYoIg/9ty21j4So+Fz/v37qhK50EEIeXGJZb4uz9I9iKCHaazjILf293Gzvp7EFEpZkKrh2VktKaERh+jHmJqEe0z7U/sz0cCa9ohS+TF5nxmkAZBelCwEMXjkjGnCWO3wXJoyrXMn1GY/ilNPDFT7rSZBKLEIi7PrBD1pVLGdq2zTboenV6wIDAQABAoIBAQCu3PSxr4pVBLLPJGFsFQggr9nUaS4f4rwJfswXlnibcratmzVxbTt7+TYuJF0OvyVZZToOm0q01lpJ5LYfy6J+C2kl3I+csRXl6Rh8xgase+x252vj+Q86phLon/A7UBGLf8htDjYti4etchK0KtUramozV9xSbBsoVwvk2+FOFdiLsc+B3PyuydB0Lvov5EDBtZJ1GbnyWk/3c++aL+lkjQbIs11A4Nwp7hUdPmM/Va8VK+DqWxbFCIr6rli5d9VOE//EHJ7S7aPp+fxV9gyv1d0WBRNktH2t8O2JVn90379/EgWuonSlRG+HrhqZKrXIKuIFJEUmGUjs8qJNzoERAoGBAOLjiGbXuOQHkshDqdB4xF1b4rvCBrr881dBAOnYqSyEUWuUD3et4qX/7GaxWlSU2IteB+r5FyfEpmqUNmKVsgLkGh3lgeTU0Mss2+2xIAODNXvba8MVUIawpvDFnLN2HEY/d+LYycBjWDk+6B1+dGlPZIxXF+8HqGnlqyBNFjP/AoGBAMvaWVB02FK4oXa8APTtvuQ2MP67Q95WdhZXdy8CEWnwJaknSTE3dXJ9nZZmFgHt54loKjbGfIOSCLeCqXm3ZGs5HQr2kY/xJXDJga6uNh71w66/q/W2z+30FFzta6BjYE/83pB+P4vUUsp/vb3SkNfRKdcNrtoL29UYdXM7QG4VAoGAQqLw/MN+2fofchHtXf0aLxE9lkd2EpUYIxhEXGn1xc1W3HGv2UaIuphfpgmQribJMqV7Tde6pUNsXQEKuAmfLpov0XgGnl6itAmIzlanQGDY5HedPr6T1/sqDKz9SPf3depOG6HwH0EOOEHxijgJmKRos48gyGNHY1LA38vEKaECgYEAmu8fRsknyOdOwMFvMLiphyWw40pM8OVh5uUfTnkR5ySAWynitSdjelsCtNZuD5VTjtm+i9cbt5v8SA1k5X9/MQc9jaGNTIuJW0mr6Km7tJgx29UNyzjgnAgQmfhQ/pvJDcIxHjz16z66lfG0slshfwYX+L0LkenFcRaf3a7A72kCgYEAhSSGHVkCTGteSyKxhbMVqTlxQQQWZKv4b+usqss00CKgs3CAKL8HCrds7fq96xVDVCvxJGYMKQzG61MBa+e1f8YSdhl5EY1IltlHkZstgts7avG6MP6AxMNjyLp1b84s2VVXTpSFA7i6KEUhl4NjqhZTslJht5Dfiy2Mmvfk2so=-----END RSA PRIVATE KEY-----` licenseVersion2Byte = []byte{0x02} pre2Bytes = []byte{0x00, 0x01} aesKeyNew, _ = hex.DecodeString("B293C506E0C7F60353C604961837B810"))
var ( licenseName string originLicense string xrayFilePath string xrayArchitecture string)
func main() { flag.StringVar(&licenseName, "g", "", "生成一个永久license,需要指定用户名") flag.StringVar(&originLicense, "p", "", "解析官方证书,需要指定证书路径") flag.StringVar(&xrayFilePath, "c", "", "patch xray,需要指定xray程序文件路径") flag.StringVar(&xrayArchitecture,"a","exe64","xray平台和架构[exe64|elf64],默认为exe64")
flag.Parse()
if originLicense != "" { parseAlready(originLicense) }
if licenseName != "" { genNew(licenseName) }
if xrayFilePath != "" { patch(xrayFilePath) }
}
func parseAlready(licenseFile string) { // 加载公钥 pubKey := importPublicKey(originPubKeyPem)
// 解析 xray-license.lic 文件 licenseFileData, err := ioutil.ReadFile(licenseFile) if err != nil { log.Panic("[!]",err) } licenseString := string(licenseFileData) tmpStrings := strings.Split(licenseString, "n") licenseString = "" for _, line := range tmpStrings { if !strings.HasPrefix(line, "#") && line != "" { licenseString += line } } //fmt.Println("your license:", licenseString)
base64DecodeData, err := base64.StdEncoding.DecodeString(licenseString) if err != nil { log.Panic("[!]",err) }
//fmt.Println("base64 decode data:", hex.EncodeToString(base64DecodeData))
licenseVersion := base64DecodeData[0] if licenseVersion == 2 { log.Println("[*] Version OK: 2") }
//解密前有一个简单的变换处理 right := len(base64DecodeData) - 1 for l := 1; l < right; l++ { r := right - l if l >= r { break } base64DecodeData[l], base64DecodeData[r] = base64DecodeData[r], base64DecodeData[l] } //fmt.Println("trans bytes:", hex.EncodeToString(base64DecodeData))
// aes解密license // | 1B : version | 16B : aes iv | 480B : cipher | aesDecData, err := Decrypt(base64DecodeData[17:], base64DecodeData[1:17]) if err != nil { log.Panic("[!]",err) } //fmt.Printf("AES DEC: %xn", aesDecData) //fmt.Println(string(aesDecData))
//另一个异或变换 for i := 0; i < len(aesDecData); i++ { aesDecData[i] = aesDecData[i] ^ 0x44 } //fmt.Println("trans 2 :", hex.EncodeToString(aesDecData)) //fmt.Println("trans 2 string:", string(aesDecData))
// 后半部分是明文的json licensePlainJsonBytes := aesDecData[0x102:] //fmt.Println("license info json:", string(licensePlainJsonBytes)) //fmt.Println("pre2bytes:", hex.EncodeToString(aesDecData[:0x2]))
license := License{} err = json.Unmarshal([]byte(licensePlainJsonBytes), &license) if err != nil { log.Panic("[!]",err) } log.Println("[*] License Parsed:", license)
// rsa 验证签名 pss sum := sha256.Sum256(licensePlainJsonBytes) //fmt.Println(sum)
// rsa使用 sha256算法,对 aes解密后的数据第三个字节开始,到后面json明文前面为止是签名 //fmt.Println("解析出来的签名:", aesDecData[2:0x102])
err = rsa.VerifyPSS(pubKey, crypto.SHA256, sum[:], aesDecData[2:0x102], nil) if err != nil { log.Println("[!]",err) } else { log.Println("[+] Varify Success!") }}
func genNew(name string) { validTime, err := time.Parse("2006-01-02 15:04:05", "9999-09-09 00:00:00")
license := License{ LicenseId: "88888888888888888888888888888888", UserId: "88888888888888888888888888888888", UserName: name, Distribution: "ADVANCED-Infiltrator", NotValidBefore: 1591891200, NotValidAfter: validTime.Unix(), }
licensePlainJsonBytes, _ := json.Marshal(license) //licensePlainJson := string(licensePlainJsonBytes) //fmt.Println("明文license信息:", licensePlainJson)
// rsa sign priKey := importPrivateKey(newPrivateKeyPem)
//sha256sum sum := sha256.Sum256(licensePlainJsonBytes) signature, err := rsa.SignPSS(rand.Reader, priKey, crypto.SHA256, sum[:], nil) if err != nil { log.Panic("[!]",err) }
licenseInfoWithSign := append(signature, licensePlainJsonBytes...) data2Enc := append(pre2Bytes, licenseInfoWithSign...)
// 加密前一次异或 for i := 0; i < len(data2Enc); i++ { data2Enc[i] = data2Enc[i] ^ 0x44 }
// session iv iv := make([]byte, 16) _, _ = rand.Read(iv) log.Println("[*] Temp AES IV:", hex.EncodeToString(iv)) aesEnc, err := Encrypt(data2Enc, iv) if err != nil { log.Panic("[!]",err) } //fmt.Println(aesEnc)
allBytes := append(iv, aesEnc...) allBytes = append(licenseVersion2Byte, allBytes...)
// 左右交换 right := len(allBytes) - 1 for l := 1; l < right; l++ { r := right - l if l >= r { break } allBytes[l], allBytes[r] = allBytes[r], allBytes[l] }
licenseText := base64.StdEncoding.EncodeToString(allBytes)
fileText := `# xray license# 需要重命名为 xray-license.lic 和 xray 可执行程序放在同一个文件夹中# user_name: Chinese# distribution: COMMUNITY-ADVANCED# 仅对修改后的xray有效

` + licenseText + ``
err = ioutil.WriteFile("xray-license.lic", []byte(fileText), os.ModePerm) if err == nil { log.Println("[+] 证书已写入文件:xray-license.lic") }}
func Decrypt(decodeData []byte, iv []byte) ([]byte, error) { block, _ := aes.NewCipher(aesKeyNew) blockMode := cipher.NewCBCDecrypter(block, iv) origin_data := make([]byte, len(decodeData)) blockMode.CryptBlocks(origin_data, decodeData) return unpad(origin_data), nil}
func unpad(ciphertext []byte) []byte { length := len(ciphertext) unpadding := int(ciphertext[length-1]) return ciphertext[:(length - unpadding)]}
func Encrypt(text []byte, iv []byte) ([]byte, error) { block, _ := aes.NewCipher(aesKeyNew) blockSize := block.BlockSize() originData := pad(text, blockSize) blockMode := cipher.NewCBCEncrypter(block, iv) crypted := make([]byte, len(originData)) blockMode.CryptBlocks(crypted, originData) //fmt.Println(len(originData)) return crypted, nil}
func pad(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...)}
type License struct { LicenseId string `json:"license_id"` UserId string `json:"user_id"` UserName string `json:"user_name"` Distribution string `json:"distribution"` NotValidBefore int64 `json:"not_valid_before"` NotValidAfter int64 `json:"not_valid_after"`}
func importPublicKey(key string) *rsa.PublicKey { block, _ := pem.Decode([]byte(key)) if block == nil { log.Panic("[!] Unable To Decode PublicKey To Request!") }
pub, _ := x509.ParsePKIXPublicKey(block.Bytes) return pub.(*rsa.PublicKey)}
func importPrivateKey(key string) *rsa.PrivateKey { block, _ := pem.Decode([]byte(key)) privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { log.Panic("[!]",err) } return privateKey}
func patch(filePath string) { amd64Bytes := make(map[string]string) /* if xrayArchitecture == "exe64"{ // jl loc_B5CB83 改为 ja loc_B5CB83 amd64Bytes["48394B380F8C0F030000"] = "48394B380F870F030000" // jnz loc_B687EC 改为 jz loc_B687EC amd64Bytes["0F856202000031C0"] = "0F846202000031C0" // jz loc_BB9D2E 改为 jmp loc_BB9D2E amd64Bytes["84C00F84CFFEFFFF"] = "84C0E9D0FEFFFFFF" } // Linux amd64 //cmp qword ptr [rsp+2F8h+var_2F8+8], 0 改为 1 //jz short loc_1434748 -> call os_Exit if xrayArchitecture == "elf64"{ //jl loc_B40BE3 amd64Bytes["4883FB010F8566020000"] = "4883FB010F8466020000" //jnz loc_B4C78C //amd64Bytes["0F8566020000"] = "0F8466020000" //jz loc_B9CC27 amd64Bytes["4839FB0F8C77010000"] = "4839FB0F8777010000" } */ amd64Bytes["4883FB010F8566020000"] = "4883FB010F8466020000" amd64Bytes["4839FB0F8C77010000"] = "4839FB0F8777010000" for originBytes, newBytes := range amd64Bytes { origin, err := ioutil.ReadFile(filePath) originTmpBytes, _ := hex.DecodeString(originBytes) newTmpBytes, _ := hex.DecodeString(newBytes) loc := bytes.LastIndex(origin, originTmpBytes) if loc > 0 { log.Printf("[*] Signature Index: %#xn", loc) newFile := replace(origin, newTmpBytes, loc) err = ioutil.WriteFile(filePath, newFile, os.ModePerm) if err == nil { log.Println("[+] Patch Success:", filePath) } } else { log.Println("[!] Can't Find Signature!",originBytes) } }
}
func replace(origin, new []byte, index int) []byte { n := make([]byte, len(origin)) copy(n[:index], origin[:index]) copy(n[index:index+len(new)], new) copy(n[index+len(new):], origin[index+len(new):]) return n}

1.9.3破解过程

测试发现1.9.1的破解代码仍然适用于1.9.3,Windows和Linux通用。

原文始发于微信公众号(Hack All):【随时删除】Xray社区高级版白嫖历史(下)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月29日14:41:46
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【随时删除】Xray社区高级版白嫖历史(下)https://cn-sec.com/archives/1379318.html

发表评论

匿名网友 填写信息