-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpatch_agy_va39.py
More file actions
executable file
·124 lines (103 loc) · 3.6 KB
/
Copy pathpatch_agy_va39.py
File metadata and controls
executable file
·124 lines (103 loc) · 3.6 KB
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
#!/usr/bin/env python3
import hashlib
import shutil
import struct
import sys
from pathlib import Path
src = Path(sys.argv[1] if len(sys.argv) > 1 else str(Path.home() / ".local/bin/agy"))
dst = Path(str(src) + ".va39")
if not src.exists():
raise SystemExit(f"Input binary does not exist: {src}")
print(f"Input binary : {src}")
print(f"SHA256 in : {hashlib.sha256(src.read_bytes()).hexdigest()}")
print()
shutil.copyfile(src, dst)
data = bytearray(dst.read_bytes())
def get(off):
return struct.unpack_from("<I", data, off)[0]
def put(off, word):
struct.pack_into("<I", data, off, word)
lo, hi = 0, len(data)
def find_section(name_target):
if data[:4] != b"\x7fELF":
return None, None
e_shoff = struct.unpack_from("<Q", data, 40)[0]
e_shentsize = struct.unpack_from("<H", data, 58)[0]
e_shnum = struct.unpack_from("<H", data, 60)[0]
e_shstrndx = struct.unpack_from("<H", data, 62)[0]
shstr_base = e_shoff + e_shstrndx * e_shentsize
shstr_off = struct.unpack_from("<Q", data, shstr_base + 24)[0]
for i in range(e_shnum):
base = e_shoff + i * e_shentsize
sh_name = struct.unpack_from("<I", data, base)[0]
sh_offset = struct.unpack_from("<Q", data, base + 24)[0]
sh_size = struct.unpack_from("<Q", data, base + 32)[0]
nend = data.index(b"\x00", shstr_off + sh_name)
section = data[shstr_off + sh_name : nend].decode("utf-8", errors="replace")
if section == name_target:
return sh_offset, sh_offset + sh_size
return None, None
sec_lo, sec_hi = find_section("google_malloc")
if sec_lo is not None:
lo, hi = sec_lo, sec_hi
print(f"Found google_malloc section: file 0x{lo:x} - 0x{hi:x} ({(hi - lo) // 1024} KB)")
else:
print("google_malloc section not found - scanning entire binary.")
ubfx_count = 0
lsl_count = 0
for off in range(lo, hi, 4):
w = get(off)
if (w & 0x7F800000) == 0x53000000:
immr = (w >> 16) & 0x3F
imms = (w >> 10) & 0x3F
if immr == 42 and imms == 44:
put(off, (w & ~((0x3F << 16) | (0x3F << 10))) | (35 << 16) | (37 << 10))
ubfx_count += 1
elif immr == 22 and imms == 21:
put(off, (w & ~((0x3F << 16) | (0x3F << 10))) | (29 << 16) | (28 << 10))
lsl_count += 1
mask_count = 0
for off in range(lo, hi - 4, 4):
if get(off) == 0x92D3800A and get(off + 4) == 0xF2E0000A:
put(off, 0x9280000A)
put(off + 4, 0xD35DFD4A)
mask_count += 1
mmap_count = 0
for off in range(lo, hi, 4):
if get(off) == 0xF2E00029:
put(off, 0xD3596129)
mmap_count += 1
word_rewrites = {
0xD2C20009: 0xD2C00409,
0xD2C2000A: 0xD2C0040A,
0xF2C20008: 0xF2DFF408,
0xF2C20009: 0xF2DFF409,
0xD2C10009: 0xD2C00209,
0xD2C1000A: 0xD2C0020A,
0xF2C38008: 0xF2DFF708,
0xF2C38009: 0xF2DFF709,
0x92560A6C: 0x925D0A6C,
0x92560A6A: 0x925D0A6A,
0xD2C3000D: 0xD2C0060D,
0xD2C3000C: 0xD2C0060C,
0xD2C08008: 0xD2C00108,
}
counts = {old: 0 for old in word_rewrites}
for off in range(lo, hi, 4):
w = get(off)
if w in word_rewrites:
put(off, word_rewrites[w])
counts[w] += 1
faccessat2_count = 0
for off in range(0, len(data) - 12, 4):
if (
get(off) == 0xAA1F03E5
and get(off + 4) == 0xAA1F03E6
and get(off + 8) == 0xD28036E0
and (get(off + 12) & 0xFC000000) == 0x94000000
):
put(off + 8, 0xD2800600)
faccessat2_count += 1
dst.write_bytes(data)
dst.chmod(0o755)
print(f"Patches applied: ubfx={ubfx_count}, mask={mask_count}, mmap={mmap_count}, tags={sum(counts.values())}, faccessat2={faccessat2_count}")