|
23 | 23 | import ghidra.app.util.importer.MessageLog; |
24 | 24 | import ghidra.framework.options.Options; |
25 | 25 | import ghidra.program.model.address.Address; |
| 26 | +import ghidra.program.model.address.AddressOutOfBoundsException; |
| 27 | +import ghidra.program.model.address.AddressRangeImpl; |
26 | 28 | import ghidra.program.model.address.AddressSet; |
27 | 29 | import ghidra.program.model.address.AddressSetView; |
28 | 30 | import ghidra.program.model.listing.Program; |
@@ -145,8 +147,13 @@ private void processModule(Program program, Address moduleHeader, TaskMonitor mo |
145 | 147 | PointerScanResult pointerScan; |
146 | 148 | var section = directory.getSectionByType(ReadyToRunSection.DEHYDRATED_DATA); |
147 | 149 | if (section == null) { |
148 | | - // TODO: determine pointer scanning range for .NET 7.0 binaries. |
149 | | - throw new UnsupportedOperationException("No dehydrated data found. This is likely .NET 7.0 metadata which is not supported at the moment."); |
| 150 | + // Fallback for .NET 7.0 / 10.0+: Scan memory for pointers manually. |
| 151 | + log.appendMsg(Constants.TAG, "No dehydrated data found. Attempting manual pointer scan."); |
| 152 | + try { |
| 153 | + pointerScan = scanForPointers(program, moduleHeader, monitor, log); |
| 154 | + } catch (Exception ex) { |
| 155 | + throw new Exception("Manual scan failed.", ex); |
| 156 | + } |
150 | 157 | } else { |
151 | 158 | try { |
152 | 159 | // NOTE: Metadata rehydrators should be changed if the file format changes per rtr version. |
@@ -221,4 +228,66 @@ private PointerScanResult rehydrateData(Program program, ReadyToRunSection rehyd |
221 | 228 |
|
222 | 229 | return result; |
223 | 230 | } |
| 231 | + |
| 232 | + private PointerScanResult scanForPointers(Program program, Address moduleHeader, TaskMonitor monitor, MessageLog log) throws CancelledException { |
| 233 | + var memory = program.getMemory(); |
| 234 | + var validAddresses = memory.getLoadedAndInitializedAddressSet(); |
| 235 | + var pointers = new java.util.ArrayList<Address>(); |
| 236 | + |
| 237 | + var moduleBlock = memory.getBlock(moduleHeader); |
| 238 | + if (moduleBlock == null) { |
| 239 | + log.appendMsg(Constants.TAG, "Could not find memory block for module header at " + moduleHeader); |
| 240 | + return new PointerScanResult(new AddressRangeImpl(moduleHeader, moduleHeader), new Address[0]); |
| 241 | + } |
| 242 | + |
| 243 | + // We use the block containing the module header as the scanning range |
| 244 | + var scanningRange = new AddressRangeImpl( |
| 245 | + moduleBlock.getStart(), |
| 246 | + moduleBlock.getEnd() |
| 247 | + ); |
| 248 | + |
| 249 | + monitor.setMessage(Constants.TAG + ": Scanning for pointers..."); |
| 250 | + monitor.setMaximum(moduleBlock.getSize()); |
| 251 | + monitor.setProgress(0); |
| 252 | + |
| 253 | + var start = moduleBlock.getStart(); |
| 254 | + var end = moduleBlock.getEnd(); |
| 255 | + |
| 256 | + // Align start to 8 bytes |
| 257 | + long offset = start.getOffset(); |
| 258 | + if (offset % 8 != 0) { |
| 259 | + start = start.add(8 - (offset % 8)); |
| 260 | + } |
| 261 | + |
| 262 | + while (start.compareTo(end) <= 0) { |
| 263 | + monitor.checkCancelled(); |
| 264 | + monitor.setProgress(start.getOffset() - moduleBlock.getStart().getOffset()); |
| 265 | + |
| 266 | + // Read 64-bit value |
| 267 | + try { |
| 268 | + long value = memory.getLong(start); |
| 269 | + |
| 270 | + // Simple heuristic: If the value is an address that exists in memory, it's a candidate pointer. |
| 271 | + // This includes pointers to code (VTable slots) and pointers to data (RelatedType, Interfaces). |
| 272 | + if (validAddresses.contains(start.getNewAddress(value))) { |
| 273 | + pointers.add(start); |
| 274 | + } |
| 275 | + } catch (MemoryAccessException e) { |
| 276 | + // Ignore read errors |
| 277 | + } |
| 278 | + |
| 279 | + try { |
| 280 | + start = start.add(8); |
| 281 | + } catch(AddressOutOfBoundsException e) { |
| 282 | + break; |
| 283 | + } |
| 284 | + } |
| 285 | + |
| 286 | + log.appendMsg(Constants.TAG, "Found " + pointers.size() + " candidate pointers."); |
| 287 | + |
| 288 | + return new PointerScanResult( |
| 289 | + scanningRange, |
| 290 | + pointers.toArray(Address[]::new) |
| 291 | + ); |
| 292 | + } |
224 | 293 | } |
0 commit comments