pwntools 0.1.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +96 -15
  3. data/Rakefile +8 -2
  4. data/lib/pwn.rb +10 -7
  5. data/lib/pwnlib/abi.rb +61 -0
  6. data/lib/pwnlib/asm.rb +357 -0
  7. data/lib/pwnlib/constants/constant.rb +19 -3
  8. data/lib/pwnlib/constants/constants.rb +46 -20
  9. data/lib/pwnlib/constants/linux/amd64.rb +32 -1
  10. data/lib/pwnlib/constants/linux/i386.rb +2 -0
  11. data/lib/pwnlib/context.rb +128 -27
  12. data/lib/pwnlib/dynelf.rb +122 -54
  13. data/lib/pwnlib/elf/elf.rb +340 -0
  14. data/lib/pwnlib/errors.rb +31 -0
  15. data/lib/pwnlib/ext/array.rb +2 -1
  16. data/lib/pwnlib/ext/helper.rb +6 -5
  17. data/lib/pwnlib/ext/integer.rb +2 -1
  18. data/lib/pwnlib/ext/string.rb +3 -2
  19. data/lib/pwnlib/logger.rb +245 -0
  20. data/lib/pwnlib/memleak.rb +59 -29
  21. data/lib/pwnlib/pwn.rb +27 -9
  22. data/lib/pwnlib/reg_sort.rb +109 -110
  23. data/lib/pwnlib/runner.rb +53 -0
  24. data/lib/pwnlib/shellcraft/generators/amd64/common/common.rb +16 -0
  25. data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +24 -0
  26. data/lib/pwnlib/shellcraft/generators/amd64/common/memcpy.rb +35 -0
  27. data/lib/pwnlib/shellcraft/generators/amd64/common/mov.rb +131 -0
  28. data/lib/pwnlib/shellcraft/generators/amd64/common/nop.rb +18 -0
  29. data/lib/pwnlib/shellcraft/generators/amd64/common/popad.rb +28 -0
  30. data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr.rb +66 -0
  31. data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +24 -0
  32. data/lib/pwnlib/shellcraft/generators/amd64/common/ret.rb +33 -0
  33. data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +24 -0
  34. data/lib/pwnlib/shellcraft/generators/amd64/linux/cat.rb +24 -0
  35. data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +24 -0
  36. data/lib/pwnlib/shellcraft/generators/amd64/linux/exit.rb +24 -0
  37. data/lib/pwnlib/shellcraft/generators/amd64/linux/linux.rb +16 -0
  38. data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +24 -0
  39. data/lib/pwnlib/shellcraft/generators/amd64/linux/open.rb +24 -0
  40. data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +24 -0
  41. data/lib/pwnlib/shellcraft/generators/amd64/linux/sleep.rb +24 -0
  42. data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +24 -0
  43. data/lib/pwnlib/shellcraft/generators/helper.rb +115 -0
  44. data/lib/pwnlib/shellcraft/generators/i386/common/common.rb +16 -0
  45. data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +24 -0
  46. data/lib/pwnlib/shellcraft/generators/i386/common/memcpy.rb +34 -0
  47. data/lib/pwnlib/shellcraft/generators/i386/common/mov.rb +93 -0
  48. data/lib/pwnlib/shellcraft/generators/i386/common/nop.rb +18 -0
  49. data/lib/pwnlib/shellcraft/generators/i386/common/pushstr.rb +41 -0
  50. data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +24 -0
  51. data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +24 -0
  52. data/lib/pwnlib/shellcraft/generators/i386/linux/cat.rb +24 -0
  53. data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +24 -0
  54. data/lib/pwnlib/shellcraft/generators/i386/linux/exit.rb +24 -0
  55. data/lib/pwnlib/shellcraft/generators/i386/linux/linux.rb +16 -0
  56. data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +24 -0
  57. data/lib/pwnlib/shellcraft/generators/i386/linux/open.rb +24 -0
  58. data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +24 -0
  59. data/lib/pwnlib/shellcraft/generators/i386/linux/sleep.rb +24 -0
  60. data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +24 -0
  61. data/lib/pwnlib/shellcraft/generators/x86/common/common.rb +29 -0
  62. data/lib/pwnlib/shellcraft/generators/x86/common/infloop.rb +24 -0
  63. data/lib/pwnlib/shellcraft/generators/x86/common/memcpy.rb +17 -0
  64. data/lib/pwnlib/shellcraft/generators/x86/common/mov.rb +17 -0
  65. data/lib/pwnlib/shellcraft/generators/x86/common/pushstr.rb +17 -0
  66. data/lib/pwnlib/shellcraft/generators/x86/common/pushstr_array.rb +86 -0
  67. data/lib/pwnlib/shellcraft/generators/x86/common/setregs.rb +84 -0
  68. data/lib/pwnlib/shellcraft/generators/x86/linux/cat.rb +54 -0
  69. data/lib/pwnlib/shellcraft/generators/x86/linux/execve.rb +72 -0
  70. data/lib/pwnlib/shellcraft/generators/x86/linux/exit.rb +34 -0
  71. data/lib/pwnlib/shellcraft/generators/x86/linux/linux.rb +16 -0
  72. data/lib/pwnlib/shellcraft/generators/x86/linux/ls.rb +67 -0
  73. data/lib/pwnlib/shellcraft/generators/x86/linux/open.rb +47 -0
  74. data/lib/pwnlib/shellcraft/generators/x86/linux/sh.rb +53 -0
  75. data/lib/pwnlib/shellcraft/generators/x86/linux/sleep.rb +52 -0
  76. data/lib/pwnlib/shellcraft/generators/x86/linux/syscall.rb +52 -0
  77. data/lib/pwnlib/shellcraft/registers.rb +148 -0
  78. data/lib/pwnlib/shellcraft/shellcraft.rb +73 -0
  79. data/lib/pwnlib/timer.rb +67 -0
  80. data/lib/pwnlib/tubes/buffer.rb +99 -0
  81. data/lib/pwnlib/tubes/process.rb +155 -0
  82. data/lib/pwnlib/tubes/serialtube.rb +114 -0
  83. data/lib/pwnlib/tubes/sock.rb +101 -0
  84. data/lib/pwnlib/tubes/tube.rb +442 -0
  85. data/lib/pwnlib/ui.rb +21 -0
  86. data/lib/pwnlib/util/cyclic.rb +97 -94
  87. data/lib/pwnlib/util/fiddling.rb +288 -220
  88. data/lib/pwnlib/util/getdents.rb +85 -0
  89. data/lib/pwnlib/util/hexdump.rb +116 -112
  90. data/lib/pwnlib/util/lists.rb +58 -0
  91. data/lib/pwnlib/util/packing.rb +223 -228
  92. data/lib/pwnlib/util/ruby.rb +19 -0
  93. data/lib/pwnlib/version.rb +3 -1
  94. data/test/abi_test.rb +22 -0
  95. data/test/asm_test.rb +177 -0
  96. data/test/constants/constant_test.rb +2 -0
  97. data/test/constants/constants_test.rb +5 -2
  98. data/test/context_test.rb +14 -3
  99. data/test/data/assembly/aarch64.s +19 -0
  100. data/test/data/assembly/amd64.s +21 -0
  101. data/test/data/assembly/arm.s +9 -0
  102. data/test/data/assembly/i386.s +21 -0
  103. data/test/data/assembly/mips.s +16 -0
  104. data/test/data/assembly/mips64.s +6 -0
  105. data/test/data/assembly/powerpc.s +18 -0
  106. data/test/data/assembly/powerpc64.s +36 -0
  107. data/test/data/assembly/sparc.s +33 -0
  108. data/test/data/assembly/sparc64.s +5 -0
  109. data/test/data/assembly/thumb.s +37 -0
  110. data/test/data/echo.rb +16 -0
  111. data/test/data/elfs/Makefile +24 -0
  112. data/test/data/elfs/amd64.frelro.elf +0 -0
  113. data/test/data/elfs/amd64.frelro.pie.elf +0 -0
  114. data/test/data/elfs/amd64.nrelro.elf +0 -0
  115. data/test/data/elfs/amd64.prelro.elf +0 -0
  116. data/test/data/elfs/amd64.static.elf +0 -0
  117. data/test/data/elfs/i386.frelro.pie.elf +0 -0
  118. data/test/data/elfs/i386.prelro.elf +0 -0
  119. data/test/data/elfs/source.cpp +19 -0
  120. data/test/data/flag +1 -0
  121. data/test/data/lib32/ld.so.2 +0 -0
  122. data/test/data/lib32/libc.so.6 +0 -0
  123. data/test/data/lib64/ld.so.2 +0 -0
  124. data/test/data/lib64/libc.so.6 +0 -0
  125. data/test/dynelf_test.rb +62 -25
  126. data/test/elf/elf_test.rb +147 -0
  127. data/test/ext_test.rb +4 -2
  128. data/test/files/use_pwn.rb +3 -6
  129. data/test/files/use_pwnlib.rb +2 -1
  130. data/test/full_file_test.rb +6 -0
  131. data/test/logger_test.rb +120 -0
  132. data/test/memleak_test.rb +5 -33
  133. data/test/reg_sort_test.rb +4 -1
  134. data/test/runner_test.rb +32 -0
  135. data/test/shellcraft/infloop_test.rb +27 -0
  136. data/test/shellcraft/linux/cat_test.rb +87 -0
  137. data/test/shellcraft/linux/ls_test.rb +109 -0
  138. data/test/shellcraft/linux/sh_test.rb +120 -0
  139. data/test/shellcraft/linux/sleep_test.rb +68 -0
  140. data/test/shellcraft/linux/syscalls/execve_test.rb +137 -0
  141. data/test/shellcraft/linux/syscalls/exit_test.rb +57 -0
  142. data/test/shellcraft/linux/syscalls/open_test.rb +87 -0
  143. data/test/shellcraft/linux/syscalls/syscall_test.rb +84 -0
  144. data/test/shellcraft/memcpy_test.rb +50 -0
  145. data/test/shellcraft/mov_test.rb +99 -0
  146. data/test/shellcraft/nop_test.rb +27 -0
  147. data/test/shellcraft/popad_test.rb +30 -0
  148. data/test/shellcraft/pushstr_array_test.rb +92 -0
  149. data/test/shellcraft/pushstr_test.rb +109 -0
  150. data/test/shellcraft/registers_test.rb +33 -0
  151. data/test/shellcraft/ret_test.rb +31 -0
  152. data/test/shellcraft/setregs_test.rb +63 -0
  153. data/test/shellcraft/shellcraft_test.rb +30 -0
  154. data/test/test_helper.rb +61 -2
  155. data/test/timer_test.rb +42 -0
  156. data/test/tubes/buffer_test.rb +46 -0
  157. data/test/tubes/process_test.rb +105 -0
  158. data/test/tubes/serialtube_test.rb +162 -0
  159. data/test/tubes/sock_test.rb +68 -0
  160. data/test/tubes/tube_test.rb +320 -0
  161. data/test/ui_test.rb +18 -0
  162. data/test/util/cyclic_test.rb +3 -1
  163. data/test/util/fiddling_test.rb +12 -3
  164. data/test/util/getdents_test.rb +33 -0
  165. data/test/util/hexdump_test.rb +9 -10
  166. data/test/util/lists_test.rb +22 -0
  167. data/test/util/packing_test.rb +5 -3
  168. metadata +357 -37
