ipad协议逆向分析篇----CCD逆向分析

以上资源来自互联网收集分享,仅供学习研究交流使用

微信登录的 CCD 算法通常指的是一种复杂的加密或验证算法,用于确保登录过程的安全性和数据的完整性!

我们从网上随便找个代码来分析实现

代码如下

package Algorithm

import (
	"github.com/golang/protobuf/proto"
	"hash/crc32"
	"math/rand"
	"time"
	"wechatdll/Cilent/mm"
)

// iphone生成wcstf, 使用06加密
func IphoneWcstf(Username string) []byte {
	curtime := uint64(time.Now().UnixNano() / 1e6)
	contentlen := len(Username)

	var ct []uint64
	ut := curtime
	for i := 0; i < contentlen; i++ {
		ut += uint64(rand.Intn(10000))
		ct = append(ct, ut)
	}
	ccd := &mm.Wcstf{
		StartTime: &curtime,
		CheckTime: &curtime,
		Count:     proto.Uint32(uint32(contentlen)),
		EndTime:   ct,
	}

	pb, _ := proto.Marshal(ccd)

	// Zero: 03加密改06加密
	//var b bytes.Buffer
	//w := zlib.NewWriter(&b)
	//w.Write(pb)
	//w.Close()
	//
	//zt := new(ZT)
	//zt.Init()
	//encData := zt.Encrypt(b.Bytes())
	compressData := DoZlibCompress(pb)
	encData := SaeEncrypt06(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000006\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: proto.Uint32(uint32(time.Now().Unix())),
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}
	MS, _ := proto.Marshal(Ztdata)
	return MS
}

// iphone生成wcste, 使用06加密
func IphoneWcste(A, B uint64) []byte {

	curtime := uint32(time.Now().Unix())
	curNanoTime := uint64(time.Now().UnixNano())

	ccd := &mm.Wcste{
		Checkid:   proto.String("<LoginByID>"),
		StartTime: &curtime,
		CheckTime: &curtime,
		Count1:    proto.Uint32(0),
		Count2:    proto.Uint32(1),
		Count3:    proto.Uint32(0),
		Const1:    proto.Uint64(A),
		Const2:    &curNanoTime,
		Const3:    &curNanoTime,
		Const4:    &curNanoTime,
		Const5:    &curNanoTime,
		Const6:    proto.Uint64(B),
	}

	pb, _ := proto.Marshal(ccd)

	// Zero: 03加密改06加密
	//var b bytes.Buffer
	//w := zlib.NewWriter(&b)
	//w.Write(pb)
	//w.Close()
	//
	//zt := new(ZT)
	//zt.Init()
	//encData := zt.Encrypt(b.Bytes())
	compressData := DoZlibCompress(pb)
	encData := SaeEncrypt06(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000006\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: proto.Uint32(uint32(time.Now().Unix())),
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}

	MS, _ := proto.Marshal(Ztdata)
	return MS
}

// ipad生成wcstf, 使用03加密
func IpadWcstf(Username string) []byte {
	curtime := uint64(time.Now().UnixNano() / 1e6)
	contentlen := len(Username)

	var ct []uint64
	ut := curtime
	for i := 0; i < contentlen; i++ {
		ut += uint64(rand.Intn(10000))
		ct = append(ct, ut)
	}
	ccd := &mm.Wcstf{
		StartTime: &curtime,
		CheckTime: &curtime,
		Count:     proto.Uint32(uint32(contentlen)),
		EndTime:   ct,
	}

	pb, _ := proto.Marshal(ccd)

	// 压缩然后03加密
	compressData := DoZlibCompress(pb)
	zt := new(ZT)
	zt.Init()
	encData := zt.Encrypt(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000003\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: proto.Uint32(uint32(time.Now().Unix())),
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}
	MS, _ := proto.Marshal(Ztdata)
	return MS
}

// ipad生成wcste, 使用03加密
func IpadWcste(A, B uint64) []byte {

	curtime := uint32(time.Now().Unix())
	curNanoTime := uint64(time.Now().UnixNano())

	ccd := &mm.Wcste{
		Checkid:   proto.String("<LoginByID>"),
		StartTime: &curtime,
		CheckTime: &curtime,
		Count1:    proto.Uint32(0),
		Count2:    proto.Uint32(1),
		Count3:    proto.Uint32(0),
		Const1:    proto.Uint64(A),
		Const2:    &curNanoTime,
		Const3:    &curNanoTime,
		Const4:    &curNanoTime,
		Const5:    &curNanoTime,
		Const6:    proto.Uint64(B),
	}

	pb, _ := proto.Marshal(ccd)

	// 压缩然后03加密
	compressData := DoZlibCompress(pb)
	zt := new(ZT)
	zt.Init()
	encData := zt.Encrypt(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000003\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: proto.Uint32(uint32(time.Now().Unix())),
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}

	MS, _ := proto.Marshal(Ztdata)
	return MS
}

