librex 0.0.68 → 0.0.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. checksums.yaml +15 -0
  2. data/README.markdown +1 -1
  3. data/Rakefile +18 -16
  4. data/lib/rex.rb +14 -10
  5. data/lib/rex/LICENSE +2 -2
  6. data/lib/rex/arch.rb +76 -76
  7. data/lib/rex/arch/sparc.rb +57 -58
  8. data/lib/rex/arch/x86.rb +506 -496
  9. data/lib/rex/assembly/nasm.rb +83 -84
  10. data/lib/rex/compat.rb +228 -173
  11. data/lib/rex/constants.rb +47 -37
  12. data/lib/rex/elfparsey.rb +0 -3
  13. data/lib/rex/elfparsey/elf.rb +107 -110
  14. data/lib/rex/elfparsey/elfbase.rb +244 -247
  15. data/lib/rex/elfparsey/exceptions.rb +0 -3
  16. data/lib/rex/elfscan.rb +0 -3
  17. data/lib/rex/elfscan/scanner.rb +184 -166
  18. data/lib/rex/elfscan/search.rb +35 -38
  19. data/lib/rex/encoder/alpha2.rb +1 -2
  20. data/lib/rex/encoder/alpha2/alpha_mixed.rb +52 -53
  21. data/lib/rex/encoder/alpha2/alpha_upper.rb +62 -63
  22. data/lib/rex/encoder/alpha2/generic.rb +77 -78
  23. data/lib/rex/encoder/alpha2/unicode_mixed.rb +101 -97
  24. data/lib/rex/encoder/alpha2/unicode_upper.rb +106 -107
  25. data/lib/rex/encoder/bloxor/bloxor.rb +326 -0
  26. data/lib/rex/encoder/ndr.rb +68 -68
  27. data/lib/rex/encoder/nonalpha.rb +50 -51
  28. data/lib/rex/encoder/nonupper.rb +50 -51
  29. data/lib/rex/encoder/xdr.rb +78 -78
  30. data/lib/rex/encoder/xor.rb +52 -53
  31. data/lib/rex/encoder/xor/dword.rb +1 -2
  32. data/lib/rex/encoder/xor/dword_additive.rb +1 -2
  33. data/lib/rex/encoders/xor_dword.rb +17 -18
  34. data/lib/rex/encoders/xor_dword_additive.rb +35 -36
  35. data/lib/rex/encoding/xor.rb +0 -1
  36. data/lib/rex/encoding/xor/byte.rb +3 -4
  37. data/lib/rex/encoding/xor/dword.rb +3 -4
  38. data/lib/rex/encoding/xor/dword_additive.rb +72 -73
  39. data/lib/rex/encoding/xor/exceptions.rb +2 -3
  40. data/lib/rex/encoding/xor/generic.rb +129 -130
  41. data/lib/rex/encoding/xor/qword.rb +3 -4
  42. data/lib/rex/encoding/xor/word.rb +3 -4
  43. data/lib/rex/exceptions.rb +100 -101
  44. data/lib/rex/exploitation/cmdstager.rb +3 -3
  45. data/lib/rex/exploitation/cmdstager/base.rb +170 -156
  46. data/lib/rex/exploitation/cmdstager/bourne.rb +105 -0
  47. data/lib/rex/exploitation/cmdstager/debug_asm.rb +110 -113
  48. data/lib/rex/exploitation/cmdstager/debug_write.rb +106 -109
  49. data/lib/rex/exploitation/cmdstager/echo.rb +164 -0
  50. data/lib/rex/exploitation/cmdstager/printf.rb +122 -0
  51. data/lib/rex/exploitation/cmdstager/tftp.rb +34 -27
  52. data/lib/rex/exploitation/cmdstager/vbs.rb +95 -98
  53. data/lib/rex/exploitation/egghunter.rb +359 -346
  54. data/lib/rex/exploitation/encryptjs.rb +60 -60
  55. data/lib/rex/exploitation/heaplib.rb +76 -76
  56. data/lib/rex/exploitation/js.rb +6 -0
  57. data/lib/rex/exploitation/js/detect.rb +69 -0
  58. data/lib/rex/exploitation/js/memory.rb +81 -0
  59. data/lib/rex/exploitation/js/network.rb +84 -0
  60. data/lib/rex/exploitation/js/utils.rb +33 -0
  61. data/lib/rex/exploitation/jsobfu.rb +448 -424
  62. data/lib/rex/exploitation/obfuscatejs.rb +301 -301
  63. data/lib/rex/exploitation/omelet.rb +257 -257
  64. data/lib/rex/exploitation/opcodedb.rb +699 -699
  65. data/lib/rex/exploitation/ropdb.rb +189 -0
  66. data/lib/rex/exploitation/seh.rb +68 -68
  67. data/lib/rex/file.rb +96 -49
  68. data/lib/rex/image_source.rb +0 -3
  69. data/lib/rex/image_source/disk.rb +45 -48
  70. data/lib/rex/image_source/image_source.rb +33 -36
  71. data/lib/rex/image_source/memory.rb +17 -20
  72. data/lib/rex/io/bidirectional_pipe.rb +118 -115
  73. data/lib/rex/io/datagram_abstraction.rb +13 -14
  74. data/lib/rex/io/ring_buffer.rb +273 -273
  75. data/lib/rex/io/stream.rb +284 -284
  76. data/lib/rex/io/stream_abstraction.rb +183 -181
  77. data/lib/rex/io/stream_server.rb +193 -193
  78. data/lib/rex/job_container.rb +167 -167
  79. data/lib/rex/logging.rb +0 -1
  80. data/lib/rex/logging/log_dispatcher.rb +113 -113
  81. data/lib/rex/logging/log_sink.rb +17 -17
  82. data/lib/rex/logging/sinks/flatfile.rb +36 -36
  83. data/lib/rex/logging/sinks/stderr.rb +27 -27
  84. data/lib/rex/mac_oui.rb +16572 -16571
  85. data/lib/rex/machparsey.rb +0 -1
  86. data/lib/rex/machparsey/exceptions.rb +0 -1
  87. data/lib/rex/machparsey/mach.rb +160 -161
  88. data/lib/rex/machparsey/machbase.rb +367 -368
  89. data/lib/rex/machscan.rb +0 -1
  90. data/lib/rex/machscan/scanner.rb +175 -176
  91. data/lib/rex/mime/encoding.rb +17 -0
  92. data/lib/rex/mime/header.rb +58 -58
  93. data/lib/rex/mime/message.rb +140 -137
  94. data/lib/rex/mime/part.rb +41 -12
  95. data/lib/rex/nop/opty2.rb +90 -90
  96. data/lib/rex/nop/opty2_tables.rb +273 -273
  97. data/lib/rex/ole.rb +0 -4
  98. data/lib/rex/ole/clsid.rb +26 -30
  99. data/lib/rex/ole/difat.rb +121 -125
  100. data/lib/rex/ole/directory.rb +205 -209
  101. data/lib/rex/ole/direntry.rb +217 -221
  102. data/lib/rex/ole/fat.rb +79 -83
  103. data/lib/rex/ole/header.rb +178 -182
  104. data/lib/rex/ole/minifat.rb +49 -53
  105. data/lib/rex/ole/propset.rb +113 -117
  106. data/lib/rex/ole/samples/create_ole.rb +8 -9
  107. data/lib/rex/ole/samples/dir.rb +10 -11
  108. data/lib/rex/ole/samples/dump_stream.rb +14 -15
  109. data/lib/rex/ole/samples/ole_info.rb +5 -6
  110. data/lib/rex/ole/storage.rb +372 -376
  111. data/lib/rex/ole/stream.rb +33 -37
  112. data/lib/rex/ole/substorage.rb +20 -24
  113. data/lib/rex/ole/util.rb +137 -141
  114. data/lib/rex/parser/acunetix_nokogiri.rb +398 -398
  115. data/lib/rex/parser/apple_backup_manifestdb.rb +116 -116
  116. data/lib/rex/parser/appscan_nokogiri.rb +359 -359
  117. data/lib/rex/parser/arguments.rb +88 -88
  118. data/lib/rex/parser/burp_session_nokogiri.rb +258 -258
  119. data/lib/rex/parser/ci_nokogiri.rb +184 -184
  120. data/lib/rex/parser/foundstone_nokogiri.rb +334 -333
  121. data/lib/rex/parser/fusionvm_nokogiri.rb +94 -94
  122. data/lib/rex/parser/ini.rb +167 -167
  123. data/lib/rex/parser/ip360_aspl_xml.rb +84 -84
  124. data/lib/rex/parser/ip360_xml.rb +77 -77
  125. data/lib/rex/parser/mbsa_nokogiri.rb +224 -224
  126. data/lib/rex/parser/nessus_xml.rb +100 -100
  127. data/lib/rex/parser/netsparker_xml.rb +89 -75
  128. data/lib/rex/parser/nexpose_raw_nokogiri.rb +677 -677
  129. data/lib/rex/parser/nexpose_simple_nokogiri.rb +322 -322
  130. data/lib/rex/parser/nexpose_xml.rb +105 -105
  131. data/lib/rex/parser/nmap_nokogiri.rb +386 -386
  132. data/lib/rex/parser/nmap_xml.rb +116 -116
  133. data/lib/rex/parser/nokogiri_doc_mixin.rb +223 -221
  134. data/lib/rex/parser/openvas_nokogiri.rb +162 -162
  135. data/lib/rex/parser/outpost24_nokogiri.rb +239 -0
  136. data/lib/rex/parser/retina_xml.rb +90 -90
  137. data/lib/rex/parser/unattend.rb +171 -0
  138. data/lib/rex/parser/wapiti_nokogiri.rb +89 -89
  139. data/lib/rex/payloads/win32/common.rb +14 -14
  140. data/lib/rex/payloads/win32/kernel.rb +36 -36
  141. data/lib/rex/payloads/win32/kernel/common.rb +32 -32
  142. data/lib/rex/payloads/win32/kernel/recovery.rb +27 -27
  143. data/lib/rex/payloads/win32/kernel/stager.rb +170 -170
  144. data/lib/rex/peparsey.rb +0 -3
  145. data/lib/rex/peparsey/exceptions.rb +0 -3
  146. data/lib/rex/peparsey/pe.rb +196 -199
  147. data/lib/rex/peparsey/pe_memdump.rb +35 -38
  148. data/lib/rex/peparsey/pebase.rb +1633 -1652
  149. data/lib/rex/peparsey/section.rb +115 -124
  150. data/lib/rex/pescan.rb +0 -3
  151. data/lib/rex/pescan/analyze.rb +351 -351
  152. data/lib/rex/pescan/scanner.rb +182 -182
  153. data/lib/rex/pescan/search.rb +59 -59
  154. data/lib/rex/platforms/windows.rb +37 -37
  155. data/lib/rex/poly.rb +111 -110
  156. data/lib/rex/poly/block.rb +419 -417
  157. data/lib/rex/poly/machine.rb +12 -0
  158. data/lib/rex/poly/machine/machine.rb +829 -0
  159. data/lib/rex/poly/machine/x86.rb +508 -0
  160. data/lib/rex/poly/register.rb +70 -70
  161. data/lib/rex/poly/register/x86.rb +22 -22
  162. data/lib/rex/post.rb +0 -1
  163. data/lib/rex/post/dir.rb +35 -36
  164. data/lib/rex/post/file.rb +140 -141
  165. data/lib/rex/post/file_stat.rb +198 -199
  166. data/lib/rex/post/io.rb +167 -168
  167. data/lib/rex/post/meterpreter.rb +1 -1
  168. data/lib/rex/post/meterpreter/channel.rb +389 -390
  169. data/lib/rex/post/meterpreter/channel_container.rb +33 -34
  170. data/lib/rex/post/meterpreter/channels/pool.rb +129 -130
  171. data/lib/rex/post/meterpreter/channels/pools/file.rb +35 -36
  172. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +72 -73
  173. data/lib/rex/post/meterpreter/channels/stream.rb +62 -63
  174. data/lib/rex/post/meterpreter/client.rb +442 -436
  175. data/lib/rex/post/meterpreter/client_core.rb +326 -310
  176. data/lib/rex/post/meterpreter/dependencies.rb +0 -1
  177. data/lib/rex/post/meterpreter/extension.rb +12 -13
  178. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +35 -36
  179. data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +71 -0
  180. data/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb +169 -0
  181. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +45 -0
  182. data/lib/rex/post/meterpreter/extensions/extapi/service/service.rb +104 -0
  183. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +77 -0
  184. data/lib/rex/post/meterpreter/extensions/extapi/window/window.rb +56 -0
  185. data/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb +75 -0
  186. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +70 -71
  187. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +361 -0
  188. data/lib/rex/post/meterpreter/extensions/kiwi/tlv.rb +76 -0
  189. data/lib/rex/post/meterpreter/extensions/lanattacks/dhcp/dhcp.rb +78 -0
  190. data/lib/rex/post/meterpreter/extensions/lanattacks/lanattacks.rb +22 -78
  191. data/lib/rex/post/meterpreter/extensions/lanattacks/tftp/tftp.rb +49 -0
  192. data/lib/rex/post/meterpreter/extensions/lanattacks/tlv.rb +4 -4
  193. data/lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb +128 -0
  194. data/lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb +16 -0
  195. data/lib/rex/post/meterpreter/extensions/networkpug/networkpug.rb +38 -39
  196. data/lib/rex/post/meterpreter/extensions/networkpug/tlv.rb +1 -1
  197. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +95 -96
  198. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +39 -40
  199. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +80 -85
  200. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +94 -95
  201. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +207 -147
  202. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +258 -259
  203. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +366 -301
  204. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +72 -73
  205. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +24 -25
  206. data/lib/rex/post/meterpreter/extensions/stdapi/net/arp.rb +59 -0
  207. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +227 -149
  208. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +107 -108
  209. data/lib/rex/post/meterpreter/extensions/stdapi/net/netstat.rb +97 -0
  210. data/lib/rex/post/meterpreter/extensions/stdapi/net/resolve.rb +106 -0
  211. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +41 -42
  212. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +102 -101
  213. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +151 -152
  214. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +142 -142
  215. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +185 -185
  216. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +38118 -38117
  217. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +7 -7
  218. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +2086 -2084
  219. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_crypt32.rb +15 -15
  220. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi.rb +80 -80
  221. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3835 -3833
  222. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +84 -28
  223. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ntdll.rb +151 -137
  224. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_shell32.rb +15 -6
  225. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb +3155 -3155
  226. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_version.rb +41 -0
  227. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wlanapi.rb +70 -70
  228. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb +128 -0
  229. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb +596 -596
  230. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +310 -301
  231. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +71 -61
  232. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +100 -100
  233. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb +14 -14
  234. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb +488 -488
  235. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +273 -264
  236. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb +5 -5
  237. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +240 -238
  238. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +17 -15
  239. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +61 -61
  240. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +654 -635
  241. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +49 -49
  242. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +103 -102
  243. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +98 -68
  244. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +165 -166
  245. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +16 -17
  246. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +34 -36
  247. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +363 -364
  248. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +102 -103
  249. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +28 -29
  250. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +303 -304
  251. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +113 -114
  252. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +260 -261
  253. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +165 -166
  254. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +69 -70
  255. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +160 -161
  256. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +143 -144
  257. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +29 -12
  258. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +230 -231
  259. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +181 -44
  260. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +12 -13
  261. data/lib/rex/post/meterpreter/object_aliases.rb +56 -57
  262. data/lib/rex/post/meterpreter/packet.rb +591 -592
  263. data/lib/rex/post/meterpreter/packet_dispatcher.rb +506 -496
  264. data/lib/rex/post/meterpreter/packet_parser.rb +72 -73
  265. data/lib/rex/post/meterpreter/packet_response_waiter.rb +56 -57
  266. data/lib/rex/post/meterpreter/ui/console.rb +112 -112
  267. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +53 -53
  268. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +911 -854
  269. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +86 -86
  270. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi.rb +65 -0
  271. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +198 -0
  272. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +444 -0
  273. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb +199 -0
  274. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb +118 -0
  275. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb +108 -0
  276. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +220 -220
  277. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +509 -0
  278. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks.rb +60 -0
  279. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +254 -0
  280. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/tftp.rb +159 -0
  281. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +182 -0
  282. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +173 -173
  283. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +40 -40
  284. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +75 -77
  285. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +30 -30
  286. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +105 -105
  287. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +182 -182
  288. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +37 -37
  289. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +504 -482
  290. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +401 -330
  291. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +883 -581
  292. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +296 -299
  293. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +320 -153
  294. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +78 -78
  295. data/lib/rex/post/permission.rb +0 -1
  296. data/lib/rex/post/process.rb +39 -40
  297. data/lib/rex/post/thread.rb +41 -42
  298. data/lib/rex/post/ui.rb +35 -36
  299. data/lib/rex/proto/addp.rb +218 -0
  300. data/lib/rex/proto/dcerpc/client.rb +344 -344
  301. data/lib/rex/proto/dcerpc/exceptions.rb +128 -128
  302. data/lib/rex/proto/dcerpc/handle.rb +32 -32
  303. data/lib/rex/proto/dcerpc/ndr.rb +56 -56
  304. data/lib/rex/proto/dcerpc/packet.rb +249 -245
  305. data/lib/rex/proto/dcerpc/response.rb +170 -170
  306. data/lib/rex/proto/dcerpc/uuid.rb +65 -65
  307. data/lib/rex/proto/dcerpc/wdscp.rb +3 -0
  308. data/lib/rex/proto/dcerpc/wdscp/constants.rb +89 -0
  309. data/lib/rex/proto/dcerpc/wdscp/packet.rb +94 -0
  310. data/lib/rex/proto/dhcp.rb +0 -1
  311. data/lib/rex/proto/dhcp/constants.rb +0 -1
  312. data/lib/rex/proto/dhcp/server.rb +303 -304
  313. data/lib/rex/proto/drda/constants.rb +1 -1
  314. data/lib/rex/proto/drda/packet.rb +186 -186
  315. data/lib/rex/proto/drda/utils.rb +104 -104
  316. data/lib/rex/proto/http.rb +1 -0
  317. data/lib/rex/proto/http/client.rb +692 -820
  318. data/lib/rex/proto/http/client_request.rb +472 -0
  319. data/lib/rex/proto/http/handler.rb +25 -25
  320. data/lib/rex/proto/http/handler/erb.rb +104 -104
  321. data/lib/rex/proto/http/handler/proc.rb +37 -37
  322. data/lib/rex/proto/http/header.rb +149 -149
  323. data/lib/rex/proto/http/packet.rb +388 -382
  324. data/lib/rex/proto/http/request.rb +332 -335
  325. data/lib/rex/proto/http/response.rb +132 -72
  326. data/lib/rex/proto/http/server.rb +348 -338
  327. data/lib/rex/proto/iax2/call.rb +310 -310
  328. data/lib/rex/proto/iax2/client.rb +197 -197
  329. data/lib/rex/proto/iax2/codecs/alaw.rb +4 -4
  330. data/lib/rex/proto/iax2/codecs/mulaw.rb +4 -4
  331. data/lib/rex/proto/ipmi.rb +57 -0
  332. data/lib/rex/proto/ipmi/channel_auth_reply.rb +88 -0
  333. data/lib/rex/proto/ipmi/open_session_reply.rb +35 -0
  334. data/lib/rex/proto/ipmi/rakp2.rb +35 -0
  335. data/lib/rex/proto/ipmi/utils.rb +125 -0
  336. data/lib/rex/proto/natpmp.rb +1 -5
  337. data/lib/rex/proto/natpmp/constants.rb +4 -4
  338. data/lib/rex/proto/natpmp/packet.rb +25 -25
  339. data/lib/rex/proto/ntlm/base.rb +271 -271
  340. data/lib/rex/proto/ntlm/constants.rb +61 -61
  341. data/lib/rex/proto/ntlm/crypt.rb +348 -352
  342. data/lib/rex/proto/ntlm/exceptions.rb +3 -3
  343. data/lib/rex/proto/ntlm/message.rb +468 -471
  344. data/lib/rex/proto/ntlm/utils.rb +746 -746
  345. data/lib/rex/proto/pjl.rb +30 -0
  346. data/lib/rex/proto/pjl/client.rb +162 -0
  347. data/lib/rex/proto/proxy/socks4a.rb +440 -440
  348. data/lib/rex/proto/rfb.rb +1 -8
  349. data/lib/rex/proto/rfb/cipher.rb +46 -49
  350. data/lib/rex/proto/rfb/client.rb +179 -182
  351. data/lib/rex/proto/rfb/constants.rb +18 -21
  352. data/lib/rex/proto/smb/client.rb +1954 -1843
  353. data/lib/rex/proto/smb/constants.rb +533 -516
  354. data/lib/rex/proto/smb/crypt.rb +21 -21
  355. data/lib/rex/proto/smb/evasions.rb +43 -43
  356. data/lib/rex/proto/smb/exceptions.rb +791 -791
  357. data/lib/rex/proto/smb/simpleclient.rb +142 -286
  358. data/lib/rex/proto/smb/simpleclient/open_file.rb +106 -0
  359. data/lib/rex/proto/smb/simpleclient/open_pipe.rb +57 -0
  360. data/lib/rex/proto/smb/utils.rb +81 -81
  361. data/lib/rex/proto/sunrpc/client.rb +158 -158
  362. data/lib/rex/proto/tftp.rb +0 -1
  363. data/lib/rex/proto/tftp/client.rb +289 -289
  364. data/lib/rex/proto/tftp/constants.rb +9 -10
  365. data/lib/rex/proto/tftp/server.rb +466 -467
  366. data/lib/rex/random_identifier_generator.rb +176 -0
  367. data/lib/rex/registry.rb +1 -1
  368. data/lib/rex/registry/hive.rb +88 -88
  369. data/lib/rex/registry/lfkey.rb +25 -25
  370. data/lib/rex/registry/nodekey.rb +30 -30
  371. data/lib/rex/registry/regf.rb +10 -10
  372. data/lib/rex/registry/valuekey.rb +43 -43
  373. data/lib/rex/registry/valuelist.rb +13 -13
  374. data/lib/rex/ropbuilder/rop.rb +254 -253
  375. data/lib/rex/script.rb +21 -22
  376. data/lib/rex/script/base.rb +51 -50
  377. data/lib/rex/script/meterpreter.rb +2 -2
  378. data/lib/rex/service.rb +24 -24
  379. data/lib/rex/service_manager.rb +132 -132
  380. data/lib/rex/services/local_relay.rb +398 -398
  381. data/lib/rex/socket.rb +758 -763
  382. data/lib/rex/socket/comm.rb +95 -95
  383. data/lib/rex/socket/comm/local.rb +507 -440
  384. data/lib/rex/socket/ip.rb +118 -118
  385. data/lib/rex/socket/parameters.rb +351 -350
  386. data/lib/rex/socket/range_walker.rb +445 -368
  387. data/lib/rex/socket/ssl_tcp.rb +323 -317
  388. data/lib/rex/socket/ssl_tcp_server.rb +173 -158
  389. data/lib/rex/socket/subnet_walker.rb +48 -48
  390. data/lib/rex/socket/switch_board.rb +259 -259
  391. data/lib/rex/socket/tcp.rb +58 -56
  392. data/lib/rex/socket/tcp_server.rb +42 -42
  393. data/lib/rex/socket/udp.rb +152 -152
  394. data/lib/rex/sslscan/result.rb +200 -0
  395. data/lib/rex/sslscan/scanner.rb +205 -0
  396. data/lib/rex/struct2.rb +0 -1
  397. data/lib/rex/struct2/c_struct.rb +162 -163
  398. data/lib/rex/struct2/c_struct_template.rb +21 -22
  399. data/lib/rex/struct2/constant.rb +6 -7
  400. data/lib/rex/struct2/element.rb +30 -31
  401. data/lib/rex/struct2/generic.rb +60 -61
  402. data/lib/rex/struct2/restraint.rb +40 -41
  403. data/lib/rex/struct2/s_string.rb +60 -61
  404. data/lib/rex/struct2/s_struct.rb +97 -98
  405. data/lib/rex/sync.rb +0 -1
  406. data/lib/rex/sync/event.rb +62 -72
  407. data/lib/rex/sync/read_write_lock.rb +149 -149
  408. data/lib/rex/sync/ref.rb +42 -42
  409. data/lib/rex/sync/thread_safe.rb +59 -59
  410. data/lib/rex/text.rb +1803 -1315
  411. data/lib/rex/thread_factory.rb +25 -25
  412. data/lib/rex/time.rb +44 -44
  413. data/lib/rex/transformer.rb +91 -91
  414. data/lib/rex/ui/interactive.rb +265 -265
  415. data/lib/rex/ui/output.rb +66 -60
  416. data/lib/rex/ui/progress_tracker.rb +79 -79
  417. data/lib/rex/ui/subscriber.rb +144 -134
  418. data/lib/rex/ui/text/color.rb +76 -76
  419. data/lib/rex/ui/text/dispatcher_shell.rb +512 -505
  420. data/lib/rex/ui/text/input.rb +96 -96
  421. data/lib/rex/ui/text/input/buffer.rb +58 -58
  422. data/lib/rex/ui/text/input/readline.rb +114 -114
  423. data/lib/rex/ui/text/input/socket.rb +77 -77
  424. data/lib/rex/ui/text/input/stdio.rb +24 -24
  425. data/lib/rex/ui/text/irb_shell.rb +45 -41
  426. data/lib/rex/ui/text/output.rb +64 -60
  427. data/lib/rex/ui/text/output/buffer.rb +42 -42
  428. data/lib/rex/ui/text/output/buffer/stdout.rb +25 -0
  429. data/lib/rex/ui/text/output/file.rb +24 -24
  430. data/lib/rex/ui/text/output/socket.rb +24 -24
  431. data/lib/rex/ui/text/output/stdio.rb +29 -29
  432. data/lib/rex/ui/text/output/tee.rb +36 -36
  433. data/lib/rex/ui/text/progress_tracker.rb +37 -37
  434. data/lib/rex/ui/text/shell.rb +371 -361
  435. data/lib/rex/ui/text/table.rb +320 -284
  436. data/lib/rex/zip.rb +0 -1
  437. data/lib/rex/zip/archive.rb +115 -94
  438. data/lib/rex/zip/blocks.rb +101 -100
  439. data/lib/rex/zip/entry.rb +108 -99
  440. data/lib/rex/zip/jar.rb +261 -206
  441. data/lib/rex/zip/samples/comment.rb +1 -2
  442. data/lib/rex/zip/samples/mkwar.rb +12 -13
  443. data/lib/rex/zip/samples/mkzip.rb +1 -2
  444. data/lib/rex/zip/samples/recursive.rb +29 -30
  445. metadata +424 -446
  446. data/lib/rex/arch/sparc.rb.ut.rb +0 -19
  447. data/lib/rex/arch/x86.rb.ut.rb +0 -94
  448. data/lib/rex/assembly/nasm.rb.ut.rb +0 -23
  449. data/lib/rex/encoder/ndr.rb.ut.rb +0 -45
  450. data/lib/rex/encoder/xdr.rb.ut.rb +0 -30
  451. data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +0 -13
  452. data/lib/rex/encoding/xor.rb.ts.rb +0 -15
  453. data/lib/rex/encoding/xor/byte.rb.ut.rb +0 -22
  454. data/lib/rex/encoding/xor/dword.rb.ut.rb +0 -16
  455. data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +0 -16
  456. data/lib/rex/encoding/xor/generic.rb.ut.rb +0 -121
  457. data/lib/rex/encoding/xor/word.rb.ut.rb +0 -14
  458. data/lib/rex/exceptions.rb.ut.rb +0 -45
  459. data/lib/rex/exploitation/egghunter.rb.ut.rb +0 -28
  460. data/lib/rex/exploitation/javascriptosdetect.js +0 -1014
  461. data/lib/rex/exploitation/javascriptosdetect.rb +0 -43
  462. data/lib/rex/exploitation/omelet.rb.ut.rb +0 -27
  463. data/lib/rex/exploitation/opcodedb.rb.ut.rb +0 -280
  464. data/lib/rex/exploitation/seh.rb.ut.rb +0 -20
  465. data/lib/rex/file.rb.ut.rb +0 -17
  466. data/lib/rex/io/ring_buffer.rb.ut.rb +0 -135
  467. data/lib/rex/nop/opty2.rb.ut.rb +0 -24
  468. data/lib/rex/parser/arguments.rb.ut.rb +0 -68
  469. data/lib/rex/parser/ini.rb.ut.rb +0 -30
  470. data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +0 -18
  471. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb.ut.rb +0 -39
  472. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb.ut.rb +0 -37
  473. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb.ut.rb +0 -52
  474. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb +0 -43
  475. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb +0 -128
  476. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb.ut.rb +0 -64
  477. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb.ut.rb +0 -29
  478. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb +0 -155
  479. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb.ut.rb +0 -128
  480. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb +0 -124
  481. data/lib/rex/proto.rb.ts.rb +0 -9
  482. data/lib/rex/proto/dcerpc.rb.ts.rb +0 -10
  483. data/lib/rex/proto/dcerpc/client.rb.ut.rb +0 -492
  484. data/lib/rex/proto/dcerpc/handle.rb.ut.rb +0 -86
  485. data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +0 -42
  486. data/lib/rex/proto/dcerpc/packet.rb.ut.rb +0 -57
  487. data/lib/rex/proto/dcerpc/response.rb.ut.rb +0 -16
  488. data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +0 -47
  489. data/lib/rex/proto/drda.rb.ts.rb +0 -18
  490. data/lib/rex/proto/drda/constants.rb.ut.rb +0 -24
  491. data/lib/rex/proto/drda/packet.rb.ut.rb +0 -110
  492. data/lib/rex/proto/drda/utils.rb.ut.rb +0 -85
  493. data/lib/rex/proto/http.rb.ts.rb +0 -13
  494. data/lib/rex/proto/http/client.rb.ut.rb +0 -96
  495. data/lib/rex/proto/http/handler/erb.rb.ut.rb +0 -22
  496. data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +0 -1
  497. data/lib/rex/proto/http/handler/proc.rb.ut.rb +0 -25
  498. data/lib/rex/proto/http/header.rb.ut.rb +0 -47
  499. data/lib/rex/proto/http/packet.rb.ut.rb +0 -166
  500. data/lib/rex/proto/http/request.rb.ut.rb +0 -215
  501. data/lib/rex/proto/http/response.rb.ut.rb +0 -150
  502. data/lib/rex/proto/http/server.rb.ut.rb +0 -80
  503. data/lib/rex/proto/ntlm.rb.ut.rb +0 -181
  504. data/lib/rex/proto/rfb.rb.ut.rb +0 -40
  505. data/lib/rex/proto/smb.rb.ts.rb +0 -9
  506. data/lib/rex/proto/smb/client.rb.ut.rb +0 -224
  507. data/lib/rex/proto/smb/constants.rb.ut.rb +0 -19
  508. data/lib/rex/proto/smb/simpleclient.rb.ut.rb +0 -129
  509. data/lib/rex/proto/smb/utils.rb.ut.rb +0 -21
  510. data/lib/rex/proto/tftp/server.rb.ut.rb +0 -29
  511. data/lib/rex/service_manager.rb.ut.rb +0 -33
  512. data/lib/rex/socket.rb.ut.rb +0 -108
  513. data/lib/rex/socket/comm/local.rb.ut.rb +0 -76
  514. data/lib/rex/socket/parameters.rb.ut.rb +0 -52
  515. data/lib/rex/socket/range_walker.rb.ut.rb +0 -56
  516. data/lib/rex/socket/ssl_tcp.rb.ut.rb +0 -40
  517. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +0 -62
  518. data/lib/rex/socket/subnet_walker.rb.ut.rb +0 -29
  519. data/lib/rex/socket/switch_board.rb.ut.rb +0 -53
  520. data/lib/rex/socket/tcp.rb.ut.rb +0 -65
  521. data/lib/rex/socket/tcp_server.rb.ut.rb +0 -45
  522. data/lib/rex/socket/udp.rb.ut.rb +0 -45
  523. data/lib/rex/test.rb +0 -36
  524. data/lib/rex/text.rb.ut.rb +0 -193
  525. data/lib/rex/transformer.rb.ut.rb +0 -39
  526. data/lib/rex/ui/text/color.rb.ut.rb +0 -19
  527. data/lib/rex/ui/text/progress_tracker.rb.ut.rb +0 -35
  528. data/lib/rex/ui/text/table.rb.ut.rb +0 -56