@@ -1,19 +1,35 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/util/fiddling'
4
5
 
5
6
  module Pwnlib
6
7
  module Constants
7
- # A class that includes name and value
8
+ # A class that includes name and value representing a constant.
9
+ # This class works like an integer, and support operations with integers.
10
+ #
11
+ # @example
12
+ # a = Pwnlib::Constants::Constant.new('a', 0x3)
13
+ # #=> Constant("a", 0x3)
14
+ # [a + 1, 2 * a, a | 6, a == 3, 0 > a]
15
+ # #=> [4, 6, 7, true, false]
8
16
  class Constant < Numeric
9
- attr_reader :str, :val
17
+ # @return [String]
18
+ attr_reader :str
19
+
20
+ # @return [Integer]
21
+ attr_reader :val
22
+
23
+ # @param [String] str
24
+ # @param [Integer] val
10
25
  def initialize(str, val)
26
+ super()
11
27
  @str = str
12
28
  @val = val
13
29
  end
14
30
 
15
31
  # We don't need to fall back to super for this, so just disable the lint.
16
- def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissing
32
+ def method_missing(method, *args, &block)
17
33
  @val.__send__(method, *args, &block)
18
34
  end
19
35
 
@@ -1,45 +1,63 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
3
+
4
+ require 'dentaku'
2
5
 