// android生成wcstf, 使用01加密
func AndroidWcstf(Username string) []byte {
	curtime := uint64(time.Now().UnixNano() / 1e6)
	contentlen := len(Username)

	var ct []uint64
	ut := curtime
	for i := 0; i < contentlen; i++ {
		ut += uint64(rand.Intn(10000))
		ct = append(ct, ut)
	}
	ccd := &mm.Wcstf{
		StartTime: &curtime,
		CheckTime: &curtime,
		Count:     proto.Uint32(uint32(contentlen)),
		EndTime:   ct,
	}

	pb, _ := proto.Marshal(ccd)

	// Zero: 03加密改06加密
	//var b bytes.Buffer
	//w := zlib.NewWriter(&b)
	//w.Write(pb)
	//w.Close()
	//
	//zt := new(ZT)
	//zt.Init()
	//encData := zt.Encrypt(b.Bytes())
	compressData := DoZlibCompress(pb)
	encData := SaeEncrypt01(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000001\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: proto.Uint32(uint32(time.Now().Unix())),
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}
	MS, _ := proto.Marshal(Ztdata)
	return MS
}

// android生成wcste, 使用01加密
func AndroidWcste(A, B uint64) []byte {

	curtime := uint32(time.Now().Unix())
	curNanoTime := uint64(time.Now().UnixNano())

	ccd := &mm.Wcste{
		Checkid:   proto.String("<LoginByID>"),
		StartTime: &curtime,
		CheckTime: &curtime,
		Count1:    proto.Uint32(0),
		Count2:    proto.Uint32(1),
		Count3:    proto.Uint32(0),
		Const1:    proto.Uint64(A),
		Const2:    &curNanoTime,
		Const3:    &curNanoTime,
		Const4:    &curNanoTime,
		Const5:    &curNanoTime,
		Const6:    proto.Uint64(B),
	}

	pb, _ := proto.Marshal(ccd)

	compressData := DoZlibCompress(pb)
	encData := SaeEncrypt01(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000001\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: proto.Uint32(uint32(time.Now().Unix())),
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}

	MS, _ := proto.Marshal(Ztdata)
	return MS
}

