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
|
import gdb
gr = gdb.execute
state = {"n": 0, "any": 0, "pend": None, "base": None, "chits": 0, "cleared": 0,
"whits": 0, "wrote": 0}
def u32(a):
return int(gdb.parse_and_eval("*(unsigned int*)0x%x" % a))
def u64(a):
return int(gdb.parse_and_eval("*(unsigned long*)0x%x" % a))
def ioc(d, t, nr, size):
return (d << 30) | (size << 16) | (t << 8) | nr
VIDHEAP = ioc(3, 0x46, 0x4a, 0xb8)
def glbase():
try:
pid = gdb.selected_inferior().pid
for line in open("/proc/%d/maps" % pid):
parts = line.split()
if "libnvidia-eglcore" in line and int(parts[2], 16) == 0:
return int(parts[0].split("-")[0], 16)
except Exception:
pass
return None
class BC(gdb.Breakpoint):
def __init__(self, addr):
super().__init__("*0x%x" % addr, internal=False)
self.silent = True
def stop(self):
state["chits"] += 1
try:
obj = int(gdb.parse_and_eval("$rdi"))
n = int(gdb.parse_and_eval("$rsi"))
cnt = u32(obj + 0x22efc)
for i in range(0, min(cnt, 32)):
p = u64(obj + 0x1428 + i * 8)
if not p:
continue
tgt = p + n * 0x10
try:
v16 = int(gdb.parse_and_eval("*(unsigned short*)0x%x" % (tgt + 0xe)))
if v16 == 0xffff:
gr("set {unsigned short}0x%x = 0" % (tgt + 0xe))
gr("set {unsigned int}0x%x = 0" % tgt)
gr("set {unsigned short}0x%x = 0" % (tgt + 0xc))
state["cleared"] += 1
print("CLEAR#%d obj=0x%x n=0x%x tgt=0x%x" % (state["cleared"], obj, n, tgt), flush=True)
except Exception:
pass
except Exception:
pass
return False
class BW(gdb.Breakpoint):
def __init__(self, addr):
super().__init__("*0x%x" % addr, internal=False)
self.silent = True
def stop(self):
state["whits"] += 1
try:
rbx = int(gdb.parse_and_eval("$rbx"))
sub = u64(rbx + 0x70)
obj2 = u64(sub + 0x58)
off = u32(obj2 + 0x60)
holder = u64(obj2 + 0x58)
base2 = u64(holder + 0x58)
word = base2 + off
val = u32(word)
if state["whits"] <= 6 or val == 0:
print("WORD#%d addr=0x%x val=0x%x" % (state["whits"], word, val), flush=True)
if val == 0:
gr("set {unsigned int}0x%x = 1" % word)
state["wrote"] += 1
except Exception:
pass
return False
class IOC(gdb.Breakpoint):
def __init__(self):
super().__init__("ioctl", internal=False)
self.silent = True
def stop(self):
if state["base"] is None:
b = glbase()
if b:
state["base"] = b
print("GLBASE 0x%x" % b, flush=True)
try:
BC(b + 0xB33D30)
BW(b + 0xDCEBD9)
print("BC-BW-SET", flush=True)
except Exception as e:
print("bpset-fail %s" % e, flush=True)
try:
req = int(gdb.parse_and_eval("$rsi")) & 0xFFFFFFFF
arg = int(gdb.parse_and_eval("$rdx"))
except Exception:
return False
if state["pend"] is not None:
try:
st = u32(state["pend"] + 0x14)
at = u32(state["pend"] + 0x38)
off = u64(state["pend"] + 0x68)
print("PREV149-OUT st=0x%x attr=0x%x off=0x%x" % (st, at, off), flush=True)
except Exception as e:
print("PREV149-STATUS unreadable %s" % e, flush=True)
state["pend"] = None
if req != VIDHEAP:
return False
state["any"] += 1
try:
fn = u32(arg + 0x08)
size = u64(arg + 0x58)
attr = u32(arg + 0x38)
owner = u32(arg + 0x28)
flags = u32(arg + 0x34)
except Exception:
return False
if fn == 2 and size == 0x10000 and (attr & 0xf000) == 0x2000 and owner == 0x474C0000:
state["n"] += 1
print("HIT149 n=%d attr=0x%x flags=0x%x owner=0x%x align=0x%x" % (
state["n"], attr, flags, owner, u64(arg + 0x60)), flush=True)
if state["n"] == 1:
gr("bt 12")
newattr = attr & 0xFFFFCFFF
gr("set {unsigned int}0x%x = 0x%x" % (arg + 0x38, newattr))
print("FLIP149 attr 0x%x -> 0x%x" % (attr, newattr), flush=True)
state["pend"] = arg
return False
try:
IOC()
print("BPS-SET", flush=True)
except Exception as e:
print("bpset-fail %s" % e, flush=True)
gr("set pagination off")
gr("set confirm off")
try:
gr("run")
except Exception as e:
print("runend %s" % e, flush=True)
print("T120-DONE n=%d any=%d chits=%d cleared=%d whits=%d wrote=%d" % (
state["n"], state["any"], state["chits"], state["cleared"],
state["whits"], state["wrote"]), flush=True)
gr("quit")
|