PE32.ob07 23 KB

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