forked from elnardu/local-boilerkey
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboilerkey.py
157 lines (115 loc) · 3.78 KB
/
boilerkey.py
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import base64
import json
import os
import sys
try:
import requests
import pyotp
except ImportError:
print("This script requires pyotp and requests packages")
print("Please run 'pip3 install pyotp requests'")
sys.exit(1)
CONFIG_PATH = os.path.dirname(os.path.realpath(__file__)) + "/config.json"
COUNTER_PATH = os.path.dirname(os.path.realpath(__file__)) + "/counter.json"
# DO NOT LOSE YOUR WAAAAAAY!
__license__ = "WTFPL"
__author__ = "Russian election hackers"
__credits__ = ["ITaP", "Mitch Daniels"]
def getActivationData(code):
print("Requesting activation data...")
HEADERS = {"User-Agent": "okhttp/3.11.0"}
PARAMS = {
"app_id": "com.duosecurity.duomobile.app.DMApplication",
"app_version": "2.3.3",
"app_build_number": "323206",
"full_disk_encryption": False,
"manufacturer": "Google",
"model": "Pixel",
"platform": "Android",
"jailbroken": False,
"version": "6.0",
"language": "EN",
"customer_protocol": 1,
}
ENDPOINT = "https://api-1b9bef70.duosecurity.com/push/v2/activation/{}"
res = requests.post(ENDPOINT.format(code), headers=HEADERS, params=PARAMS)
if res.json().get("code") == 40403:
print(
"Invalid activation code."
"Please request a new link in BoilerKey settings."
)
sys.exit(1)
if not res.json()["response"]:
print("Unknown error")
print(res.json())
sys.exit(1)
return res.json()["response"]
def validateLink(link):
try:
assert "m-1b9bef70.duosecurity.com" in link
code = link.split("/")[-1]
assert len(code) == 20
return True, code
except Exception:
return False, None
def createConfig(activationData):
with open(CONFIG_PATH, "w") as f:
json.dump(activationData, f, indent=2)
print("Activation data saved!")
def getConfig():
with open(CONFIG_PATH, "r") as f:
return json.load(f)
def setCounter(number):
with open(COUNTER_PATH, "w") as f:
json.dump({"counter": number}, f, indent=2)
def getCounter():
with open(COUNTER_PATH, "r") as f:
return json.load(f)["counter"]
def generatePassword():
config = getConfig()
counter = getCounter()
hotp = pyotp.HOTP(base64.b32encode(config["hotp_secret"].encode()))
hotpPassword = hotp.at(counter)
if config.get("pin"):
password = "{},{}".format(config.get("pin"), hotpPassword)
else:
password = hotpPassword
setCounter(counter + 1)
return password
def askForInfo():
print(
"""Hello there.
1. Please go to the BoilerKey settings (https://purdue.edu/boilerkey)
and click on 'Set up a new Duo Mobile BoilerKey'
2. Follow the process until you see the qr code
3. Paste the link (https://m-1b9bef70.duosecurity.com/activate/XXXXXXXXXXX)
under the qr code right here and press Enter"""
)
valid = False
while not valid:
link = input()
valid, activationCode = validateLink(link)
if not valid:
print("Invalid link. Please try again")
print(
"""4. (Optional) In order to generate full password (pin,XXXXXX),
script needs your pin. You can leave this empty."""
)
pin = input()
if len(pin) != 4:
pin = ""
print("Invalid pin")
activationData = getActivationData(activationCode)
activationData["pin"] = pin
createConfig(activationData)
setCounter(0)
print("Setup successful!")
print("Here is your password: ", generatePassword())
def main():
if not os.path.isfile(CONFIG_PATH) or not os.path.isfile(COUNTER_PATH):
print("Configuration files not found! Running setup...")
askForInfo()
else:
print(generatePassword())
if __name__ == "__main__":
main()