librex 0.0.20 → 0.0.21

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