summaryrefslogtreecommitdiffstats
path: root/crack-qr-uri.go
blob: f222ecf028498c2d7020674605633884e02c2a4e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"flag"
	"fmt"
	"golang.org/x/crypto/pbkdf2"
	"net/url"
	"os"
	"reflect"
	"strconv"
	"strings"
)

func main() {
	var uri = flag.String("uri", "", "Example: igmobileotp://?action=secactivate&enc=VRUq6IoLWQRCMRITZEHtHUSWJiPwgu%2FN1BFyUHE5kxuHIEYoE3zmNTrAHeeUM5S3gzCnTy%2F%2Bdnbu%2FsjjQW%2BNEISx8C4ra8rLpxOl8E8w4KXHgjeBRgdvSzl%2BbzX5RYRrQlWgK8hsBT4pQYE0eFgW2TmRbzXu1Mu7XjKDcwsJLew32jQC2qyPLP8hljnv2rHwwsMfhQwgJUJYfctwLWWEDUFukEckaZ4O&v=1&mac=mhVL8BWKaishMa5%2B")
	var threadsPtr = flag.Int("threads", 4, "Number of threads to use. Set to ncores, or ncores - 1. Load is 100% CPU")

	flag.Parse()

	threads := *threadsPtr

	if *uri == "" {
		panic("Specify a URI")
	}

	obj, err := url.Parse(*uri)
	if err != nil {
		panic(err)
	}

	if obj.Scheme != "igmobileotp" {
		fmt.Println("Only the scheme igmobileotp is currently supported")
	}

	// Parse the query string component
	q := obj.Query()

	if (len(q["action"]) != 1) || (q["action"][0] != "secactivate") {
		fmt.Println("Only the secactivate action is currently supported")
	}

	// Validate the encrypted data really exists
	if len(q["enc"]) != 1 {
		panic("No enc provided")
	}

	// Validate we have a MAC that we can verify decryption with
	if len(q["mac"]) != 1 {
		panic("No mac provided")
	}
	mac, err := base64.StdEncoding.DecodeString(q["mac"][0])
	if err != nil {
		panic(err)
	}

	// Decode the enc paramater
	enc, err := base64.StdEncoding.DecodeString(q["enc"][0])
	if err != nil {
		panic(err)
	}

	// Extract out the payload that is used for HMAC validation
	from := strings.Index(*uri, "?") + 1 // 1 more, because the ?
	to := strings.LastIndex(*uri, "&")
	hmacPayload := (*uri)[from:to]

	fmt.Println(hmacPayload)

	// Farm the work out to threads
	passwords := make(chan []byte)
	doner := make(chan bool, threads)

	for i := 0; i < threads; i++ {
		go checkPassword(enc[0:8], []byte(hmacPayload), mac, passwords, doner)
	}

	//for i := 54998317; i < 54998318; i++ {
	for i := 0; i < 99999999; i++ {
		passwords <- []byte(strconv.Itoa(i))
	}

	close(passwords)

	for i := 0; i < threads; i++ {
		<-doner
	}

	fmt.Println("Password was not found. Is your URI corrupted?")
	os.Exit(1)

}

func checkPassword(salt []byte, macedPayload []byte, macValue []byte, passwords <-chan []byte, doner chan<- bool) {
	for password := range passwords {
		dk := pbkdf2.Key(password, salt, 1000, 64, sha256.New)

		// Validate whether the key is correct with a HMAC verification
		hmacKey := dk[16:48]

		macer := hmac.New(sha256.New, hmacKey)
		macer.Write(macedPayload)
		calculatedMac := macer.Sum(nil)

		if reflect.DeepEqual(calculatedMac[0:12], macValue) {
			// Success!
			fmt.Println("Password found: ", string(password))
			os.Exit(0)
		}
	}

	doner <- true
}