3
- require 'pwnlib/context'
4
6
  require 'pwnlib/constants/constant'
7
+ require 'pwnlib/context'
8
+ require 'pwnlib/errors'
5
9
 
6
10
  module Pwnlib
7
- # Module containing constants
11
+ # Module containing constants.
12
+ #
8
13
  # @example
9
14
  # context.arch = 'amd64'
10
15
  # Pwnlib::Constants.SYS_read
11
- # # => Constant('SYS_read', 0x0)
16
+ # #=> Constant('SYS_read', 0x0)
12
17
  module Constants
13
- # @note Do not create and call instance method here. Instead, call module method on {Constants}.
14
- module ClassMethods
15
- include ::Pwnlib::Context
16
- ENV_STORE = {} # rubocop:disable Style/MutableConstant
17
- # Try getting constants when method missing
18
+ class << self
19
+ # To support getting constants like +Pwnlib::Constants.SYS_read+.
20
+ #
21
+ # @return [Constant]
22
+ #
23
+ # @raise [NoMethodError]
18
24
  def method_missing(method, *args, &block)
19
25
  args.empty? && block.nil? && get_constant(method) || super
20
26
  end
21
27
 
28
+ # @return [Boolean]
22
29
  def respond_to_missing?(method, _include_all)
23
30
  !get_constant(method).nil?
