mirror of
https://gitlab.com/riglol/rigolee/hdo-tools.git
synced 2025-04-28 18:27:28 +09:00
See https://www.eevblog.com/forum/testgear/hacking-the-hdo1khdo4k-rigol-12-bit-scope/msg4503478/#msg4503478 Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
228 lines
4.3 KiB
Go
228 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/aes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os/user"
|
|
"path/filepath"
|
|
)
|
|
|
|
/*
|
|
0 maybe device ID, not needed to work
|
|
1
|
|
2 lic name string
|
|
3 lic Type "0"
|
|
4 lic time "0"
|
|
5
|
|
*/
|
|
|
|
var keyFile string
|
|
var deviceId string
|
|
|
|
func initCmdline() {
|
|
flag.StringVar(&keyFile, "k", "Key.data", "key file")
|
|
flag.StringVar(&deviceId, "id", "HDO4XXXXXX", "devide Id")
|
|
flag.Parse()
|
|
}
|
|
|
|
func Expand(path string) string {
|
|
if len(path) == 0 || path[0] != '~' {
|
|
return path
|
|
}
|
|
usr, err := user.Current()
|
|
if err != nil {
|
|
return path
|
|
}
|
|
return filepath.Join(usr.HomeDir, path[1:])
|
|
}
|
|
|
|
const delta = 0x9E3779B9
|
|
|
|
func mx(sum uint32, y uint32, z uint32, p uint32, e uint32, k []uint32) uint32 {
|
|
return ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum ^ y) + (k[p&3^e] ^ z))
|
|
}
|
|
|
|
func fixk(k []uint32) []uint32 {
|
|
if len(k) < 4 {
|
|
key := make([]uint32, 4)
|
|
copy(key, k)
|
|
return key
|
|
}
|
|
return k
|
|
}
|
|
|
|
func XXTeaEncrypt(v []uint32, k []uint32) []uint32 {
|
|
length := uint32(len(v))
|
|
n := length - 1
|
|
k = fixk(k)
|
|
var y, z, sum, e, p, q uint32
|
|
z = v[n]
|
|
sum = 0
|
|
for q = 6 + 52/length; q > 0; q-- {
|
|
sum += delta
|
|
e = sum >> 2 & 3
|
|
for p = 0; p < n; p++ {
|
|
y = v[p+1]
|
|
v[p] += mx(sum, y, z, p, e, k)
|
|
z = v[p]
|
|
}
|
|
y = v[0]
|
|
v[n] += mx(sum, y, z, p, e, k)
|
|
z = v[n]
|
|
}
|
|
return v
|
|
}
|
|
|
|
func XXTeaDecrypt(v []uint32, k []uint32) []uint32 {
|
|
length := uint32(len(v))
|
|
n := length - 1
|
|
k = fixk(k)
|
|
var y, z, sum, e, p, q uint32
|
|
y = v[0]
|
|
q = 6 + 52/length
|
|
for sum = q * delta; sum != 0; sum -= delta {
|
|
e = sum >> 2 & 3
|
|
for p = n; p > 0; p-- {
|
|
z = v[p-1]
|
|
v[p] -= mx(sum, y, z, p, e, k)
|
|
y = v[p]
|
|
}
|
|
z = v[n]
|
|
v[0] -= mx(sum, y, z, p, e, k)
|
|
y = v[0]
|
|
}
|
|
return v
|
|
}
|
|
|
|
func HexString(data []byte) string {
|
|
var buf bytes.Buffer
|
|
for i := 0; i < len(data)-1; i++ {
|
|
buf.WriteString(fmt.Sprintf("%02X ", data[i]))
|
|
}
|
|
buf.WriteString(fmt.Sprintf("%02X", data[len(data)-1]))
|
|
return buf.String()
|
|
}
|
|
|
|
func HexStringS(data []byte, sep string) string {
|
|
var buf bytes.Buffer
|
|
for i := 0; i < len(data)-1; i++ {
|
|
buf.WriteString(fmt.Sprintf("%02X%s", data[i], sep))
|
|
}
|
|
buf.WriteString(fmt.Sprintf("%02X", data[len(data)-1]))
|
|
return buf.String()
|
|
}
|
|
|
|
func HexStringLsb(data []byte, sep string) string {
|
|
var buf bytes.Buffer
|
|
for i := 0; i < len(data)-1; i++ {
|
|
buf.WriteString(fmt.Sprintf("%02x%s", (data[i]<<4)|(data[i]>>4), sep))
|
|
}
|
|
t := data[len(data)-1]
|
|
buf.WriteString(fmt.Sprintf("%02x", (t<<4)|(t>>4)))
|
|
return buf.String()
|
|
}
|
|
|
|
func decodeDefaultXXTEA(data []byte) []byte {
|
|
k := []uint32{0x03920001, 0x08410841, 0x18C32104, 0x318639C7}
|
|
N := len(data)
|
|
u32 := make([]uint32, N>>2)
|
|
for i, _ := range u32 {
|
|
u32[i] = binary.LittleEndian.Uint32(data[i*4:])
|
|
}
|
|
u32d := XXTeaDecrypt(u32, k)
|
|
res := make([]uint8, N)
|
|
for i, v := range u32d {
|
|
binary.LittleEndian.PutUint32(res[i*4:], v)
|
|
}
|
|
return res
|
|
}
|
|
|
|
func EncryptLicenseString(key []uint8, str string) (string, error) {
|
|
block, err := aes.NewCipher(key)
|
|
if nil != err {
|
|
return "", err
|
|
}
|
|
x := make([]uint8, 48)
|
|
copy(x, []uint8(str))
|
|
block.Encrypt(x, x)
|
|
block.Encrypt(x[0x10:], x[0x10:])
|
|
block.Encrypt(x[0x20:], x[0x20:])
|
|
return HexStringLsb(x, ""), nil
|
|
}
|
|
|
|
func MakeLicense(key []uint8, deviceId, feature string) string {
|
|
s := fmt.Sprintf("%s#0#%s#4#0#0", deviceId, feature)
|
|
res, err := EncryptLicenseString(key, s)
|
|
if nil != err {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("HDO4000-%s@%s", feature, res)
|
|
}
|
|
|
|
func LoadKeys() ([]uint8, error) {
|
|
data, err := ioutil.ReadFile(Expand(keyFile))
|
|
if nil != err {
|
|
return nil, err
|
|
}
|
|
dd := decodeDefaultXXTEA(data)
|
|
i := bytes.Index(dd, []uint8(";"))
|
|
if -1 == i {
|
|
return nil, errors.New("key format error")
|
|
}
|
|
fmt.Printf("Key: %v\n", string(dd))
|
|
return dd[i+1:], nil
|
|
|
|
}
|
|
|
|
// BND
|
|
// MSO
|
|
// COMP
|
|
// EMBD
|
|
// AUTO
|
|
// FLEX
|
|
// AUDIO
|
|
// AERO
|
|
// ARINC
|
|
// DG
|
|
// JITTER
|
|
// EYE
|
|
// RTSA
|
|
// CM_USB
|
|
// CM_ENET
|
|
// CM_IPI
|
|
// CM_HDMI
|
|
// PWR
|
|
// UPA
|
|
// RLU
|
|
// BODE
|
|
// BW7T10
|
|
// BW7T20
|
|
// BW100T20
|
|
// BW2T4
|
|
// BW2T8
|
|
// BW4T8
|
|
// COUNT
|
|
// UNKNOWN
|
|
|
|
var options []string = []string{"EMBD", "AUTO", "BW2T8", "COMP", "AERO", "FLEX", "AUDIO", "RLU", "UPA"}
|
|
|
|
func main() {
|
|
initCmdline()
|
|
k, err := LoadKeys()
|
|
if nil != err {
|
|
fmt.Printf("error %v\n", err)
|
|
return
|
|
}
|
|
fmt.Printf("Generating options for %s\n", deviceId)
|
|
for _, o := range options {
|
|
lic := MakeLicense(k[0:32], deviceId, o)
|
|
fmt.Printf(":SYST:OPT:INST %v\n", lic)
|
|
}
|
|
|
|
}
|