resedit 1.7.3 → 1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/resedit.rb +10 -4
- data/lib/resedit/app/mz_command.rb +15 -6
- data/lib/resedit/classes/changeable.rb +27 -13
- data/lib/resedit/classes/config.rb +35 -0
- data/lib/resedit/{mz/mzenv.rb → classes/env.rb} +30 -15
- data/lib/resedit/classes/exefile.rb +339 -0
- data/lib/resedit/classes/hexwriter.rb +7 -15
- data/lib/resedit/mz/bw.rb +67 -0
- data/lib/resedit/mz/le.rb +234 -0
- data/lib/resedit/mz/multiexe.rb +85 -0
- data/lib/resedit/mz/mz.rb +231 -124
- metadata +8 -5
- data/lib/resedit/mz/mz_body.rb +0 -145
- data/lib/resedit/mz/mz_header.rb +0 -200
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resedit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.8'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bjfn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11
|
11
|
+
date: 2017-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chunky_png
|
@@ -70,6 +70,9 @@ files:
|
|
70
70
|
- lib/resedit/app/text_convert.rb
|
71
71
|
- lib/resedit/classes/changeable.rb
|
72
72
|
- lib/resedit/classes/colorizer.rb
|
73
|
+
- lib/resedit/classes/config.rb
|
74
|
+
- lib/resedit/classes/env.rb
|
75
|
+
- lib/resedit/classes/exefile.rb
|
73
76
|
- lib/resedit/classes/hexwriter.rb
|
74
77
|
- lib/resedit/convert/bitconv.rb
|
75
78
|
- lib/resedit/convert/bitstream.rb
|
@@ -80,10 +83,10 @@ files:
|
|
80
83
|
- lib/resedit/image/image.rb
|
81
84
|
- lib/resedit/image/image_factory.rb
|
82
85
|
- lib/resedit/image/png_image.rb
|
86
|
+
- lib/resedit/mz/bw.rb
|
87
|
+
- lib/resedit/mz/le.rb
|
88
|
+
- lib/resedit/mz/multiexe.rb
|
83
89
|
- lib/resedit/mz/mz.rb
|
84
|
-
- lib/resedit/mz/mz_body.rb
|
85
|
-
- lib/resedit/mz/mz_header.rb
|
86
|
-
- lib/resedit/mz/mzenv.rb
|
87
90
|
- lib/resedit/text/conv_keybru.rb
|
88
91
|
- lib/resedit/text/conv_table.rb
|
89
92
|
- lib/resedit/text/escaper.rb
|
data/lib/resedit/mz/mz_body.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
require 'resedit/classes/changeable'
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'crabstone'
|
5
|
-
include Crabstone
|
6
|
-
$nocrabstone = false
|
7
|
-
rescue LoadError
|
8
|
-
$nocrabstone = true
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
module Resedit
|
13
|
-
|
14
|
-
class MZBody < Changeable
|
15
|
-
|
16
|
-
attr_reader :segments, :appSeg, :mz
|
17
|
-
|
18
|
-
def initialize(mz, file, size)
|
19
|
-
@mz = mz
|
20
|
-
super(file, size)
|
21
|
-
@segments = nil
|
22
|
-
@addsz = 0
|
23
|
-
end
|
24
|
-
|
25
|
-
def reloadSegments()
|
26
|
-
@segments = Set.new()
|
27
|
-
for i in 0..@mz.header.info[:NumberOfRelocations]-1
|
28
|
-
r = @mz.header.getRelocation(i)
|
29
|
-
@segments.add(r[1])
|
30
|
-
sd = segData(r, 2)
|
31
|
-
next if !sd
|
32
|
-
val = sd.unpack('v')[0]
|
33
|
-
@segments.add(val)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def patchRelocs(add)
|
38
|
-
@segments = Set.new()
|
39
|
-
for i in 0..@mz.header.info[:NumberOfRelocations]-1
|
40
|
-
r = @mz.header.getRelocation(i)
|
41
|
-
@segments.add(r[1])
|
42
|
-
ofs = seg2Linear(r[0], r[1])
|
43
|
-
val = getData(ofs, 2).unpack('v')[0] + add
|
44
|
-
fix(ofs, [val].pack('v'))
|
45
|
-
@segments.add(val)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def seg2Linear(a,s) (s << 4) + a end
|
50
|
-
|
51
|
-
def seg4Linear(linear)
|
52
|
-
linear >>= 4
|
53
|
-
reloadSegments() if !@segments
|
54
|
-
min = @segments.sort.reverse.find{|e| e <= linear}
|
55
|
-
return min ? min : 0
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
def linear2seg(linear, inSegments=nil)
|
60
|
-
inSegments = [seg4Linear(linear)] if !inSegments
|
61
|
-
res = []
|
62
|
-
inSegments.each{|s|
|
63
|
-
raise sprintf("Linear %X less than segment %04X", inSegments[0], s) if linear < (s<<4)
|
64
|
-
a = linear - (s << 4)
|
65
|
-
res += [a,s]
|
66
|
-
}
|
67
|
-
return res
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
def segData(reloc, size, isStr=false)
|
72
|
-
ofs = seg2Linear(reloc[0], reloc[1])
|
73
|
-
return nil if ofs > @root.size()
|
74
|
-
return getData(ofs, size) if !isStr
|
75
|
-
return colVal(ofs, size)
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
def removeAppend()
|
80
|
-
mode(HOW_CHANGED)
|
81
|
-
undo(0) if @root.obuf.length==0
|
82
|
-
@addsz = 0
|
83
|
-
end
|
84
|
-
|
85
|
-
def revert(what)
|
86
|
-
super(what)
|
87
|
-
@addsz = 0
|
88
|
-
end
|
89
|
-
|
90
|
-
def append(bytes, where=nil)
|
91
|
-
mode(HOW_CHANGED)
|
92
|
-
relfix = @mz.header.relocFix
|
93
|
-
res = @addsz
|
94
|
-
buf = @addsz>0 ? @root.nbuf[0, @addsz] : ''
|
95
|
-
buf += bytes
|
96
|
-
removeAppend()
|
97
|
-
@addsz = buf.length
|
98
|
-
sz = @mz.header.rebuildHeader(@addsz)
|
99
|
-
insert(0, bytes + "\x00"*(sz-@addsz))
|
100
|
-
seg = linear2seg(res)
|
101
|
-
res = [res, seg, sz/0x10]
|
102
|
-
patchRelocs(sz/0x10 - relfix)
|
103
|
-
return res
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
def print(what, how)
|
108
|
-
if what=="header"
|
109
|
-
reloadSegments() if !@segments
|
110
|
-
puts "Known segments: " + @segments.sort.map{ |i| sprintf('%04X',i) }.join(", ")
|
111
|
-
return true
|
112
|
-
end
|
113
|
-
@realOfs = @mz.header.headerSize()
|
114
|
-
return super(what, how)
|
115
|
-
end
|
116
|
-
|
117
|
-
|
118
|
-
def dasm(ofs, size, how)
|
119
|
-
raise "Crabstone gem required to disasm." if $nocrabstone
|
120
|
-
mode(parseHow(how))
|
121
|
-
cs = Disassembler.new(ARCH_X86, MODE_16)
|
122
|
-
begin
|
123
|
-
while true
|
124
|
-
begin
|
125
|
-
d = getData(ofs,size)
|
126
|
-
cs.disasm(d, ofs).each {|i|
|
127
|
-
seg = linear2seg(i.address)
|
128
|
-
bts = i.bytes.map { |b| sprintf("%02X",b) }.join
|
129
|
-
inst = colStr(sprintf("%14s\t%s\t%s", bts, i.mnemonic, i.op_str), changed?(i.address, i.bytes.length))
|
130
|
-
printf("%08X %04X:%04X%s\n",i.address, seg[1], seg[0], inst)
|
131
|
-
}
|
132
|
-
break
|
133
|
-
rescue
|
134
|
-
ofs-=1
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
ensure
|
139
|
-
cs.close()
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|
data/lib/resedit/mz/mz_header.rb
DELETED
@@ -1,200 +0,0 @@
|
|
1
|
-
require 'resedit/classes/changeable'
|
2
|
-
|
3
|
-
module Resedit
|
4
|
-
|
5
|
-
class MZHeader < Changeable
|
6
|
-
MAGIC = 0x5a4D
|
7
|
-
BLK = 0x200
|
8
|
-
PARA = 0x10
|
9
|
-
HSIZE = 0x1C
|
10
|
-
HDRDESCR = [:Magic, :BytesInLastBlock, :BlocksInFile, :NumberOfRelocations, :HeaderParagraphs, :MinExtraParagraphs, :MaxExtraParagraphs,
|
11
|
-
:SS, :SP, :Checksum, :IP, :CS, :RelocTableOffset, :OverlayNumber]
|
12
|
-
|
13
|
-
attr_reader :info, :mz, :relocFix
|
14
|
-
|
15
|
-
def initialize(mz, file, size)
|
16
|
-
raise "Not MZ file" if size < HSIZE
|
17
|
-
@mz = mz
|
18
|
-
super(file, HSIZE)
|
19
|
-
@fsize = size
|
20
|
-
@_infoOrig = loadInfo()
|
21
|
-
@_info = nil
|
22
|
-
@info = @_infoOrig
|
23
|
-
@relocFix = 0
|
24
|
-
raise "Not MZ file" if MAGIC != @info[:Magic]
|
25
|
-
addData(file, headerSize() - HSIZE)
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
def mode(how)
|
30
|
-
super(how)
|
31
|
-
if @mode == HOW_ORIGINAL
|
32
|
-
@info = @_infoOrig
|
33
|
-
else
|
34
|
-
@_info = loadInfo() if !@_info
|
35
|
-
@info = @_info
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
def change(ofs, bytes)
|
41
|
-
super(ofs, bytes)
|
42
|
-
@_info = nil if (ofs < HSIZE)
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
def loadInfo()
|
47
|
-
v = getData(0, HSIZE).unpack('v*')
|
48
|
-
return HDRDESCR.map.with_index { |x, i| [x, v[i]] }.to_h
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
def setInfo(field, values)
|
53
|
-
raise "Unknown header field #{field}" if !HDRDESCR.include?(field)
|
54
|
-
values = [values] if !values.is_a?(Array)
|
55
|
-
change(HDRDESCR.index(field)*2, values.pack('v*'))
|
56
|
-
end
|
57
|
-
|
58
|
-
def changeSize(size)
|
59
|
-
mode(HOW_CHANGED)
|
60
|
-
mod = size % BLK
|
61
|
-
setInfo(:BytesInLastBlock, [mod, size / BLK + (mod ? 1 : 0)])
|
62
|
-
end
|
63
|
-
|
64
|
-
def setBodySize(size); changeSize(size + headerSize()) end
|
65
|
-
|
66
|
-
def rebuildHeader(codesize)
|
67
|
-
mode(HOW_ORIGINAL)
|
68
|
-
ss = @info[:SS]
|
69
|
-
cs = @info[:CS]
|
70
|
-
sz = fileSize()-headerSize()
|
71
|
-
codesize += PARA - codesize % PARA if codesize % PARA!=0
|
72
|
-
changeSize(sz + codesize + headerSize())
|
73
|
-
paras = codesize / PARA
|
74
|
-
setInfo(:SS, ss+paras)
|
75
|
-
setInfo(:CS, cs+paras)
|
76
|
-
for i in 0..@mz.header.info[:NumberOfRelocations]-1
|
77
|
-
rel = getRelocation(i)
|
78
|
-
rel[1] += paras-@relocFix
|
79
|
-
fix(@info[:RelocTableOffset] + i * 4, rel.pack('vv'))
|
80
|
-
end
|
81
|
-
mode(HOW_CHANGED)
|
82
|
-
@relocFix = paras
|
83
|
-
MZEnv.instance().set(:relocFix, paras.to_s)
|
84
|
-
return codesize
|
85
|
-
end
|
86
|
-
|
87
|
-
def addHeaderSize(size)
|
88
|
-
mode(HOW_CHANGED)
|
89
|
-
paras = size/16 + (size%16 == 0 ? 0 : 1)
|
90
|
-
insert(headerSize(), "\x00" * (paras * PARA))
|
91
|
-
changeSize(fileSize() + paras * PARA)
|
92
|
-
setInfo(:HeaderParagraphs, @info[:HeaderParagraphs] + paras)
|
93
|
-
mode(HOW_CHANGED)
|
94
|
-
end
|
95
|
-
|
96
|
-
def loadChanges(file)
|
97
|
-
super(file)
|
98
|
-
mode(HOW_ORIGINAL)
|
99
|
-
ocs = @info[:CS]
|
100
|
-
mode(HOW_CHANGED)
|
101
|
-
ncs = @info[:CS]
|
102
|
-
@relocFix = ncs - ocs
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
def headerSize()
|
107
|
-
return @info[:HeaderParagraphs] * PARA
|
108
|
-
end
|
109
|
-
|
110
|
-
|
111
|
-
def fileSize()
|
112
|
-
sz = @info[:BlocksInFile] * BLK
|
113
|
-
if @info[:BytesInLastBlock] != 0
|
114
|
-
sz -= BLK - @info[:BytesInLastBlock]
|
115
|
-
end
|
116
|
-
return sz
|
117
|
-
end
|
118
|
-
|
119
|
-
|
120
|
-
def getRelocation(idx)
|
121
|
-
raise "Wrong relocation index " if idx<0 || idx >= @info[:NumberOfRelocations]
|
122
|
-
return getData(@info[:RelocTableOffset] + idx * 4, 4).unpack('vv')
|
123
|
-
end
|
124
|
-
|
125
|
-
def setRelocation(idx, data)
|
126
|
-
raise "Wrong relocation index " if idx<0 || idx >= @info[:NumberOfRelocations]
|
127
|
-
change(@info[:RelocTableOffset] + idx * 4, data.pack('vv'))
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
def freeSpace(middle = false)
|
132
|
-
return @info[:RelocTableOffset] - HSIZE if middle
|
133
|
-
return headerSize() - HSIZE - @info[:NumberOfRelocations] * 4
|
134
|
-
end
|
135
|
-
|
136
|
-
def setSpaceForRelocs(count)
|
137
|
-
add = count - @info[:NumberOfRelocations]
|
138
|
-
return if add<=0
|
139
|
-
add -= freeSpace()/4
|
140
|
-
return if add<=0
|
141
|
-
addHeaderSize(add*4)
|
142
|
-
setInfo(:NumberOfRelocations, count)
|
143
|
-
mode(HOW_CHANGED)
|
144
|
-
end
|
145
|
-
|
146
|
-
def addReloc(ofs)
|
147
|
-
mode(HOW_CHANGED)
|
148
|
-
#check relocation exists
|
149
|
-
for i in 0..@info[:NumberOfRelocations]-1
|
150
|
-
rel = getRelocation(i)
|
151
|
-
if @mz.body.seg2Linear(rel[0], rel[1]) == ofs
|
152
|
-
return false
|
153
|
-
end
|
154
|
-
end
|
155
|
-
#add relocation
|
156
|
-
setSpaceForRelocs(@info[:NumberOfRelocations]+1)
|
157
|
-
val = @mz.body.linear2seg(ofs)
|
158
|
-
setRelocation(@info[:NumberOfRelocations], val)
|
159
|
-
return true
|
160
|
-
end
|
161
|
-
|
162
|
-
def print(what, how)
|
163
|
-
mode(parseHow(how))
|
164
|
-
if what == "header"
|
165
|
-
ofs=0
|
166
|
-
@info.each{|k,v|
|
167
|
-
printf("%20s:\t%s\n", k.to_s, colVal(ofs, 2))
|
168
|
-
ofs+=2
|
169
|
-
}
|
170
|
-
puts
|
171
|
-
fsz = fileSize()
|
172
|
-
hsz = headerSize()
|
173
|
-
s = colStr(sprintf("%d (%X)", fsz,fsz), changed?(2, 4))
|
174
|
-
printf("mz file size: %s\treal file size: %d (0x%X)\n", s, @fsize, @fsize)
|
175
|
-
printf("header size: %s\n", colStr(hsz, changed?(8, 2)))
|
176
|
-
printf("code size: %s\n", colStr(fsz - hsz, @mz.body.changed?(0)))
|
177
|
-
printf("reloc table size: %s\n", colStr(@info[:NumberOfRelocations] * 4, changed?(6, 2)))
|
178
|
-
printf("free space in header: before relocs 0x%X, after relocs 0x%X\n", freeSpace(true), freeSpace())
|
179
|
-
printf("reloc fix: 0x%X\n", @relocFix)
|
180
|
-
return true
|
181
|
-
end
|
182
|
-
@mz.body.mode(@mode)
|
183
|
-
if what == "reloc"
|
184
|
-
ofs = @info[:RelocTableOffset]
|
185
|
-
for i in 0..@info[:NumberOfRelocations]-1
|
186
|
-
s1 = colVal(ofs,2)
|
187
|
-
s2 = colVal(ofs+2,2)
|
188
|
-
s3 = @mz.body.segData(getRelocation(i), 2, true)
|
189
|
-
printf("%08X\t%s:%s\t= %s\n", ofs, s2, s1, s3)
|
190
|
-
ofs += 4
|
191
|
-
end
|
192
|
-
return true
|
193
|
-
end
|
194
|
-
return super(what, how)
|
195
|
-
end
|
196
|
-
|
197
|
-
|
198
|
-
end
|
199
|
-
|
200
|
-
end
|