-
Notifications
You must be signed in to change notification settings - Fork 26
/
bruteForcePinFromCsv.cs
144 lines (121 loc) · 4.88 KB
/
bruteForcePinFromCsv.cs
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
/*
Original algorithm by Wouter Bokslag & Jason F. <https://github.com/prototux>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License at <http://www.gnu.org/licenses/> for
more details.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class Program
{
public static Int32 transform(int data, int[] sec)
{
Int32 result = ((data % sec[0]) * sec[2]) - ((data / sec[0]) * sec[1]);
if (result < 0)
result += (sec[0] * sec[2]) + sec[1];
return result;
}
public static string getKey(string seedTXT, string appKeyTXT)
{
Int32 result;
string[] seed = { seedTXT.Substring(0, 2), seedTXT.Substring(2, 2), seedTXT.Substring(4, 2), seedTXT.Substring(6, 2) };
string[] appKey = { appKeyTXT.Substring(0, 2), appKeyTXT.Substring(2, 2) };
// Hardcoded secrets
int[] sec_1 = { 0xB2, 0x3F, 0xAA };
int[] sec_2 = { 0xB1, 0x02, 0xAB };
// Compute each 16b part of the response, with the twist, and return it
Int32 res_msb = transform(Int16.Parse(appKey[0] + appKey[1], System.Globalization.NumberStyles.HexNumber), sec_1) | transform(Int16.Parse(seed[0] + seed[3], System.Globalization.NumberStyles.HexNumber), sec_2);
Int32 res_lsb = transform(Int16.Parse(seed[1] + seed[2], System.Globalization.NumberStyles.HexNumber), sec_1) | transform(res_msb, sec_2);
result = (res_msb << 16) | res_lsb;
return result.ToString("X8");
}
public static void Main(string[] args)
{
if (args.Any() && File.Exists(args[0]))
{
BruteForcePinFromCsv(args[0]);
}
else
{
Console.WriteLine("You need to pass a csv file as an argument");
}
Console.WriteLine("Press [Enter] to close...");
Console.ReadLine();
}
private static bool IsPinValid(string challenge, string response, int possiblePin)
{
var key = getKey(challenge, possiblePin.ToString("X4"));
return key.Equals(response, StringComparison.InvariantCultureIgnoreCase);
}
/*
* file is a csv file which contains challenge response pairs separated by ; or , character
*/
private static void BruteForcePinFromCsv(string file)
{
var possiblePins = new List<int>();
var fileContent = File.ReadAllLines(file);
var pin = 0;
var lineCounter = 0;
//first round collect all valid pins for all of the challenge-response pairs
foreach (var line in fileContent)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
lineCounter++;
var csvLine = line.Replace(" ", string.Empty).Replace(",", ";").Split(';');
while (pin < 65536)
{
var challenge = csvLine[0];
var response = csvLine[1];
if (IsPinValid(challenge, response, pin))
{
possiblePins.Add(pin);
}
pin++;
}
}
var validPinCounter = new Dictionary<string, int>();
foreach (var possiblePin in possiblePins)
{
foreach (var line in fileContent)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
var csvLine = line.Replace(" ", string.Empty).Replace(",", ";").Split(';');
var challenge = csvLine[0];
var response = csvLine[1];
if (!IsPinValid(challenge, response, possiblePin))
{
if (validPinCounter.ContainsKey(possiblePin.ToString("X4")))
{
validPinCounter.Remove(possiblePin.ToString("X4"));
}
}
else
{
if (!validPinCounter.ContainsKey(possiblePin.ToString("X4")))
{
validPinCounter[possiblePin.ToString("X4")] = 0;
}
validPinCounter[possiblePin.ToString("X4")] = validPinCounter[possiblePin.ToString("X4")] + 1;
}
}
}
var pins = validPinCounter.Where(x => x.Value == lineCounter).Select(x => x.Key);
Console.WriteLine("Valid pins: " + string.Join(", ", pins));
}
}