@@ -1,8 +1,5 @@
1
- #!/usr/bin/env ruby
2
1
  # -*- coding: binary -*-
3
2
 
4
- # $Id: pebase.rb 15548 2012-06-29 06:08:20Z rapid7 $
5
-
6
3
  require 'rex/peparsey/exceptions'
7
4
  require 'rex/struct2'
8
5
 
@@ -11,1671 +8,1655 @@ module PeParsey
11
8
  class PeBase
12
9
 
13
10
 
14
- # #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
15
-
16
- IMAGE_DOS_SIGNATURE = 0x5a4d
17
-
18
- #
19
- # typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
20
- # WORD e_magic; // Magic number
21
- # WORD e_cblp; // Bytes on last page of file
22
- # WORD e_cp; // Pages in file
23
- # WORD e_crlc; // Relocations
24
- # WORD e_cparhdr; // Size of header in paragraphs
25
- # WORD e_minalloc; // Minimum extra paragraphs needed
26
- # WORD e_maxalloc; // Maximum extra paragraphs needed
27
- # WORD e_ss; // Initial (relative) SS value
28
- # WORD e_sp; // Initial SP value
29
- # WORD e_csum; // Checksum
30
- # WORD e_ip; // Initial IP value
31
- # WORD e_cs; // Initial (relative) CS value
32
- # WORD e_lfarlc; // File address of relocation table
33
- # WORD e_ovno; // Overlay number
34
- # WORD e_res[4]; // Reserved words
35
- # WORD e_oemid; // OEM identifier (for e_oeminfo)
36
- # WORD e_oeminfo; // OEM information; e_oemid specific
37
- # WORD e_res2[10]; // Reserved words
38
- # LONG e_lfanew; // File address of new exe header
39
- # } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
40
- #
41
-
42
- IMAGE_DOS_HEADER_SIZE = 64
43
- IMAGE_DOS_HEADER = Rex::Struct2::CStructTemplate.new(
44
- [ 'uint16v', 'e_magic', IMAGE_DOS_SIGNATURE ],
45
- [ 'uint16v', 'e_cblp', 0 ],
46
- [ 'uint16v', 'e_cp', 0 ],
47
- [ 'uint16v', 'e_crlc', 0 ],
48
- [ 'uint16v', 'e_cparhdr', 0 ],
49
- [ 'uint16v', 'e_minalloc', 0 ],
50
- [ 'uint16v', 'e_maxalloc', 0 ],
51
- [ 'uint16v', 'e_ss', 0 ],
52
- [ 'uint16v', 'e_sp', 0 ],
53
- [ 'uint16v', 'e_csum', 0 ],
54
- [ 'uint16v', 'e_ip', 0 ],
55
- [ 'uint16v', 'e_cs', 0 ],
56
- [ 'uint16v', 'e_lfarlc', 0 ],
57
- [ 'uint16v', 'e_ovno', 0 ],
58
- [ 'template', 'e_res', Rex::Struct2::CStructTemplate.new(
59
- [ 'uint16v', 'e_res_0', 0 ],
60
- [ 'uint16v', 'e_res_1', 0 ],
61
- [ 'uint16v', 'e_res_2', 0 ],
62
- [ 'uint16v', 'e_res_3', 0 ]
63
- )],
64
- [ 'uint16v', 'e_oemid', 0 ],
65
- [ 'uint16v', 'e_oeminfo', 0 ],
66
- [ 'template', 'e_res2', Rex::Struct2::CStructTemplate.new(
67
- [ 'uint16v', 'e_res2_0', 0 ],
68
- [ 'uint16v', 'e_res2_1', 0 ],
69
- [ 'uint16v', 'e_res2_2', 0 ],
70
- [ 'uint16v', 'e_res2_3', 0 ],
71
- [ 'uint16v', 'e_res2_4', 0 ],
72
- [ 'uint16v', 'e_res2_5', 0 ],
73
- [ 'uint16v', 'e_res2_6', 0 ],
74
- [ 'uint16v', 'e_res2_7', 0 ],
75
- [ 'uint16v', 'e_res2_8', 0 ],
76
- [ 'uint16v', 'e_res2_9', 0 ]
77
- )],
78
- [ 'uint32v', 'e_lfanew', 0 ]
79
- )
80
-
81
-
82
- class HeaderAccessor
83
- attr_accessor :dos, :file, :opt, :sections, :config, :exceptions, :tls
84
- def initialize
85
- end
86
- end
87
-
88
- class GenericStruct
89
- attr_accessor :struct
90
- def initialize(_struct)
91
- self.struct = _struct
92
- end
93
-
94
- # The following methods are just pass-throughs for struct
95
-
96
- # Access a value
97
- def v
98
- struct.v
99
- end
100
-
101
- # Access a value by array
102
- def [](*args)
103
- struct[*args]
104
- end
105
-
106
- # Obtain an array of all fields
107
- def keys
108
- struct.keys
109
- end
110
-
111
- def method_missing(meth, *args)
112
- v[meth.to_s] || (raise NoMethodError.new, meth)
113
- end
114
- end
115
-
116
- class GenericHeader < GenericStruct
117
- end
118
-
119
- class DosHeader < GenericHeader
120
-
121
- def initialize(rawdata)
122
- dos_header = IMAGE_DOS_HEADER.make_struct
123
-
124
- if !dos_header.from_s(rawdata)
125
- raise DosHeaderError, "Couldn't parse IMAGE_DOS_HEADER", caller
126
- end
127
-
128
- if dos_header.v['e_magic'] != IMAGE_DOS_SIGNATURE
129
- raise DosHeaderError, "Couldn't find DOS e_magic", caller
130
- end
131
-
132
- self.struct = dos_header
133
- end
134
-
135
- def e_lfanew
136
- v['e_lfanew']
137
- end
138
- end
139
-
140
-
141
- def self._parse_dos_header(rawdata)
142
- return DosHeader.new(rawdata)
143
- end
144
-
145
- #
146
- # typedef struct _IMAGE_FILE_HEADER {
147
- # WORD Machine;
148
- # WORD NumberOfSections;
149
- # DWORD TimeDateStamp;
150
- # DWORD PointerToSymbolTable;
151
- # DWORD NumberOfSymbols;
152
- # WORD SizeOfOptionalHeader;
153
- # WORD Characteristics;
154
- # } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
155
- #
156
- # #define IMAGE_NT_SIGNATURE 0x00004550 // PE00
157
- # #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
158
- # #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
159
- # #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
160
- # #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
161
- # #define IMAGE_SIZEOF_FILE_HEADER 20
162
- #
163
-
164
- IMAGE_NT_SIGNATURE = 0x00004550
165
- IMAGE_FILE_MACHINE_I386 = 0x014c
166
- IMAGE_FILE_MACHINE_IA64 = 0x0200
167
- IMAGE_FILE_MACHINE_ALPHA64 = 0x0284
168
- IMAGE_FILE_MACHINE_AMD64 = 0x8664
169
- IMAGE_FILE_HEADER_SIZE = 20+4 # because we include the signature
170
- IMAGE_FILE_HEADER = Rex::Struct2::CStructTemplate.new(
171
- # not really in the header, but easier for us this way
172
- [ 'uint32v', 'NtSignature', 0 ],
173
- [ 'uint16v', 'Machine', 0 ],
174
- [ 'uint16v', 'NumberOfSections', 0 ],
175
- [ 'uint32v', 'TimeDateStamp', 0 ],
176
- [ 'uint32v', 'PointerToSymbolTable', 0 ],
177
- [ 'uint32v', 'NumberOfSymbols', 0 ],
178
- [ 'uint16v', 'SizeOfOptionalHeader', 0 ],
179
- [ 'uint16v', 'Characteristics', 0 ]
180
- )
181
-
182
- SUPPORTED_MACHINES = [
183
- IMAGE_FILE_MACHINE_I386,
184
- IMAGE_FILE_MACHINE_IA64,
185
- IMAGE_FILE_MACHINE_ALPHA64,
186
- IMAGE_FILE_MACHINE_AMD64
187
- ]
188
-
189
- class FileHeader < GenericHeader
190
- def initialize(rawdata)
191
- file_header = IMAGE_FILE_HEADER.make_struct
192
-
193
- if !file_header.from_s(rawdata)
194
- raise FileHeaderError, "Couldn't parse IMAGE_FILE_HEADER", caller
195
- end
196
-
197
- if file_header.v['NtSignature'] != IMAGE_NT_SIGNATURE
198
- raise FileHeaderError, "Couldn't find the PE magic!"
199
- end
200
-
201
- if SUPPORTED_MACHINES.include?(file_header.v['Machine']) == false
202
- raise FileHeaderError, "Unsupported machine type: #{file_header.v['Machine']}", caller
203
- end
204
-
205
- self.struct = file_header
206
- end
207
-
208
- def Machine
209
- v['Machine']
210
- end
211
-
212
- def SizeOfOptionalHeader
213
- v['SizeOfOptionalHeader']
214
- end
215
-
216
- def NumberOfSections
217
- v['NumberOfSections']
218
- end
219
- end
220
-
221
- def self._parse_file_header(rawdata)
222
- return FileHeader.new(rawdata)
223
- end
224
-
225
- #
226
- # typedef struct _IMAGE_IMPORT_DESCRIPTOR {
227
- # union {
228
- # DWORD Characteristics; // 0 for terminating null import descriptor
229
- # DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
230
- # };
231
- # DWORD TimeDateStamp; // 0 if not bound,
232
- # // -1 if bound, and real date\time stamp
233
- # // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
234
- # // O.W. date/time stamp of DLL bound to (Old BIND)
235
- #
236
- # DWORD ForwarderChain; // -1 if no forwarders
237
- # DWORD Name;
238
- # DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
239
- # } IMAGE_IMPORT_DESCRIPTOR;
240
- #
241
- IMAGE_ORDINAL_FLAG32 = 0x80000000
242
- IMAGE_IMPORT_DESCRIPTOR_SIZE = 20
243
- IMAGE_IMPORT_DESCRIPTOR = Rex::Struct2::CStructTemplate.new(
244
- [ 'uint32v', 'OriginalFirstThunk', 0 ],
245
- [ 'uint32v', 'TimeDateStamp', 0 ],
246
- [ 'uint32v', 'ForwarderChain', 0 ],
247
- [ 'uint32v', 'Name', 0 ],
248
- [ 'uint32v', 'FirstThunk', 0 ]
249
- )
250
-
251
- #
252
- # typedef struct _IMAGE_IMPORT_BY_NAME {
253
- # WORD Hint;
254
- # BYTE Name[1];
255
- # } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
256
- #
257
-
258
- class ImportDescriptor
259
- attr_accessor :name, :entries
260
- def initialize(_name, _entries)
261
- self.name = _name
262
- self.entries = _entries
263
- end
264
- end
265
-
266
- class ImportEntry
267
- attr_accessor :name, :ordinal
268
- def initialize(_name, _ordinal)
269
- self.name = _name
270
- self.ordinal = _ordinal
271
- end
272
- end
273
-
274
- #
275
- # typedef struct _IMAGE_EXPORT_DIRECTORY {
276
- # DWORD Characteristics;
277
- # DWORD TimeDateStamp;
278
- # WORD MajorVersion;
279
- # WORD MinorVersion;
280
- # DWORD Name;
281
- # DWORD Base;
282
- # DWORD NumberOfFunctions;
283
- # DWORD NumberOfNames;
284
- # DWORD AddressOfFunctions; // RVA from base of image
285
- # DWORD AddressOfNames; // RVA from base of image
286
- # DWORD AddressOfNameOrdinals; // RVA from base of image
287
- # } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
288
- #
289
- IMAGE_EXPORT_DESCRIPTOR_SIZE = 40
290
- IMAGE_EXPORT_DESCRIPTOR = Rex::Struct2::CStructTemplate.new(
291
- [ 'uint32v', 'Characteristics', 0 ],
292
- [ 'uint32v', 'TimeDateStamp', 0 ],
293
- [ 'uint16v', 'MajorVersion', 0 ],
294
- [ 'uint16v', 'MinorVersion', 0 ],
295
- [ 'uint32v', 'Name', 0 ],
296
- [ 'uint32v', 'Base', 0 ],
297
- [ 'uint32v', 'NumberOfFunctions', 0 ],
298
- [ 'uint32v', 'NumberOfNames', 0 ],
299
- [ 'uint32v', 'AddressOfFunctions', 0 ],
300
- [ 'uint32v', 'AddressOfNames', 0 ],
301
- [ 'uint32v', 'AddressOfNameOrdinals', 0 ]
302
- )
303
-
304
- class ExportDirectory
305
- attr_accessor :name, :entries, :base
306
-
307
- def initialize(_name, _entries, _base)
308
- self.name = _name
309
- self.entries = _entries
310
- self.base = _base
311
- end
312
- end
313
-
314
- class ExportEntry
315
- attr_accessor :name, :ordinal, :rva
316
- def initialize(_name, _ordinal, _rva)
317
- self.name = _name
318
- self.ordinal = _ordinal
319
- self.rva = _rva
320
- end
321
- end
322
-
323
- #
324
- # typedef struct _IMAGE_DATA_DIRECTORY {
325
- # DWORD VirtualAddress;
326
- # DWORD Size;
327
- # } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
328
- #
329
- IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
330
- IMAGE_DATA_DIRECTORY_SIZE = 8
331
- IMAGE_DIRECTORY_ENTRY_EXPORT = 0
332
- IMAGE_DIRECTORY_ENTRY_IMPORT = 1
333
- IMAGE_DIRECTORY_ENTRY_RESOURCE = 2
334
- IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3
335
- IMAGE_DIRECTORY_ENTRY_SECURITY = 4
336
- IMAGE_DIRECTORY_ENTRY_BASERELOC = 5
337
- IMAGE_DIRECTORY_ENTRY_DEBUG = 6
338
- IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7
339
- IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7
340
- IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8
341
- IMAGE_DIRECTORY_ENTRY_TLS = 9
342
- IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
343
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11
344
- IMAGE_DIRECTORY_ENTRY_IAT = 12
345
- IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13
346
- IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
347
- IMAGE_DATA_DIRECTORY = Rex::Struct2::CStructTemplate.new(
348
- [ 'uint32v', 'VirtualAddress', 0 ],
349
- [ 'uint32v', 'Size', 0 ]
350
- )
351
-
352
- #
353
- # typedef struct _IMAGE_OPTIONAL_HEADER {
354
- # //
355
- # // Standard fields.
356
- # //
357
- #
358
- # WORD Magic;
359
- # BYTE MajorLinkerVersion;
360
- # BYTE MinorLinkerVersion;
361
- # DWORD SizeOfCode;
362
- # DWORD SizeOfInitializedData;
363
- # DWORD SizeOfUninitializedData;
364
- # DWORD AddressOfEntryPoint;
365
- # DWORD BaseOfCode;
366
- # DWORD BaseOfData;
367
- #
368
- # //
369
- # // NT additional fields.
370
- # //
371
- #
372
- # DWORD ImageBase;
373
- # DWORD SectionAlignment;
374
- # DWORD FileAlignment;
375
- # WORD MajorOperatingSystemVersion;
376
- # WORD MinorOperatingSystemVersion;
377
- # WORD MajorImageVersion;
378
- # WORD MinorImageVersion;
379
- # WORD MajorSubsystemVersion;
380
- # WORD MinorSubsystemVersion;
381
- # DWORD Win32VersionValue;
382
- # DWORD SizeOfImage;
383
- # DWORD SizeOfHeaders;
384
- # DWORD CheckSum;
385
- # WORD Subsystem;
386
- # WORD DllCharacteristics;
387
- # DWORD SizeOfStackReserve;
388
- # DWORD SizeOfStackCommit;
389
- # DWORD SizeOfHeapReserve;
390
- # DWORD SizeOfHeapCommit;
391
- # DWORD LoaderFlags;
392
- # DWORD NumberOfRvaAndSizes;
393
- # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
394
- # } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
395
- #
396
- # #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
397
- # #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
398
- #
399
-
400
- IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b
401
- IMAGE_SIZEOF_NT_OPTIONAL32_HEADER = 224
402
- IMAGE_OPTIONAL_HEADER32 = Rex::Struct2::CStructTemplate.new(
403
- [ 'uint16v', 'Magic', 0 ],
404
- [ 'uint8', 'MajorLinkerVersion', 0 ],
405
- [ 'uint8', 'MinorLinkerVersion', 0 ],
406
- [ 'uint32v', 'SizeOfCode', 0 ],
407
- [ 'uint32v', 'SizeOfInitializeData', 0 ],
408
- [ 'uint32v', 'SizeOfUninitializeData', 0 ],
409
- [ 'uint32v', 'AddressOfEntryPoint', 0 ],
410
- [ 'uint32v', 'BaseOfCode', 0 ],
411
- [ 'uint32v', 'BaseOfData', 0 ],
412
- [ 'uint32v', 'ImageBase', 0 ],
413
- [ 'uint32v', 'SectionAlignment', 0 ],
414
- [ 'uint32v', 'FileAlignment', 0 ],
415
- [ 'uint16v', 'MajorOperatingSystemVersion', 0 ],
416
- [ 'uint16v', 'MinorOperatingSystemVersion', 0 ],
417
- [ 'uint16v', 'MajorImageVersion', 0 ],
418
- [ 'uint16v', 'MinorImageVersion', 0 ],
419
- [ 'uint16v', 'MajorSubsystemVersion', 0 ],
420
- [ 'uint16v', 'MinorSubsystemVersion', 0 ],
421
- [ 'uint32v', 'Win32VersionValue', 0 ],
422
- [ 'uint32v', 'SizeOfImage', 0 ],
423
- [ 'uint32v', 'SizeOfHeaders', 0 ],
424
- [ 'uint32v', 'CheckSum', 0 ],
425
- [ 'uint16v', 'Subsystem', 0 ],
426
- [ 'uint16v', 'DllCharacteristics', 0 ],
427
- [ 'uint32v', 'SizeOfStackReserve', 0 ],
428
- [ 'uint32v', 'SizeOfStackCommit', 0 ],
429
- [ 'uint32v', 'SizeOfHeapReserve', 0 ],
430
- [ 'uint32v', 'SizeOfHeapCommit', 0 ],
431
- [ 'uint32v', 'LoaderFlags', 0 ],
432
- [ 'uint32v', 'NumberOfRvaAndSizes', 0 ],
433
- [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new(
434
- [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ],
435
- [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ],
436
- [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ],
437
- [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ],
438
- [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ],
439
- [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ],
440
- [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ],
441
- [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ],
442
- [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ],
443
- [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ],
444
- [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ],
445
- [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ],
446
- [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ],
447
- [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ],
448
- [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ],
449
- [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ]
450
- )]
451
- )
452
-
453
- #
454
- # typedef struct _IMAGE_OPTIONAL_HEADER64 {
455
- # USHORT Magic;
456
- # UCHAR MajorLinkerVersion;
457
- # UCHAR MinorLinkerVersion;
458
- # ULONG SizeOfCode;
459
- # ULONG SizeOfInitializedData;
460
- # ULONG SizeOfUninitializedData;
461
- # ULONG AddressOfEntryPoint;
462
- # ULONG BaseOfCode;
463
- # ULONGLONG ImageBase;
464
- # ULONG SectionAlignment;
465
- # ULONG FileAlignment;
466
- # USHORT MajorOperatingSystemVersion;
467
- # USHORT MinorOperatingSystemVersion;
468
- # USHORT MajorImageVersion;
469
- # USHORT MinorImageVersion;
470
- # USHORT MajorSubsystemVersion;
471
- # USHORT MinorSubsystemVersion;
472
- # ULONG Win32VersionValue;
473
- # ULONG SizeOfImage;
474
- # ULONG SizeOfHeaders;
475
- # ULONG CheckSum;
476
- # USHORT Subsystem;
477
- # USHORT DllCharacteristics;
478
- # ULONGLONG SizeOfStackReserve;
479
- # ULONGLONG SizeOfStackCommit;
480
- # ULONGLONG SizeOfHeapReserve;
481
- # ULONGLONG SizeOfHeapCommit;
482
- # ULONG LoaderFlags;
483
- # ULONG NumberOfRvaAndSizes;
484
- # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
485
- # } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
486
- #
487
- # #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
488
- # #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
489
- #
490
-
491
- IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
492
- IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240
493
- IMAGE_OPTIONAL_HEADER64 = Rex::Struct2::CStructTemplate.new(
494
- [ 'uint16v', 'Magic', 0 ],
495
- [ 'uint8', 'MajorLinkerVersion', 0 ],
496
- [ 'uint8', 'MinorLinkerVersion', 0 ],
497
- [ 'uint32v', 'SizeOfCode', 0 ],
498
- [ 'uint32v', 'SizeOfInitializeData', 0 ],
499
- [ 'uint32v', 'SizeOfUninitializeData', 0 ],
500
- [ 'uint32v', 'AddressOfEntryPoint', 0 ],
501
- [ 'uint32v', 'BaseOfCode', 0 ],
502
- [ 'uint64v', 'ImageBase', 0 ],
503
- [ 'uint32v', 'SectionAlignment', 0 ],
504
- [ 'uint32v', 'FileAlignment', 0 ],
505
- [ 'uint16v', 'MajorOperatingsystemVersion', 0 ],
506
- [ 'uint16v', 'MinorOperatingsystemVersion', 0 ],
507
- [ 'uint16v', 'MajorImageVersion', 0 ],
508
- [ 'uint16v', 'MinorImageVersion', 0 ],
509
- [ 'uint16v', 'MajorSubsystemVersion', 0 ],
510
- [ 'uint16v', 'MinorSubsystemVersion', 0 ],
511
- [ 'uint32v', 'Win32VersionValue', 0 ],
512
- [ 'uint32v', 'SizeOfImage', 0 ],
513
- [ 'uint32v', 'SizeOfHeaders', 0 ],
514
- [ 'uint32v', 'CheckSum', 0 ],
515
- [ 'uint16v', 'Subsystem', 0 ],
516
- [ 'uint16v', 'DllCharacteristics', 0 ],
517
- [ 'uint64v', 'SizeOfStackReserve', 0 ],
518
- [ 'uint64v', 'SizeOfStackCommit', 0 ],
519
- [ 'uint64v', 'SizeOfHeapReserve', 0 ],
520
- [ 'uint64v', 'SizeOfHeapCommit', 0 ],
521
- [ 'uint32v', 'LoaderFlags', 0 ],
522
- [ 'uint32v', 'NumberOfRvaAndSizes', 0 ],
523
- [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new(
524
- [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ],
525
- [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ],
526
- [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ],
527
- [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ],
528
- [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ],
529
- [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ],
530
- [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ],
531
- [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ],
532
- [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ],
533
- [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ],
534
- [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ],
535
- [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ],
536
- [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ],
537
- [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ],
538
- [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ],
539
- [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ]
540
- )]
541
- )
542
-
543
- class OptionalHeader < GenericHeader
544
- def ImageBase
545
- v['ImageBase']
546
- end
547
- def FileAlignment
548
- v['FileAlignment']
549
- end
550
- end
551
-
552
- class OptionalHeader32 < OptionalHeader
553
- def initialize(rawdata)
554
- optional_header = IMAGE_OPTIONAL_HEADER32.make_struct
555
-
556
- if !optional_header.from_s(rawdata)
557
- raise OptionalHeaderError, "Couldn't parse IMAGE_OPTIONAL_HEADER32", caller
558
- end
559
-
560
- if optional_header.v['Magic'] != IMAGE_NT_OPTIONAL_HDR32_MAGIC
561
- raise OptionalHeaderError, "Magic did not match!", caller()
562
- end
563
-
564
- self.struct = optional_header
565
- end
566
- end
567
-
568
- class OptionalHeader64 < OptionalHeader
569
- def initialize(rawdata)
570
- optional_header = IMAGE_OPTIONAL_HEADER64.make_struct
571
-
572
- if !optional_header.from_s(rawdata)
573
- raise OptionalHeaderError, "Couldn't parse IMAGE_OPTIONAL_HEADER64", caller
574
- end
575
-
576
- if optional_header.v['Magic'] != IMAGE_NT_OPTIONAL_HDR64_MAGIC
577
- raise OptionalHeaderError, "Magic did not match!", caller()
578
- end
579
-
580
- self.struct = optional_header
581
- end
582
- end
583
-
584
- def self._parse_optional_header(rawdata)
585
- case rawdata.length
586
- # no optional header
587
- when 0
588
- return nil
589
-
590
- # good, good
591
- when IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
592
- return OptionalHeader32.new(rawdata)
593
-
594
- when IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
595
- return OptionalHeader64.new(rawdata)
596
-
597
- # bad, bad
598
- else
599
- raise OptionalHeaderError, "I don't know this header size, #{rawdata.length}", caller
600
- end
601
-
602
- end
603
-
604
- #
605
- # typedef struct _IMAGE_SECTION_HEADER {
606
- # BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
607
- # union {
608
- # DWORD PhysicalAddress;
609
- # DWORD VirtualSize;
610
- # } Misc;
611
- # DWORD VirtualAddress;
612
- # DWORD SizeOfRawData;
613
- # DWORD PointerToRawData;
614
- # DWORD PointerToRelocations;
615
- # DWORD PointerToLinenumbers;
616
- # WORD NumberOfRelocations;
617
- # WORD NumberOfLinenumbers;
618
- # DWORD Characteristics;
619
- # } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
620
- #
621
- # #define IMAGE_SIZEOF_SECTION_HEADER 40
622
- #
623
-
624
- IMAGE_SIZEOF_SECTION_HEADER = 40
625
- IMAGE_SECTION_HEADER = Rex::Struct2::CStructTemplate.new(
626
- [ 'string', 'Name', 8, '' ],
627
- [ 'uint32v', 'Misc', 0 ],
628
- [ 'uint32v', 'VirtualAddress', 0 ],
629
- [ 'uint32v', 'SizeOfRawData', 0 ],
630
- [ 'uint32v', 'PointerToRawData', 0 ],
631
- [ 'uint32v', 'PointerToRelocations', 0 ],
632
- [ 'uint32v', 'NumberOfRelocations', 0 ],
633
- [ 'uint32v', 'NumberOfLineNumbers', 0 ],
634
- [ 'uint32v', 'Characteristics', 0 ]
635
- )
636
-
637
- class SectionHeader < GenericHeader
638
- def initialize(rawdata)
639
- section_header = IMAGE_SECTION_HEADER.make_struct
640
-
641
- if !section_header.from_s(rawdata)
642
- raise SectionHeaderError, "Could not parse header", caller
643
- end
644
-
645
- self.struct = section_header
646
- end
647
-
648
- def VirtualAddress
649
- v['VirtualAddress']
650
- end
651
- def SizeOfRawData
652
- v['SizeOfRawData']
653
- end
654
- def PointerToRawData
655
- v['PointerToRawData']
656
- end
657
- end
658
-
659
- def self._parse_section_headers(rawdata)
660
- section_headers = [ ]
661
- size = IMAGE_SIZEOF_SECTION_HEADER
662
- numsections = rawdata.length / size
663
-
664
- numsections.times do |i|
665
- data = rawdata[i * size, size]
666
- section_headers << SectionHeader.new(data)
667
- end
668
-
669
- return section_headers
670
- end
671
-
672
- #
673
- # typedef struct _IMAGE_BASE_RELOCATION {
674
- # DWORD VirtualAddress;
675
- # DWORD SizeOfBlock;
676
- # // WORD TypeOffset[1];
677
- # } IMAGE_BASE_RELOCATION;
678
- # typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
679
- #
680
- # #define IMAGE_SIZEOF_BASE_RELOCATION 8
681
- #
682
- IMAGE_SIZEOF_BASE_RELOCATION = 8
683
- IMAGE_BASE_RELOCATION = Rex::Struct2::CStructTemplate.new(
684
- [ 'uint32v', 'VirtualAddress', 0 ],
685
- [ 'uint32v', 'SizeOfBlock', 0 ]
686
- )
687
- IMAGE_BASE_RELOCATION_TYPE_OFFSET = Rex::Struct2::CStructTemplate.new(
688
- [ 'uint16v', 'TypeOffset', 0 ]
689
- )
690
-
691
- class RelocationDirectory
692
- attr_accessor :entries, :rva
693
-
694
- def initialize(rva, entries)
695
- self.rva = rva
696
- self.entries = entries
697
- self.name = name
698
- self.characteristics = chars
699
- self.timedate = timedate
700
- self.version = version
701
- self.entries = []
702
- end
703
- end
704
-
705
- class RelocationEntry
706
- attr_accessor :rva, :reltype
707
-
708
- def initialize(_rva, _type)
709
- self.rva = _rva
710
- self.reltype = _type
711
- end
712
- end
713
-
714
-
715
- class ResourceDirectory
716
- attr_accessor :entries, :name
717
-
718
- def initialize(name, entries)
719
- self.name = name
720
- self.entries = entries
721
- end
722
- end
723
-
724
- class ResourceEntry
725
- attr_accessor :path, :lang, :code, :rva, :size, :pe, :file
726
-
727
- def initialize(pe, path, lang, code, rva, size, file)
728
- self.pe = pe
729
- self.path = path
730
- self.lang = lang
731
- self.code = code
732
- self.rva = rva
733
- self.size = size
734
- self.file = file.to_s
735
- end
736
-
737
- def data
738
- pe._isource.read(pe.rva_to_file_offset(rva), size)
739
- end
740
- end
741
-
742
- #
743
- # typedef struct {
744
- # DWORD Size;
745
- # DWORD TimeDateStamp;
746
- # WORD MajorVersion;
747
- # WORD MinorVersion;
748
- # DWORD GlobalFlagsClear;
749
- # DWORD GlobalFlagsSet;
750
- # DWORD CriticalSectionDefaultTimeout;
751
- # DWORD DeCommitFreeBlockThreshold;
752
- # DWORD DeCommitTotalFreeThreshold;
753
- # DWORD LockPrefixTable; // VA
754
- # DWORD MaximumAllocationSize;
755
- # DWORD VirtualMemoryThreshold;
756
- # DWORD ProcessHeapFlags;
757
- # DWORD ProcessAffinityMask;
758
- # WORD CSDVersion;
759
- # WORD Reserved1;
760
- # DWORD EditList; // VA
761
- # DWORD SecurityCookie; // VA
762
- # DWORD SEHandlerTable; // VA
763
- # DWORD SEHandlerCount;
764
- # } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
765
- #
766
- IMAGE_LOAD_CONFIG_DIRECTORY32 = Rex::Struct2::CStructTemplate.new(
767
- [ 'uint32v', 'Size', 0 ],
768
- [ 'uint32v', 'TimeDateStamp', 0 ],
769
- [ 'uint16v', 'MajorVersion', 0 ],
770
- [ 'uint16v', 'MinorVersion', 0 ],
771
- [ 'uint32v', 'GlobalFlagsClear', 0 ],
772
- [ 'uint32v', 'GlobalFlagsSet', 0 ],
773
- [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
774
- [ 'uint32v', 'DeCommitFreeBlockThreshold', 0 ],
775
- [ 'uint32v', 'DeCommitTotalFreeThreshold', 0 ],
776
- [ 'uint32v', 'LockPrefixTable', 0 ],
777
- [ 'uint32v', 'MaximumAllocationSize', 0 ],
778
- [ 'uint32v', 'VirtualMemoryThreshold', 0 ],
779
- [ 'uint32v', 'ProcessHeapFlags', 0 ],
780
- [ 'uint32v', 'ProcessAffinityMask', 0 ],
781
- [ 'uint16v', 'CSDVersion', 0 ],
782
- [ 'uint16v', 'Reserved1', 0 ],
783
- [ 'uint32v', 'EditList', 0 ],
784
- [ 'uint32v', 'SecurityCookie', 0 ],
785
- [ 'uint32v', 'SEHandlerTable', 0 ],
786
- [ 'uint32v', 'SEHandlerCount', 0 ]
787
- )
788
-
789
- #
790
- # typedef struct {
791
- # ULONG Size;
792
- # ULONG TimeDateStamp;
793
- # USHORT MajorVersion;
794
- # USHORT MinorVersion;
795
- # ULONG GlobalFlagsClear;
796
- # ULONG GlobalFlagsSet;
797
- # ULONG CriticalSectionDefaultTimeout;
798
- # ULONGLONG DeCommitFreeBlockThreshold;
799
- # ULONGLONG DeCommitTotalFreeThreshold;
800
- # ULONGLONG LockPrefixTable; // VA
801
- # ULONGLONG MaximumAllocationSize;
802
- # ULONGLONG VirtualMemoryThreshold;
803
- # ULONGLONG ProcessAffinityMask;
804
- # ULONG ProcessHeapFlags;
805
- # USHORT CSDVersion;
806
- # USHORT Reserved1;
807
- # ULONGLONG EditList; // VA
808
- # ULONGLONG SecurityCookie; // VA
809
- # ULONGLONG SEHandlerTable; // VA
810
- # ULONGLONG SEHandlerCount;
811
- # } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
812
- #
813
- IMAGE_LOAD_CONFIG_DIRECTORY64 = Rex::Struct2::CStructTemplate.new(
814
- [ 'uint32v', 'Size', 0 ],
815
- [ 'uint32v', 'TimeDateStamp', 0 ],
816
- [ 'uint16v', 'MajorVersion', 0 ],
817
- [ 'uint16v', 'MinorVersion', 0 ],
818
- [ 'uint32v', 'GlobalFlagsClear', 0 ],
819
- [ 'uint32v', 'GlobalFlagsSet', 0 ],
820
- [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
821
- [ 'uint64v', 'DeCommitFreeBlockThreshold', 0 ],
822
- [ 'uint64v', 'DeCommitTotalFreeThreshold', 0 ],
823
- [ 'uint64v', 'LockPrefixTable', 0 ],
824
- [ 'uint64v', 'MaximumAllocationSize', 0 ],
825
- [ 'uint64v', 'VirtualMemoryThreshold', 0 ],
826
- [ 'uint64v', 'ProcessAffinityMask', 0 ],
827
- [ 'uint32v', 'ProcessHeapFlags', 0 ],
828
- [ 'uint16v', 'CSDVersion', 0 ],
829
- [ 'uint16v', 'Reserved1', 0 ],
830
- [ 'uint64v', 'EditList', 0 ],
831
- [ 'uint64v', 'SecurityCookie', 0 ],
832
- [ 'uint64v', 'SEHandlerTable', 0 ],
833
- [ 'uint64v', 'SEHandlerCount', 0 ]
834
- )
835
-
836
-
837
- class ConfigHeader < GenericHeader
838
-
839
- end
840
-
841
- # doesn't seem to be used -- not compatible with 64-bit
842
- #def self._parse_config_header(rawdata)
843
- # header = IMAGE_LOAD_CONFIG_DIRECTORY32.make_struct
844
- # header.from_s(rawdata)
845
- # ConfigHeader.new(header)
846
- #end
847
-
848
- def _parse_config_header
849
-
850
- #
851
- # Get the data directory entry, size, etc
852
- #
853
- exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]
854
- rva = exports_entry.v['VirtualAddress']
855
- size = exports_entry.v['Size']
856
-
857
- return nil if size == 0
858
-
859
- #
860
- # Ok, so we have the data directory, now lets parse it
861
- #
862
-
863
- dirdata = _isource.read(rva_to_file_offset(rva), size)
864
- klass = (ptr_64?) ? IMAGE_LOAD_CONFIG_DIRECTORY64 : IMAGE_LOAD_CONFIG_DIRECTORY32
865
- header = klass.make_struct
866
-
867
- header.from_s(dirdata)
868
-
869
- @config = ConfigHeader.new(header)
870
- end
871
-
872
-
873
- def config
874
- _parse_config_header if @config.nil?
875
- @config
876
- end
877
-
878
- #
879
- # TLS Directory
880
- #
881
-
882
- #
883
- # typedef struct {
884
- # DWORD Size;
885
- # DWORD TimeDateStamp;
886
- # WORD MajorVersion;
887
- # WORD MinorVersion;
888
- # DWORD GlobalFlagsClear;
889
- # DWORD GlobalFlagsSet;
890
- # DWORD CriticalSectionDefaultTimeout;
891
- # DWORD DeCommitFreeBlockThreshold;
892
- # DWORD DeCommitTotalFreeThreshold;
893
- # DWORD LockPrefixTable; // VA
894
- # DWORD MaximumAllocationSize;
895
- # DWORD VirtualMemoryThreshold;
896
- # DWORD ProcessHeapFlags;
897
- # DWORD ProcessAffinityMask;
898
- # WORD CSDVersion;
899
- # WORD Reserved1;
900
- # DWORD EditList; // VA
901
- # DWORD SecurityCookie; // VA
902
- # DWORD SEHandlerTable; // VA
903
- # DWORD SEHandlerCount;
904
- # } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
905
- #
906
- IMAGE_LOAD_TLS_DIRECTORY32 = Rex::Struct2::CStructTemplate.new(
907
- [ 'uint32v', 'Size', 0 ],
908
- [ 'uint32v', 'TimeDateStamp', 0 ],
909
- [ 'uint16v', 'MajorVersion', 0 ],
910
- [ 'uint16v', 'MinorVersion', 0 ],
911
- [ 'uint32v', 'GlobalFlagsClear', 0 ],
912
- [ 'uint32v', 'GlobalFlagsSet', 0 ],
913
- [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
914
- [ 'uint32v', 'DeCommitFreeBlockThreshold', 0 ],
915
- [ 'uint32v', 'DeCommitTotalFreeThreshold', 0 ],
916
- [ 'uint32v', 'LockPrefixTable', 0 ],
917
- [ 'uint32v', 'MaximumAllocationSize', 0 ],
918
- [ 'uint32v', 'VirtualMemoryThreshold', 0 ],
919
- [ 'uint32v', 'ProcessHeapFlags', 0 ],
920
- [ 'uint32v', 'ProcessAffinityMask', 0 ],
921
- [ 'uint16v', 'CSDVersion', 0 ],
922
- [ 'uint16v', 'Reserved1', 0 ],
923
- [ 'uint32v', 'EditList', 0 ],
924
- [ 'uint32v', 'SecurityCookie', 0 ],
925
- [ 'uint32v', 'SEHandlerTable', 0 ],
926
- [ 'uint32v', 'SEHandlerCount', 0 ]
927
- )
928
-
929
- #
930
- # typedef struct {
931
- # ULONG Size;
932
- # ULONG TimeDateStamp;
933
- # USHORT MajorVersion;
934
- # USHORT MinorVersion;
935
- # ULONG GlobalFlagsClear;
936
- # ULONG GlobalFlagsSet;
937
- # ULONG CriticalSectionDefaultTimeout;
938
- # ULONGLONG DeCommitFreeBlockThreshold;
939
- # ULONGLONG DeCommitTotalFreeThreshold;
940
- # ULONGLONG LockPrefixTable; // VA
941
- # ULONGLONG MaximumAllocationSize;
942
- # ULONGLONG VirtualMemoryThreshold;
943
- # ULONGLONG ProcessAffinityMask;
944
- # ULONG ProcessHeapFlags;
945
- # USHORT CSDVersion;
946
- # USHORT Reserved1;
947
- # ULONGLONG EditList; // VA
948
- # ULONGLONG SecurityCookie; // VA
949
- # ULONGLONG SEHandlerTable; // VA
950
- # ULONGLONG SEHandlerCount;
951
- # } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
952
- #
953
- IMAGE_LOAD_TLS_DIRECTORY64 = Rex::Struct2::CStructTemplate.new(
954
- [ 'uint32v', 'Size', 0 ],
955
- [ 'uint32v', 'TimeDateStamp', 0 ],
956
- [ 'uint16v', 'MajorVersion', 0 ],
957
- [ 'uint16v', 'MinorVersion', 0 ],
958
- [ 'uint32v', 'GlobalFlagsClear', 0 ],
959
- [ 'uint32v', 'GlobalFlagsSet', 0 ],
960
- [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
961
- [ 'uint64v', 'DeCommitFreeBlockThreshold', 0 ],
962
- [ 'uint64v', 'DeCommitTotalFreeThreshold', 0 ],
963
- [ 'uint64v', 'LockPrefixTable', 0 ],
964
- [ 'uint64v', 'MaximumAllocationSize', 0 ],
965
- [ 'uint64v', 'VirtualMemoryThreshold', 0 ],
966
- [ 'uint64v', 'ProcessAffinityMask', 0 ],
967
- [ 'uint32v', 'ProcessHeapFlags', 0 ],
968
- [ 'uint16v', 'CSDVersion', 0 ],
969
- [ 'uint16v', 'Reserved1', 0 ],
970
- [ 'uint64v', 'EditList', 0 ],
971
- [ 'uint64v', 'SecurityCookie', 0 ],
972
- [ 'uint64v', 'SEHandlerTable', 0 ],
973
- [ 'uint64v', 'SEHandlerCount', 0 ]
974
- )
975
-
976
-
977
- class TLSHeader < GenericHeader
978
-
979
- end
980
-
981
- def _parse_tls_header
982
-
983
- #
984
- # Get the data directory entry, size, etc
985
- #
986
- exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_TLS]
987
- rva = exports_entry.v['VirtualAddress']
988
- size = exports_entry.v['Size']
989
-
990
- return nil if size == 0
991
-
992
- #
993
- # Ok, so we have the data directory, now lets parse it
994
- #
995
-
996
- dirdata = _isource.read(rva_to_file_offset(rva), size)
997
- klass = (ptr_64?) ? IMAGE_LOAD_TLS_DIRECTORY64 : IMAGE_LOAD_TLS_DIRECTORY32
998
- header = klass.make_struct
999
-
1000
- header.from_s(dirdata)
1001
-
1002
- @tls = TLSHeader.new(header)
1003
- end
1004
-
1005
-
1006
- def tls
1007
- _parse_config_header if @tls.nil?
1008
- @tls
1009
- end
1010
-
1011
- ##
1012
- #
1013
- # Exception directory
1014
- #
1015
- ##
1016
-
1017
- #
1018
- # typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {
1019
- # DWORD BeginAddress;
1020
- # DWORD EndAddress;
1021
- # DWORD UnwindInfoAddress;
1022
- # } _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;
1023
- #
1024
- IMAGE_RUNTIME_FUNCTION_ENTRY_SZ = 12
1025
- IMAGE_RUNTIME_FUNCTION_ENTRY = Rex::Struct2::CStructTemplate.new(
1026
- [ 'uint32v', 'BeginAddress', 0 ],
1027
- [ 'uint32v', 'EndAddress', 0 ],
1028
- [ 'uint32v', 'UnwindInfoAddress', 0 ]
1029
- )
1030
-
1031
- UNWIND_INFO_HEADER_SZ = 4
1032
- UNWIND_INFO_HEADER = Rex::Struct2::CStructTemplate.new(
1033
- [ 'uint8', 'VersionFlags', 0 ],
1034
- [ 'uint8', 'SizeOfProlog', 0 ],
1035
- [ 'uint8', 'CountOfCodes', 0 ],
1036
- [ 'uint8', 'FrameRegisterAndOffset', 0 ]
1037
- )
1038
-
1039
- UWOP_PUSH_NONVOL = 0 # 1 node
1040
- UWOP_ALLOC_LARGE = 1 # 2 or 3 nodes
1041
- UWOP_ALLOC_SMALL = 2 # 1 node
1042
- UWOP_SET_FPREG = 3 # 1 node
1043
- UWOP_SAVE_NONVOL = 4 # 2 nodes
1044
- UWOP_SAVE_NONVOL_FAR = 5 # 3 nodes
1045
- UWOP_SAVE_XMM128 = 8 # 2 nodes
1046
- UWOP_SAVE_XMM128_FAR = 9 # 3 nodes
1047
- UWOP_PUSH_MACHFRAME = 10 # 1 node
1048
-
1049
- UNW_FLAG_EHANDLER = 1
1050
- UNW_FLAG_UHANDLER = 2
1051
- UNW_FLAG_CHAININFO = 4
1052
-
1053
- class UnwindCode
1054
- def initialize(data)
1055
-
1056
- self.code_offset = data[0].to_i
1057
- self.unwind_op = data[1].to_i & 0xf
1058
- self.op_info = data[1].to_i >> 4
1059
- self.frame_offset = data[2..3].unpack("v")[0]
1060
-
1061
- data.slice!(0, 4)
1062
- end
1063
-
1064
- attr_reader :code_offset, :unwind_op, :op_info, :frame_offset
1065
- attr_writer :code_offset, :unwind_op, :op_info, :frame_offset
1066
-
1067
- end
1068
-
1069
- class UnwindInfo
1070
- def initialize(pe, unwind_rva)
1071
- data = pe.read_rva(unwind_rva, UNWIND_INFO_HEADER_SZ)
1072
-
1073
- unwind = UNWIND_INFO_HEADER.make_struct
1074
- unwind.from_s(data)
1075
-
1076
- @version = unwind.v['VersionFlags'] & 0x7
1077
- @flags = unwind.v['VersionFlags'] >> 3
1078
- @size_of_prolog = unwind.v['SizeOfProlog']
1079
- @count_of_codes = unwind.v['CountOfCodes']
1080
- @frame_register = unwind.v['FrameRegisterAndOffset'] & 0xf
1081
- @frame_register_offset = unwind.v['FrameRegisterAndOffset'] >> 4
1082
-
1083
- # Parse unwind codes
1084
- clist = pe.read_rva(unwind_rva + UNWIND_INFO_HEADER_SZ, count_of_codes * 4)
1085
-
1086
- @unwind_codes = []
1087
-
1088
- while clist.length > 0
1089
- @unwind_codes << UnwindCode.new(clist)
1090
- end
1091
- end
1092
-
1093
- attr_reader :version, :flags, :size_of_prolog, :count_of_codes
1094
- attr_reader :frame_register, :frame_register_offset
1095
-
1096
- def unwind_codes
1097
- @unwind_codes
1098
- end
1099
-
1100
- end
1101
-
1102
- class RuntimeFunctionEntry
1103
-
1104
- def initialize(pe, data)
1105
- @pe = pe
1106
- @begin_address, @end_address, @unwind_info_address = data.unpack("VVV");
1107
- self.unwind_info = UnwindInfo.new(pe, unwind_info_address)
1108
- end
1109
-
1110
- attr_reader :begin_address, :end_address, :unwind_info_address
1111
- attr_reader :unwind_info
1112
- attr_writer :unwind_info
1113
-
1114
- end
1115
-
1116
- def _load_exception_directory
1117
- @exception = []
1118
-
1119
- exception_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_EXCEPTION]
1120
- rva = exception_entry.v['VirtualAddress']
1121
- size = exception_entry.v['Size']
1122
-
1123
- return if (rva == 0)
1124
-
1125
- data = _isource.read(rva_to_file_offset(rva), size)
1126
-
1127
- case hdr.file.Machine
1128
- when IMAGE_FILE_MACHINE_AMD64
1129
- count = data.length / IMAGE_RUNTIME_FUNCTION_ENTRY_SZ
1130
-
1131
- count.times { |current|
1132
- @exception << RuntimeFunctionEntry.new(self,
1133
- data.slice!(0, IMAGE_RUNTIME_FUNCTION_ENTRY_SZ))
1134
- }
1135
- else
1136
- end
1137
-
1138
- return @exception
1139
- end
1140
-
1141
-
1142
- def exception
1143
- _load_exception_directory if @exception.nil?
1144
- @exception
1145
- end
1146
-
1147
- #
1148
- # Just a stupid routine to round an offset up to it's alignment.
1149
- #
1150
- # For example, you're going to want this for FileAlignment and
1151
- # SectionAlignment, etc...
1152
- #
1153
- def self._align_offset(offset, alignment)
1154
- offset += alignment - 1
1155
- offset -= offset % alignment
1156
- return offset
1157
- end
1158
-
1159
- #
1160
- # instance stuff
1161
- #
1162
-
1163
- attr_accessor :_isource
1164
- attr_accessor :_dos_header, :_file_header, :_optional_header,
1165
- :_section_headers, :_config_header, :_tls_header, :_exception_header
1166
-
1167
- attr_accessor :sections, :header_section, :image_base
1168
-
1169
- attr_accessor :_imports_cache, :_imports_cached
1170
- attr_accessor :_exports_cache, :_exports_cached
1171
- attr_accessor :_relocations_cache, :_relocations_cached
1172
- attr_accessor :_resources_cache, :_resources_cached
1173
-
1174
- attr_accessor :hdr
1175
-
1176
- def self.new_from_file(filename, disk_backed = false)
1177
-
1178
- file = ::File.new(filename)
1179
- file.binmode # windows... :\
1180
-
1181
- if disk_backed
1182
- return self.new(ImageSource::Disk.new(file))
1183
- else
1184
- obj = new_from_string(file.read)
1185
- file.close
1186
- return obj
1187
- end
1188
- end
1189
-
1190
- def self.new_from_string(data)
1191
- return self.new(ImageSource::Memory.new(data))
1192
- end
1193
-
1194
- def close
1195
- _isource.close
1196
- end
1197
-
1198
- #
1199
- #
1200
- # Random rva, vma, file offset, section offset, etc
1201
- # conversion routines...
1202
- #
1203
- #
1204
- def rva_to_vma(rva)
1205
- return rva + image_base
1206
- end
1207
-
1208
- def vma_to_rva(vma)
1209
- return vma - image_base
1210
- end
1211
-
1212
- def rva_to_file_offset(rva)
1213
- all_sections.each do |section|
1214
- if section.contains_rva?(rva)
1215
- return section.rva_to_file_offset(rva)
1216
- end
1217
- end
1218
- raise WtfError, "wtf!", caller
1219
- end
1220
-
1221
- def vma_to_file_offset(vma)
1222
- return rva_to_file_offset(vma_to_rva(vma))
1223
- end
1224
-
1225
- def file_offset_to_rva(foffset)
1226
- if foffset < 0
1227
- raise WtfError, "lame", caller
1228
- end
1229
-
1230
- all_sections.each do |section|
1231
- if section.contains_file_offset?(foffset)
1232
- return section.file_offset_to_rva(foffset)
1233
- end
1234
- end
1235
-
1236
- raise WtfError, "wtf! #{foffset}", caller
1237
- end
1238
-
1239
- def file_offset_to_vma(foffset)
1240
- return rva_to_vma(file_offset_to_rva(foffset))
1241
- end
1242
-
1243
- #
1244
- #
1245
- # Some routines to find which section something belongs
1246
- # to. These will search all_sections (so including
1247
- # our fake header section, etc...
1248
- #
1249
- #
1250
-
1251
- #
1252
- # Find a section by an RVA
1253
- #
1254
- def _find_section_by_rva(rva)
1255
- all_sections.each do |section|
1256
- if section.contains_rva?(rva)
1257
- return section
1258
- end
1259
- end
1260
-
1261
- return nil
1262
- end
1263
- def find_section_by_rva(rva)
1264
- section = _find_section_by_rva(rva)
1265
-
1266
- if !section
1267
- raise WtfError, "Cannot find rva! #{rva}", caller
1268
- end
1269
-
1270
- return section
1271
- end
1272
-
1273
- #
1274
- # Find a section by a VMA
1275
- #
1276
- def find_section_by_vma(vma)
1277
- return find_section_by_rva(vma_to_rva(vma))
1278
- end
1279
-
1280
- def valid_rva?(rva)
1281
- _find_section_by_rva(rva) != nil
1282
- end
1283
- def valid_vma?(vma)
1284
- _find_section_by_rva(vma_to_rva(vma)) != nil
1285
- end
1286
-
1287
- #
1288
- #
1289
- # Some convenient methods to read a vma/rva without having
1290
- # the section... (inefficent though I suppose...)
1291
- #
1292
- #
1293
-
1294
- def read_rva(rva, length)
1295
- return find_section_by_rva(rva).read_rva(rva, length)
1296
- end
1297
-
1298
- def read_vma(vma, length)
1299
- return read_rva(vma_to_rva(vma), length)
1300
- end
1301
-
1302
- def read_asciiz_rva(rva)
1303
- return find_section_by_rva(rva).read_asciiz_rva(rva)
1304
- end
1305
-
1306
- def read_asciiz_vma(vma)
1307
- return read_asciiz_rva(vma_to_rva(vma))
1308
- end
1309
-
1310
- #
1311
- #
1312
- # Imports, exports, and other stuff!
1313
- #
1314
- #
1315
-
1316
- #
1317
- # We lazily parse the imports, and then cache it
1318
- #
1319
- def imports
1320
- if !_imports_cached
1321
- self._imports_cache = _load_imports
1322
- self._imports_cached = true
1323
- end
1324
- return _imports_cache
1325
- end
1326
-
1327
- def _load_imports
1328
- #
1329
- # Get the data directory entry, size, etc
1330
- #
1331
- imports_entry = _optional_header['DataDirectory'][1]
1332
- rva = imports_entry.v['VirtualAddress']
1333
- size = imports_entry.v['Size']
1334
-
1335
- return nil if size == 0
1336
-
1337
- #
1338
- # Ok, so we have the data directory, now lets parse it
1339
- #
1340
-
1341
- imports = [ ]
1342
-
1343
- descriptors_data = _isource.read(rva_to_file_offset(rva), size)
1344
-
1345
- while descriptors_data.length >= IMAGE_IMPORT_DESCRIPTOR_SIZE
1346
- descriptor = IMAGE_IMPORT_DESCRIPTOR.make_struct
1347
- descriptor.from_s(descriptors_data)
1348
- descriptors_data = descriptor.leftover
1349
-
1350
- othunk = descriptor.v['OriginalFirstThunk']
1351
- fthunk = descriptor.v['FirstThunk']
1352
-
1353
- break if fthunk == 0
1354
-
1355
- dllname = _isource.read_asciiz(rva_to_file_offset(descriptor.v['Name']))
1356
-
1357
- import = ImportDescriptor.new(dllname, [ ])
1358
-
1359
- # we prefer the Characteristics/OriginalFirstThunk...
1360
- thunk_off = rva_to_file_offset(othunk == 0 ? fthunk : othunk)
1361
-
1362
- while (orgrva = _isource.read(thunk_off, 4).unpack('V')[0]) != 0
1363
- hint = nil
1364
- name = nil
1365
-
1366
- if (orgrva & IMAGE_ORDINAL_FLAG32) != 0
1367
- hint = orgrva & 0xffff
1368
- else
1369
- foff = rva_to_file_offset(orgrva)
1370
- hint = _isource.read(foff, 2).unpack('v')[0]
1371
- name = _isource.read_asciiz(foff + 2)
1372
- end
1373
-
1374
- import.entries << ImportEntry.new(name, hint)
1375
-
1376
- thunk_off += 4
1377
- end
1378
-
1379
- imports << import
1380
- end
1381
-
1382
- return imports
1383
- end
1384
-
1385
-
1386
-
1387
- #
1388
- # We lazily parse the exports, and then cache it
1389
- #
1390
- def exports
1391
- if !_exports_cached
1392
- self._exports_cache = _load_exports
1393
- self._exports_cached = true
1394
- end
1395
- return _exports_cache
1396
- end
1397
-
1398
- def _load_exports
1399
-
1400
- #
1401
- # Get the data directory entry, size, etc
1402
- #
1403
- exports_entry = _optional_header['DataDirectory'][0]
1404
- rva = exports_entry.v['VirtualAddress']
1405
- size = exports_entry.v['Size']
1406
-
1407
- return nil if size == 0
11
+ # #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
12
+ IMAGE_DOS_SIGNATURE = 0x5a4d
13
+
14
+ IMAGE_DOS_HEADER_SIZE = 64
15
+ # Struct
16
+ # typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
17
+ # WORD e_magic; // Magic number
18
+ # WORD e_cblp; // Bytes on last page of file
19
+ # WORD e_cp; // Pages in file
20
+ # WORD e_crlc; // Relocations
21
+ # WORD e_cparhdr; // Size of header in paragraphs
22
+ # WORD e_minalloc; // Minimum extra paragraphs needed
23
+ # WORD e_maxalloc; // Maximum extra paragraphs needed
24
+ # WORD e_ss; // Initial (relative) SS value
25
+ # WORD e_sp; // Initial SP value
26
+ # WORD e_csum; // Checksum
27
+ # WORD e_ip; // Initial IP value
28
+ # WORD e_cs; // Initial (relative) CS value
29
+ # WORD e_lfarlc; // File address of relocation table
30
+ # WORD e_ovno; // Overlay number
31
+ # WORD e_res[4]; // Reserved words
32
+ # WORD e_oemid; // OEM identifier (for e_oeminfo)
33
+ # WORD e_oeminfo; // OEM information; e_oemid specific
34
+ # WORD e_res2[10]; // Reserved words
35
+ # LONG e_lfanew; // File address of new exe header
36
+ # } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
37
+ IMAGE_DOS_HEADER = Rex::Struct2::CStructTemplate.new(
38
+ [ 'uint16v', 'e_magic', IMAGE_DOS_SIGNATURE ],
39
+ [ 'uint16v', 'e_cblp', 0 ],
40
+ [ 'uint16v', 'e_cp', 0 ],
41
+ [ 'uint16v', 'e_crlc', 0 ],
42
+ [ 'uint16v', 'e_cparhdr', 0 ],
43
+ [ 'uint16v', 'e_minalloc', 0 ],
44
+ [ 'uint16v', 'e_maxalloc', 0 ],
45
+ [ 'uint16v', 'e_ss', 0 ],
46
+ [ 'uint16v', 'e_sp', 0 ],
47
+ [ 'uint16v', 'e_csum', 0 ],
48
+ [ 'uint16v', 'e_ip', 0 ],
49
+ [ 'uint16v', 'e_cs', 0 ],
50
+ [ 'uint16v', 'e_lfarlc', 0 ],
51
+ [ 'uint16v', 'e_ovno', 0 ],
52
+ [ 'template', 'e_res', Rex::Struct2::CStructTemplate.new(
53
+ [ 'uint16v', 'e_res_0', 0 ],
54
+ [ 'uint16v', 'e_res_1', 0 ],
55
+ [ 'uint16v', 'e_res_2', 0 ],
56
+ [ 'uint16v', 'e_res_3', 0 ]
57
+ )],
58
+ [ 'uint16v', 'e_oemid', 0 ],
59
+ [ 'uint16v', 'e_oeminfo', 0 ],
60
+ [ 'template', 'e_res2', Rex::Struct2::CStructTemplate.new(
61
+ [ 'uint16v', 'e_res2_0', 0 ],
62
+ [ 'uint16v', 'e_res2_1', 0 ],
63
+ [ 'uint16v', 'e_res2_2', 0 ],
64
+ [ 'uint16v', 'e_res2_3', 0 ],
65
+ [ 'uint16v', 'e_res2_4', 0 ],
66
+ [ 'uint16v', 'e_res2_5', 0 ],
67
+ [ 'uint16v', 'e_res2_6', 0 ],
68
+ [ 'uint16v', 'e_res2_7', 0 ],
69
+ [ 'uint16v', 'e_res2_8', 0 ],
70
+ [ 'uint16v', 'e_res2_9', 0 ]
71
+ )],
72
+ [ 'uint32v', 'e_lfanew', 0 ]
73
+ )
74
+
75
+
76
+ class HeaderAccessor
77
+ attr_accessor :dos, :file, :opt, :sections, :config, :exceptions, :tls
78
+ def initialize
79
+ end
80
+ end
81
+
82
+ class GenericStruct
83
+ attr_accessor :struct
84
+ def initialize(_struct)
85
+ self.struct = _struct
86
+ end
87
+
88
+ # The following methods are just pass-throughs for struct
89
+
90
+ # Access a value
91
+ def v
92
+ struct.v
93
+ end
94
+
95
+ # Access a value by array
96
+ def [](*args)
97
+ struct[*args]
98
+ end
99
+
100
+ # Obtain an array of all fields
101
+ def keys
102
+ struct.keys
103
+ end
104
+
105
+ def method_missing(meth, *args)
106
+ v[meth.to_s] || (raise NoMethodError.new, meth)
107
+ end
108
+ end
109
+
110
+ class GenericHeader < GenericStruct
111
+ end
112
+
113
+ class DosHeader < GenericHeader
114
+
115
+ def initialize(rawdata)
116
+ dos_header = IMAGE_DOS_HEADER.make_struct
117
+
118
+ if !dos_header.from_s(rawdata)
119
+ raise DosHeaderError, "Couldn't parse IMAGE_DOS_HEADER", caller
120
+ end
121
+
122
+ if dos_header.v['e_magic'] != IMAGE_DOS_SIGNATURE
123
+ raise DosHeaderError, "Couldn't find DOS e_magic", caller
124
+ end
125
+
126
+ self.struct = dos_header
127
+ end
128
+
129
+ def e_lfanew
130
+ v['e_lfanew']
131
+ end
132
+ end
133
+
134
+
135
+ def self._parse_dos_header(rawdata)
136
+ return DosHeader.new(rawdata)
137
+ end
138
+
139
+ # #define IMAGE_NT_SIGNATURE 0x00004550 // PE00
140
+ IMAGE_NT_SIGNATURE = 0x00004550
141
+ # #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
142
+ IMAGE_FILE_MACHINE_I386 = 0x014c
143
+ # #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
144
+ IMAGE_FILE_MACHINE_IA64 = 0x0200
145
+ # #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
146
+ IMAGE_FILE_MACHINE_ALPHA64 = 0x0284
147
+ # #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
148
+ IMAGE_FILE_MACHINE_AMD64 = 0x8664
149
+ # #define IMAGE_SIZEOF_FILE_HEADER 20
150
+ IMAGE_FILE_HEADER_SIZE = 20+4 # because we include the signature
151
+
152
+ # C struct defining the PE file header
153
+ # typedef struct _IMAGE_FILE_HEADER {
154
+ # WORD Machine;
155
+ # WORD NumberOfSections;
156
+ # DWORD TimeDateStamp;
157
+ # DWORD PointerToSymbolTable;
158
+ # DWORD NumberOfSymbols;
159
+ # WORD SizeOfOptionalHeader;
160
+ # WORD Characteristics;
161
+ # } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
162
+ IMAGE_FILE_HEADER = Rex::Struct2::CStructTemplate.new(
163
+ # not really in the header, but easier for us this way
164
+ [ 'uint32v', 'NtSignature', 0 ],
165
+ [ 'uint16v', 'Machine', 0 ],
166
+ [ 'uint16v', 'NumberOfSections', 0 ],
167
+ [ 'uint32v', 'TimeDateStamp', 0 ],
168
+ [ 'uint32v', 'PointerToSymbolTable', 0 ],
169
+ [ 'uint32v', 'NumberOfSymbols', 0 ],
170
+ [ 'uint16v', 'SizeOfOptionalHeader', 0 ],
171
+ [ 'uint16v', 'Characteristics', 0 ]
172
+ )
173
+
174
+ SUPPORTED_MACHINES = [
175
+ IMAGE_FILE_MACHINE_I386,
176
+ IMAGE_FILE_MACHINE_IA64,
177
+ IMAGE_FILE_MACHINE_ALPHA64,
178
+ IMAGE_FILE_MACHINE_AMD64
179
+ ]
180
+
181
+ class FileHeader < GenericHeader
182
+ def initialize(rawdata)
183
+ file_header = IMAGE_FILE_HEADER.make_struct
184
+
185
+ if !file_header.from_s(rawdata)
186
+ raise FileHeaderError, "Couldn't parse IMAGE_FILE_HEADER", caller
187
+ end
188
+
189
+ if file_header.v['NtSignature'] != IMAGE_NT_SIGNATURE
190
+ raise FileHeaderError, "Couldn't find the PE magic!"
191
+ end
192
+
193
+ if SUPPORTED_MACHINES.include?(file_header.v['Machine']) == false
194
+ raise FileHeaderError, "Unsupported machine type: #{file_header.v['Machine']}", caller
195
+ end
196
+
197
+ self.struct = file_header
198
+ end
199
+
200
+ def Machine
201
+ v['Machine']
202
+ end
203
+
204
+ def SizeOfOptionalHeader
205
+ v['SizeOfOptionalHeader']
206
+ end
207
+
208
+ def NumberOfSections
209
+ v['NumberOfSections']
210
+ end
211
+ end
212
+
213
+ def self._parse_file_header(rawdata)
214
+ return FileHeader.new(rawdata)
215
+ end
216
+
217
+ IMAGE_ORDINAL_FLAG32 = 0x80000000
218
+ IMAGE_IMPORT_DESCRIPTOR_SIZE = 20
219
+ # Struct
220
+ # typedef struct _IMAGE_IMPORT_DESCRIPTOR {
221
+ # union {
222
+ # DWORD Characteristics; // 0 for terminating null import descriptor
223
+ # DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
224
+ # };
225
+ # DWORD TimeDateStamp; // 0 if not bound,
226
+ # // -1 if bound, and real date\time stamp
227
+ # // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
228
+ # // O.W. date/time stamp of DLL bound to (Old BIND)
229
+ #
230
+ # DWORD ForwarderChain; // -1 if no forwarders
231
+ # DWORD Name;
232
+ # DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
233
+ # } IMAGE_IMPORT_DESCRIPTOR;
234
+ IMAGE_IMPORT_DESCRIPTOR = Rex::Struct2::CStructTemplate.new(
235
+ [ 'uint32v', 'OriginalFirstThunk', 0 ],
236
+ [ 'uint32v', 'TimeDateStamp', 0 ],
237
+ [ 'uint32v', 'ForwarderChain', 0 ],
238
+ [ 'uint32v', 'Name', 0 ],
239
+ [ 'uint32v', 'FirstThunk', 0 ]
240
+ )
241
+
242
+ # typedef struct _IMAGE_IMPORT_BY_NAME {
243
+ # WORD Hint;
244
+ # BYTE Name[1];
245
+ # } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
246
+ #
247
+
248
+ class ImportDescriptor
249
+ attr_accessor :name, :entries
250
+ def initialize(_name, _entries)
251
+ self.name = _name
252
+ self.entries = _entries
253
+ end
254
+ end
255
+
256
+ class ImportEntry
257
+ attr_accessor :name, :ordinal
258
+ def initialize(_name, _ordinal)
259
+ self.name = _name
260
+ self.ordinal = _ordinal
261
+ end
262
+ end
263
+
264
+ # sizeof(struct _IMAGE_EXPORT_DESCRIPTOR)
265
+ IMAGE_EXPORT_DESCRIPTOR_SIZE = 40
266
+ # Struct defining the export table
267
+ # typedef struct _IMAGE_EXPORT_DIRECTORY {
268
+ # DWORD Characteristics;
269
+ # DWORD TimeDateStamp;
270
+ # WORD MajorVersion;
271
+ # WORD MinorVersion;
272
+ # DWORD Name;
273
+ # DWORD Base;
274
+ # DWORD NumberOfFunctions;
275
+ # DWORD NumberOfNames;
276
+ # DWORD AddressOfFunctions; // RVA from base of image
277
+ # DWORD AddressOfNames; // RVA from base of image
278
+ # DWORD AddressOfNameOrdinals; // RVA from base of image
279
+ # } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
280
+ IMAGE_EXPORT_DESCRIPTOR = Rex::Struct2::CStructTemplate.new(
281
+ [ 'uint32v', 'Characteristics', 0 ],
282
+ [ 'uint32v', 'TimeDateStamp', 0 ],
283
+ [ 'uint16v', 'MajorVersion', 0 ],
284
+ [ 'uint16v', 'MinorVersion', 0 ],
285
+ [ 'uint32v', 'Name', 0 ],
286
+ [ 'uint32v', 'Base', 0 ],
287
+ [ 'uint32v', 'NumberOfFunctions', 0 ],
288
+ [ 'uint32v', 'NumberOfNames', 0 ],
289
+ [ 'uint32v', 'AddressOfFunctions', 0 ],
290
+ [ 'uint32v', 'AddressOfNames', 0 ],
291
+ [ 'uint32v', 'AddressOfNameOrdinals', 0 ]
292
+ )
293
+
294
+ class ExportDirectory
295
+ attr_accessor :name, :entries, :base
296
+
297
+ def initialize(_name, _entries, _base)
298
+ self.name = _name
299
+ self.entries = _entries
300
+ self.base = _base
301
+ end
302
+ end
303
+
304
+ class ExportEntry
305
+ attr_accessor :name, :ordinal, :rva
306
+ def initialize(_name, _ordinal, _rva)
307
+ self.name = _name
308
+ self.ordinal = _ordinal
309
+ self.rva = _rva
310
+ end
311
+ end
312
+
313
+ IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
314
+ IMAGE_DATA_DIRECTORY_SIZE = 8
315
+ IMAGE_DIRECTORY_ENTRY_EXPORT = 0
316
+ IMAGE_DIRECTORY_ENTRY_IMPORT = 1
317
+ IMAGE_DIRECTORY_ENTRY_RESOURCE = 2
318
+ IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3
319
+ IMAGE_DIRECTORY_ENTRY_SECURITY = 4
320
+ IMAGE_DIRECTORY_ENTRY_BASERELOC = 5
321
+ IMAGE_DIRECTORY_ENTRY_DEBUG = 6
322
+ IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7
323
+ IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7
324
+ IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8
325
+ IMAGE_DIRECTORY_ENTRY_TLS = 9
326
+ IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
327
+ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11
328
+ IMAGE_DIRECTORY_ENTRY_IAT = 12
329
+ IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13
330
+ IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
331
+ # Struct
332
+ # typedef struct _IMAGE_DATA_DIRECTORY {
333
+ # DWORD VirtualAddress;
334
+ # DWORD Size;
335
+ # } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
336
+ IMAGE_DATA_DIRECTORY = Rex::Struct2::CStructTemplate.new(
337
+ [ 'uint32v', 'VirtualAddress', 0 ],
338
+ [ 'uint32v', 'Size', 0 ]
339
+ )
340
+
341
+ # Struct
342
+ # typedef struct _IMAGE_OPTIONAL_HEADER {
343
+ # //
344
+ # // Standard fields.
345
+ # //
346
+ #
347
+ # WORD Magic;
348
+ # BYTE MajorLinkerVersion;
349
+ # BYTE MinorLinkerVersion;
350
+ # DWORD SizeOfCode;
351
+ # DWORD SizeOfInitializedData;
352
+ # DWORD SizeOfUninitializedData;
353
+ # DWORD AddressOfEntryPoint;
354
+ # DWORD BaseOfCode;
355
+ # DWORD BaseOfData;
356
+ #
357
+ # //
358
+ # // NT additional fields.
359
+ # //
360
+ #
361
+ # DWORD ImageBase;
362
+ # DWORD SectionAlignment;
363
+ # DWORD FileAlignment;
364
+ # WORD MajorOperatingSystemVersion;
365
+ # WORD MinorOperatingSystemVersion;
366
+ # WORD MajorImageVersion;
367
+ # WORD MinorImageVersion;
368
+ # WORD MajorSubsystemVersion;
369
+ # WORD MinorSubsystemVersion;
370
+ # DWORD Win32VersionValue;
371
+ # DWORD SizeOfImage;
372
+ # DWORD SizeOfHeaders;
373
+ # DWORD CheckSum;
374
+ # WORD Subsystem;
375
+ # WORD DllCharacteristics;
376
+ # DWORD SizeOfStackReserve;
377
+ # DWORD SizeOfStackCommit;
378
+ # DWORD SizeOfHeapReserve;
379
+ # DWORD SizeOfHeapCommit;
380
+ # DWORD LoaderFlags;
381
+ # DWORD NumberOfRvaAndSizes;
382
+ # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
383
+ # } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
384
+ #
385
+ # #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
386
+ # #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
387
+ #
388
+
389
+ IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b
390
+ IMAGE_SIZEOF_NT_OPTIONAL32_HEADER = 224
391
+ IMAGE_OPTIONAL_HEADER32 = Rex::Struct2::CStructTemplate.new(
392
+ [ 'uint16v', 'Magic', 0 ],
393
+ [ 'uint8', 'MajorLinkerVersion', 0 ],
394
+ [ 'uint8', 'MinorLinkerVersion', 0 ],
395
+ [ 'uint32v', 'SizeOfCode', 0 ],
396
+ [ 'uint32v', 'SizeOfInitializeData', 0 ],
397
+ [ 'uint32v', 'SizeOfUninitializeData', 0 ],
398
+ [ 'uint32v', 'AddressOfEntryPoint', 0 ],
399
+ [ 'uint32v', 'BaseOfCode', 0 ],
400
+ [ 'uint32v', 'BaseOfData', 0 ],
401
+ [ 'uint32v', 'ImageBase', 0 ],
402
+ [ 'uint32v', 'SectionAlignment', 0 ],
403
+ [ 'uint32v', 'FileAlignment', 0 ],
404
+ [ 'uint16v', 'MajorOperatingSystemVersion', 0 ],
405
+ [ 'uint16v', 'MinorOperatingSystemVersion', 0 ],
406
+ [ 'uint16v', 'MajorImageVersion', 0 ],
407
+ [ 'uint16v', 'MinorImageVersion', 0 ],
408
+ [ 'uint16v', 'MajorSubsystemVersion', 0 ],
409
+ [ 'uint16v', 'MinorSubsystemVersion', 0 ],
410
+ [ 'uint32v', 'Win32VersionValue', 0 ],
411
+ [ 'uint32v', 'SizeOfImage', 0 ],
412
+ [ 'uint32v', 'SizeOfHeaders', 0 ],
413
+ [ 'uint32v', 'CheckSum', 0 ],
414
+ [ 'uint16v', 'Subsystem', 0 ],
415
+ [ 'uint16v', 'DllCharacteristics', 0 ],
416
+ [ 'uint32v', 'SizeOfStackReserve', 0 ],
417
+ [ 'uint32v', 'SizeOfStackCommit', 0 ],
418
+ [ 'uint32v', 'SizeOfHeapReserve', 0 ],
419
+ [ 'uint32v', 'SizeOfHeapCommit', 0 ],
420
+ [ 'uint32v', 'LoaderFlags', 0 ],
421
+ [ 'uint32v', 'NumberOfRvaAndSizes', 0 ],
422
+ [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new(
423
+ [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ],
424
+ [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ],
425
+ [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ],
426
+ [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ],
427
+ [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ],
428
+ [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ],
429
+ [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ],
430
+ [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ],
431
+ [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ],
432
+ [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ],
433
+ [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ],
434
+ [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ],
435
+ [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ],
436
+ [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ],
437
+ [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ],
438
+ [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ]
439
+ )]
440
+ )
441
+
442
+ # #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
443
+ IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
444
+ # #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
445
+ IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240
446
+
447
+ # Struct
448
+ # typedef struct _IMAGE_OPTIONAL_HEADER64 {
449
+ # USHORT Magic;
450
+ # UCHAR MajorLinkerVersion;
451
+ # UCHAR MinorLinkerVersion;
452
+ # ULONG SizeOfCode;
453
+ # ULONG SizeOfInitializedData;
454
+ # ULONG SizeOfUninitializedData;
455
+ # ULONG AddressOfEntryPoint;
456
+ # ULONG BaseOfCode;
457
+ # ULONGLONG ImageBase;
458
+ # ULONG SectionAlignment;
459
+ # ULONG FileAlignment;
460
+ # USHORT MajorOperatingSystemVersion;
461
+ # USHORT MinorOperatingSystemVersion;
462
+ # USHORT MajorImageVersion;
463
+ # USHORT MinorImageVersion;
464
+ # USHORT MajorSubsystemVersion;
465
+ # USHORT MinorSubsystemVersion;
466
+ # ULONG Win32VersionValue;
467
+ # ULONG SizeOfImage;
468
+ # ULONG SizeOfHeaders;
469
+ # ULONG CheckSum;
470
+ # USHORT Subsystem;
471
+ # USHORT DllCharacteristics;
472
+ # ULONGLONG SizeOfStackReserve;
473
+ # ULONGLONG SizeOfStackCommit;
474
+ # ULONGLONG SizeOfHeapReserve;
475
+ # ULONGLONG SizeOfHeapCommit;
476
+ # ULONG LoaderFlags;
477
+ # ULONG NumberOfRvaAndSizes;
478
+ # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
479
+ # } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
480
+ IMAGE_OPTIONAL_HEADER64 = Rex::Struct2::CStructTemplate.new(
481
+ [ 'uint16v', 'Magic', 0 ],
482
+ [ 'uint8', 'MajorLinkerVersion', 0 ],
483
+ [ 'uint8', 'MinorLinkerVersion', 0 ],
484
+ [ 'uint32v', 'SizeOfCode', 0 ],
485
+ [ 'uint32v', 'SizeOfInitializeData', 0 ],
486
+ [ 'uint32v', 'SizeOfUninitializeData', 0 ],
487
+ [ 'uint32v', 'AddressOfEntryPoint', 0 ],
488
+ [ 'uint32v', 'BaseOfCode', 0 ],
489
+ [ 'uint64v', 'ImageBase', 0 ],
490
+ [ 'uint32v', 'SectionAlignment', 0 ],
491
+ [ 'uint32v', 'FileAlignment', 0 ],
492
+ [ 'uint16v', 'MajorOperatingsystemVersion', 0 ],
493
+ [ 'uint16v', 'MinorOperatingsystemVersion', 0 ],
494
+ [ 'uint16v', 'MajorImageVersion', 0 ],
495
+ [ 'uint16v', 'MinorImageVersion', 0 ],
496
+ [ 'uint16v', 'MajorSubsystemVersion', 0 ],
497
+ [ 'uint16v', 'MinorSubsystemVersion', 0 ],
498
+ [ 'uint32v', 'Win32VersionValue', 0 ],
499
+ [ 'uint32v', 'SizeOfImage', 0 ],
500
+ [ 'uint32v', 'SizeOfHeaders', 0 ],
501
+ [ 'uint32v', 'CheckSum', 0 ],
502
+ [ 'uint16v', 'Subsystem', 0 ],
503
+ [ 'uint16v', 'DllCharacteristics', 0 ],
504
+ [ 'uint64v', 'SizeOfStackReserve', 0 ],
505
+ [ 'uint64v', 'SizeOfStackCommit', 0 ],
506
+ [ 'uint64v', 'SizeOfHeapReserve', 0 ],
507
+ [ 'uint64v', 'SizeOfHeapCommit', 0 ],
508
+ [ 'uint32v', 'LoaderFlags', 0 ],
509
+ [ 'uint32v', 'NumberOfRvaAndSizes', 0 ],
510
+ [ 'template', 'DataDirectory', Rex::Struct2::CStructTemplate.new(
511
+ [ 'template', 'DataDirectoryEntry_0', IMAGE_DATA_DIRECTORY ],
512
+ [ 'template', 'DataDirectoryEntry_1', IMAGE_DATA_DIRECTORY ],
513
+ [ 'template', 'DataDirectoryEntry_2', IMAGE_DATA_DIRECTORY ],
514
+ [ 'template', 'DataDirectoryEntry_3', IMAGE_DATA_DIRECTORY ],
515
+ [ 'template', 'DataDirectoryEntry_4', IMAGE_DATA_DIRECTORY ],
516
+ [ 'template', 'DataDirectoryEntry_5', IMAGE_DATA_DIRECTORY ],
517
+ [ 'template', 'DataDirectoryEntry_6', IMAGE_DATA_DIRECTORY ],
518
+ [ 'template', 'DataDirectoryEntry_7', IMAGE_DATA_DIRECTORY ],
519
+ [ 'template', 'DataDirectoryEntry_8', IMAGE_DATA_DIRECTORY ],
520
+ [ 'template', 'DataDirectoryEntry_9', IMAGE_DATA_DIRECTORY ],
521
+ [ 'template', 'DataDirectoryEntry_10', IMAGE_DATA_DIRECTORY ],
522
+ [ 'template', 'DataDirectoryEntry_11', IMAGE_DATA_DIRECTORY ],
523
+ [ 'template', 'DataDirectoryEntry_12', IMAGE_DATA_DIRECTORY ],
524
+ [ 'template', 'DataDirectoryEntry_13', IMAGE_DATA_DIRECTORY ],
525
+ [ 'template', 'DataDirectoryEntry_14', IMAGE_DATA_DIRECTORY ],
526
+ [ 'template', 'DataDirectoryEntry_15', IMAGE_DATA_DIRECTORY ]
527
+ )]
528
+ )
529
+
530
+ class OptionalHeader < GenericHeader
531
+ def ImageBase
532
+ v['ImageBase']
533
+ end
534
+ def FileAlignment
535
+ v['FileAlignment']
536
+ end
537
+ end
538
+
539
+ class OptionalHeader32 < OptionalHeader
540
+ def initialize(rawdata)
541
+ optional_header = IMAGE_OPTIONAL_HEADER32.make_struct
542
+
543
+ if !optional_header.from_s(rawdata)
544
+ raise OptionalHeaderError, "Couldn't parse IMAGE_OPTIONAL_HEADER32", caller
545
+ end
546
+
547
+ if optional_header.v['Magic'] != IMAGE_NT_OPTIONAL_HDR32_MAGIC
548
+ raise OptionalHeaderError, "Magic did not match!", caller()
549
+ end
550
+
551
+ self.struct = optional_header
552
+ end
553
+ end
554
+
555
+ class OptionalHeader64 < OptionalHeader
556
+ def initialize(rawdata)
557
+ optional_header = IMAGE_OPTIONAL_HEADER64.make_struct
558
+
559
+ if !optional_header.from_s(rawdata)
560
+ raise OptionalHeaderError, "Couldn't parse IMAGE_OPTIONAL_HEADER64", caller
561
+ end
562
+
563
+ if optional_header.v['Magic'] != IMAGE_NT_OPTIONAL_HDR64_MAGIC
564
+ raise OptionalHeaderError, "Magic did not match!", caller()
565
+ end
566
+
567
+ self.struct = optional_header
568
+ end
569
+ end
570
+
571
+ def self._parse_optional_header(rawdata)
572
+ case rawdata.length
573
+ # no optional header
574
+ when 0
575
+ return nil
576
+
577
+ # good, good
578
+ when IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
579
+ return OptionalHeader32.new(rawdata)
580
+
581
+ when IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
582
+ return OptionalHeader64.new(rawdata)
583
+
584
+ # bad, bad
585
+ else
586
+ raise OptionalHeaderError, "I don't know this header size, #{rawdata.length}", caller
587
+ end
588
+
589
+ end
590
+
591
+ # #define IMAGE_SIZEOF_SECTION_HEADER 40
592
+ IMAGE_SIZEOF_SECTION_HEADER = 40
593
+ # Struct
594
+ # typedef struct _IMAGE_SECTION_HEADER {
595
+ # BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
596
+ # union {
597
+ # DWORD PhysicalAddress;
598
+ # DWORD VirtualSize;
599
+ # } Misc;
600
+ # DWORD VirtualAddress;
601
+ # DWORD SizeOfRawData;
602
+ # DWORD PointerToRawData;
603
+ # DWORD PointerToRelocations;
604
+ # DWORD PointerToLinenumbers;
605
+ # WORD NumberOfRelocations;
606
+ # WORD NumberOfLinenumbers;
607
+ # DWORD Characteristics;
608
+ # } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
609
+ IMAGE_SECTION_HEADER = Rex::Struct2::CStructTemplate.new(
610
+ [ 'string', 'Name', 8, '' ],
611
+ [ 'uint32v', 'Misc', 0 ],
612
+ [ 'uint32v', 'VirtualAddress', 0 ],
613
+ [ 'uint32v', 'SizeOfRawData', 0 ],
614
+ [ 'uint32v', 'PointerToRawData', 0 ],
615
+ [ 'uint32v', 'PointerToRelocations', 0 ],
616
+ [ 'uint32v', 'NumberOfRelocations', 0 ],
617
+ [ 'uint32v', 'NumberOfLineNumbers', 0 ],
618
+ [ 'uint32v', 'Characteristics', 0 ]
619
+ )
620
+
621
+ class SectionHeader < GenericHeader
622
+ def initialize(rawdata)
623
+ section_header = IMAGE_SECTION_HEADER.make_struct
624
+
625
+ if !section_header.from_s(rawdata)
626
+ raise SectionHeaderError, "Could not parse header", caller
627
+ end
628
+
629
+ self.struct = section_header
630
+ end
631
+
632
+ def VirtualAddress
633
+ v['VirtualAddress']
634
+ end
635
+ def SizeOfRawData
636
+ v['SizeOfRawData']
637
+ end
638
+ def PointerToRawData
639
+ v['PointerToRawData']
640
+ end
641
+ end
642
+
643
+ def self._parse_section_headers(rawdata)
644
+ section_headers = [ ]
645
+ size = IMAGE_SIZEOF_SECTION_HEADER
646
+ numsections = rawdata.length / size
647
+
648
+ numsections.times do |i|
649
+ data = rawdata[i * size, size]
650
+ section_headers << SectionHeader.new(data)
651
+ end
652
+
653
+ return section_headers
654
+ end
655
+
656
+ # #define IMAGE_SIZEOF_BASE_RELOCATION 8
657
+ IMAGE_SIZEOF_BASE_RELOCATION = 8
658
+
659
+ # Struct
660
+ # typedef struct _IMAGE_BASE_RELOCATION {
661
+ # DWORD VirtualAddress;
662
+ # DWORD SizeOfBlock;
663
+ # // WORD TypeOffset[1];
664
+ # } IMAGE_BASE_RELOCATION;
665
+ # typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
666
+ IMAGE_BASE_RELOCATION = Rex::Struct2::CStructTemplate.new(
667
+ [ 'uint32v', 'VirtualAddress', 0 ],
668
+ [ 'uint32v', 'SizeOfBlock', 0 ]
669
+ )
670
+ IMAGE_BASE_RELOCATION_TYPE_OFFSET = Rex::Struct2::CStructTemplate.new(
671
+ [ 'uint16v', 'TypeOffset', 0 ]
672
+ )
673
+
674
+ class RelocationDirectory
675
+ attr_accessor :entries, :rva
676
+
677
+ def initialize(rva, entries)
678
+ self.rva = rva
679
+ self.entries = entries
680
+ self.name = name
681
+ self.characteristics = chars
682
+ self.timedate = timedate
683
+ self.version = version
684
+ self.entries = []
685
+ end
686
+ end
687
+
688
+ class RelocationEntry
689
+ attr_accessor :rva, :reltype
690
+
691
+ def initialize(_rva, _type)
692
+ self.rva = _rva
693
+ self.reltype = _type
694
+ end
695
+ end
696
+
697
+
698
+ class ResourceDirectory
699
+ attr_accessor :entries, :name
700
+
701
+ def initialize(name, entries)
702
+ self.name = name
703
+ self.entries = entries
704
+ end
705
+ end
706
+
707
+ class ResourceEntry
708
+ attr_accessor :path, :lang, :code, :rva, :size, :pe, :file
709
+
710
+ def initialize(pe, path, lang, code, rva, size, file)
711
+ self.pe = pe
712
+ self.path = path
713
+ self.lang = lang
714
+ self.code = code
715
+ self.rva = rva
716
+ self.size = size
717
+ self.file = file.to_s
718
+ end
719
+
720
+ def data
721
+ pe._isource.read(pe.rva_to_file_offset(rva), size)
722
+ end
723
+ end
724
+
725
+ # Struct
726
+ # typedef struct {
727
+ # DWORD Size;
728
+ # DWORD TimeDateStamp;
729
+ # WORD MajorVersion;
730
+ # WORD MinorVersion;
731
+ # DWORD GlobalFlagsClear;
732
+ # DWORD GlobalFlagsSet;
733
+ # DWORD CriticalSectionDefaultTimeout;
734
+ # DWORD DeCommitFreeBlockThreshold;
735
+ # DWORD DeCommitTotalFreeThreshold;
736
+ # DWORD LockPrefixTable; // VA
737
+ # DWORD MaximumAllocationSize;
738
+ # DWORD VirtualMemoryThreshold;
739
+ # DWORD ProcessHeapFlags;
740
+ # DWORD ProcessAffinityMask;
741
+ # WORD CSDVersion;
742
+ # WORD Reserved1;
743
+ # DWORD EditList; // VA
744
+ # DWORD SecurityCookie; // VA
745
+ # DWORD SEHandlerTable; // VA
746
+ # DWORD SEHandlerCount;
747
+ # } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
748
+ #
749
+ IMAGE_LOAD_CONFIG_DIRECTORY32 = Rex::Struct2::CStructTemplate.new(
750
+ [ 'uint32v', 'Size', 0 ],
751
+ [ 'uint32v', 'TimeDateStamp', 0 ],
752
+ [ 'uint16v', 'MajorVersion', 0 ],
753
+ [ 'uint16v', 'MinorVersion', 0 ],
754
+ [ 'uint32v', 'GlobalFlagsClear', 0 ],
755
+ [ 'uint32v', 'GlobalFlagsSet', 0 ],
756
+ [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
757
+ [ 'uint32v', 'DeCommitFreeBlockThreshold', 0 ],
758
+ [ 'uint32v', 'DeCommitTotalFreeThreshold', 0 ],
759
+ [ 'uint32v', 'LockPrefixTable', 0 ],
760
+ [ 'uint32v', 'MaximumAllocationSize', 0 ],
761
+ [ 'uint32v', 'VirtualMemoryThreshold', 0 ],
762
+ [ 'uint32v', 'ProcessHeapFlags', 0 ],
763
+ [ 'uint32v', 'ProcessAffinityMask', 0 ],
764
+ [ 'uint16v', 'CSDVersion', 0 ],
765
+ [ 'uint16v', 'Reserved1', 0 ],
766
+ [ 'uint32v', 'EditList', 0 ],
767
+ [ 'uint32v', 'SecurityCookie', 0 ],
768
+ [ 'uint32v', 'SEHandlerTable', 0 ],
769
+ [ 'uint32v', 'SEHandlerCount', 0 ]
770
+ )
771
+
772
+ # Struct
773
+ # typedef struct {
774
+ # ULONG Size;
775
+ # ULONG TimeDateStamp;
776
+ # USHORT MajorVersion;
777
+ # USHORT MinorVersion;
778
+ # ULONG GlobalFlagsClear;
779
+ # ULONG GlobalFlagsSet;
780
+ # ULONG CriticalSectionDefaultTimeout;
781
+ # ULONGLONG DeCommitFreeBlockThreshold;
782
+ # ULONGLONG DeCommitTotalFreeThreshold;
783
+ # ULONGLONG LockPrefixTable; // VA
784
+ # ULONGLONG MaximumAllocationSize;
785
+ # ULONGLONG VirtualMemoryThreshold;
786
+ # ULONGLONG ProcessAffinityMask;
787
+ # ULONG ProcessHeapFlags;
788
+ # USHORT CSDVersion;
789
+ # USHORT Reserved1;
790
+ # ULONGLONG EditList; // VA
791
+ # ULONGLONG SecurityCookie; // VA
792
+ # ULONGLONG SEHandlerTable; // VA
793
+ # ULONGLONG SEHandlerCount;
794
+ # } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
795
+ IMAGE_LOAD_CONFIG_DIRECTORY64 = Rex::Struct2::CStructTemplate.new(
796
+ [ 'uint32v', 'Size', 0 ],
797
+ [ 'uint32v', 'TimeDateStamp', 0 ],
798
+ [ 'uint16v', 'MajorVersion', 0 ],
799
+ [ 'uint16v', 'MinorVersion', 0 ],
800
+ [ 'uint32v', 'GlobalFlagsClear', 0 ],
801
+ [ 'uint32v', 'GlobalFlagsSet', 0 ],
802
+ [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
803
+ [ 'uint64v', 'DeCommitFreeBlockThreshold', 0 ],
804
+ [ 'uint64v', 'DeCommitTotalFreeThreshold', 0 ],
805
+ [ 'uint64v', 'LockPrefixTable', 0 ],
806
+ [ 'uint64v', 'MaximumAllocationSize', 0 ],
807
+ [ 'uint64v', 'VirtualMemoryThreshold', 0 ],
808
+ [ 'uint64v', 'ProcessAffinityMask', 0 ],
809
+ [ 'uint32v', 'ProcessHeapFlags', 0 ],
810
+ [ 'uint16v', 'CSDVersion', 0 ],
811
+ [ 'uint16v', 'Reserved1', 0 ],
812
+ [ 'uint64v', 'EditList', 0 ],
813
+ [ 'uint64v', 'SecurityCookie', 0 ],
814
+ [ 'uint64v', 'SEHandlerTable', 0 ],
815
+ [ 'uint64v', 'SEHandlerCount', 0 ]
816
+ )
817
+
818
+
819
+ class ConfigHeader < GenericHeader
820
+
821
+ end
822
+
823
+ #--
824
+ # doesn't seem to be used -- not compatible with 64-bit
825
+ #def self._parse_config_header(rawdata)
826
+ # header = IMAGE_LOAD_CONFIG_DIRECTORY32.make_struct
827
+ # header.from_s(rawdata)
828
+ # ConfigHeader.new(header)
829
+ #end
830
+ #++
831
+
832
+ def _parse_config_header
833
+
834
+ #
835
+ # Get the data directory entry, size, etc
836
+ #
837
+ exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]
838
+ rva = exports_entry.v['VirtualAddress']
839
+ size = exports_entry.v['Size']
840
+
841
+ return nil if size == 0
842
+
843
+ #
844
+ # Ok, so we have the data directory, now lets parse it
845
+ #
846
+
847
+ dirdata = _isource.read(rva_to_file_offset(rva), size)
848
+ klass = (ptr_64?) ? IMAGE_LOAD_CONFIG_DIRECTORY64 : IMAGE_LOAD_CONFIG_DIRECTORY32
849
+ header = klass.make_struct
850
+
851
+ header.from_s(dirdata)
852
+
853
+ @config = ConfigHeader.new(header)
854
+ end
855
+
856
+
857
+ def config
858
+ _parse_config_header if @config.nil?
859
+ @config
860
+ end
861
+
862
+ #
863
+ # TLS Directory
864
+ #
865
+
866
+ # Struct
867
+ # typedef struct {
868
+ # DWORD Size;
869
+ # DWORD TimeDateStamp;
870
+ # WORD MajorVersion;
871
+ # WORD MinorVersion;
872
+ # DWORD GlobalFlagsClear;
873
+ # DWORD GlobalFlagsSet;
874
+ # DWORD CriticalSectionDefaultTimeout;
875
+ # DWORD DeCommitFreeBlockThreshold;
876
+ # DWORD DeCommitTotalFreeThreshold;
877
+ # DWORD LockPrefixTable; // VA
878
+ # DWORD MaximumAllocationSize;
879
+ # DWORD VirtualMemoryThreshold;
880
+ # DWORD ProcessHeapFlags;
881
+ # DWORD ProcessAffinityMask;
882
+ # WORD CSDVersion;
883
+ # WORD Reserved1;
884
+ # DWORD EditList; // VA
885
+ # DWORD SecurityCookie; // VA
886
+ # DWORD SEHandlerTable; // VA
887
+ # DWORD SEHandlerCount;
888
+ # } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
889
+ IMAGE_LOAD_TLS_DIRECTORY32 = Rex::Struct2::CStructTemplate.new(
890
+ [ 'uint32v', 'Size', 0 ],
891
+ [ 'uint32v', 'TimeDateStamp', 0 ],
892
+ [ 'uint16v', 'MajorVersion', 0 ],
893
+ [ 'uint16v', 'MinorVersion', 0 ],
894
+ [ 'uint32v', 'GlobalFlagsClear', 0 ],
895
+ [ 'uint32v', 'GlobalFlagsSet', 0 ],
896
+ [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
897
+ [ 'uint32v', 'DeCommitFreeBlockThreshold', 0 ],
898
+ [ 'uint32v', 'DeCommitTotalFreeThreshold', 0 ],
899
+ [ 'uint32v', 'LockPrefixTable', 0 ],
900
+ [ 'uint32v', 'MaximumAllocationSize', 0 ],
901
+ [ 'uint32v', 'VirtualMemoryThreshold', 0 ],
902
+ [ 'uint32v', 'ProcessHeapFlags', 0 ],
903
+ [ 'uint32v', 'ProcessAffinityMask', 0 ],
904
+ [ 'uint16v', 'CSDVersion', 0 ],
905
+ [ 'uint16v', 'Reserved1', 0 ],
906
+ [ 'uint32v', 'EditList', 0 ],
907
+ [ 'uint32v', 'SecurityCookie', 0 ],
908
+ [ 'uint32v', 'SEHandlerTable', 0 ],
909
+ [ 'uint32v', 'SEHandlerCount', 0 ]
910
+ )
911
+
912
+ # Struct
913
+ # typedef struct {
914
+ # ULONG Size;
915
+ # ULONG TimeDateStamp;
916
+ # USHORT MajorVersion;
917
+ # USHORT MinorVersion;
918
+ # ULONG GlobalFlagsClear;
919
+ # ULONG GlobalFlagsSet;
920
+ # ULONG CriticalSectionDefaultTimeout;
921
+ # ULONGLONG DeCommitFreeBlockThreshold;
922
+ # ULONGLONG DeCommitTotalFreeThreshold;
923
+ # ULONGLONG LockPrefixTable; // VA
924
+ # ULONGLONG MaximumAllocationSize;
925
+ # ULONGLONG VirtualMemoryThreshold;
926
+ # ULONGLONG ProcessAffinityMask;
927
+ # ULONG ProcessHeapFlags;
928
+ # USHORT CSDVersion;
929
+ # USHORT Reserved1;
930
+ # ULONGLONG EditList; // VA
931
+ # ULONGLONG SecurityCookie; // VA
932
+ # ULONGLONG SEHandlerTable; // VA
933
+ # ULONGLONG SEHandlerCount;
934
+ # } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
935
+ IMAGE_LOAD_TLS_DIRECTORY64 = Rex::Struct2::CStructTemplate.new(
936
+ [ 'uint32v', 'Size', 0 ],
937
+ [ 'uint32v', 'TimeDateStamp', 0 ],
938
+ [ 'uint16v', 'MajorVersion', 0 ],
939
+ [ 'uint16v', 'MinorVersion', 0 ],
940
+ [ 'uint32v', 'GlobalFlagsClear', 0 ],
941
+ [ 'uint32v', 'GlobalFlagsSet', 0 ],
942
+ [ 'uint32v', 'CriticalSectionDefaultTimeout', 0 ],
943
+ [ 'uint64v', 'DeCommitFreeBlockThreshold', 0 ],
944
+ [ 'uint64v', 'DeCommitTotalFreeThreshold', 0 ],
945
+ [ 'uint64v', 'LockPrefixTable', 0 ],
946
+ [ 'uint64v', 'MaximumAllocationSize', 0 ],
947
+ [ 'uint64v', 'VirtualMemoryThreshold', 0 ],
948
+ [ 'uint64v', 'ProcessAffinityMask', 0 ],
949
+ [ 'uint32v', 'ProcessHeapFlags', 0 ],
950
+ [ 'uint16v', 'CSDVersion', 0 ],
951
+ [ 'uint16v', 'Reserved1', 0 ],
952
+ [ 'uint64v', 'EditList', 0 ],
953
+ [ 'uint64v', 'SecurityCookie', 0 ],
954
+ [ 'uint64v', 'SEHandlerTable', 0 ],
955
+ [ 'uint64v', 'SEHandlerCount', 0 ]
956
+ )
957
+
958
+
959
+ class TLSHeader < GenericHeader
960
+
961
+ end
962
+
963
+ def _parse_tls_header
964
+
965
+ #
966
+ # Get the data directory entry, size, etc
967
+ #
968
+ exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_TLS]
969
+ rva = exports_entry.v['VirtualAddress']
970
+ size = exports_entry.v['Size']
971
+
972
+ return nil if size == 0
973
+
974
+ #
975
+ # Ok, so we have the data directory, now lets parse it
976
+ #
977
+
978
+ dirdata = _isource.read(rva_to_file_offset(rva), size)
979
+ klass = (ptr_64?) ? IMAGE_LOAD_TLS_DIRECTORY64 : IMAGE_LOAD_TLS_DIRECTORY32
980
+ header = klass.make_struct
981
+
982
+ header.from_s(dirdata)
983
+
984
+ @tls = TLSHeader.new(header)
985
+ end
986
+
987
+
988
+ def tls
989
+ _parse_config_header if @tls.nil?
990
+ @tls
991
+ end
992
+
993
+ ##
994
+ #
995
+ # Exception directory
996
+ #
997
+ ##
998
+
999
+ IMAGE_RUNTIME_FUNCTION_ENTRY_SZ = 12
1000
+ # Struct
1001
+ # typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {
1002
+ # DWORD BeginAddress;
1003
+ # DWORD EndAddress;
1004
+ # DWORD UnwindInfoAddress;
1005
+ # } _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;
1006
+ IMAGE_RUNTIME_FUNCTION_ENTRY = Rex::Struct2::CStructTemplate.new(
1007
+ [ 'uint32v', 'BeginAddress', 0 ],
1008
+ [ 'uint32v', 'EndAddress', 0 ],
1009
+ [ 'uint32v', 'UnwindInfoAddress', 0 ]
1010
+ )
1011
+
1012
+ UNWIND_INFO_HEADER_SZ = 4
1013
+ UNWIND_INFO_HEADER = Rex::Struct2::CStructTemplate.new(
1014
+ [ 'uint8', 'VersionFlags', 0 ],
1015
+ [ 'uint8', 'SizeOfProlog', 0 ],
1016
+ [ 'uint8', 'CountOfCodes', 0 ],
1017
+ [ 'uint8', 'FrameRegisterAndOffset', 0 ]
1018
+ )
1019
+
1020
+ UWOP_PUSH_NONVOL = 0 # 1 node
1021
+ UWOP_ALLOC_LARGE = 1 # 2 or 3 nodes
1022
+ UWOP_ALLOC_SMALL = 2 # 1 node
1023
+ UWOP_SET_FPREG = 3 # 1 node
1024
+ UWOP_SAVE_NONVOL = 4 # 2 nodes
1025
+ UWOP_SAVE_NONVOL_FAR = 5 # 3 nodes
1026
+ UWOP_SAVE_XMM128 = 8 # 2 nodes
1027
+ UWOP_SAVE_XMM128_FAR = 9 # 3 nodes
1028
+ UWOP_PUSH_MACHFRAME = 10 # 1 node
1029
+
1030
+ UNW_FLAG_EHANDLER = 1
1031
+ UNW_FLAG_UHANDLER = 2
1032
+ UNW_FLAG_CHAININFO = 4
1033
+
1034
+ class UnwindCode
1035
+ def initialize(data)
1036
+
1037
+ self.code_offset = data[0].to_i
1038
+ self.unwind_op = data[1].to_i & 0xf
1039
+ self.op_info = data[1].to_i >> 4
1040
+ self.frame_offset = data[2..3].unpack("v")[0]
1041
+
1042
+ data.slice!(0, 4)
1043
+ end
1044
+
1045
+ attr_reader :code_offset, :unwind_op, :op_info, :frame_offset
1046
+ attr_writer :code_offset, :unwind_op, :op_info, :frame_offset
1047
+
1048
+ end
1049
+
1050
+ class UnwindInfo
1051
+ def initialize(pe, unwind_rva)
1052
+ data = pe.read_rva(unwind_rva, UNWIND_INFO_HEADER_SZ)
1053
+
1054
+ unwind = UNWIND_INFO_HEADER.make_struct
1055
+ unwind.from_s(data)
1056
+
1057
+ @version = unwind.v['VersionFlags'] & 0x7
1058
+ @flags = unwind.v['VersionFlags'] >> 3
1059
+ @size_of_prolog = unwind.v['SizeOfProlog']
1060
+ @count_of_codes = unwind.v['CountOfCodes']
1061
+ @frame_register = unwind.v['FrameRegisterAndOffset'] & 0xf
1062
+ @frame_register_offset = unwind.v['FrameRegisterAndOffset'] >> 4
1063
+
1064
+ # Parse unwind codes
1065
+ clist = pe.read_rva(unwind_rva + UNWIND_INFO_HEADER_SZ, count_of_codes * 4)
1066
+
1067
+ @unwind_codes = []
1068
+
1069
+ while clist.length > 0
1070
+ @unwind_codes << UnwindCode.new(clist)
1071
+ end
1072
+ end
1073
+
1074
+ attr_reader :version, :flags, :size_of_prolog, :count_of_codes
1075
+ attr_reader :frame_register, :frame_register_offset
1076
+
1077
+ def unwind_codes
1078
+ @unwind_codes
1079
+ end
1080
+
1081
+ end
1082
+
1083
+ class RuntimeFunctionEntry
1084
+
1085
+ def initialize(pe, data)
1086
+ @pe = pe
1087
+ @begin_address, @end_address, @unwind_info_address = data.unpack("VVV");
1088
+ self.unwind_info = UnwindInfo.new(pe, unwind_info_address)
1089
+ end
1090
+
1091
+ attr_reader :begin_address, :end_address, :unwind_info_address
1092
+ attr_reader :unwind_info
1093
+ attr_writer :unwind_info
1094
+
1095
+ end
1096
+
1097
+ def _load_exception_directory
1098
+ @exception = []
1099
+
1100
+ exception_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_EXCEPTION]
1101
+ rva = exception_entry.v['VirtualAddress']
1102
+ size = exception_entry.v['Size']
1103
+
1104
+ return if (rva == 0)
1105
+
1106
+ data = _isource.read(rva_to_file_offset(rva), size)
1107
+
1108
+ case hdr.file.Machine
1109
+ when IMAGE_FILE_MACHINE_AMD64
1110
+ count = data.length / IMAGE_RUNTIME_FUNCTION_ENTRY_SZ
1111
+
1112
+ count.times { |current|
1113
+ @exception << RuntimeFunctionEntry.new(self,
1114
+ data.slice!(0, IMAGE_RUNTIME_FUNCTION_ENTRY_SZ))
1115
+ }
1116
+ else
1117
+ end
1118
+
1119
+ return @exception
1120
+ end
1121
+
1122
+
1123
+ def exception
1124
+ _load_exception_directory if @exception.nil?
1125
+ @exception
1126
+ end
1127
+
1128
+ #
1129
+ # Just a stupid routine to round an offset up to it's alignment.
1130
+ #
1131
+ # For example, you're going to want this for FileAlignment and
1132
+ # SectionAlignment, etc...
1133
+ #
1134
+ def self._align_offset(offset, alignment)
1135
+ offset += alignment - 1
1136
+ offset -= offset % alignment
1137
+ return offset
1138
+ end
1139
+
1140
+ #
1141
+ # instance stuff
1142
+ #
1143
+
1144
+ attr_accessor :_isource
1145
+ attr_accessor :_dos_header, :_file_header, :_optional_header,
1146
+ :_section_headers, :_config_header, :_tls_header, :_exception_header
1147
+
1148
+ attr_accessor :sections, :header_section, :image_base
1149
+
1150
+ attr_accessor :_imports_cache, :_imports_cached
1151
+ attr_accessor :_exports_cache, :_exports_cached
1152
+ attr_accessor :_relocations_cache, :_relocations_cached
1153
+ attr_accessor :_resources_cache, :_resources_cached
1154
+
1155
+ attr_accessor :hdr
1156
+
1157
+ def self.new_from_file(filename, disk_backed = false)
1158
+
1159
+ file = ::File.new(filename)
1160
+ file.binmode # windows... :\
1161
+
1162
+ if disk_backed
1163
+ return self.new(ImageSource::Disk.new(file))
1164
+ else
1165
+ obj = new_from_string(file.read)
1166
+ file.close
1167
+ return obj
1168
+ end
1169
+ end
1170
+
1171
+ def self.new_from_string(data)
1172
+ return self.new(ImageSource::Memory.new(data))
1173
+ end
1174
+
1175
+ def close
1176
+ _isource.close
1177
+ end
1178
+
1179
+ #
1180
+ #
1181
+ # Random rva, vma, file offset, section offset, etc
1182
+ # conversion routines...
1183
+ #
1184
+ #
1185
+ def rva_to_vma(rva)
1186
+ return rva + image_base
1187
+ end
1188
+
1189
+ def vma_to_rva(vma)
1190
+ return vma - image_base
1191
+ end
1192
+
1193
+ def rva_to_file_offset(rva)
1194
+ all_sections.each do |section|
1195
+ if section.contains_rva?(rva)
1196
+ return section.rva_to_file_offset(rva)
1197
+ end
1198
+ end
1199
+ raise WtfError, "wtf!", caller
1200
+ end
1201
+
1202
+ def vma_to_file_offset(vma)
1203
+ return rva_to_file_offset(vma_to_rva(vma))
1204
+ end
1205
+
1206
+ def file_offset_to_rva(foffset)
1207
+ if foffset < 0
1208
+ raise WtfError, "lame", caller
1209
+ end
1210
+
1211
+ all_sections.each do |section|
1212
+ if section.contains_file_offset?(foffset)
1213
+ return section.file_offset_to_rva(foffset)
1214
+ end
1215
+ end
1216
+
1217
+ raise WtfError, "wtf! #{foffset}", caller
1218
+ end
1219
+
1220
+ def file_offset_to_vma(foffset)
1221
+ return rva_to_vma(file_offset_to_rva(foffset))
1222
+ end
1223
+
1224
+ #
1225
+ #
1226
+ # Some routines to find which section something belongs
1227
+ # to. These will search all_sections (so including
1228
+ # our fake header section, etc...
1229
+ #
1230
+ #
1231
+
1232
+ #
1233
+ # Find a section by an RVA
1234
+ #
1235
+ def _find_section_by_rva(rva)
1236
+ all_sections.each do |section|
1237
+ if section.contains_rva?(rva)
1238
+ return section
1239
+ end
1240
+ end
1241
+
1242
+ return nil
1243
+ end
1244
+ def find_section_by_rva(rva)
1245
+ section = _find_section_by_rva(rva)
1246
+
1247
+ if !section
1248
+ raise WtfError, "Cannot find rva! #{rva}", caller
1249
+ end
1250
+
1251
+ return section
1252
+ end
1253
+
1254
+ #
1255
+ # Find a section by a VMA
1256
+ #
1257
+ def find_section_by_vma(vma)
1258
+ return find_section_by_rva(vma_to_rva(vma))
1259
+ end
1260
+
1261
+ def valid_rva?(rva)
1262
+ _find_section_by_rva(rva) != nil
1263
+ end
1264
+ def valid_vma?(vma)
1265
+ _find_section_by_rva(vma_to_rva(vma)) != nil
1266
+ end
1267
+
1268
+ #
1269
+ #
1270
+ # Some convenient methods to read a vma/rva without having
1271
+ # the section... (inefficent though I suppose...)
1272
+ #
1273
+ #
1274
+
1275
+ def read_rva(rva, length)
1276
+ return find_section_by_rva(rva).read_rva(rva, length)
1277
+ end
1278
+
1279
+ def read_vma(vma, length)
1280
+ return read_rva(vma_to_rva(vma), length)
1281
+ end
1282
+
1283
+ def read_asciiz_rva(rva)
1284
+ return find_section_by_rva(rva).read_asciiz_rva(rva)
1285
+ end
1286
+
1287
+ def read_asciiz_vma(vma)
1288
+ return read_asciiz_rva(vma_to_rva(vma))
1289
+ end
1290
+
1291
+ #
1292
+ #
1293
+ # Imports, exports, and other stuff!
1294
+ #
1295
+ #
1296
+
1297
+ #
1298
+ # We lazily parse the imports, and then cache it
1299
+ #
1300
+ def imports
1301
+ if !_imports_cached
1302
+ self._imports_cache = _load_imports
1303
+ self._imports_cached = true
1304
+ end
1305
+ return _imports_cache
1306
+ end
1307
+
1308
+ def _load_imports
1309
+ #
1310
+ # Get the data directory entry, size, etc
1311
+ #
1312
+ imports_entry = _optional_header['DataDirectory'][1]
1313
+ rva = imports_entry.v['VirtualAddress']
1314
+ size = imports_entry.v['Size']
1315
+
1316
+ return nil if size == 0
1317
+
1318
+ #
1319
+ # Ok, so we have the data directory, now lets parse it
1320
+ #
1321
+
1322
+ imports = [ ]
1323
+
1324
+ descriptors_data = _isource.read(rva_to_file_offset(rva), size)
1325
+
1326
+ while descriptors_data.length >= IMAGE_IMPORT_DESCRIPTOR_SIZE
1327
+ descriptor = IMAGE_IMPORT_DESCRIPTOR.make_struct
1328
+ descriptor.from_s(descriptors_data)
1329
+ descriptors_data = descriptor.leftover
1330
+
1331
+ othunk = descriptor.v['OriginalFirstThunk']
1332
+ fthunk = descriptor.v['FirstThunk']
1333
+
1334
+ break if fthunk == 0
1335
+
1336
+ dllname = _isource.read_asciiz(rva_to_file_offset(descriptor.v['Name']))
1337
+
1338
+ import = ImportDescriptor.new(dllname, [ ])
1339
+
1340
+ # we prefer the Characteristics/OriginalFirstThunk...
1341
+ thunk_off = rva_to_file_offset(othunk == 0 ? fthunk : othunk)
1342
+
1343
+ while (orgrva = _isource.read(thunk_off, 4).unpack('V')[0]) != 0
1344
+ hint = nil
1345
+ name = nil
1346
+
1347
+ if (orgrva & IMAGE_ORDINAL_FLAG32) != 0
1348
+ hint = orgrva & 0xffff
1349
+ else
1350
+ foff = rva_to_file_offset(orgrva)
1351
+ hint = _isource.read(foff, 2).unpack('v')[0]
1352
+ name = _isource.read_asciiz(foff + 2)
1353
+ end
1354
+
1355
+ import.entries << ImportEntry.new(name, hint)
1356
+
1357
+ thunk_off += 4
1358
+ end
1359
+
1360
+ imports << import
1361
+ end
1362
+
1363
+ return imports
1364
+ end
1365
+
1366
+
1367
+
1368
+ #
1369
+ # We lazily parse the exports, and then cache it
1370
+ #
1371
+ def exports
1372
+ if !_exports_cached
1373
+ self._exports_cache = _load_exports
1374
+ self._exports_cached = true
1375
+ end
1376
+ return _exports_cache
1377
+ end
1378
+
1379
+ def _load_exports
1380
+
1381
+ #
1382
+ # Get the data directory entry, size, etc
1383
+ #
1384
+ exports_entry = _optional_header['DataDirectory'][0]
1385
+ rva = exports_entry.v['VirtualAddress']
1386
+ size = exports_entry.v['Size']
1387
+
1388
+ return nil if size == 0
1408
1389
 
1409
- #
1410
- # Ok, so we have the data directory, now lets parse it
1411
- #
1390
+ #
1391
+ # Ok, so we have the data directory, now lets parse it
1392
+ #
1412
1393
 
1413
- directory = IMAGE_EXPORT_DESCRIPTOR.make_struct
1414
- directory.from_s(_isource.read(rva_to_file_offset(rva), IMAGE_EXPORT_DESCRIPTOR_SIZE))
1394
+ directory = IMAGE_EXPORT_DESCRIPTOR.make_struct
1395
+ directory.from_s(_isource.read(rva_to_file_offset(rva), IMAGE_EXPORT_DESCRIPTOR_SIZE))
1415
1396
 
1416
- #
1417
- # We can have nameless exports, so we need to do the whole
1418
- # NumberOfFunctions NumberOfNames foo
1419
- #
1420
- num_functions = directory.v['NumberOfFunctions']
1421
- num_names = directory.v['NumberOfNames']
1397
+ #
1398
+ # We can have nameless exports, so we need to do the whole
1399
+ # NumberOfFunctions NumberOfNames foo
1400
+ #
1401
+ num_functions = directory.v['NumberOfFunctions']
1402
+ num_names = directory.v['NumberOfNames']
1422
1403
 
1423
- dllname_rva = directory.v['Name']
1424
- dllname = _isource.read_asciiz(rva_to_file_offset(dllname_rva))
1404
+ dllname_rva = directory.v['Name']
1405
+ dllname = _isource.read_asciiz(rva_to_file_offset(dllname_rva))
1425
1406
 
1426
- # FIXME Base, etc
1427
- fun_off = rva_to_file_offset(directory.v['AddressOfFunctions'])
1428
- name_off = rva_to_file_offset(directory.v['AddressOfNames'])
1429
- ord_off = rva_to_file_offset(directory.v['AddressOfNameOrdinals'])
1430
- base = directory.v['Base']
1407
+ # FIXME Base, etc
1408
+ fun_off = rva_to_file_offset(directory.v['AddressOfFunctions'])
1409
+ name_off = rva_to_file_offset(directory.v['AddressOfNames'])
1410
+ ord_off = rva_to_file_offset(directory.v['AddressOfNameOrdinals'])
1411
+ base = directory.v['Base']
1431
1412
 
1432
- # Allocate the list of names
1433
- names = Array.new(num_functions)
1413
+ # Allocate the list of names
1414
+ names = Array.new(num_functions)
1434
1415
 
1435
- #
1436
- # Iterate the names and name/ordinal list, getting the names
1437
- # and storing them in the name list...
1438
- #
1439
- num_names.times do |i|
1440
- name_rva = _isource.read(name_off + (i * 4), 4).unpack('V')[0]
1441
- ordinal = _isource.read(ord_off + (i * 2), 2).unpack('v')[0]
1442
- name = _isource.read_asciiz(rva_to_file_offset(name_rva))
1416
+ #
1417
+ # Iterate the names and name/ordinal list, getting the names
1418
+ # and storing them in the name list...
1419
+ #
1420
+ num_names.times do |i|
1421
+ name_rva = _isource.read(name_off + (i * 4), 4).unpack('V')[0]
1422
+ ordinal = _isource.read(ord_off + (i * 2), 2).unpack('v')[0]
1423
+ name = _isource.read_asciiz(rva_to_file_offset(name_rva))
1443
1424
 
1444
- # store the exported name in the name list
1445
- names[ordinal] = name
1446
- end
1425
+ # store the exported name in the name list
1426
+ names[ordinal] = name
1427
+ end
1447
1428
 
1448
- exports = ExportDirectory.new(dllname, [ ], base)
1429
+ exports = ExportDirectory.new(dllname, [ ], base)
1449
1430
 
1450
- #
1451
- # Now just iterate the functions (rvas) list..
1452
- #
1453
- num_functions.times do |i|
1454
- rva = _isource.read(fun_off + (i * 4), 4).unpack('V')[0]
1431
+ #
1432
+ # Now just iterate the functions (rvas) list..
1433
+ #
1434
+ num_functions.times do |i|
1435
+ rva = _isource.read(fun_off + (i * 4), 4).unpack('V')[0]
1455
1436
 
1456
- # ExportEntry.new(name, ordinal, rva)
1457
- exports.entries << ExportEntry.new(names[i], i + base, rva)
1458
- end
1437
+ # ExportEntry.new(name, ordinal, rva)
1438
+ exports.entries << ExportEntry.new(names[i], i + base, rva)
1439
+ end
1459
1440
 
1460
- return exports
1461
- end
1462
-
1463
- #
1464
- # Base relocations in the hizzy
1465
- #
1466
- def relocations
1467
- if !_relocations_cached
1468
- self._relocations_cache = _load_relocations
1469
- self._relocations_cached = true
1470
- end
1471
- return _relocations_cache
1472
- end
1441
+ return exports
1442
+ end
1443
+
1444
+ #
1445
+ # Base relocations in the hizzy
1446
+ #
1447
+ def relocations
1448
+ if !_relocations_cached
1449
+ self._relocations_cache = _load_relocations
1450
+ self._relocations_cached = true
1451
+ end
1452
+ return _relocations_cache
1453
+ end
1473
1454
 
1474
- def _load_relocations
1455
+ def _load_relocations
1475
1456
 
1476
- #
1477
- # Get the data directory entry, size, etc
1478
- #
1479
- exports_entry = _optional_header['DataDirectory'][5]
1480
- rva = exports_entry.v['VirtualAddress']
1481
- size = exports_entry.v['Size']
1457
+ #
1458
+ # Get the data directory entry, size, etc
1459
+ #
1460
+ exports_entry = _optional_header['DataDirectory'][5]
1461
+ rva = exports_entry.v['VirtualAddress']
1462
+ size = exports_entry.v['Size']
1482
1463
 
1483
- return nil if size == 0
1464
+ return nil if size == 0
1484
1465
 
1485
- #
1486
- # Ok, so we have the data directory, now lets parse it
1487
- #
1488
-
1489
- dirdata = _isource.read(rva_to_file_offset(rva), size)
1490
-
1491
- relocdirs = [ ]
1492
-
1493
- while dirdata.length >= IMAGE_SIZEOF_BASE_RELOCATION
1494
- header = IMAGE_BASE_RELOCATION.make_struct
1495
- header.from_s(dirdata)
1496
- dirdata = header.leftover
1466
+ #
1467
+ # Ok, so we have the data directory, now lets parse it
1468
+ #
1469
+
1470
+ dirdata = _isource.read(rva_to_file_offset(rva), size)
1471
+
1472
+ relocdirs = [ ]
1473
+
1474
+ while dirdata.length >= IMAGE_SIZEOF_BASE_RELOCATION
1475
+ header = IMAGE_BASE_RELOCATION.make_struct
1476
+ header.from_s(dirdata)
1477
+ dirdata = header.leftover
1497
1478
 
1498
- numrelocs = (header.v['SizeOfBlock'] - IMAGE_SIZEOF_BASE_RELOCATION) / 2
1499
-
1500
- relocbase = header.v['VirtualAddress']
1501
-
1502
- relocdir = RelocationDirectory.new(relocbase, [ ])
1503
-
1504
- numrelocs.times do
1505
- reloc = IMAGE_BASE_RELOCATION_TYPE_OFFSET.make_struct
1506
- reloc.from_s(dirdata)
1507
- dirdata = reloc.leftover
1508
-
1509
- typeoffset = reloc.v['TypeOffset']
1510
-
1511
- relocrva = relocbase + (typeoffset & 0xfff)
1512
- reloctype = (typeoffset >> 12) & 0xf
1513
-
1514
- relocdir.entries << RelocationEntry.new(relocrva, reloctype)
1515
- end
1516
-
1517
- relocdirs << relocdir
1518
- end
1519
-
1520
- return relocdirs
1521
- end
1522
-
1523
-
1524
- #
1525
- # We lazily parse the resources, and then cache them
1526
- #
1527
- def resources
1528
- if !_resources_cached
1529
- _load_resources
1530
- self._resources_cached = true
1531
- end
1532
-
1533
- return self._resources_cache
1534
- end
1535
-
1536
- def _load_resources
1537
- #
1538
- # Get the data directory entry, size, etc
1539
- #
1540
- rsrc_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_RESOURCE]
1541
- rva = rsrc_entry.v['VirtualAddress']
1542
- size = rsrc_entry.v['Size']
1543
-
1544
- return nil if size == 0
1545
-
1546
- #
1547
- # Ok, so we have the data directory, now lets parse it
1548
- #
1549
- data = _isource.read(rva_to_file_offset(rva), size)
1550
-
1551
- self._resources_cache = {}
1552
- _parse_resource_directory(data)
1553
- end
1554
-
1555
- def _parse_resource_directory(data, rname=0, rvalue=0x80000000, path='0', pname=nil)
1556
-
1557
- pname = _parse_resource_name(data, rname)
1558
- if (path.scan('/').length == 1)
1559
- if (pname !~ /^\d+/)
1560
- path = "/" + pname
1561
- else
1562
- path = "/" + _resource_lookup( (rname & ~0x80000000).to_s)
1563
- end
1564
- end
1565
-
1566
-
1567
- rvalue &= ~0x80000000
1568
- vals = data[rvalue, 16].unpack('VVvvvv')
1569
-
1570
- chars = vals[0]
1571
- tdate = vals[1]
1572
- vers = "#{vals[2]}#{vals[3]}"
1573
- count = vals[4] + vals[5]
1574
-
1575
- 0.upto(count-1) do |i|
1576
-
1577
- ename, evalue = data[rvalue + 16 + ( i * 8), 8].unpack('VV')
1578
- epath = path + '/' + i.to_s
1579
-
1580
- if (ename & 0x80000000 != 0)
1581
- pname = _parse_resource_name(data, ename)
1582
- end
1583
-
1584
- if (evalue & 0x80000000 != 0)
1585
- # This is a subdirectory
1586
- _parse_resource_directory(data, ename, evalue, epath, pname)
1587
- else
1588
- # This is an entry
1589
- _parse_resource_entry(data, ename, evalue, epath, pname)
1590
- end
1591
- end
1592
-
1593
- end
1594
-
1595
- def _resource_lookup(i)
1596
- tbl = {
1597
- '1' => 'RT_CURSOR',
1598
- '2' => 'RT_BITMAP',
1599
- '3' => 'RT_ICON',
1600
- '4' => 'RT_MENU',
1601
- '5' => 'RT_DIALOG',
1602
- '6' => 'RT_STRING',
1603
- '7' => 'RT_FONTDIR',
1604
- '8' => 'RT_FONT',
1605
- '9' => 'RT_ACCELERATORS',
1606
- '10' => 'RT_RCDATA',
1607
- '11' => 'RT_MESSAGETABLE',
1608
- '12' => 'RT_GROUP_CURSOR',
1609
- '14' => 'RT_GROUP_ICON',
1610
- '16' => 'RT_VERSION',
1611
- '17' => 'RT_DLGINCLUDE',
1612
- '19' => 'RT_PLUGPLAY',
1613
- '20' => 'RT_VXD',
1614
- '21' => 'RT_ANICURSOR',
1615
- '22' => 'RT_ANIICON',
1616
- '23' => 'RT_HTML',
1617
- '24' => 'RT_MANIFEST',
1618
- '32767' => 'RT_ERROR',
1619
- '8192' => 'RT_NEWRESOURCE',
1620
- '8194' => 'RT_NEWBITMAP',
1621
- '8196' => 'RT_NEWMENU',
1622
- '8197' => 'RT_NEWDIALOG'
1623
- }
1624
- tbl[i] || i
1625
- end
1626
-
1627
- def _parse_resource_entry(data, rname, rvalue, path, pname)
1628
-
1629
- rva, size, code = data[rvalue, 12].unpack('VVV')
1630
- lang = _parse_resource_name(data, rname)
1631
-
1632
- ent = ResourceEntry.new(
1633
- self,
1634
- path,
1635
- lang,
1636
- code,
1637
- rva,
1638
- size,
1639
- pname
1640
- )
1641
- self._resources_cache[path] = ent
1642
- end
1643
-
1644
- def _parse_resource_name(data, rname)
1645
- if (rname & 0x80000000 != 0)
1646
- rname &= ~0x80000000
1647
- unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ]
1648
- unistr, trash = unistr.split(/\x00\x00/, 2)
1649
- return unistr ? unistr.gsub(/\x00/, '') : nil
1650
- end
1651
-
1652
- rname.to_s
1653
- end
1654
-
1655
- def update_checksum
1656
- off = _dos_header.e_lfanew + IMAGE_FILE_HEADER_SIZE + 0x40
1657
- _isource.rawdata[off, 4] = [0].pack('V')
1658
-
1659
- rem = _isource.size % 4
1660
- sum_me = ''
1661
- sum_me << _isource.rawdata
1662
- sum_me << "\x00" * (4 - rem) if rem > 0
1663
-
1664
- cksum = 0
1665
- sum_me.unpack('V*').each { |el|
1666
- cksum = (cksum & 0xffffffff) + (cksum >> 32) + el
1667
- if cksum > 2**32
1668
- cksum = (cksum & 0xffffffff) + (cksum >> 32)
1669
- end
1670
- }
1671
-
1672
- cksum = (cksum & 0xffff) + (cksum >> 16)
1673
- cksum += (cksum >> 16)
1674
- cksum &= 0xffff
1675
-
1676
- cksum += _isource.size
1677
-
1678
- _isource.rawdata[off, 4] = [cksum].pack('V')
1679
- end
1479
+ numrelocs = (header.v['SizeOfBlock'] - IMAGE_SIZEOF_BASE_RELOCATION) / 2
1480
+
1481
+ relocbase = header.v['VirtualAddress']
1482
+
1483
+ relocdir = RelocationDirectory.new(relocbase, [ ])
1484
+
1485
+ numrelocs.times do
1486
+ reloc = IMAGE_BASE_RELOCATION_TYPE_OFFSET.make_struct
1487
+ reloc.from_s(dirdata)
1488
+ dirdata = reloc.leftover
1489
+
1490
+ typeoffset = reloc.v['TypeOffset']
1491
+
1492
+ relocrva = relocbase + (typeoffset & 0xfff)
1493
+ reloctype = (typeoffset >> 12) & 0xf
1494
+
1495
+ relocdir.entries << RelocationEntry.new(relocrva, reloctype)
1496
+ end
1497
+
1498
+ relocdirs << relocdir
1499
+ end
1500
+
1501
+ return relocdirs
1502
+ end
1503
+
1504
+
1505
+ #
1506
+ # We lazily parse the resources, and then cache them
1507
+ #
1508
+ def resources
1509
+ if !_resources_cached
1510
+ _load_resources
1511
+ self._resources_cached = true
1512
+ end
1513
+
1514
+ return self._resources_cache
1515
+ end
1516
+
1517
+ def _load_resources
1518
+ #
1519
+ # Get the data directory entry, size, etc
1520
+ #
1521
+ rsrc_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_RESOURCE]
1522
+ rva = rsrc_entry.v['VirtualAddress']
1523
+ size = rsrc_entry.v['Size']
1524
+
1525
+ return nil if size == 0
1526
+
1527
+ #
1528
+ # Ok, so we have the data directory, now lets parse it
1529
+ #
1530
+ data = _isource.read(rva_to_file_offset(rva), size)
1531
+
1532
+ self._resources_cache = {}
1533
+ _parse_resource_directory(data)
1534
+ end
1535
+
1536
+ def _parse_resource_directory(data, rname=0, rvalue=0x80000000, path='0', pname=nil)
1537
+
1538
+ pname = _parse_resource_name(data, rname)
1539
+ if (path.scan('/').length == 1)
1540
+ if (pname !~ /^\d+/)
1541
+ path = "/" + pname
1542
+ else
1543
+ path = "/" + _resource_lookup( (rname & ~0x80000000).to_s)
1544
+ end
1545
+ end
1546
+
1547
+
1548
+ rvalue &= ~0x80000000
1549
+ vals = data[rvalue, 16].unpack('VVvvvv')
1550
+
1551
+ chars = vals[0]
1552
+ tdate = vals[1]
1553
+ vers = "#{vals[2]}#{vals[3]}"
1554
+ count = vals[4] + vals[5]
1555
+
1556
+ 0.upto(count-1) do |i|
1557
+
1558
+ ename, evalue = data[rvalue + 16 + ( i * 8), 8].unpack('VV')
1559
+ epath = path + '/' + i.to_s
1560
+
1561
+ if (ename & 0x80000000 != 0)
1562
+ pname = _parse_resource_name(data, ename)
1563
+ end
1564
+
1565
+ if (evalue & 0x80000000 != 0)
1566
+ # This is a subdirectory
1567
+ _parse_resource_directory(data, ename, evalue, epath, pname)
1568
+ else
1569
+ # This is an entry
1570
+ _parse_resource_entry(data, ename, evalue, epath, pname)
1571
+ end
1572
+ end
1573
+
1574
+ end
1575
+
1576
+ def _resource_lookup(i)
1577
+ tbl = {
1578
+ '1' => 'RT_CURSOR',
1579
+ '2' => 'RT_BITMAP',
1580
+ '3' => 'RT_ICON',
1581
+ '4' => 'RT_MENU',
1582
+ '5' => 'RT_DIALOG',
1583
+ '6' => 'RT_STRING',
1584
+ '7' => 'RT_FONTDIR',
1585
+ '8' => 'RT_FONT',
1586
+ '9' => 'RT_ACCELERATORS',
1587
+ '10' => 'RT_RCDATA',
1588
+ '11' => 'RT_MESSAGETABLE',
1589
+ '12' => 'RT_GROUP_CURSOR',
1590
+ '14' => 'RT_GROUP_ICON',
1591
+ '16' => 'RT_VERSION',
1592
+ '17' => 'RT_DLGINCLUDE',
1593
+ '19' => 'RT_PLUGPLAY',
1594
+ '20' => 'RT_VXD',
1595
+ '21' => 'RT_ANICURSOR',
1596
+ '22' => 'RT_ANIICON',
1597
+ '23' => 'RT_HTML',
1598
+ '24' => 'RT_MANIFEST',
1599
+ '32767' => 'RT_ERROR',
1600
+ '8192' => 'RT_NEWRESOURCE',
1601
+ '8194' => 'RT_NEWBITMAP',
1602
+ '8196' => 'RT_NEWMENU',
1603
+ '8197' => 'RT_NEWDIALOG'
1604
+ }
1605
+ tbl[i] || i
1606
+ end
1607
+
1608
+ def _parse_resource_entry(data, rname, rvalue, path, pname)
1609
+
1610
+ rva, size, code = data[rvalue, 12].unpack('VVV')
1611
+ lang = _parse_resource_name(data, rname)
1612
+
1613
+ ent = ResourceEntry.new(
1614
+ self,
1615
+ path,
1616
+ lang,
1617
+ code,
1618
+ rva,
1619
+ size,
1620
+ pname
1621
+ )
1622
+ self._resources_cache[path] = ent
1623
+ end
1624
+
1625
+ def _parse_resource_name(data, rname)
1626
+ if (rname & 0x80000000 != 0)
1627
+ rname &= ~0x80000000
1628
+ unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ]
1629
+ unistr, trash = unistr.split(/\x00\x00/n, 2)
1630
+ return unistr ? unistr.gsub(/\x00/n, '') : nil
1631
+ end
1632
+
1633
+ rname.to_s
1634
+ end
1635
+
1636
+ def update_checksum
1637
+ off = _dos_header.e_lfanew + IMAGE_FILE_HEADER_SIZE + 0x40
1638
+ _isource.rawdata[off, 4] = [0].pack('V')
1639
+
1640
+ rem = _isource.size % 4
1641
+ sum_me = ''
1642
+ sum_me << _isource.rawdata
1643
+ sum_me << "\x00" * (4 - rem) if rem > 0
1644
+
1645
+ cksum = 0
1646
+ sum_me.unpack('V*').each { |el|
1647
+ cksum = (cksum & 0xffffffff) + (cksum >> 32) + el
1648
+ if cksum > 2**32
1649
+ cksum = (cksum & 0xffffffff) + (cksum >> 32)
1650
+ end
1651
+ }
1652
+
1653
+ cksum = (cksum & 0xffff) + (cksum >> 16)
1654
+ cksum += (cksum >> 16)
1655
+ cksum &= 0xffff
1656
+
1657
+ cksum += _isource.size
1658
+
1659
+ _isource.rawdata[off, 4] = [cksum].pack('V')
1660
+ end
1680
1661
 
1681
1662
  end end end