Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7597 | akron1 | 1 | (* |
2 | BSD 2-Clause License |
||
3 | |||
4 | Copyright (c) 2018, 2019, Anton Krotov |
||
5 | All rights reserved. |
||
6 | *) |
||
7 | |||
8 | MODULE PE32; |
||
9 | |||
10 | IMPORT BIN, LISTS, UTILS, WR := WRITER, mConst := CONSTANTS, CHL := CHUNKLISTS; |
||
11 | |||
12 | |||
13 | CONST |
||
14 | |||
15 | SIZE_OF_DWORD = 4; |
||
16 | SIZE_OF_WORD = 2; |
||
17 | |||
18 | SIZE_OF_IMAGE_EXPORT_DIRECTORY = 40; |
||
19 | |||
20 | IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; |
||
21 | |||
22 | IMAGE_SIZEOF_SHORT_NAME = 8; |
||
23 | |||
24 | SIZE_OF_IMAGE_FILE_HEADER* = 20; |
||
25 | |||
26 | SIZE_OF_IMAGE_SECTION_HEADER* = 40; |
||
27 | |||
28 | (* SectionHeader.Characteristics *) |
||
29 | |||
30 | SHC_text = 060000020H; |
||
31 | SHC_data = 0C0000040H; |
||
32 | SHC_bss = 0C00000C0H; |
||
33 | |||
34 | SectionAlignment = 1000H; |
||
35 | FileAlignment = 200H; |
||
36 | |||
37 | |||
38 | TYPE |
||
39 | |||
40 | WORD = WCHAR; |
||
41 | DWORD = INTEGER; |
||
42 | |||
43 | NAME* = ARRAY IMAGE_SIZEOF_SHORT_NAME OF CHAR; |
||
44 | |||
45 | |||
46 | IMAGE_DATA_DIRECTORY = RECORD |
||
47 | |||
48 | VirtualAddress: DWORD; |
||
49 | Size: DWORD |
||
50 | |||
51 | END; |
||
52 | |||
53 | |||
54 | IMAGE_OPTIONAL_HEADER = RECORD |
||
55 | |||
56 | Magic: WORD; |
||
57 | MajorLinkerVersion: BYTE; |
||
58 | MinorLinkerVersion: BYTE; |
||
59 | SizeOfCode: DWORD; |
||
60 | SizeOfInitializedData: DWORD; |
||
61 | SizeOfUninitializedData: DWORD; |
||
62 | AddressOfEntryPoint: DWORD; |
||
63 | BaseOfCode: DWORD; |
||
64 | BaseOfData: DWORD; |
||
65 | ImageBase: DWORD; |
||
66 | SectionAlignment: DWORD; |
||
67 | FileAlignment: DWORD; |
||
68 | MajorOperatingSystemVersion: WORD; |
||
69 | MinorOperatingSystemVersion: WORD; |
||
70 | MajorImageVersion: WORD; |
||
71 | MinorImageVersion: WORD; |
||
72 | MajorSubsystemVersion: WORD; |
||
73 | MinorSubsystemVersion: WORD; |
||
74 | Win32VersionValue: DWORD; |
||
75 | SizeOfImage: DWORD; |
||
76 | SizeOfHeaders: DWORD; |
||
77 | CheckSum: DWORD; |
||
78 | Subsystem: WORD; |
||
79 | DllCharacteristics: WORD; |
||
80 | SizeOfStackReserve: DWORD; |
||
81 | SizeOfStackCommit: DWORD; |
||
82 | SizeOfHeapReserve: DWORD; |
||
83 | SizeOfHeapCommit: DWORD; |
||
84 | LoaderFlags: DWORD; |
||
85 | NumberOfRvaAndSizes: DWORD; |
||
86 | |||
87 | DataDirectory: ARRAY IMAGE_NUMBEROF_DIRECTORY_ENTRIES OF IMAGE_DATA_DIRECTORY |
||
88 | |||
89 | END; |
||
90 | |||
91 | |||
92 | IMAGE_FILE_HEADER* = RECORD |
||
93 | |||
94 | Machine*: WORD; |
||
95 | NumberOfSections*: WORD; |
||
96 | TimeDateStamp*: DWORD; |
||
97 | PointerToSymbolTable*: DWORD; |
||
98 | NumberOfSymbols*: DWORD; |
||
99 | SizeOfOptionalHeader*: WORD; |
||
100 | Characteristics*: WORD |
||
101 | |||
102 | END; |
||
103 | |||
104 | |||
105 | IMAGE_NT_HEADERS = RECORD |
||
106 | |||
107 | Signature: ARRAY 4 OF BYTE; |
||
108 | FileHeader: IMAGE_FILE_HEADER; |
||
109 | OptionalHeader: IMAGE_OPTIONAL_HEADER |
||
110 | |||
111 | END; |
||
112 | |||
113 | |||
114 | IMAGE_SECTION_HEADER* = RECORD |
||
115 | |||
116 | Name*: NAME; |
||
117 | |||
118 | VirtualSize*, |
||
119 | VirtualAddress*, |
||
120 | SizeOfRawData*, |
||
121 | PointerToRawData*, |
||
122 | PointerToRelocations*, |
||
123 | PointerToLinenumbers*: DWORD; |
||
124 | |||
125 | NumberOfRelocations*, |
||
126 | NumberOfLinenumbers*: WORD; |
||
127 | |||
128 | Characteristics*: DWORD |
||
129 | |||
130 | END; |
||
131 | |||
132 | |||
133 | IMAGE_EXPORT_DIRECTORY = RECORD |
||
134 | |||
135 | Characteristics: DWORD; |
||
136 | TimeDateStamp: DWORD; |
||
137 | MajorVersion: WORD; |
||
138 | MinorVersion: WORD; |
||
139 | Name, |
||
140 | Base, |
||
141 | NumberOfFunctions, |
||
142 | NumberOfNames, |
||
143 | AddressOfFunctions, |
||
144 | AddressOfNames, |
||
145 | AddressOfNameOrdinals: DWORD |
||
146 | |||
147 | END; |
||
148 | |||
149 | |||
150 | VIRTUAL_ADDR = RECORD |
||
151 | |||
152 | Code, Data, Bss, Import: INTEGER |
||
153 | |||
154 | END; |
||
155 | |||
156 | |||
157 | FILE = WR.FILE; |
||
158 | |||
159 | |||
160 | VAR |
||
161 | |||
162 | msdos: ARRAY 128 OF BYTE; |
||
163 | PEHeader: IMAGE_NT_HEADERS; |
||
164 | SectionHeaders: ARRAY 16 OF IMAGE_SECTION_HEADER; |
||
165 | Relocations: LISTS.LIST; |
||
166 | bit64: BOOLEAN; |
||
167 | libcnt: INTEGER; |
||
168 | |||
169 | |||
170 | PROCEDURE SIZE (): INTEGER; |
||
171 | RETURN SIZE_OF_DWORD * (ORD(bit64) + 1) |
||
172 | END SIZE; |
||
173 | |||
174 | |||
175 | PROCEDURE Export (program: BIN.PROGRAM; DataRVA: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER; |
||
176 | BEGIN |
||
177 | |||
178 | ExportDir.Characteristics := 0; |
||
179 | ExportDir.TimeDateStamp := PEHeader.FileHeader.TimeDateStamp; |
||
180 | ExportDir.MajorVersion := 0X; |
||
181 | ExportDir.MinorVersion := 0X; |
||
182 | ExportDir.Name := program.modname + DataRVA; |
||
183 | ExportDir.Base := 0; |
||
184 | ExportDir.NumberOfFunctions := LISTS.count(program.exp_list); |
||
185 | ExportDir.NumberOfNames := ExportDir.NumberOfFunctions; |
||
186 | ExportDir.AddressOfFunctions := SIZE_OF_IMAGE_EXPORT_DIRECTORY; |
||
187 | ExportDir.AddressOfNames := ExportDir.AddressOfFunctions + ExportDir.NumberOfFunctions * SIZE_OF_DWORD; |
||
188 | ExportDir.AddressOfNameOrdinals := ExportDir.AddressOfNames + ExportDir.NumberOfFunctions * SIZE_OF_DWORD |
||
189 | |||
190 | RETURN SIZE_OF_IMAGE_EXPORT_DIRECTORY + ExportDir.NumberOfFunctions * (2 * SIZE_OF_DWORD + SIZE_OF_WORD) |
||
191 | END Export; |
||
192 | |||
193 | |||
194 | PROCEDURE align (n, _align: INTEGER): INTEGER; |
||
195 | BEGIN |
||
196 | IF n MOD _align # 0 THEN |
||
197 | n := n + _align - (n MOD _align) |
||
198 | END |
||
199 | |||
200 | RETURN n |
||
201 | END align; |
||
202 | |||
203 | |||
204 | PROCEDURE GetProcCount (lib: BIN.IMPRT): INTEGER; |
||
205 | VAR |
||
206 | import: BIN.IMPRT; |
||
207 | res: INTEGER; |
||
208 | |||
209 | BEGIN |
||
210 | res := 0; |
||
211 | import := lib.next(BIN.IMPRT); |
||
212 | WHILE (import # NIL) & (import.label # 0) DO |
||
213 | INC(res); |
||
214 | import := import.next(BIN.IMPRT) |
||
215 | END |
||
216 | |||
217 | RETURN res |
||
218 | END GetProcCount; |
||
219 | |||
220 | |||
221 | PROCEDURE GetImportSize (imp_list: LISTS.LIST): INTEGER; |
||
222 | VAR |
||
223 | import: BIN.IMPRT; |
||
224 | proccnt: INTEGER; |
||
225 | procoffs: INTEGER; |
||
226 | OriginalCurrentThunk, |
||
227 | CurrentThunk: INTEGER; |
||
228 | |||
229 | BEGIN |
||
230 | libcnt := 0; |
||
231 | proccnt := 0; |
||
232 | import := imp_list.first(BIN.IMPRT); |
||
233 | WHILE import # NIL DO |
||
234 | IF import.label = 0 THEN |
||
235 | INC(libcnt) |
||
236 | ELSE |
||
237 | INC(proccnt) |
||
238 | END; |
||
239 | import := import.next(BIN.IMPRT) |
||
240 | END; |
||
241 | |||
242 | procoffs := 0; |
||
243 | |||
244 | import := imp_list.first(BIN.IMPRT); |
||
245 | WHILE import # NIL DO |
||
246 | IF import.label = 0 THEN |
||
247 | import.OriginalFirstThunk := procoffs; |
||
248 | import.FirstThunk := procoffs + (GetProcCount(import) + 1); |
||
249 | OriginalCurrentThunk := import.OriginalFirstThunk; |
||
250 | CurrentThunk := import.FirstThunk; |
||
251 | procoffs := procoffs + (GetProcCount(import) + 1) * 2 |
||
252 | ELSE |
||
253 | import.OriginalFirstThunk := OriginalCurrentThunk; |
||
254 | import.FirstThunk := CurrentThunk; |
||
255 | INC(OriginalCurrentThunk); |
||
256 | INC(CurrentThunk) |
||
257 | END; |
||
258 | import := import.next(BIN.IMPRT) |
||
259 | END |
||
260 | |||
261 | RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SIZE() |
||
262 | END GetImportSize; |
||
263 | |||
264 | |||
265 | PROCEDURE fixup (program: BIN.PROGRAM; Address: VIRTUAL_ADDR); |
||
266 | VAR |
||
267 | reloc: BIN.RELOC; |
||
268 | iproc: BIN.IMPRT; |
||
269 | L: INTEGER; |
||
270 | delta: INTEGER; |
||
271 | AdrImp: INTEGER; |
||
272 | |||
273 | BEGIN |
||
274 | AdrImp := Address.Import + (libcnt + 1) * 5 * SIZE_OF_DWORD; |
||
275 | |||
276 | reloc := program.rel_list.first(BIN.RELOC); |
||
277 | WHILE reloc # NIL DO |
||
278 | |||
279 | L := BIN.get32le(program.code, reloc.offset); |
||
280 | delta := 3 - reloc.offset - Address.Code - 7 * ORD(bit64); |
||
281 | |||
282 | CASE reloc.opcode OF |
||
283 | |||
284 | |BIN.PICDATA: |
||
285 | BIN.put32le(program.code, reloc.offset, L + Address.Data + delta) |
||
286 | |||
287 | |BIN.PICCODE: |
||
288 | BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + Address.Code + delta) |
||
289 | |||
290 | |BIN.PICBSS: |
||
291 | BIN.put32le(program.code, reloc.offset, L + Address.Bss + delta) |
||
292 | |||
293 | |BIN.PICIMP: |
||
294 | iproc := BIN.GetIProc(program, L); |
||
295 | BIN.put32le(program.code, reloc.offset, iproc.FirstThunk * SIZE() + AdrImp + delta) |
||
296 | |||
297 | END; |
||
298 | |||
299 | reloc := reloc.next(BIN.RELOC) |
||
300 | END |
||
301 | END fixup; |
||
302 | |||
303 | |||
304 | PROCEDURE WriteWord (file: FILE; w: WORD); |
||
305 | BEGIN |
||
306 | WR.Write16LE(file, ORD(w)) |
||
307 | END WriteWord; |
||
308 | |||
309 | |||
310 | PROCEDURE WriteName* (File: FILE; name: NAME); |
||
311 | VAR |
||
312 | i, nameLen: INTEGER; |
||
313 | |||
314 | BEGIN |
||
315 | nameLen := LENGTH(name); |
||
316 | |||
317 | FOR i := 0 TO nameLen - 1 DO |
||
318 | WR.WriteByte(File, ORD(name[i])) |
||
319 | END; |
||
320 | |||
321 | i := LEN(name) - nameLen; |
||
322 | WHILE i > 0 DO |
||
323 | WR.WriteByte(File, 0); |
||
324 | DEC(i) |
||
325 | END |
||
326 | |||
327 | END WriteName; |
||
328 | |||
329 | |||
330 | PROCEDURE WriteSectionHeader* (file: FILE; h: IMAGE_SECTION_HEADER); |
||
331 | VAR |
||
332 | i, nameLen: INTEGER; |
||
333 | |||
334 | BEGIN |
||
335 | nameLen := LENGTH(h.Name); |
||
336 | |||
337 | FOR i := 0 TO nameLen - 1 DO |
||
338 | WR.WriteByte(file, ORD(h.Name[i])) |
||
339 | END; |
||
340 | |||
341 | i := LEN(h.Name) - nameLen; |
||
342 | WHILE i > 0 DO |
||
343 | WR.WriteByte(file, 0); |
||
344 | DEC(i) |
||
345 | END; |
||
346 | |||
347 | WR.Write32LE(file, h.VirtualSize); |
||
348 | WR.Write32LE(file, h.VirtualAddress); |
||
349 | WR.Write32LE(file, h.SizeOfRawData); |
||
350 | WR.Write32LE(file, h.PointerToRawData); |
||
351 | WR.Write32LE(file, h.PointerToRelocations); |
||
352 | WR.Write32LE(file, h.PointerToLinenumbers); |
||
353 | |||
354 | WriteWord(file, h.NumberOfRelocations); |
||
355 | WriteWord(file, h.NumberOfLinenumbers); |
||
356 | |||
357 | WR.Write32LE(file, h.Characteristics) |
||
358 | END WriteSectionHeader; |
||
359 | |||
360 | |||
361 | PROCEDURE WriteFileHeader* (file: FILE; h: IMAGE_FILE_HEADER); |
||
362 | BEGIN |
||
363 | WriteWord(file, h.Machine); |
||
364 | WriteWord(file, h.NumberOfSections); |
||
365 | |||
366 | WR.Write32LE(file, h.TimeDateStamp); |
||
367 | WR.Write32LE(file, h.PointerToSymbolTable); |
||
368 | WR.Write32LE(file, h.NumberOfSymbols); |
||
369 | |||
370 | WriteWord(file, h.SizeOfOptionalHeader); |
||
371 | WriteWord(file, h.Characteristics) |
||
372 | END WriteFileHeader; |
||
373 | |||
374 | |||
375 | PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; BaseAddress: INTEGER; console, dll, amd64: BOOLEAN); |
||
376 | VAR |
||
377 | i, n: INTEGER; |
||
378 | |||
379 | Size: RECORD |
||
380 | |||
381 | Code, Data, Bss, Stack, Import, Reloc, Export: INTEGER |
||
382 | |||
383 | END; |
||
384 | |||
385 | Address: VIRTUAL_ADDR; |
||
386 | |||
387 | File: FILE; |
||
388 | |||
389 | import: BIN.IMPRT; |
||
390 | ImportTable: CHL.INTLIST; |
||
391 | |||
392 | ExportDir: IMAGE_EXPORT_DIRECTORY; |
||
393 | export: BIN.EXPRT; |
||
394 | |||
395 | |||
396 | PROCEDURE WriteExportDir (file: FILE; e: IMAGE_EXPORT_DIRECTORY); |
||
397 | BEGIN |
||
398 | WR.Write32LE(file, e.Characteristics); |
||
399 | WR.Write32LE(file, e.TimeDateStamp); |
||
400 | |||
401 | WriteWord(file, e.MajorVersion); |
||
402 | WriteWord(file, e.MinorVersion); |
||
403 | |||
404 | WR.Write32LE(file, e.Name); |
||
405 | WR.Write32LE(file, e.Base); |
||
406 | WR.Write32LE(file, e.NumberOfFunctions); |
||
407 | WR.Write32LE(file, e.NumberOfNames); |
||
408 | WR.Write32LE(file, e.AddressOfFunctions); |
||
409 | WR.Write32LE(file, e.AddressOfNames); |
||
410 | WR.Write32LE(file, e.AddressOfNameOrdinals) |
||
411 | END WriteExportDir; |
||
412 | |||
413 | |||
414 | PROCEDURE WriteOptHeader (file: FILE; h: IMAGE_OPTIONAL_HEADER); |
||
415 | VAR |
||
416 | i: INTEGER; |
||
417 | |||
418 | BEGIN |
||
419 | |||
420 | WriteWord(file, h.Magic); |
||
421 | |||
422 | WR.WriteByte(file, h.MajorLinkerVersion); |
||
423 | WR.WriteByte(file, h.MinorLinkerVersion); |
||
424 | |||
425 | WR.Write32LE(file, h.SizeOfCode); |
||
426 | WR.Write32LE(file, h.SizeOfInitializedData); |
||
427 | WR.Write32LE(file, h.SizeOfUninitializedData); |
||
428 | WR.Write32LE(file, h.AddressOfEntryPoint); |
||
429 | WR.Write32LE(file, h.BaseOfCode); |
||
430 | |||
431 | IF bit64 THEN |
||
432 | WR.Write64LE(file, h.ImageBase) |
||
433 | ELSE |
||
434 | WR.Write32LE(file, h.BaseOfData); |
||
435 | WR.Write32LE(file, h.ImageBase) |
||
436 | END; |
||
437 | |||
438 | WR.Write32LE(file, h.SectionAlignment); |
||
439 | WR.Write32LE(file, h.FileAlignment); |
||
440 | |||
441 | WriteWord(file, h.MajorOperatingSystemVersion); |
||
442 | WriteWord(file, h.MinorOperatingSystemVersion); |
||
443 | WriteWord(file, h.MajorImageVersion); |
||
444 | WriteWord(file, h.MinorImageVersion); |
||
445 | WriteWord(file, h.MajorSubsystemVersion); |
||
446 | WriteWord(file, h.MinorSubsystemVersion); |
||
447 | |||
448 | WR.Write32LE(file, h.Win32VersionValue); |
||
449 | WR.Write32LE(file, h.SizeOfImage); |
||
450 | WR.Write32LE(file, h.SizeOfHeaders); |
||
451 | WR.Write32LE(file, h.CheckSum); |
||
452 | |||
453 | WriteWord(file, h.Subsystem); |
||
454 | WriteWord(file, h.DllCharacteristics); |
||
455 | |||
456 | IF bit64 THEN |
||
457 | WR.Write64LE(file, h.SizeOfStackReserve); |
||
458 | WR.Write64LE(file, h.SizeOfStackCommit); |
||
459 | WR.Write64LE(file, h.SizeOfHeapReserve); |
||
460 | WR.Write64LE(file, h.SizeOfHeapCommit) |
||
461 | ELSE |
||
462 | WR.Write32LE(file, h.SizeOfStackReserve); |
||
463 | WR.Write32LE(file, h.SizeOfStackCommit); |
||
464 | WR.Write32LE(file, h.SizeOfHeapReserve); |
||
465 | WR.Write32LE(file, h.SizeOfHeapCommit) |
||
466 | END; |
||
467 | |||
468 | WR.Write32LE(file, h.LoaderFlags); |
||
469 | WR.Write32LE(file, h.NumberOfRvaAndSizes); |
||
470 | |||
471 | FOR i := 0 TO LEN(h.DataDirectory) - 1 DO |
||
472 | WR.Write32LE(file, h.DataDirectory[i].VirtualAddress); |
||
473 | WR.Write32LE(file, h.DataDirectory[i].Size) |
||
474 | END |
||
475 | |||
476 | END WriteOptHeader; |
||
477 | |||
478 | |||
479 | PROCEDURE WritePEHeader (file: FILE; h: IMAGE_NT_HEADERS); |
||
480 | BEGIN |
||
481 | WR.Write(file, h.Signature, LEN(h.Signature)); |
||
482 | WriteFileHeader(file, h.FileHeader); |
||
483 | WriteOptHeader(file, h.OptionalHeader) |
||
484 | END WritePEHeader; |
||
485 | |||
486 | |||
487 | PROCEDURE InitSection (VAR section: IMAGE_SECTION_HEADER; Name: NAME; Characteristics: DWORD); |
||
488 | BEGIN |
||
489 | section.Name := Name; |
||
490 | section.PointerToRelocations := 0; |
||
491 | section.PointerToLinenumbers := 0; |
||
492 | section.NumberOfRelocations := 0X; |
||
493 | section.NumberOfLinenumbers := 0X; |
||
494 | section.Characteristics := Characteristics |
||
495 | END InitSection; |
||
496 | |||
497 | |||
498 | BEGIN |
||
499 | bit64 := amd64; |
||
500 | Relocations := LISTS.create(NIL); |
||
501 | |||
502 | Size.Code := CHL.Length(program.code); |
||
503 | Size.Data := CHL.Length(program.data); |
||
504 | Size.Bss := program.bss; |
||
505 | Size.Stack := program.stack; |
||
506 | |||
507 | PEHeader.Signature[0] := 50H; |
||
508 | PEHeader.Signature[1] := 45H; |
||
509 | PEHeader.Signature[2] := 0; |
||
510 | PEHeader.Signature[3] := 0; |
||
511 | |||
512 | IF amd64 THEN |
||
513 | PEHeader.FileHeader.Machine := 08664X |
||
514 | ELSE |
||
515 | PEHeader.FileHeader.Machine := 014CX |
||
516 | END; |
||
517 | |||
518 | PEHeader.FileHeader.NumberOfSections := WCHR(4 + ORD(dll)); |
||
519 | |||
520 | PEHeader.FileHeader.TimeDateStamp := UTILS.UnixTime(); |
||
521 | PEHeader.FileHeader.PointerToSymbolTable := 0H; |
||
522 | PEHeader.FileHeader.NumberOfSymbols := 0H; |
||
523 | PEHeader.FileHeader.SizeOfOptionalHeader := WCHR(0E0H + 10H * ORD(amd64)); |
||
524 | PEHeader.FileHeader.Characteristics := WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll)); |
||
525 | |||
526 | PEHeader.OptionalHeader.Magic := WCHR(010BH + 100H * ORD(amd64)); |
||
527 | PEHeader.OptionalHeader.MajorLinkerVersion := mConst.vMajor; |
||
528 | PEHeader.OptionalHeader.MinorLinkerVersion := mConst.vMinor; |
||
529 | PEHeader.OptionalHeader.SizeOfCode := align(Size.Code, FileAlignment); |
||
530 | PEHeader.OptionalHeader.SizeOfInitializedData := 0; |
||
531 | PEHeader.OptionalHeader.SizeOfUninitializedData := 0; |
||
532 | PEHeader.OptionalHeader.AddressOfEntryPoint := SectionAlignment; |
||
533 | PEHeader.OptionalHeader.BaseOfCode := SectionAlignment; |
||
534 | PEHeader.OptionalHeader.BaseOfData := PEHeader.OptionalHeader.BaseOfCode + align(Size.Code, SectionAlignment); |
||
535 | PEHeader.OptionalHeader.ImageBase := BaseAddress; |
||
536 | PEHeader.OptionalHeader.SectionAlignment := SectionAlignment; |
||
537 | PEHeader.OptionalHeader.FileAlignment := FileAlignment; |
||
538 | PEHeader.OptionalHeader.MajorOperatingSystemVersion := 1X; |
||
539 | PEHeader.OptionalHeader.MinorOperatingSystemVersion := 0X; |
||
540 | PEHeader.OptionalHeader.MajorImageVersion := 0X; |
||
541 | PEHeader.OptionalHeader.MinorImageVersion := 0X; |
||
542 | PEHeader.OptionalHeader.MajorSubsystemVersion := 4X; |
||
543 | PEHeader.OptionalHeader.MinorSubsystemVersion := 0X; |
||
544 | PEHeader.OptionalHeader.Win32VersionValue := 0H; |
||
545 | PEHeader.OptionalHeader.SizeOfImage := SectionAlignment; |
||
546 | PEHeader.OptionalHeader.SizeOfHeaders := 400H; |
||
547 | PEHeader.OptionalHeader.CheckSum := 0; |
||
548 | PEHeader.OptionalHeader.Subsystem := WCHR((2 + ORD(console)) * ORD(~dll)); |
||
549 | PEHeader.OptionalHeader.DllCharacteristics := 0040X; |
||
550 | PEHeader.OptionalHeader.SizeOfStackReserve := Size.Stack; |
||
551 | PEHeader.OptionalHeader.SizeOfStackCommit := Size.Stack DIV 16; |
||
552 | PEHeader.OptionalHeader.SizeOfHeapReserve := 100000H; |
||
553 | PEHeader.OptionalHeader.SizeOfHeapCommit := 10000H; |
||
554 | PEHeader.OptionalHeader.LoaderFlags := 0; |
||
555 | PEHeader.OptionalHeader.NumberOfRvaAndSizes := IMAGE_NUMBEROF_DIRECTORY_ENTRIES; |
||
556 | |||
557 | InitSection(SectionHeaders[0], ".text", SHC_text); |
||
558 | SectionHeaders[0].VirtualSize := Size.Code; |
||
559 | SectionHeaders[0].VirtualAddress := 1000H; |
||
560 | SectionHeaders[0].SizeOfRawData := align(Size.Code, FileAlignment); |
||
561 | SectionHeaders[0].PointerToRawData := PEHeader.OptionalHeader.SizeOfHeaders; |
||
562 | |||
563 | InitSection(SectionHeaders[1], ".data", SHC_data); |
||
564 | SectionHeaders[1].VirtualSize := Size.Data; |
||
565 | SectionHeaders[1].VirtualAddress := align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment); |
||
566 | SectionHeaders[1].SizeOfRawData := align(Size.Data, FileAlignment); |
||
567 | SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData; |
||
568 | |||
569 | InitSection(SectionHeaders[2], ".bss", SHC_bss); |
||
570 | SectionHeaders[2].VirtualSize := Size.Bss; |
||
571 | SectionHeaders[2].VirtualAddress := align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment); |
||
572 | SectionHeaders[2].SizeOfRawData := 0; |
||
573 | SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData; |
||
574 | |||
575 | Size.Import := GetImportSize(program.imp_list); |
||
576 | |||
577 | InitSection(SectionHeaders[3], ".idata", SHC_data); |
||
578 | SectionHeaders[3].VirtualSize := Size.Import + CHL.Length(program.import); |
||
579 | SectionHeaders[3].VirtualAddress := align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment); |
||
580 | SectionHeaders[3].SizeOfRawData := align(SectionHeaders[3].VirtualSize, FileAlignment); |
||
581 | SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData; |
||
582 | |||
583 | Address.Code := SectionHeaders[0].VirtualAddress + PEHeader.OptionalHeader.ImageBase; |
||
584 | Address.Data := SectionHeaders[1].VirtualAddress + PEHeader.OptionalHeader.ImageBase; |
||
585 | Address.Bss := SectionHeaders[2].VirtualAddress + PEHeader.OptionalHeader.ImageBase; |
||
586 | Address.Import := SectionHeaders[3].VirtualAddress + PEHeader.OptionalHeader.ImageBase; |
||
587 | |||
588 | fixup(program, Address); |
||
589 | |||
590 | IF dll THEN |
||
591 | Size.Export := Export(program, SectionHeaders[1].VirtualAddress, ExportDir); |
||
592 | |||
593 | InitSection(SectionHeaders[4], ".edata", SHC_data); |
||
594 | SectionHeaders[4].VirtualSize := Size.Export + CHL.Length(program.export); |
||
595 | SectionHeaders[4].VirtualAddress := align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment); |
||
596 | SectionHeaders[4].SizeOfRawData := align(SectionHeaders[4].VirtualSize, FileAlignment); |
||
597 | SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData; |
||
598 | END; |
||
599 | |||
600 | FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO |
||
601 | PEHeader.OptionalHeader.DataDirectory[i].VirtualAddress := 0; |
||
602 | PEHeader.OptionalHeader.DataDirectory[i].Size := 0 |
||
603 | END; |
||
604 | |||
605 | IF dll THEN |
||
606 | PEHeader.OptionalHeader.DataDirectory[0].VirtualAddress := SectionHeaders[4].VirtualAddress; |
||
607 | PEHeader.OptionalHeader.DataDirectory[0].Size := SectionHeaders[4].VirtualSize |
||
608 | END; |
||
609 | |||
610 | PEHeader.OptionalHeader.DataDirectory[1].VirtualAddress := SectionHeaders[3].VirtualAddress; |
||
611 | PEHeader.OptionalHeader.DataDirectory[1].Size := SectionHeaders[3].VirtualSize; |
||
612 | |||
613 | FOR i := 0 TO ORD(PEHeader.FileHeader.NumberOfSections) - 1 DO |
||
614 | INC(PEHeader.OptionalHeader.SizeOfInitializedData, SectionHeaders[i].SizeOfRawData) |
||
615 | END; |
||
616 | |||
617 | DEC(PEHeader.OptionalHeader.SizeOfInitializedData, SectionHeaders[0].SizeOfRawData); |
||
618 | DEC(PEHeader.OptionalHeader.SizeOfInitializedData, SectionHeaders[2].SizeOfRawData); |
||
619 | |||
620 | PEHeader.OptionalHeader.SizeOfUninitializedData := align(SectionHeaders[2].VirtualSize, FileAlignment); |
||
621 | |||
622 | FOR i := 0 TO ORD(PEHeader.FileHeader.NumberOfSections) - 1 DO |
||
623 | INC(PEHeader.OptionalHeader.SizeOfImage, align(SectionHeaders[i].VirtualSize, SectionAlignment)) |
||
624 | END; |
||
625 | |||
626 | n := 0; |
||
627 | BIN.InitArray(msdos, n, "4D5A80000100000004001000FFFF000040010000000000004000000000000000"); |
||
628 | BIN.InitArray(msdos, n, "0000000000000000000000000000000000000000000000000000000080000000"); |
||
629 | BIN.InitArray(msdos, n, "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F"); |
||
630 | BIN.InitArray(msdos, n, "742062652072756E20696E20444F53206D6F64652E0D0A240000000000000000"); |
||
631 | |||
632 | File := WR.Create(FileName); |
||
633 | |||
634 | WR.Write(File, msdos, LEN(msdos)); |
||
635 | |||
636 | WritePEHeader(File, PEHeader); |
||
637 | |||
638 | FOR i := 0 TO ORD(PEHeader.FileHeader.NumberOfSections) - 1 DO |
||
639 | WriteSectionHeader(File, SectionHeaders[i]) |
||
640 | END; |
||
641 | |||
642 | WR.Padding(File, FileAlignment); |
||
643 | |||
644 | CHL.WriteToFile(File, program.code); |
||
645 | WR.Padding(File, FileAlignment); |
||
646 | |||
647 | CHL.WriteToFile(File, program.data); |
||
648 | WR.Padding(File, FileAlignment); |
||
649 | |||
650 | n := (libcnt + 1) * 5; |
||
651 | ImportTable := CHL.CreateIntList(); |
||
652 | |||
653 | FOR i := 0 TO (Size.Import - n * SIZE_OF_DWORD) DIV SIZE() + n - 1 DO |
||
654 | CHL.PushInt(ImportTable, 0) |
||
655 | END; |
||
656 | |||
657 | i := 0; |
||
658 | import := program.imp_list.first(BIN.IMPRT); |
||
659 | WHILE import # NIL DO |
||
660 | IF import.label = 0 THEN |
||
661 | CHL.SetInt(ImportTable, i + 0, import.OriginalFirstThunk * SIZE() + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); |
||
662 | CHL.SetInt(ImportTable, i + 1, 0); |
||
663 | CHL.SetInt(ImportTable, i + 2, 0); |
||
664 | CHL.SetInt(ImportTable, i + 3, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress); |
||
665 | CHL.SetInt(ImportTable, i + 4, import.FirstThunk * SIZE() + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); |
||
666 | i := i + 5 |
||
667 | END; |
||
668 | import := import.next(BIN.IMPRT) |
||
669 | END; |
||
670 | |||
671 | CHL.SetInt(ImportTable, i + 0, 0); |
||
672 | CHL.SetInt(ImportTable, i + 1, 0); |
||
673 | CHL.SetInt(ImportTable, i + 2, 0); |
||
674 | CHL.SetInt(ImportTable, i + 3, 0); |
||
675 | CHL.SetInt(ImportTable, i + 4, 0); |
||
676 | |||
677 | import := program.imp_list.first(BIN.IMPRT); |
||
678 | WHILE import # NIL DO |
||
679 | IF import.label # 0 THEN |
||
680 | CHL.SetInt(ImportTable, import.OriginalFirstThunk + n, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2); |
||
681 | CHL.SetInt(ImportTable, import.FirstThunk + n, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2) |
||
682 | END; |
||
683 | import := import.next(BIN.IMPRT) |
||
684 | END; |
||
685 | |||
686 | FOR i := 0 TO n - 1 DO |
||
687 | WR.Write32LE(File, CHL.GetInt(ImportTable, i)) |
||
688 | END; |
||
689 | |||
690 | FOR i := n TO CHL.Length(ImportTable) - 1 DO |
||
691 | IF amd64 THEN |
||
692 | WR.Write64LE(File, CHL.GetInt(ImportTable, i)) |
||
693 | ELSE |
||
694 | WR.Write32LE(File, CHL.GetInt(ImportTable, i)) |
||
695 | END |
||
696 | END; |
||
697 | |||
698 | CHL.WriteToFile(File, program.import); |
||
699 | WR.Padding(File, FileAlignment); |
||
700 | |||
701 | IF dll THEN |
||
702 | |||
703 | INC(ExportDir.AddressOfFunctions, SectionHeaders[4].VirtualAddress); |
||
704 | INC(ExportDir.AddressOfNames, SectionHeaders[4].VirtualAddress); |
||
705 | INC(ExportDir.AddressOfNameOrdinals, SectionHeaders[4].VirtualAddress); |
||
706 | |||
707 | WriteExportDir(File, ExportDir); |
||
708 | |||
709 | export := program.exp_list.first(BIN.EXPRT); |
||
710 | WHILE export # NIL DO |
||
711 | WR.Write32LE(File, export.label + SectionHeaders[0].VirtualAddress); |
||
712 | export := export.next(BIN.EXPRT) |
||
713 | END; |
||
714 | |||
715 | export := program.exp_list.first(BIN.EXPRT); |
||
716 | WHILE export # NIL DO |
||
717 | WR.Write32LE(File, export.nameoffs + Size.Export + SectionHeaders[4].VirtualAddress); |
||
718 | export := export.next(BIN.EXPRT) |
||
719 | END; |
||
720 | |||
721 | FOR i := 0 TO ExportDir.NumberOfFunctions - 1 DO |
||
722 | WriteWord(File, WCHR(i)) |
||
723 | END; |
||
724 | |||
725 | CHL.WriteToFile(File, program.export); |
||
726 | WR.Padding(File, FileAlignment) |
||
727 | END; |
||
728 | |||
729 | WR.Close(File) |
||
730 | END write; |
||
731 | |||
732 | |||
733 | END PE32. |