24
31
  end
25
32
 
26
- # Eval for Constants
33
+ # Eval for Constants.
27
34
  #
28
35
  # @param [String] str
29
- # The string to be evaluate.
36
+ # The string to be evaluated.
30
37
  #
31
38
  # @return [Constant]
32
- # The evaluate result.
39
+ # The evaluated result.
33
40
  #
34
- # @example
35
- # eval('O_CREAT')
36
- # => Constant('(O_CREAT)', 0x40)
41
+ # @raise [Pwnlib::Errors::ConstantNotFoundError]
42
+ # Raised when undefined constant(s) provided.
37
43
  #
38
- # @todo(david942j): Support eval('O_CREAT | O_APPEND') (i.e. safeeval)
44
+ # @example
45
+ # Constants.eval('O_CREAT')
46
+ # #=> Constant('(O_CREAT)', 0x40)
47
+ # Constants.eval('O_CREAT | O_APPEND')
48
+ # #=> Constant('(O_CREAT | O_APPEND)', 0x440)
49
+ # @example
50
+ # Constants.eval('meow')
51
+ # # Pwnlib::Errors::ConstantNotFoundError: Undefined constant(s): meow
39
52
  def eval(str)
40
53
  return str unless str.instance_of?(String)
41
- const = get_constant(str.strip.to_sym)
42
- ::Pwnlib::Constants::Constant.new("(#{str})", const.val)
54
+
55
+ begin
56
+ val = calculator.evaluate!(str.strip).to_i
57
+ rescue Dentaku::UnboundVariableError => e
58
+ raise ::Pwnlib::Errors::ConstantNotFoundError, "Undefined constant(s): #{e.unbound_variables.join(', ')}"
59
+ end
60
+ ::Pwnlib::Constants::Constant.new("(#{str})", val)
43
61
  end
44
62
 
45
63
  private
@@ -48,6 +66,7 @@ module Pwnlib
48
66
  [context.os, context.arch]
49
67
  end
50
68
 
69
+ ENV_STORE = {} # rubocop:disable Style/MutableConstant
51
70
  def current_store
52
71
  ENV_STORE[current_arch_key] ||= load_constants(current_arch_key)
53
72
  end
@@ -56,9 +75,15 @@ module Pwnlib
56
75
  current_store[symbol]
57
76
  end
58
77
 
59
- # Small class for instance_eval loaded file
78
+ CALCULATORS = {} # rubocop:disable Style/MutableConstant
79
+ def calculator
80
+ CALCULATORS[current_arch_key] ||= Dentaku::Calculator.new.store(current_store)
81
+ end
82
+
83
+ # Small class for instance_eval loaded file.
60
84
  class ConstantBuilder
61
85
  attr_reader :tbl
86
+
62
87
  def initialize
63
88
  @tbl = {}
64
89
  end
@@ -71,12 +96,13 @@ module Pwnlib
71
96
  def load_constants((os, arch))
72
97
  filename = File.join(__dir__, os, "#{arch}.rb")
73
98
  return {} unless File.exist?(filename)
99
+
74
100
  builder = ConstantBuilder.new
75
101
  builder.instance_eval(IO.read(filename))
76
102
  builder.tbl
77
103
  end
78
- end
79
104
 
80
- extend ClassMethods
105
+ include ::Pwnlib::Context
106
+ end
81
107
  end
82
108
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  const :__NR_read, 0
2
4
  const :__NR_write, 1
