-
-
Notifications
You must be signed in to change notification settings - Fork 182
/
lockdown_value.go
executable file
·292 lines (268 loc) · 10.2 KB
/
lockdown_value.go
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
package ios
import (
"bytes"
"fmt"
"github.com/Masterminds/semver"
plist "howett.net/plist"
)
// BasebandKeyHashInformationType containing some baseband related
// data directly from the ios device
type BasebandKeyHashInformationType struct {
AKeyStatus int
SKeyHash []byte
SKeyStatus int
}
// NonVolatileRAMType contains some internal device info
// and can be retrieved by getting all values
type NonVolatileRAMType struct {
AutoBoot []byte `plist:"auto-boot"`
BacklightLevel []byte `plist:"backlight-level"`
BootArgs string `plist:"boot-args"`
Bootdelay []byte `plist:"bootdelay"`
ComAppleSystemTz0Size []byte `plist:"com.apple.System.tz0-size"`
OblitBegins []byte `plist:"oblit-begins"`
Obliteration []byte `plist:"obliteration"`
}
// GetAllValuesResponse just the wrapper for AllValuesType
type GetAllValuesResponse struct {
Request string
Value AllValuesType
}
// AllValuesType contains all possible values that can be requested from
// LockDown
type AllValuesType struct {
ActivationState string
ActivationStateAcknowledged bool
BasebandActivationTicketVersion string
BasebandCertID int `plist:"BasebandCertId"`
BasebandChipID int
BasebandKeyHashInformation BasebandKeyHashInformationType
BasebandMasterKeyHash string
BasebandRegionSKU []byte
BasebandSerialNumber []byte
BasebandStatus string
BasebandVersion string
BluetoothAddress string
BoardID int `plist:"BoardId"`
BrickState bool
BuildVersion string
CPUArchitecture string
CarrierBundleInfoArray []interface{}
CertID int
ChipID int
ChipSerialNo []byte
DeviceClass string
DeviceColor string
DeviceName string
DieID int
EthernetAddress string
FirmwareVersion string
FusingStatus int
HardwareModel string
HardwarePlatform string
HasSiDP bool
HostAttached bool
InternationalMobileEquipmentIdentity string
MLBSerialNumber string
MobileEquipmentIdentifier string
MobileSubscriberCountryCode string
MobileSubscriberNetworkCode string
ModelNumber string
NonVolatileRAM NonVolatileRAMType
PartitionType string
PasswordProtected bool
PkHash []byte
ProductName string
ProductType string
ProductVersion string
ProductionSOC bool
ProtocolVersion string
ProximitySensorCalibration []byte
RegionInfo string
SBLockdownEverRegisteredKey bool
SIMStatus string
SIMTrayStatus string
SerialNumber string
SoftwareBehavior []byte
SoftwareBundleVersion string
SupportedDeviceFamilies []int
TelephonyCapability bool
TimeIntervalSince1970 float64
TimeZone string
TimeZoneOffsetFromUTC float64
TrustedHostAttached bool
UniqueChipID uint64
UniqueDeviceID string
UseRaptorCerts bool
Uses24HourClock bool
WiFiAddress string
WirelessBoardSerialNumber string
KCTPostponementInfoPRIVersion string `plist:"kCTPostponementInfoPRIVersion"`
KCTPostponementInfoPRLName int `plist:"kCTPostponementInfoPRLName"`
KCTPostponementInfoServiceProvisioningState bool `plist:"kCTPostponementInfoServiceProvisioningState"`
KCTPostponementStatus string `plist:"kCTPostponementStatus"`
}
type valueRequest struct {
Label string
Key string `plist:"Key,omitempty"`
Request string
Domain string `plist:"Domain,omitempty"`
Value interface{} `plist:"Value,omitempty"`
}
func newGetValue(key string) valueRequest {
data := valueRequest{
Label: "go.ios.control",
Key: key,
Request: "GetValue",
}
return data
}
func newSetValue(key string, domain string, value interface{}) valueRequest {
data := valueRequest{
Label: "go.ios.control",
Key: key,
Domain: domain,
Request: "SetValue",
Value: value,
}
return data
}
// GetValues retrieves a GetAllValuesResponse containing all values lockdown returns
func (lockDownConn *LockDownConnection) GetValues() (GetAllValuesResponse, error) {
err := lockDownConn.Send(newGetValue(""))
if err != nil {
return GetAllValuesResponse{}, err
}
resp, err := lockDownConn.ReadMessage()
if err != nil {
return GetAllValuesResponse{}, err
}
response := getAllValuesResponseFromBytes(resp)
return response, nil
}
// GetProductVersion gets the iOS version of a device
func GetProductVersion(device DeviceEntry) (*semver.Version, error) {
lockdownConnection, err := ConnectLockdownWithSession(device)
if err != nil {
return &semver.Version{}, err
}
defer lockdownConnection.Close()
version, err := lockdownConnection.GetProductVersion()
if err != nil {
return &semver.Version{}, err
}
v, err := semver.NewVersion(version)
return v, err
}
// GetWifiMac gets the static MAC address of the device WiFi.
// note: this does not report the dynamic MAC if you enable the
// "automatic WiFi address" feature.
func GetWifiMac(device DeviceEntry) (string, error) {
lockdownConnection, err := ConnectLockdownWithSession(device)
if err != nil {
return "", err
}
defer lockdownConnection.Close()
wifiMac, err := lockdownConnection.GetValue("WiFiAddress")
if err != nil {
return "", err
}
return wifiMac.(string), err
}
// GetProductVersion returns the ProductVersion of the device f.ex. "10.3"
func (lockDownConn *LockDownConnection) GetProductVersion() (string, error) {
msg, err := lockDownConn.GetValue("ProductVersion")
if err != nil {
return "", fmt.Errorf("Failed getting ProductVersion: %v", err)
}
result, ok := msg.(string)
if !ok {
return "", fmt.Errorf("could not convert response to string: %+v", msg)
}
return result, nil
}
// GetValue gets and returns the string value for the lockdown key
func (lockDownConn *LockDownConnection) GetValue(key string) (interface{}, error) {
lockDownConn.Send(newGetValue(key))
resp, err := lockDownConn.ReadMessage()
response := getValueResponsefromBytes(resp)
return response.Value, err
}
// GetValueForDomain gets and returns the string value for the lockdown key and domain
func (lockDownConn *LockDownConnection) GetValueForDomain(key string, domain string) (interface{}, error) {
gv := newGetValue(key)
gv.Domain = domain
lockDownConn.Send(gv)
resp, err := lockDownConn.ReadMessage()
response := getValueResponsefromBytes(resp)
return response.Value, err
}
// SetValueForDomain sets the string value for the lockdown key and domain. If the device returns an error it will be returned as a go error.
func (lockDownConn *LockDownConnection) SetValueForDomain(key string, domain string, value interface{}) error {
gv := newSetValue(key, domain, value)
lockDownConn.Send(gv)
resp, err := lockDownConn.ReadMessage()
response := getValueResponsefromBytes(resp)
if response.Error != "" {
return fmt.Errorf("Failed setting '%s' to '%s' with err: %s", key, value, response.Error)
}
return err
}
// ValueResponse contains the response for a GetValue or SetValue Request
type ValueResponse struct {
Key string
Request string
Error string
Domain string
Value interface{}
}
func getValueResponsefromBytes(plistBytes []byte) ValueResponse {
decoder := plist.NewDecoder(bytes.NewReader(plistBytes))
var getValueResponse ValueResponse
_ = decoder.Decode(&getValueResponse)
return getValueResponse
}
func getAllValuesResponseFromBytes(plistBytes []byte) GetAllValuesResponse {
decoder := plist.NewDecoder(bytes.NewReader(plistBytes))
var getAllValuesResponse GetAllValuesResponse
_ = decoder.Decode(&getAllValuesResponse)
return getAllValuesResponse
}
// GetValuesPlist returns the full lockdown values response as a map, so it can be converted to JSON easily.
func GetValuesPlist(device DeviceEntry) (map[string]interface{}, error) {
lockdownConnection, err := ConnectLockdownWithSession(device)
if err != nil {
return map[string]interface{}{}, err
}
defer lockdownConnection.Close()
err = lockdownConnection.Send(newGetValue(""))
if err != nil {
return map[string]interface{}{}, err
}
resp, err := lockdownConnection.ReadMessage()
if err != nil {
return map[string]interface{}{}, err
}
plist, err := ParsePlist(resp)
if err != nil {
return map[string]interface{}{}, err
}
plist, ok := plist["Value"].(map[string]interface{})
if !ok {
return plist, fmt.Errorf("Failed converting lockdown response:%+v", plist)
}
return plist, err
}
// GetValues returns all values of deviceInformation from lockdown
func GetValues(device DeviceEntry) (GetAllValuesResponse, error) {
lockdownConnection, err := ConnectLockdownWithSession(device)
if err != nil {
return GetAllValuesResponse{}, err
}
defer lockdownConnection.Close()
allValues, err := lockdownConnection.GetValues()
if err != nil {
return GetAllValuesResponse{}, err
}
return allValues, nil
}