PE32.ob07 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2020, 2023, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE PE32;
  7. IMPORT BIN, LISTS, UTILS, WR := WRITER, CHL := CHUNKLISTS;
  8. CONST
  9. SIZE_OF_DWORD = 4;
  10. SIZE_OF_WORD = 2;
  11. SIZE_OF_IMAGE_EXPORT_DIRECTORY = 40;
  12. IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
  13. IMAGE_SIZEOF_SHORT_NAME = 8;
  14. SIZE_OF_IMAGE_FILE_HEADER* = 20;
  15. SIZE_OF_IMAGE_SECTION_HEADER* = 40;
  16. (* SectionHeader.Characteristics *)
  17. SHC_text = 060000020H;
  18. SHC_data = 040000040H;
  19. SHC_bss = 0C0000080H;
  20. SectionAlignment = 1000H;
  21. TYPE
  22. WORD = WCHAR;
  23. DWORD = INTEGER;
  24. NAME* = ARRAY IMAGE_SIZEOF_SHORT_NAME OF CHAR;
  25. IMAGE_DATA_DIRECTORY = RECORD
  26. VirtualAddress: DWORD;
  27. Size: DWORD
  28. END;
  29. IMAGE_OPTIONAL_HEADER = RECORD
  30. Magic: WORD;
  31. MajorLinkerVersion: BYTE;
  32. MinorLinkerVersion: BYTE;
  33. SizeOfCode: DWORD;
  34. SizeOfInitializedData: DWORD;
  35. SizeOfUninitializedData: DWORD;
  36. AddressOfEntryPoint: DWORD;
  37. BaseOfCode: DWORD;
  38. BaseOfData: DWORD;
  39. ImageBase: DWORD;
  40. SectionAlignment: DWORD;
  41. FileAlignment: DWORD;
  42. MajorOperatingSystemVersion: WORD;
  43. MinorOperatingSystemVersion: WORD;
  44. MajorImageVersion: WORD;
  45. MinorImageVersion: WORD;
  46. MajorSubsystemVersion: WORD;
  47. MinorSubsystemVersion: WORD;
  48. Win32VersionValue: DWORD;
  49. SizeOfImage: DWORD;
  50. SizeOfHeaders: DWORD;
  51. CheckSum: DWORD;
  52. Subsystem: WORD;
  53. DllCharacteristics: WORD;
  54. SizeOfStackReserve: DWORD;
  55. SizeOfStackCommit: DWORD;
  56. SizeOfHeapReserve: DWORD;
  57. SizeOfHeapCommit: DWORD;
  58. LoaderFlags: DWORD;
  59. NumberOfRvaAndSizes: DWORD;
  60. DataDirectory: ARRAY IMAGE_NUMBEROF_DIRECTORY_ENTRIES OF IMAGE_DATA_DIRECTORY
  61. END;
  62. IMAGE_FILE_HEADER* = RECORD
  63. Machine*: WORD;
  64. NumberOfSections*: WORD;
  65. TimeDateStamp*: DWORD;
  66. PointerToSymbolTable*: DWORD;
  67. NumberOfSymbols*: DWORD;
  68. SizeOfOptionalHeader*: WORD;
  69. Characteristics*: WORD
  70. END;
  71. IMAGE_SECTION_HEADER* = RECORD
  72. Name*: NAME;
  73. VirtualSize*,
  74. VirtualAddress*,
  75. SizeOfRawData*,
  76. PointerToRawData*,
  77. PointerToRelocations*,
  78. PointerToLinenumbers*: DWORD;
  79. NumberOfRelocations*,
  80. NumberOfLinenumbers*: WORD;
  81. Characteristics*: DWORD
  82. END;
  83. IMAGE_EXPORT_DIRECTORY = RECORD
  84. Characteristics: DWORD;
  85. TimeDateStamp: DWORD;
  86. MajorVersion: WORD;
  87. MinorVersion: WORD;
  88. Name,
  89. Base,
  90. NumberOfFunctions,
  91. NumberOfNames,
  92. AddressOfFunctions,
  93. AddressOfNames,
  94. AddressOfNameOrdinals: DWORD
  95. END;
  96. VIRTUAL_ADDR* = RECORD
  97. Code*, Data*, Bss*, Import*: INTEGER
  98. END;
  99. VAR
  100. Signature: ARRAY 4 OF BYTE;
  101. FileHeader: IMAGE_FILE_HEADER;
  102. OptionalHeader: IMAGE_OPTIONAL_HEADER;
  103. msdos: ARRAY 128 OF BYTE;
  104. SectionHeaders: ARRAY 16 OF IMAGE_SECTION_HEADER;
  105. libcnt: INTEGER;
  106. SizeOfWord: INTEGER;
  107. FileAlignment: INTEGER;
  108. PROCEDURE Export (program: BIN.PROGRAM; name: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER;
  109. BEGIN
  110. ExportDir.Characteristics := 0;
  111. ExportDir.TimeDateStamp := FileHeader.TimeDateStamp;
  112. ExportDir.MajorVersion := 0X;
  113. ExportDir.MinorVersion := 0X;
  114. ExportDir.Name := name;
  115. ExportDir.Base := 0;
  116. ExportDir.NumberOfFunctions := LISTS.count(program.exp_list);
  117. ExportDir.NumberOfNames := ExportDir.NumberOfFunctions;
  118. ExportDir.AddressOfFunctions := SIZE_OF_IMAGE_EXPORT_DIRECTORY;
  119. ExportDir.AddressOfNames := ExportDir.AddressOfFunctions + ExportDir.NumberOfFunctions * SIZE_OF_DWORD;
  120. ExportDir.AddressOfNameOrdinals := ExportDir.AddressOfNames + ExportDir.NumberOfFunctions * SIZE_OF_DWORD
  121. RETURN SIZE_OF_IMAGE_EXPORT_DIRECTORY + ExportDir.NumberOfFunctions * (2 * SIZE_OF_DWORD + SIZE_OF_WORD)
  122. END Export;
  123. PROCEDURE GetProcCount (lib: BIN.IMPRT): INTEGER;
  124. VAR
  125. imp: BIN.IMPRT;
  126. res: INTEGER;
  127. BEGIN
  128. res := 0;
  129. imp := lib.next(BIN.IMPRT);
  130. WHILE (imp # NIL) & (imp.label # 0) DO
  131. INC(res);
  132. imp := imp.next(BIN.IMPRT)
  133. END
  134. RETURN res
  135. END GetProcCount;
  136. PROCEDURE GetImportSize (imp_list: LISTS.LIST): INTEGER;
  137. VAR
  138. imp: BIN.IMPRT;
  139. proccnt: INTEGER;
  140. procoffs: INTEGER;
  141. OriginalCurrentThunk,
  142. CurrentThunk: INTEGER;
  143. BEGIN
  144. libcnt := 0;
  145. proccnt := 0;
  146. imp := imp_list.first(BIN.IMPRT);
  147. WHILE imp # NIL DO
  148. IF imp.label = 0 THEN
  149. INC(libcnt)
  150. ELSE
  151. INC(proccnt)
  152. END;
  153. imp := imp.next(BIN.IMPRT)
  154. END;
  155. procoffs := 0;
  156. imp := imp_list.first(BIN.IMPRT);
  157. WHILE imp # NIL DO
  158. IF imp.label = 0 THEN
  159. imp.OriginalFirstThunk := procoffs;
  160. imp.FirstThunk := procoffs + (GetProcCount(imp) + 1);
  161. OriginalCurrentThunk := imp.OriginalFirstThunk;
  162. CurrentThunk := imp.FirstThunk;
  163. INC(procoffs, (GetProcCount(imp) + 1) * 2)
  164. ELSE
  165. imp.OriginalFirstThunk := OriginalCurrentThunk;
  166. imp.FirstThunk := CurrentThunk;
  167. INC(OriginalCurrentThunk);
  168. INC(CurrentThunk)
  169. END;
  170. imp := imp.next(BIN.IMPRT)
  171. END
  172. RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SizeOfWord
  173. END GetImportSize;
  174. PROCEDURE fixup* (program: BIN.PROGRAM; Address: VIRTUAL_ADDR; amd64: BOOLEAN);
  175. VAR
  176. reloc: BIN.RELOC;
  177. iproc: BIN.IMPRT;
  178. code: CHL.BYTELIST;
  179. L, delta, delta0, AdrImp, offset: INTEGER;
  180. BEGIN
  181. AdrImp := Address.Import + (libcnt + 1) * 5 * SIZE_OF_DWORD;
  182. code := program.code;
  183. reloc := program.rel_list.first(BIN.RELOC);
  184. delta0 := 3 - 7 * ORD(amd64) - Address.Code;
  185. WHILE reloc # NIL DO
  186. offset := reloc.offset;
  187. L := BIN.get32le(code, offset);
  188. delta := delta0 - offset;
  189. CASE reloc.opcode OF
  190. |BIN.PICDATA:
  191. INC(delta, L + Address.Data)
  192. |BIN.PICCODE:
  193. INC(delta, BIN.GetLabel(program, L) + Address.Code)
  194. |BIN.PICBSS:
  195. INC(delta, L + Address.Bss)
  196. |BIN.PICIMP:
  197. iproc := BIN.GetIProc(program, L);
  198. INC(delta, iproc.FirstThunk * SizeOfWord + AdrImp)
  199. END;
  200. BIN.put32le(code, offset, delta);
  201. reloc := reloc.next(BIN.RELOC)
  202. END
  203. END fixup;
  204. PROCEDURE WriteWord (w: WORD);
  205. BEGIN
  206. WR.Write16LE(ORD(w))
  207. END WriteWord;
  208. PROCEDURE WriteName* (name: NAME);
  209. VAR
  210. i, nameLen: INTEGER;
  211. BEGIN
  212. nameLen := LENGTH(name);
  213. FOR i := 0 TO nameLen - 1 DO
  214. WR.WriteByte(ORD(name[i]))
  215. END;
  216. i := LEN(name) - nameLen;
  217. WHILE i > 0 DO
  218. WR.WriteByte(0);
  219. DEC(i)
  220. END
  221. END WriteName;
  222. PROCEDURE WriteSectionHeader* (h: IMAGE_SECTION_HEADER);
  223. VAR
  224. i, nameLen: INTEGER;
  225. BEGIN
  226. nameLen := LENGTH(h.Name);
  227. FOR i := 0 TO nameLen - 1 DO
  228. WR.WriteByte(ORD(h.Name[i]))
  229. END;
  230. i := LEN(h.Name) - nameLen;
  231. WHILE i > 0 DO
  232. WR.WriteByte(0);
  233. DEC(i)
  234. END;
  235. WR.Write32LE(h.VirtualSize);
  236. WR.Write32LE(h.VirtualAddress);
  237. WR.Write32LE(h.SizeOfRawData);
  238. WR.Write32LE(h.PointerToRawData);
  239. WR.Write32LE(h.PointerToRelocations);
  240. WR.Write32LE(h.PointerToLinenumbers);
  241. WriteWord(h.NumberOfRelocations);
  242. WriteWord(h.NumberOfLinenumbers);
  243. WR.Write32LE(h.Characteristics)
  244. END WriteSectionHeader;
  245. PROCEDURE WriteFileHeader* (h: IMAGE_FILE_HEADER);
  246. BEGIN
  247. WriteWord(h.Machine);
  248. WriteWord(h.NumberOfSections);
  249. WR.Write32LE(h.TimeDateStamp);
  250. WR.Write32LE(h.PointerToSymbolTable);
  251. WR.Write32LE(h.NumberOfSymbols);
  252. WriteWord(h.SizeOfOptionalHeader);
  253. WriteWord(h.Characteristics)
  254. END WriteFileHeader;
  255. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; console, dll, amd64: BOOLEAN; fa: INTEGER);
  256. VAR
  257. i, n, temp: INTEGER;
  258. Size: RECORD
  259. Code, Data, Bss, Import, Reloc, Export: INTEGER
  260. END;
  261. BaseAddress: INTEGER;
  262. Address: VIRTUAL_ADDR;
  263. _import: BIN.IMPRT;
  264. ImportTable: CHL.INTLIST;
  265. ExportDir: IMAGE_EXPORT_DIRECTORY;
  266. export: BIN.EXPRT;
  267. PROCEDURE WriteExportDir (e: IMAGE_EXPORT_DIRECTORY);
  268. BEGIN
  269. WR.Write32LE(e.Characteristics);
  270. WR.Write32LE(e.TimeDateStamp);
  271. WriteWord(e.MajorVersion);
  272. WriteWord(e.MinorVersion);
  273. WR.Write32LE(e.Name);
  274. WR.Write32LE(e.Base);
  275. WR.Write32LE(e.NumberOfFunctions);
  276. WR.Write32LE(e.NumberOfNames);
  277. WR.Write32LE(e.AddressOfFunctions);
  278. WR.Write32LE(e.AddressOfNames);
  279. WR.Write32LE(e.AddressOfNameOrdinals)
  280. END WriteExportDir;
  281. PROCEDURE WriteOptHeader (h: IMAGE_OPTIONAL_HEADER; amd64: BOOLEAN);
  282. VAR
  283. i: INTEGER;
  284. BEGIN
  285. WriteWord(h.Magic);
  286. WR.WriteByte(h.MajorLinkerVersion);
  287. WR.WriteByte(h.MinorLinkerVersion);
  288. WR.Write32LE(h.SizeOfCode);
  289. WR.Write32LE(h.SizeOfInitializedData);
  290. WR.Write32LE(h.SizeOfUninitializedData);
  291. WR.Write32LE(h.AddressOfEntryPoint);
  292. WR.Write32LE(h.BaseOfCode);
  293. IF amd64 THEN
  294. WR.Write64LE(h.ImageBase)
  295. ELSE
  296. WR.Write32LE(h.BaseOfData);
  297. WR.Write32LE(h.ImageBase)
  298. END;
  299. WR.Write32LE(h.SectionAlignment);
  300. WR.Write32LE(h.FileAlignment);
  301. WriteWord(h.MajorOperatingSystemVersion);
  302. WriteWord(h.MinorOperatingSystemVersion);
  303. WriteWord(h.MajorImageVersion);
  304. WriteWord(h.MinorImageVersion);
  305. WriteWord(h.MajorSubsystemVersion);
  306. WriteWord(h.MinorSubsystemVersion);
  307. WR.Write32LE(h.Win32VersionValue);
  308. WR.Write32LE(h.SizeOfImage);
  309. WR.Write32LE(h.SizeOfHeaders);
  310. WR.Write32LE(h.CheckSum);
  311. WriteWord(h.Subsystem);
  312. WriteWord(h.DllCharacteristics);
  313. IF amd64 THEN
  314. WR.Write64LE(h.SizeOfStackReserve);
  315. WR.Write64LE(h.SizeOfStackCommit);
  316. WR.Write64LE(h.SizeOfHeapReserve);
  317. WR.Write64LE(h.SizeOfHeapCommit)
  318. ELSE
  319. WR.Write32LE(h.SizeOfStackReserve);
  320. WR.Write32LE(h.SizeOfStackCommit);
  321. WR.Write32LE(h.SizeOfHeapReserve);
  322. WR.Write32LE(h.SizeOfHeapCommit)
  323. END;
  324. WR.Write32LE(h.LoaderFlags);
  325. WR.Write32LE(h.NumberOfRvaAndSizes);
  326. FOR i := 0 TO LEN(h.DataDirectory) - 1 DO
  327. WR.Write32LE(h.DataDirectory[i].VirtualAddress);
  328. WR.Write32LE(h.DataDirectory[i].Size)
  329. END
  330. END WriteOptHeader;
  331. PROCEDURE InitSection (VAR section: IMAGE_SECTION_HEADER; Name: NAME; VirtualSize: INTEGER; Characteristics: DWORD);
  332. BEGIN
  333. section.Name := Name;
  334. section.VirtualSize := VirtualSize;
  335. section.SizeOfRawData := WR.align(VirtualSize, FileAlignment);
  336. section.PointerToRelocations := 0;
  337. section.PointerToLinenumbers := 0;
  338. section.NumberOfRelocations := 0X;
  339. section.NumberOfLinenumbers := 0X;
  340. section.Characteristics := Characteristics
  341. END InitSection;
  342. BEGIN
  343. IF (fa = 512) OR (fa = 1024) OR (fa = 2048) OR (fa = 4096) THEN
  344. FileAlignment := fa
  345. ELSE
  346. FileAlignment := 512
  347. END;
  348. SizeOfWord := SIZE_OF_DWORD * (ORD(amd64) + 1);
  349. Size.Code := CHL.Length(program.code);
  350. Size.Data := CHL.Length(program.data);
  351. Size.Bss := program.bss;
  352. IF dll THEN
  353. BaseAddress := 10000000H
  354. ELSE
  355. BaseAddress := 400000H
  356. END;
  357. Signature[0] := 50H;
  358. Signature[1] := 45H;
  359. Signature[2] := 0;
  360. Signature[3] := 0;
  361. IF amd64 THEN
  362. FileHeader.Machine := 08664X
  363. ELSE
  364. FileHeader.Machine := 014CX
  365. END;
  366. FileHeader.NumberOfSections := WCHR(4 + ORD(dll));
  367. FileHeader.TimeDateStamp := UTILS.UnixTime();
  368. FileHeader.PointerToSymbolTable := 0H;
  369. FileHeader.NumberOfSymbols := 0H;
  370. FileHeader.SizeOfOptionalHeader := WCHR(0E0H + 10H * ORD(amd64));
  371. FileHeader.Characteristics := WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll));
  372. OptionalHeader.Magic := WCHR(010BH + 100H * ORD(amd64));
  373. OptionalHeader.MajorLinkerVersion := UTILS.vMajor;
  374. OptionalHeader.MinorLinkerVersion := UTILS.vMinor;
  375. OptionalHeader.SizeOfCode := WR.align(Size.Code, FileAlignment);
  376. OptionalHeader.SizeOfInitializedData := 0;
  377. OptionalHeader.SizeOfUninitializedData := 0;
  378. OptionalHeader.AddressOfEntryPoint := SectionAlignment;
  379. OptionalHeader.BaseOfCode := SectionAlignment;
  380. OptionalHeader.BaseOfData := OptionalHeader.BaseOfCode + WR.align(Size.Code, SectionAlignment);
  381. OptionalHeader.ImageBase := BaseAddress;
  382. OptionalHeader.SectionAlignment := SectionAlignment;
  383. OptionalHeader.FileAlignment := FileAlignment;
  384. OptionalHeader.MajorOperatingSystemVersion := 1X;
  385. OptionalHeader.MinorOperatingSystemVersion := 0X;
  386. OptionalHeader.MajorImageVersion := 0X;
  387. OptionalHeader.MinorImageVersion := 0X;
  388. OptionalHeader.MajorSubsystemVersion := 4X;
  389. OptionalHeader.MinorSubsystemVersion := 0X;
  390. OptionalHeader.Win32VersionValue := 0H;
  391. OptionalHeader.SizeOfImage := SectionAlignment;
  392. OptionalHeader.SizeOfHeaders := MAX(FileAlignment, 1024);
  393. OptionalHeader.CheckSum := 0;
  394. OptionalHeader.Subsystem := WCHR((2 + ORD(console)) * ORD(~dll));
  395. OptionalHeader.DllCharacteristics := 0040X;
  396. OptionalHeader.SizeOfStackReserve := 100000H;
  397. OptionalHeader.SizeOfStackCommit := 10000H;
  398. OptionalHeader.SizeOfHeapReserve := 100000H;
  399. OptionalHeader.SizeOfHeapCommit := 10000H;
  400. OptionalHeader.LoaderFlags := 0;
  401. OptionalHeader.NumberOfRvaAndSizes := IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
  402. FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO
  403. OptionalHeader.DataDirectory[i].VirtualAddress := 0;
  404. OptionalHeader.DataDirectory[i].Size := 0
  405. END;
  406. InitSection(SectionHeaders[0], ".text", Size.Code, SHC_text);
  407. SectionHeaders[0].VirtualAddress := SectionAlignment;
  408. SectionHeaders[0].PointerToRawData := OptionalHeader.SizeOfHeaders;
  409. InitSection(SectionHeaders[1], ".data", Size.Data, SHC_data);
  410. SectionHeaders[1].VirtualAddress := WR.align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment);
  411. SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData;
  412. InitSection(SectionHeaders[2], ".bss", Size.Bss, SHC_bss);
  413. SectionHeaders[2].VirtualAddress := WR.align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment);
  414. SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData;
  415. SectionHeaders[2].SizeOfRawData := 0;
  416. Size.Import := GetImportSize(program.imp_list);
  417. InitSection(SectionHeaders[3], ".idata", Size.Import + CHL.Length(program._import), SHC_data);
  418. SectionHeaders[3].VirtualAddress := WR.align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment);
  419. SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData;
  420. Address.Code := SectionHeaders[0].VirtualAddress + OptionalHeader.ImageBase;
  421. Address.Data := SectionHeaders[1].VirtualAddress + OptionalHeader.ImageBase;
  422. Address.Bss := SectionHeaders[2].VirtualAddress + OptionalHeader.ImageBase;
  423. Address.Import := SectionHeaders[3].VirtualAddress + OptionalHeader.ImageBase;
  424. fixup(program, Address, amd64);
  425. IF dll THEN
  426. Size.Export := Export(program, SectionHeaders[1].VirtualAddress + program.modname, ExportDir);
  427. InitSection(SectionHeaders[4], ".edata", Size.Export + CHL.Length(program.export), SHC_data);
  428. SectionHeaders[4].VirtualAddress := WR.align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment);
  429. SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData;
  430. OptionalHeader.DataDirectory[0].VirtualAddress := SectionHeaders[4].VirtualAddress;
  431. OptionalHeader.DataDirectory[0].Size := SectionHeaders[4].VirtualSize
  432. END;
  433. OptionalHeader.DataDirectory[1].VirtualAddress := SectionHeaders[3].VirtualAddress;
  434. OptionalHeader.DataDirectory[1].Size := SectionHeaders[3].VirtualSize;
  435. FOR i := 1 TO ORD(FileHeader.NumberOfSections) - 1 DO
  436. INC(OptionalHeader.SizeOfInitializedData, SectionHeaders[i].SizeOfRawData)
  437. END;
  438. OptionalHeader.SizeOfUninitializedData := WR.align(SectionHeaders[2].VirtualSize, FileAlignment);
  439. FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO
  440. INC(OptionalHeader.SizeOfImage, WR.align(SectionHeaders[i].VirtualSize, SectionAlignment))
  441. END;
  442. n := 0;
  443. BIN.InitArray(msdos, n, "4D5A80000100000004001000FFFF000040010000000000004000000000000000");
  444. BIN.InitArray(msdos, n, "0000000000000000000000000000000000000000000000000000000080000000");
  445. BIN.InitArray(msdos, n, "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F");
  446. BIN.InitArray(msdos, n, "742062652072756E20696E20444F53206D6F64652E0D0A240000000000000000");
  447. WR.Create(FileName);
  448. WR.Write(msdos, LEN(msdos));
  449. WR.Write(Signature, LEN(Signature));
  450. WriteFileHeader(FileHeader);
  451. WriteOptHeader(OptionalHeader, amd64);
  452. FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO
  453. WriteSectionHeader(SectionHeaders[i])
  454. END;
  455. WR.Padding(FileAlignment);
  456. CHL.WriteToFile(program.code);
  457. WR.Padding(FileAlignment);
  458. CHL.WriteToFile(program.data);
  459. WR.Padding(FileAlignment);
  460. n := (libcnt + 1) * 5;
  461. ImportTable := CHL.CreateIntList();
  462. FOR i := 0 TO (Size.Import - n * SIZE_OF_DWORD) DIV SizeOfWord + n - 1 DO
  463. CHL.PushInt(ImportTable, 0)
  464. END;
  465. i := 0;
  466. _import := program.imp_list.first(BIN.IMPRT);
  467. WHILE _import # NIL DO
  468. IF _import.label = 0 THEN
  469. CHL.SetInt(ImportTable, i + 0, _import.OriginalFirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD);
  470. CHL.SetInt(ImportTable, i + 1, 0);
  471. CHL.SetInt(ImportTable, i + 2, 0);
  472. CHL.SetInt(ImportTable, i + 3, _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress);
  473. CHL.SetInt(ImportTable, i + 4, _import.FirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD);
  474. INC(i, 5)
  475. END;
  476. _import := _import.next(BIN.IMPRT)
  477. END;
  478. CHL.SetInt(ImportTable, i + 0, 0);
  479. CHL.SetInt(ImportTable, i + 1, 0);
  480. CHL.SetInt(ImportTable, i + 2, 0);
  481. CHL.SetInt(ImportTable, i + 3, 0);
  482. CHL.SetInt(ImportTable, i + 4, 0);
  483. _import := program.imp_list.first(BIN.IMPRT);
  484. WHILE _import # NIL DO
  485. IF _import.label # 0 THEN
  486. temp := _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2;
  487. CHL.SetInt(ImportTable, _import.OriginalFirstThunk + n, temp);
  488. CHL.SetInt(ImportTable, _import.FirstThunk + n, temp)
  489. END;
  490. _import := _import.next(BIN.IMPRT)
  491. END;
  492. FOR i := 0 TO n - 1 DO
  493. WR.Write32LE(CHL.GetInt(ImportTable, i))
  494. END;
  495. FOR i := n TO CHL.Length(ImportTable) - 1 DO
  496. IF amd64 THEN
  497. WR.Write64LE(CHL.GetInt(ImportTable, i))
  498. ELSE
  499. WR.Write32LE(CHL.GetInt(ImportTable, i))
  500. END
  501. END;
  502. CHL.WriteToFile(program._import);
  503. WR.Padding(FileAlignment);
  504. IF dll THEN
  505. INC(ExportDir.AddressOfFunctions, SectionHeaders[4].VirtualAddress);
  506. INC(ExportDir.AddressOfNames, SectionHeaders[4].VirtualAddress);
  507. INC(ExportDir.AddressOfNameOrdinals, SectionHeaders[4].VirtualAddress);
  508. WriteExportDir(ExportDir);
  509. export := program.exp_list.first(BIN.EXPRT);
  510. WHILE export # NIL DO
  511. WR.Write32LE(export.label + SectionHeaders[0].VirtualAddress);
  512. export := export.next(BIN.EXPRT)
  513. END;
  514. export := program.exp_list.first(BIN.EXPRT);
  515. WHILE export # NIL DO
  516. WR.Write32LE(export.nameoffs + Size.Export + SectionHeaders[4].VirtualAddress);
  517. export := export.next(BIN.EXPRT)
  518. END;
  519. FOR i := 0 TO ExportDir.NumberOfFunctions - 1 DO
  520. WriteWord(WCHR(i))
  521. END;
  522. CHL.WriteToFile(program.export);
  523. WR.Padding(FileAlignment)
  524. END;
  525. WR.Close
  526. END write;
  527. END PE32.