3
5
  const :__NR_open, 2
@@ -235,7 +237,6 @@ const :__NR_epoll_ctl, 233
235
237
  const :__NR_tgkill, 234
236
238
  const :__NR_utimes, 235
237
239
  const :__NR_vserver, 236
238
- const :__NR_vserver, 236
239
240
  const :__NR_mbind, 237
240
241
  const :__NR_set_mempolicy, 238
241
242
  const :__NR_get_mempolicy, 239
@@ -302,6 +303,36 @@ const :__NR_recvmmsg, 299
302
303
  const :__NR_fanotify_init, 300
303
304
  const :__NR_fanotify_mark, 301
304
305
  const :__NR_prlimit64, 302
306
+ const :__NR_name_to_handle_at, 303
307
+ const :__NR_open_by_handle_at, 304
308
+ const :__NR_clock_adjtime, 305
309
+ const :__NR_syncfs, 306
310
+ const :__NR_sendmmsg, 307
311
+ const :__NR_setns, 308
312
+ const :__NR_getcpu, 309
313
+ const :__NR_process_vm_readv, 310
314
+ const :__NR_process_vm_writev, 311
315
+ const :__NR_kcmp, 312
316
+ const :__NR_finit_module, 313
317
+ const :__NR_sched_setattr, 314
318
+ const :__NR_sched_getattr, 315
319
+ const :__NR_renameat2, 316
320
+ const :__NR_seccomp, 317
321
+ const :__NR_getrandom, 318
322
+ const :__NR_memfd_create, 319
323
+ const :__NR_kexec_file_load, 320
324
+ const :__NR_bpf, 321
325
+ const :__NR_execveat, 322
326
+ const :__NR_userfaultfd, 323
327
+ const :__NR_membarrier, 324
328
+ const :__NR_mlock2, 325
329
+ const :__NR_copy_file_range, 326
330
+ const :__NR_preadv2, 327
331
+ const :__NR_pwritev2, 328
332
+ const :__NR_pkey_mprotect, 329
333
+ const :__NR_pkey_alloc, 330
334
+ const :__NR_pkey_free, 331
335
+ const :__NR_statx, 332
305
336
  const :SYS32_restart_syscall, 0
306
337
  const :SYS32_exit, 1
307
338
  const :SYS32_fork, 2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  const :__NR_exit, 1
2
4
  const :__NR_fork, 2
3
5
  const :__NR_read, 3
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'logger'
4
5
 
@@ -17,7 +18,7 @@ module Pwnlib
17
18
  newline: "\n",
18
19
  os: 'linux',
19
20
  signed: false,
20
- timeout: Float::INFINITY
21
+ timeout: :forever
21
22
  }.freeze
22
23
 
23
24
  OSES = %w(linux freebsd windows).sort
@@ -30,10 +31,11 @@ module Pwnlib
30
31
  LITTLE_64 = { endian: 'little', bits: 64 }.freeze
31
32
 
32
33
  class << self
34
+ private
35
+
33
36
  def longest(d)
34
37
  Hash[d.sort_by { |k, _v| k.size }.reverse]
35
38
  end
36
- private :longest
37
39
  end
38
40
 
