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