-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApplyExtHeader.java
More file actions
117 lines (108 loc) · 4.81 KB
/
ApplyExtHeader.java
File metadata and controls
117 lines (108 loc) · 4.81 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
//@category 3DS
import ghidra.app.script.GhidraScript;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.mem.MemoryBlockException;
import util.ExHeader;
import util.SegmentBlock;
import util.SegmentOffset;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
public class ApplyExtHeader extends GhidraScript {
@Override
protected void run() throws Exception {
File exhFile = askFile("Import extended header", "OK");
ExHeader exh = new ExHeader(exhFile, currentProgram.getMinAddress().getAddressSpace());
SegmentBlock[] segments = exh.getSegments();
Memory memory = currentProgram.getMemory();
MemoryBlock[] blocks = memory.getBlocks();
// Double check all segments are proper already
Set<SegmentBlock> segmentsToFind = new HashSet<>(Arrays.asList(segments));
for (MemoryBlock block : blocks) {
// Does this block correspond to a segment?
SegmentBlock[] segs = segmentsToFind.stream().filter(s ->
(s.getStart() == block.getStart()) &&
(s.getEnd() == block.getEnd()))
.toArray(SegmentBlock[]::new);
if (segs.length >= 1) {
segmentsToFind.remove(segs[0]);
} else {
// Missing at least one block
break;
}
}
// If all segments found, we're good - don't change anything
if (segmentsToFind.isEmpty()) return;
// If not all segments found, we need to join/split/etc.
// Join all blocks
for (int i = 0; i < blocks.length - 1; i++) {
int I = i;
MemoryBlock nextBlock = Arrays.stream(blocks)
.filter(b -> b.getStart().compareTo(blocks[I].getStart()) > 0)
.min(Comparator.naturalOrder()).get();
try {
// If adjacent, join the two
memory.join(blocks[I], nextBlock);
} catch (MemoryBlockException e) {
// If no adjacent block, make a new block in between and join the three
long size = nextBlock.getStart().subtract(blocks[I].getEnd().add(1));
byte[] zeros = new byte[(int) size];
MemoryBlock temp = createMemoryBlock(
"temp", blocks[I].getEnd().add(1), zeros, false);
memory.join(temp, nextBlock);
memory.join(blocks[I], temp);
}
}
currentProgram.setImageBase(toAddr(0x100000), true);
// Split according to segment info
for (SegmentBlock seg : Arrays.stream(segments)
.sorted(Comparator.comparing(SegmentBlock::getStart))
.toArray(SegmentBlock[]::new)) {
if (seg.getSize() <= 0) continue;
MemoryBlock curBlock = memory.getBlock(seg.getStart());
if (curBlock == null) {
// Must create block
memory.createBlock(memory.getBlocks()[0],
seg.idAsString(), seg.getStart(), seg.getSize());
continue;
} else {
// Split start if necessary
if (curBlock.getStart().compareTo(seg.getStart()) < 0) {
memory.split(curBlock, seg.getStart());
curBlock = memory.getBlock(seg.getStart());
}
// Split end if necessary
if (curBlock.getEnd().add(1).compareTo(seg.getEnd()) > 0) {
if (!curBlock.contains(seg.getEnd())) {
// Need to make a new block, then join
MemoryBlock temp = memory.createBlock(
curBlock,
"temp",
curBlock.getEnd().add(1),
seg.getSize() - curBlock.getSize());
memory.join(curBlock, temp);
} else {
memory.split(curBlock, seg.getEnd());
}
}
}
// Set Read-Write-Execute
switch (SegmentOffset.ID.values()[seg.getID()]) {
case TEXT -> curBlock.setPermissions(true, false, true);
case RODATA -> curBlock.setPermissions(true, false, false);
case DATA, BSS -> curBlock.setPermissions(true, true, true);
case INVALID -> throw new Exception("Unknown segment type!");
}
curBlock.setName(seg.idAsString());
}
// Remove any gaps in between
for (MemoryBlock block : memory.getBlocks()) {
if (block.getName().contains("split")) {
memory.removeBlock(block, monitor);
}
}
}
}