forked from Velocidex/go-pe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rva.go
69 lines (57 loc) · 1.8 KB
/
rva.go
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
package pe
import "errors"
var (
addressNotFound = errors.New("Address not found")
)
// An RVA resolver maps a VirtualAddress to a file physical
// address. When the physical file is mapped into memory, sections in
// the file are mapped at different memory addresses. Internally the
// PE file contains pointers to those virtual addresses. This means we
// need to convert these pointers to mapped memory back into the file
// so we can read their data. The RVAResolver is responsible for this
// - it is populated from the header's sections.
type Run struct {
VirtualAddress uint32
VirtualEnd uint32
PhysicalAddress uint32
}
type RVAResolver struct {
// For now very simple O(n) search.
Runs []*Run
ImageBase uint64
Is64Bit bool
}
func (self *RVAResolver) GetFileAddress(offset uint32) (uint32, error) {
for _, run := range self.Runs {
if offset >= run.VirtualAddress &&
offset < run.VirtualEnd {
return offset - run.VirtualAddress + run.PhysicalAddress, nil
}
}
return 0, addressNotFound
}
func NewRVAResolver(header *IMAGE_NT_HEADERS) *RVAResolver {
result := &RVAResolver{}
optional_header := header.OptionalHeader()
if optional_header.Magic() == 0x20b {
// It is a 64 bit header
optional_header64 := header.Profile.IMAGE_OPTIONAL_HEADER64(
optional_header.Reader, optional_header.Offset)
result.ImageBase = optional_header64.ImageBase()
result.Is64Bit = true
} else {
result.ImageBase = uint64(header.OptionalHeader().ImageBase())
}
for _, section := range header.Sections() {
if section.SizeOfRawData() == 0 {
continue
}
run := &Run{
VirtualAddress: section.VirtualAddress(),
VirtualEnd: section.VirtualAddress() + section.SizeOfRawData(),
PhysicalAddress: section.PointerToRawData(),
}
result.Runs = append(result.Runs, run)
}
return result
}