diff --git a/ddp_example.go b/ddp_example.go new file mode 100644 index 0000000..ea5c001 --- /dev/null +++ b/ddp_example.go @@ -0,0 +1,103 @@ +// Dynamic decryption procedure example - (c) 2005 - 2006 Omar A. Herrera Reyna +// This code is released under GNU General Public License v3.0 +// +// The following Go program illustrates an implementation of a DDP. +// It mirrors the original C example but uses Go's standard libraries. +// The encrypted payload is decrypted only when the key derived from +// the current UTC hour, month and year matches the expected value. +// When successful, the program prints the decrypted bytes. +// Note: Executing the decrypted bytes as code is not included here. + +package main + +import ( + "crypto/cipher" + "crypto/md5" + "encoding/hex" + "fmt" + "golang.org/x/crypto/blowfish" + "time" +) + +const ( + scodeSize = 172 + 8 +) + +var ( + keyXOR = [8]byte{0x0F, 0x20, 0x6A, 0x04, 0x10, 0x0D, 0x6E, 0x08} + scodeMD5 = [16]byte{0x81, 0xED, 0xD3, 0x62, 0xC6, 0xE3, 0x89, 0x4F, + 0xD5, 0xA5, 0x6C, 0x95, 0xCE, 0x55, 0x25, 0xE0} + encryptedPayload = []byte{ + 0xD7, 0x5A, 0x9A, 0x75, 0x12, 0x8C, 0x44, 0xC0, 0xC3, 0xEB, 0xBC, 0x32, 0x86, 0xD8, 0xB2, 0xD4, + 0xAF, 0xB6, 0x36, 0xB4, 0x24, 0x4D, 0x7F, 0x2F, 0x6D, 0x70, 0x32, 0xA7, 0xDD, 0xCC, 0xAB, 0x0C, + 0x5F, 0x9E, 0x79, 0x26, 0x70, 0xA5, 0x6F, 0xAC, 0xB4, 0xB6, 0x71, 0x13, 0xBE, 0xDB, 0xDA, 0x0F, + 0xAD, 0x1C, 0x10, 0x8D, 0x31, 0x18, 0x34, 0x5E, 0xEA, 0x74, 0xC7, 0xD2, 0x55, 0x86, 0xB8, 0xFA, + 0x40, 0x47, 0x0E, 0x78, 0xA5, 0xAB, 0x45, 0x8E, 0x08, 0x0C, 0xDA, 0x68, 0xD6, 0x42, 0x54, 0x99, + 0xE6, 0x54, 0xA1, 0xFC, 0x48, 0xAB, 0xBA, 0x9E, 0x62, 0x6D, 0x52, 0x3C, 0x49, 0xCA, 0x2A, 0xAB, + 0x63, 0x0B, 0xCD, 0x1A, 0x3C, 0xF7, 0x15, 0x2E, 0xB1, 0x4D, 0x15, 0x11, 0xEA, 0x78, 0x27, 0x3B, + 0x33, 0x81, 0xD3, 0x9D, 0x8D, 0x9B, 0xE7, 0xBB, 0x0C, 0xC5, 0x97, 0x8C, 0x8E, 0x38, 0x49, 0xE7, + 0xFD, 0xAB, 0x13, 0x28, 0x9F, 0x45, 0xAC, 0x1C, 0xE0, 0x62, 0xC3, 0x82, 0x47, 0xB8, 0x4A, 0xA3, + 0xB0, 0x14, 0x2C, 0xFA, 0xC4, 0xE1, 0x51, 0x6A, 0x15, 0x77, 0xDF, 0xA0, 0x3F, 0x24, 0x98, 0x36, + 0x7B, 0x2D, 0xC2, 0x22, 0x82, 0x76, 0x9A, 0xBC, 0x81, 0xBF, 0x09, 0x01, 0x9C, 0xBE, 0xB2, 0x54, + 0xEB, 0xF2, 0xFC, 0x7D, 0xD1, 0x77, 0x44, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + } +) + +func deriveKey(t time.Time) [8]byte { + var keyTime [8]byte + keyTime[0] = byte(t.Hour()) + keyTime[1] = byte(t.Month() - 1) // tm_mon is 0-based + year := t.Year() - 1900 // tm_year is years since 1900 + keyTime[2] = byte(year) + keyTime[3] = byte(year >> 8) + keyTime[4] = keyTime[0] + keyTime[5] = keyTime[1] + keyTime[6] = keyTime[2] + keyTime[7] = keyTime[3] + + var key [8]byte + for i := 0; i < 8; i++ { + key[i] = keyTime[i] ^ keyXOR[i] + } + return key +} + +func decryptPayload(key [8]byte) ([]byte, error) { + block, err := blowfish.NewCipher(key[:]) + if err != nil { + return nil, err + } + decrypted := make([]byte, len(encryptedPayload)) + iv := make([]byte, blowfish.BlockSize) + mode := cipher.NewCBCDecrypter(block, iv) + paddedLen := ((scodeSize + blowfish.BlockSize - 1) / blowfish.BlockSize) * blowfish.BlockSize + buf := make([]byte, paddedLen) + copy(buf, encryptedPayload[:scodeSize]) + mode.CryptBlocks(decrypted[:paddedLen], buf) + copy(decrypted[paddedLen:], encryptedPayload[paddedLen:]) + return decrypted, nil +} + +func main() { + var decrypted []byte + for { + time.Sleep(10 * time.Second) + key := deriveKey(time.Now().UTC()) + d, err := decryptPayload(key) + if err != nil { + fmt.Println("decrypt error:", err) + continue + } + hash := md5.Sum(d[8:scodeSize]) + if hash == scodeMD5 { + decrypted = d + fmt.Printf("CORRECT KEY = %X\n", key) + break + } + } + + fmt.Println("Encrypted payload:") + fmt.Println(hex.Dump(encryptedPayload)) + fmt.Println("Decrypted payload:") + fmt.Println(hex.Dump(decrypted[8:])) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..52f8750 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module ddp + +go 1.23.8 + +require golang.org/x/crypto v0.39.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9699b43 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=