39
41
  ARCHS = longest(
@@ -76,19 +78,26 @@ module Pwnlib
76
78
 
77
79
  VALID_SIGNED = SIGNEDNESSES.keys
78
80
 
79
- # XXX(Darkpi): Should we just hard-coded all levels here,
80
- # or should we use Logger#const_defined?
81
- # (This would include constant SEV_LEVEL, and exclude UNKNOWN)?
81
+ # We use Logger#const_defined for pwnlib logger.
82
82
  LOG_LEVELS = %w(DEBUG INFO WARN ERROR FATAL UNKNOWN).freeze
83
83
 
84
+ # Instantiate a {Pwnlib::Context::ContextType} object.
84
85
  def initialize(**kwargs)
85
86
  @attrs = DEFAULT.dup
86
87
  update(**kwargs)
87
88
  end
88
89
 
90
+ # Convenience function, which is shorthand for setting multiple variables at once.
91
+ #
92
+ # @param [Hash] kwargs
93
+ # Variables to be assigned in the environment.
94
+ #
95
+ # @example
96
+ # context.update(arch: 'amd64', os: :linux)
89
97
  def update(**kwargs)
90
98
  kwargs.each do |k, v|
91
99
  next if v.nil?
100
+
92
101
  public_send("#{k}=", v)
93
102
  end
94
103
  self
@@ -97,16 +106,29 @@ module Pwnlib
97
106
  alias [] update
98
107
  alias call update
99
108
 
109
+ # Create a string representation of self.
100
110
  def to_s
101
111
  vals = @attrs.map { |k, v| "#{k} = #{v.inspect}" }
102
112
  "#{self.class}(#{vals.join(', ')})"
103
113
  end
104
114
 
105
- # This would return what the block return.
115
+ # Create a context manager for a block.
116
+ #
117
+ # @param [Hash] kwargs
118
+ # Variables to be assigned in the environment.
119
+ #
120
+ # @return
121
+ # This would return what the block returned.
122
+ #
123
+ # @example
124
+ # context.local(arch: 'amd64') { puts context.endian }
125
+ # # little
106
126
  def local(**kwargs)
107
127
  raise ArgumentError, "Need a block for #{self.class}##{__callee__}" unless block_given?
108
- # XXX(Darkpi): improve performance for this if this is too slow, since we use this in many
109
- # places that has argument endian / signed / ...
128
+
129
+ # XXX(Darkpi):
130
+ # improve performance for this if this is too slow, since we use this in many places that has argument
131
+ # endian / signed / ...
110
132
  old_attrs = @attrs.dup
111
133
  begin
112
134
  update(**kwargs)
@@ -116,6 +138,13 @@ module Pwnlib
116
138
  end
117
139
  end
118
140
 
141
+ # Clear the contents of the context, which will set all values to their defaults.
142
+ #
143
+ # @example
144
+ # context.arch = 'amd64'
145
+ # context.clear
146
+ # context.bits == 32
147
+ # #=> true
119
148
  def clear
120
149
  @attrs = DEFAULT.dup
121
150
  end
@@ -125,74 +154,136 @@ module Pwnlib
125
154
  define_method(k) { @attrs[k] }
126
155
  end
127
156
 
157
+ # Set the newline.
158
+ #
159
+ # @param [String] newline
160
+ # The newline.
161
+ #
162
+ # @example
163
+ # context.newline = "\r\n"
128
164
  def newline=(newline)
129
165
  @attrs[:newline] = newline
130
166
  end
131
167
 
132
- # TODO(Darkpi): Timeout module.
168
+ # Set the default amount of time to wait for a blocking operation before it times out.
169
+ #
170
+ # @param [Float, :forever] timeout
171
+ # Any positive floating number, indicates timeout in seconds.
172
+ #
173
+ # @example
174
+ # context.timeout = 5.14
133
175
  def timeout=(timeout)
134
176
  @attrs[:timeout] = timeout
135
177
  end
136
178
 
137
- # Difference from Python pwntools:
138
- # We always change +bits+ and +endian+ field whether user have already changed them.
179
+ # Set the architecture of the target binary.
180
+ #
181
+ # @param [String, Symbol] arch
182
+ # The architecture. Only values in {Pwnlib::Context::ContextType::ARCHS} are available.
183
+ #
184
+ # @diff We always change +bits+ and +endian+ field whether user have already changed them.
139
185
  def arch=(arch)
140
- arch = arch.downcase.gsub(/[[:punct:]]/, '')
186
+ arch = arch.to_s.downcase.gsub(/[[:punct:]]/, '')
141
187
  defaults = ARCHS[arch]
142
188
  raise ArgumentError, "arch must be one of #{ARCHS.keys.sort.inspect}" unless defaults
189
+
143
190
  defaults.each { |k, v| @attrs[k] = v }
144
191
  @attrs[:arch] = arch
145
192
  end
146
193
 
194
+ # Set the word size of the target machine in bits (i.e. the size of general purpose registers).
195
+ #
196
+ # @param [Integer] bits
197
+ # The word size.
147
198
  def bits=(bits)
148
- raise ArgumentError, "bits must be > 0 (#{bits} given)" unless bits > 0
199
+ raise ArgumentError, "bits must be > 0 (#{bits} given)" unless bits.positive?
200
+
149
201
  @attrs[:bits] = bits
150
202
  end
151
203
 
204
+ # The word size of the target machine.
152
205
  def bytes
153
206
  bits / 8
154
207
  end
155
208
 
209
+ # Set the word size of the target machine in bytes (i.e. the size of general purpose registers).
210
+ #
211
+ # @param [Integer] bytes
212
+ # The word size.
156
213
  def bytes=(bytes)
157
214
  self.bits = bytes * 8
158
215
  end
159
216
 
217
+ # The endianness of the target machine.
218
+ #
219
+ # @param [String, Symbol] endian
220
+ # The endianness. Only values in {Pwnlib::Context::ContextType::ENDIANNESSES} are available.
221
+ #
222
+ # @example
223
+ # context.endian = :big
160
224
  def endian=(endian)
161
- endian = ENDIANNESSES[endian.downcase]
225
+ endian = ENDIANNESSES[endian.to_s.downcase]
162
226
  raise ArgumentError, "endian must be one of #{ENDIANNESSES.sort.inspect}" if endian.nil?
227
+
163
228
  @attrs[:endian] = endian
164
229
  end
165
230
 
231
+ # Set the verbosity of the logger in +Pwnlib+.
232
+ #
233
+ # @param [String, Symbol] value
234
+ # The verbosity. Only values in {Pwnlib::Context::ContextType::LOG_LEVELS} are available.
235
+ #
236
+ # @example
237
+ # context.log_level = :debug
166
238
  def log_level=(value)
167
239
  log_level = nil
168
240
  case value
169
- when String
170
- value = value.upcase
241
+ when String, Symbol
242
+ value = value.to_s.upcase
171
243
  log_level = Logger.const_get(value) if LOG_LEVELS.include?(value)
172
244
  when Integer
173
245
  log_level = value
174
246
  end
175
247
  raise ArgumentError, "log_level must be an integer or one of #{LOG_LEVELS.inspect}" unless log_level
248
+
176
249
  @attrs[:log_level] = log_level
177
250
  end
178
251
 
252
+ # Set the operating system of the target machine.
253
+ #
254
+ # @param [String, Symbol] os
255
+ # The name of the os. Only values in {Pwnlib::Context::ContextType::OSES} are available.
256
+ #
257
+ # @example
258
+ # context.os = :windows
179
259
  def os=(os)
180
- os = os.downcase
260
+ os = os.to_s.downcase
181
261
  raise ArgumentError, "os must be one of #{OSES.sort.inspect}" unless OSES.include?(os)
262
+
182
263
  @attrs[:os] = os
183
264
  end
184
265
 
266
+ # Set the signedness for packing opreation.
267
+ #
268
+ # @param [String, Symbol, true, false] value
269
+ # The signedness. Only values in {Pwnlib::Context::ContextType::SIGNEDNESSES} are available.
270
+ #
271
+ # @example
272
+ # context.signed == false
273
+ # #=> true
274
+ # context.signed = 'signed'
275
+ # context.signed == true
276
+ # #=> true
185
277
  def signed=(value)
186
278
  signed = nil
187
279
  case value
188
- when String
189
- signed = SIGNEDNESSES[value.downcase]
280
+ when String, Symbol
281
+ signed = SIGNEDNESSES[value.to_s.downcase]
190
282
  when true, false
191
283
  signed = value
192
284
  end
193
- if signed.nil?
194
- raise ArgumentError, "signed must be boolean or one of #{SIGNEDNESSES.keys.sort.inspect}"
195
- end
285
+ raise ArgumentError, "signed must be boolean or one of #{SIGNEDNESSES.keys.sort.inspect}" if signed.nil?
286
+
196
287
  @attrs[:signed] = signed
197
288
  end
198
289
 
@@ -201,20 +292,30 @@ module Pwnlib
201
292
 
202
293
  @context = ContextType.new
203
294
 
295
+ # @!attribute [r] context
296
+ # @return [ContextType] the singleton context for all class.
204
297
  class << self
205
298
  attr_reader :context
206
299
  end
207
300
 
208
- # For include.
301
+ # A module for include hook for context.
302
+ # Including Pwnlib::Context from module M would add +context+ as a private instance method and a private class
303
+ # method for module M.
209
304
  # @!visibility private
210
- def context
211
- ::Pwnlib::Context.context
305
+ module IncludeContext
306
+ private
307
+
308
+ def context
309
+ ::Pwnlib::Context.context
310
+ end
212
311
  end
213
312
 
214
313
  # @!visibility private
215
314
  def self.included(base)
216
- # XXX(Darkpi): Should we do this?
217
- base.__send__(:private, :context)
315
+ base.include(IncludeContext)
316
+ class << base
317
+ include IncludeContext
318
+ end
218
319
  end
219
320
  end
220
321
  end