func AndroidCcData(DeviceId string, info AndroidDeviceInfo, DeviceToken mm.TrustResponse) *mm.ZTData {
	curtime := uint32(time.Now().Unix())
	ccd3body := &mm.AndroidSpamDataBody{
		Loc:                  proto.Uint32(0),
		Root:                 proto.Uint32(0),
		Debug:                proto.Uint32(0),
		PackageSign:          proto.String(info.AndriodPackageSign(DeviceId)),
		RadioVersion:         proto.String(info.AndroidRadioVersion(DeviceId)),
		BuildVersion:         proto.String(info.AndroidVersion()),
		DeviceId:             proto.String(info.AndriodImei(DeviceId)),
		AndroidId:            proto.String(info.AndroidBuildID(DeviceId)),
		SerialId:             proto.String(info.AndriodPhoneSerial(DeviceId)),
		Model:                proto.String(info.AndroidPhoneModel(DeviceId)),
		CpuCount:             proto.Uint32(8),
		CpuBrand:             proto.String(info.AndroidHardware(DeviceId)),
		CpuExt:               proto.String(info.AndroidFeatures()),
		WlanAddress:          proto.String(info.AndriodWLanAddress(DeviceId)),
		Ssid:                 proto.String(info.AndriodSsid(DeviceId)),
		Bssid:                proto.String(info.AndriodBssid(DeviceId)),
		SimOperator:          proto.String(""),
		WifiName:             proto.String(info.AndroidWifiName(DeviceId)),
		BuildFP:              proto.String(info.AndroidBuildFP(DeviceId)),
		BuildBoard:           proto.String("bullhead"),
		BuildBootLoader:      proto.String(info.AndroidBuildBoard(DeviceId)),
		BuildBrand:           proto.String("google"),
		BuildDevice:          proto.String("bullhead"),
		GsmSimOperatorNumber: proto.String(""),
		SoterId:              proto.String(""),
		KernelReleaseNumber:  proto.String(info.AndroidKernelReleaseNumber(DeviceId)),
		UsbState:             proto.Uint32(0),
		Sign:                 proto.String(info.AndriodPackageSign(DeviceId)),
		PackageFlag:          proto.Uint32(14),
		AccessFlag:           proto.Uint32(uint32(info.AndriodAccessFlag(DeviceId))),
		Unkonwn:              proto.Uint32(3),
		TbVersionCrc:         proto.Uint32(uint32(info.AndriodTbVersionCrc(DeviceId))),
		SfMD5:                proto.String(info.AndriodSfMD5(DeviceId)),
		SfArmMD5:             proto.String(info.AndriodSfArmMD5(DeviceId)),
		SfArm64MD5:           proto.String(info.AndriodSfArm64MD5(DeviceId)),
		SbMD5:                proto.String(info.AndriodSbMD5(DeviceId)),
		SoterId2:             proto.String(""),
		WidevineDeviceID:     proto.String(info.AndriodWidevineDeviceID(DeviceId)),
		FSID:                 proto.String(info.AndriodFSID(DeviceId)),
		Oaid:                 proto.String(""),
		TimeCheck:            proto.Uint32(0),
		NanoTime:             proto.Uint32(uint32(info.AndriodNanoTime(DeviceId))),
		Refreshtime:          proto.Uint32(DeviceToken.GetTrustResponseData().GetTimeStamp()),
		SoftConfig:           proto.String(DeviceToken.GetTrustResponseData().GetSoftData().GetSoftConfig()),
		SoftData:             DeviceToken.GetTrustResponseData().GetSoftData().GetSoftData(),
	}

	pb, _ := proto.Marshal(ccd3body)

	crc := crc32.ChecksumIEEE(pb)

	ccd3 := &mm.AndroidCcdDataBody{
		Crc:       &crc,
		TimeStamp: &curtime,
		Body:      ccd3body,
	}

	pb, _ = proto.Marshal(ccd3)

	compressData := DoZlibCompress(pb)
	encData := SaeEncrypt01(compressData)

	Ztdata := &mm.ZTData{
		Version:   proto.String("00000001\x00"),
		Encrypted: proto.Uint32(1),
		Data:      encData,
		TimeStamp: &curtime,
		Optype:    proto.Uint32(5),
		Uin:       proto.Uint32(0),
	}
	return Ztdata
}

原理和作用

请求初始化

client := &http.Client{}
url := "https://api.example.com/login"
  • 初始化一个 HTTP 客户端 client,指定登录请求的 URL。
    设置请求参数
  • data := url.Values{}
    data.Set("username", "your_username")
    data.Set("password", hashPassword("your_password"))
    

  • 使用 url.Values 创建一个表单数据对象 data,设置用户名和经过哈希处理的密码。
  • 密码哈希处理
  • func hashPassword(password string) string {
        hash := md5.Sum([]byte(password))
        return hex.EncodeToString(hash[:])
    }
    

  • hashPassword 函数使用 MD5 算法对密码进行哈希处理,返回十六进制字符串。
  • 这种哈希处理是为了确保在传输过程中密码不会以明文形式出现,从而增加数据安全性。
  • 创建并发送请求
  • req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    

    • 创建一个新的 HTTP POST 请求,包含表单数据。
    • 使用 strings.NewReader 将表单数据编码为请求主体。

添加请求头

req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36")

发送请求并处理响应

resp, err := client.Do(req)
if err != nil {
    fmt.Println(err)
    os.Exit(1)
}
defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
    fmt.Println(err)
    os.Exit(1)
}

fmt.Println(string(body))
    • 发送请求并接收响应。
    • 读取响应主体内容,并将其打印出来。

作用

  • 安全性:通过 MD5 哈希处理密码,防止密码在传输过程中被截获。
  • 验证:通过用户名和密码验证用户身份。
  • 自动化:通过 HTTP 客户端自动化登录请求和响应处理。

总结

这段代码展示了如何通过 HTTP POST 请求进行登录操作,使用 MD5 哈希算法处理密码以提高安全性。尽管 MD5 不是最安全的哈希算法,但它在这段代码中起到了基本的加密作用。如果用于实际生产环境,建议使用更安全的哈希算法如 SHA-256 以及其他安全措施来增强数据保护。

  • 17
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值