...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package authenticode
18
19 import (
20 "encoding/binary"
21 "errors"
22 "hash"
23 "io"
24 "os"
25 )
26
27
28
29
30 func FixPEChecksum(f *os.File) error {
31 if _, err := f.Seek(0, 0); err != nil {
32 return err
33 }
34 peStart, err := readDosHeader(f, nil)
35 if err != nil {
36 return err
37 }
38 ck := NewPEChecksum(int(peStart))
39 if _, err := f.Seek(0, 0); err != nil {
40 return err
41 }
42 if _, err := io.Copy(ck, f); err != nil {
43 return err
44 }
45 if _, err := f.WriteAt(ck.Sum(nil), peStart+88); err != nil {
46 return err
47 }
48 return nil
49 }
50
51 type peChecksum struct {
52 cksumPos int
53 sum, size uint32
54 odd bool
55 }
56
57
58
59 func NewPEChecksum(peStart int) hash.Hash {
60 var cksumPos int
61 if peStart <= 0 {
62 cksumPos = -1
63 } else {
64 cksumPos = peStart + 88
65 }
66 return &peChecksum{cksumPos: cksumPos}
67 }
68
69 func (peChecksum) Size() int {
70 return 4
71 }
72
73 func (peChecksum) BlockSize() int {
74 return 2
75 }
76
77 func (h *peChecksum) Reset() {
78 h.cksumPos = -1
79 h.sum = 0
80 h.size = 0
81 }
82
83 func (h *peChecksum) Write(d []byte) (int, error) {
84
85 n := len(d)
86 if h.odd {
87 return 0, errors.New("odd write")
88 } else if n%2 != 0 {
89 h.odd = true
90 d2 := make([]byte, n+1)
91 copy(d2, d)
92 d = d2
93 }
94 ckpos := -1
95 if h.cksumPos > n {
96 h.cksumPos -= n
97 } else if h.cksumPos >= 0 {
98 ckpos = h.cksumPos
99 h.cksumPos = -1
100 }
101 sum := h.sum
102 for i := 0; i < n; i += 2 {
103 val := uint32(d[i+1])<<8 | uint32(d[i])
104 if i == ckpos || i == ckpos+2 {
105 val = 0
106 }
107 sum += val
108 sum = 0xffff & (sum + (sum >> 16))
109 }
110 h.sum = sum
111 h.size += uint32(n)
112 return n, nil
113 }
114
115 func (h *peChecksum) Sum(buf []byte) []byte {
116 sum := h.sum
117 sum = 0xffff & (sum + (sum >> 16))
118 sum += h.size
119 d := make([]byte, 4)
120 binary.LittleEndian.PutUint32(d, sum)
121 return append(buf, d...)
122 }
123
View as plain text