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