pwntools 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -3
  3. data/lib/pwn.rb +1 -0
  4. data/lib/pwnlib/abi.rb +1 -0
  5. data/lib/pwnlib/asm.rb +83 -42
  6. data/lib/pwnlib/constants/constant.rb +4 -1
  7. data/lib/pwnlib/constants/constants.rb +3 -0
  8. data/lib/pwnlib/constants/linux/amd64.rb +2 -0
  9. data/lib/pwnlib/constants/linux/i386.rb +2 -0
  10. data/lib/pwnlib/context.rb +10 -1
  11. data/lib/pwnlib/dynelf.rb +7 -2
  12. data/lib/pwnlib/elf/elf.rb +79 -6
  13. data/lib/pwnlib/errors.rb +3 -2
  14. data/lib/pwnlib/ext/array.rb +2 -1
  15. data/lib/pwnlib/ext/helper.rb +3 -2
  16. data/lib/pwnlib/ext/integer.rb +2 -1
  17. data/lib/pwnlib/ext/string.rb +3 -2
  18. data/lib/pwnlib/logger.rb +21 -1
  19. data/lib/pwnlib/memleak.rb +1 -0
  20. data/lib/pwnlib/pwn.rb +5 -1
  21. data/lib/pwnlib/reg_sort.rb +5 -0
  22. data/lib/pwnlib/runner.rb +53 -0
  23. data/lib/pwnlib/shellcraft/generators/amd64/common/common.rb +2 -0
  24. data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +1 -0
  25. data/lib/pwnlib/shellcraft/generators/amd64/common/memcpy.rb +5 -1
  26. data/lib/pwnlib/shellcraft/generators/amd64/common/mov.rb +4 -0
  27. data/lib/pwnlib/shellcraft/generators/amd64/common/nop.rb +2 -0
  28. data/lib/pwnlib/shellcraft/generators/amd64/common/popad.rb +1 -0
  29. data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr.rb +3 -1
  30. data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +1 -0
  31. data/lib/pwnlib/shellcraft/generators/amd64/common/ret.rb +1 -0
  32. data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +3 -2
  33. data/lib/pwnlib/shellcraft/generators/amd64/linux/cat.rb +3 -2
  34. data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +1 -0
  35. data/lib/pwnlib/shellcraft/generators/amd64/linux/exit.rb +1 -0
  36. data/lib/pwnlib/shellcraft/generators/amd64/linux/linux.rb +2 -0
  37. data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +1 -0
  38. data/lib/pwnlib/shellcraft/generators/amd64/linux/open.rb +1 -0
  39. data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +3 -2
  40. data/lib/pwnlib/shellcraft/generators/amd64/linux/sleep.rb +24 -0
  41. data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +1 -0
  42. data/lib/pwnlib/shellcraft/generators/helper.rb +11 -2
  43. data/lib/pwnlib/shellcraft/generators/i386/common/common.rb +2 -0
  44. data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +1 -0
  45. data/lib/pwnlib/shellcraft/generators/i386/common/memcpy.rb +34 -0
  46. data/lib/pwnlib/shellcraft/generators/i386/common/mov.rb +3 -0
  47. data/lib/pwnlib/shellcraft/generators/i386/common/nop.rb +2 -0
  48. data/lib/pwnlib/shellcraft/generators/i386/common/pushstr.rb +2 -0
  49. data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +1 -0
  50. data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +3 -2
  51. data/lib/pwnlib/shellcraft/generators/i386/linux/cat.rb +3 -2
  52. data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +1 -0
  53. data/lib/pwnlib/shellcraft/generators/i386/linux/exit.rb +1 -0
  54. data/lib/pwnlib/shellcraft/generators/i386/linux/linux.rb +2 -0
  55. data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +1 -0
  56. data/lib/pwnlib/shellcraft/generators/i386/linux/open.rb +1 -0
  57. data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +3 -2
  58. data/lib/pwnlib/shellcraft/generators/i386/linux/sleep.rb +24 -0
  59. data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +1 -0
  60. data/lib/pwnlib/shellcraft/generators/x86/common/common.rb +5 -3
  61. data/lib/pwnlib/shellcraft/generators/x86/common/infloop.rb +2 -0
  62. data/lib/pwnlib/shellcraft/generators/x86/common/memcpy.rb +17 -0
  63. data/lib/pwnlib/shellcraft/generators/x86/common/mov.rb +2 -0
  64. data/lib/pwnlib/shellcraft/generators/x86/common/pushstr.rb +2 -0
  65. data/lib/pwnlib/shellcraft/generators/x86/common/pushstr_array.rb +1 -0
  66. data/lib/pwnlib/shellcraft/generators/x86/common/setregs.rb +8 -6
  67. data/lib/pwnlib/shellcraft/generators/x86/linux/cat.rb +1 -0
  68. data/lib/pwnlib/shellcraft/generators/x86/linux/execve.rb +3 -0
  69. data/lib/pwnlib/shellcraft/generators/x86/linux/exit.rb +1 -0
  70. data/lib/pwnlib/shellcraft/generators/x86/linux/linux.rb +2 -0
  71. data/lib/pwnlib/shellcraft/generators/x86/linux/ls.rb +1 -0
  72. data/lib/pwnlib/shellcraft/generators/x86/linux/open.rb +1 -0
  73. data/lib/pwnlib/shellcraft/generators/x86/linux/sh.rb +1 -0
  74. data/lib/pwnlib/shellcraft/generators/x86/linux/sleep.rb +52 -0
  75. data/lib/pwnlib/shellcraft/generators/x86/linux/syscall.rb +10 -10
  76. data/lib/pwnlib/shellcraft/registers.rb +5 -1
  77. data/lib/pwnlib/shellcraft/shellcraft.rb +8 -3
  78. data/lib/pwnlib/timer.rb +6 -2
  79. data/lib/pwnlib/tubes/buffer.rb +4 -1
  80. data/lib/pwnlib/tubes/process.rb +2 -0
  81. data/lib/pwnlib/tubes/serialtube.rb +3 -1
  82. data/lib/pwnlib/tubes/sock.rb +7 -1
  83. data/lib/pwnlib/tubes/tube.rb +23 -3
  84. data/lib/pwnlib/ui.rb +21 -0
  85. data/lib/pwnlib/util/cyclic.rb +2 -0
  86. data/lib/pwnlib/util/fiddling.rb +37 -5
  87. data/lib/pwnlib/util/getdents.rb +1 -0
  88. data/lib/pwnlib/util/hexdump.rb +8 -5
  89. data/lib/pwnlib/util/lists.rb +3 -0
  90. data/lib/pwnlib/util/packing.rb +5 -2
  91. data/lib/pwnlib/util/ruby.rb +1 -0
  92. data/lib/pwnlib/version.rb +2 -1
  93. data/test/abi_test.rb +1 -0
  94. data/test/asm_test.rb +75 -85
  95. data/test/constants/constant_test.rb +1 -0
  96. data/test/constants/constants_test.rb +1 -0
  97. data/test/context_test.rb +1 -0
  98. data/test/data/assembly/aarch64.s +19 -0
  99. data/test/data/assembly/amd64.s +21 -0
  100. data/test/data/assembly/arm.s +9 -0
  101. data/test/data/assembly/i386.s +21 -0
  102. data/test/data/assembly/mips.s +16 -0
  103. data/test/data/assembly/mips64.s +6 -0
  104. data/test/data/assembly/powerpc.s +18 -0
  105. data/test/data/assembly/powerpc64.s +36 -0
  106. data/test/data/assembly/sparc.s +33 -0
  107. data/test/data/assembly/sparc64.s +5 -0
  108. data/test/data/assembly/thumb.s +37 -0
  109. data/test/data/echo.rb +1 -0
  110. data/test/dynelf_test.rb +3 -1
  111. data/test/elf/elf_test.rb +18 -0
  112. data/test/ext_test.rb +1 -0
  113. data/test/files/use_pwn.rb +1 -0
  114. data/test/files/use_pwnlib.rb +1 -0
  115. data/test/full_file_test.rb +6 -0
  116. data/test/logger_test.rb +24 -3
  117. data/test/memleak_test.rb +1 -0
  118. data/test/reg_sort_test.rb +1 -0
  119. data/test/runner_test.rb +32 -0
  120. data/test/shellcraft/infloop_test.rb +1 -0
  121. data/test/shellcraft/linux/cat_test.rb +1 -0
  122. data/test/shellcraft/linux/ls_test.rb +1 -0
  123. data/test/shellcraft/linux/sh_test.rb +1 -0
  124. data/test/shellcraft/linux/sleep_test.rb +68 -0
  125. data/test/shellcraft/linux/syscalls/execve_test.rb +1 -0
  126. data/test/shellcraft/linux/syscalls/exit_test.rb +1 -0
  127. data/test/shellcraft/linux/syscalls/open_test.rb +1 -0
  128. data/test/shellcraft/linux/syscalls/syscall_test.rb +1 -0
  129. data/test/shellcraft/memcpy_test.rb +20 -5
  130. data/test/shellcraft/mov_test.rb +1 -0
  131. data/test/shellcraft/nop_test.rb +1 -0
  132. data/test/shellcraft/popad_test.rb +1 -0
  133. data/test/shellcraft/pushstr_array_test.rb +1 -0
  134. data/test/shellcraft/pushstr_test.rb +1 -0
  135. data/test/shellcraft/registers_test.rb +1 -0
  136. data/test/shellcraft/ret_test.rb +1 -0
  137. data/test/shellcraft/setregs_test.rb +9 -8
  138. data/test/shellcraft/shellcraft_test.rb +1 -0
  139. data/test/test_helper.rb +28 -0
  140. data/test/timer_test.rb +2 -1
  141. data/test/tubes/buffer_test.rb +1 -0
  142. data/test/tubes/process_test.rb +8 -2
  143. data/test/tubes/serialtube_test.rb +1 -4
  144. data/test/tubes/sock_test.rb +1 -0
  145. data/test/tubes/tube_test.rb +10 -1
  146. data/test/ui_test.rb +18 -0
  147. data/test/util/cyclic_test.rb +1 -0
  148. data/test/util/fiddling_test.rb +8 -0
  149. data/test/util/getdents_test.rb +1 -0
  150. data/test/util/hexdump_test.rb +2 -1
  151. data/test/util/lists_test.rb +1 -0
  152. data/test/util/packing_test.rb +3 -2
  153. metadata +119 -59
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/shellcraft/generators/x86/common/pushstr'
4
5
  require 'pwnlib/shellcraft/generators/x86/common/pushstr_array'
@@ -34,6 +35,7 @@ module Pwnlib
34
35
  argv = case argv
35
36
  when String
36
37
  raise ArgumentError, "#{argv.inspect} is not a valid register name" unless register?(argv)
38
+
37
39
  argv
38
40
  when Array
39
41
  cat Common.pushstr_array(abi.register_arguments[2], argv)
@@ -46,6 +48,7 @@ module Pwnlib
46
48
  envp = case envp
47
49
  when String
48
50
  raise ArgumentError, "#{envp.inspect} is not a valid register name" unless register?(envp)
51
+
49
52
  envp
50
53
  when Hash
51
54
  cat Common.pushstr_array(abi.register_arguments[3], envp.map { |k, v| "#{k}=#{v}" })
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/shellcraft/generators/x86/linux/linux'
4
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pwnlib/shellcraft/generators/helper'
2
4
 
3
5
  module Pwnlib
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/shellcraft/generators/x86/common/pushstr'
4
5
  require 'pwnlib/shellcraft/generators/x86/linux/linux'
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/shellcraft/generators/x86/linux/linux'
4
5
 
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/shellcraft/generators/x86/linux/execve'
4
5
  require 'pwnlib/shellcraft/generators/x86/linux/linux'
@@ -0,0 +1,52 @@
1
+ # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
3
+
4
+ require 'pwnlib/shellcraft/generators/x86/common/pushstr'
5
+ require 'pwnlib/shellcraft/generators/x86/linux/linux'
6
+ require 'pwnlib/shellcraft/generators/x86/linux/syscall'
7
+ require 'pwnlib/util/packing'
8
+
9
+ module Pwnlib
10
+ module Shellcraft
11
+ module Generators
12
+ module X86
13
+ module Linux
14
+ # Sleep for a specified number of seconds.
15
+ #
16
+ # @param [Float] seconds
17
+ # The seconds to sleep.
18
+ #
19
+ # @example
20
+ # context.arch = :amd64
21
+ # puts shellcraft.sleep(1)
22
+ # # /* push "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" */
23
+ # # push 1
24
+ # # dec byte ptr [rsp]
25
+ # # push 1
26
+ # # /* call nanosleep("rsp", 0) */
27
+ # # push 0x23 /* (SYS_nanosleep) */
28
+ # # pop rax
29
+ # # mov rdi, rsp
30
+ # # xor esi, esi /* 0 */
31
+ # # syscall
32
+ # # add rsp, 16 /* recover rsp */
33
+ # #=> nil
34
+ #
35
+ # @note
36
+ # Syscall +nanosleep+ accepts a data pointer as argument, the stack will be used for putting the data
37
+ # needed. The generated assembly will use sizeof(struct timespec) = 16 bytes for putting data.
38
+ def sleep(seconds)
39
+ # pushes the data onto stack
40
+ tv_sec = seconds.to_i
41
+ tv_nsec = ((seconds - tv_sec) * 1e9).to_i
42
+ data = ::Pwnlib::Util::Packing.p64(tv_sec) + ::Pwnlib::Util::Packing.p64(tv_nsec)
43
+ cat Common.pushstr(data, append_null: false)
44
+ sp = ::Pwnlib::ABI::ABI.default.stack_pointer
45
+ cat Linux.syscall('SYS_nanosleep', sp, 0)
46
+ cat "add #{sp}, #{data.size} /* recover #{sp} */"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,7 +1,9 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/shellcraft/generators/x86/common/setregs'
4
5
  require 'pwnlib/shellcraft/generators/x86/linux/linux'
6
+ require 'pwnlib/util/ruby'
5
7
 
6
8
  module Pwnlib
7
9
  module Shellcraft
@@ -23,25 +25,23 @@ module Pwnlib
23
25
  # #=> nil
24
26
  def syscall(*arguments)
25
27
  abi = ::Pwnlib::ABI::ABI.syscall
26
- syscall, arg0, arg1, arg2, arg3, arg4, arg5 = arguments
27
- if syscall.respond_to?(:to_s) && syscall.to_s.start_with?('SYS_')
28
- syscall_repr = syscall.to_s[4..-1] + '(%s)'
28
+ registers = abi.register_arguments
29
+ reg_ctx = registers.zip(arguments).to_h
30
+ syscall = arguments.first
31
+ if syscall.to_s.start_with?('SYS_')
32
+ fmt = syscall.to_s[4..-1] + '(%s)'
29
33
  args = []
30
34
  else
31
- syscall_repr = 'syscall(%s)'
35
+ fmt = 'syscall(%s)'
32
36
  args = [syscall ? syscall.inspect : '?']
33
37
  end
34
38
  # arg0 to arg5
35
39
  1.upto(6) do |i|
36
40
  args.push(arguments[i] ? arguments[i].inspect : '?')
37
41
  end
38
-
39
42
  args.pop while args.last == '?'
40
- syscall_repr = format(syscall_repr, args.join(', '))
41
- registers = abi.register_arguments
42
- arguments = [syscall, arg0, arg1, arg2, arg3, arg4, arg5]
43
- reg_ctx = registers.zip(arguments).to_h
44
- cat "/* call #{syscall_repr} */"
43
+
44
+ cat "/* call #{format(fmt, args.join(', '))} */"
45
45
  cat Common.setregs(reg_ctx) if arguments.any? { |v| !v.nil? }
46
46
  cat abi.syscall_str
47
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pwnlib/context'
2
4
 
3
5
  module Pwnlib
@@ -55,6 +57,7 @@ module Pwnlib
55
57
  @size = size
56
58
  X86_ORDERED.each do |row|
57
59
  next unless row.include?(name)
60
+
58
61
  @bigger = row[0, row.index(name)]
59
62
  @smaller = row[(row.index(name) + 1)..-1]
60
63
  @native64 = row[0]
@@ -122,6 +125,7 @@ module Pwnlib
122
125
  def get_register(name)
123
126
  return name if name.instance_of?(Register)
124
127
  return INTEL[name.to_s] if name.instance_of?(String) || name.instance_of?(Symbol)
128
+
125
129
  nil
126
130
  end
127
131
 
@@ -132,7 +136,7 @@ module Pwnlib
132
136
  def bits_required(value)
133
137
  bits = 0
134
138
  value = value.abs
135
- while value > 0
139
+ while value.positive?
136
140
  bits += 8
137
141
  value >>= 8
138
142
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'singleton'
4
5
 
@@ -19,7 +20,7 @@ module Pwnlib
19
20
 
20
21
  # All files under generators/ will be required.
21
22
  def initialize
22
- Dir[File.join(__dir__, 'generators', '**', '*.rb')].each do |f|
23
+ Dir[File.join(__dir__, 'generators', '**', '*.rb')].sort.each do |f|
23
24
  require f
24
25
  end
25
26
  end
@@ -29,15 +30,17 @@ module Pwnlib
29
30
  #
30
31
  # With this method, +context.local(arch: 'amd64') { shellcraft.sh }+ will invoke
31
32
  # {Shellcraft::Generators::Amd64::Linux#sh}.
32
- def method_missing(method, *args, &block)
33
+ def method_missing(method, *args, **kwargs, &block)
33
34
  mod = find_module_for(method)
34
35
  return super if mod.nil?
35
- mod.public_send(method, *args, &block)
36
+
37
+ mod.public_send(method, *args, **kwargs, &block)
36
38
  end
37
39
 
38
40
  # For +respond_to?+.
39
41
  def respond_to_missing?(method, include_private = false)
40
42
  return true if find_module_for(method)
43
+
41
44
  super
42
45
  end
43
46
 
@@ -55,9 +58,11 @@ module Pwnlib
55
58
  # try search in Common module
56
59
  common_module = arch_module.const_get(:Common)
57
60
  return common_module if common_module.singleton_methods.include?(method)
61
+
58
62
  # search in ${os} module
59
63
  os_module = arch_module.const_get(context.os.capitalize)
60
64
  return os_module if os_module.singleton_methods.include?(method)
65
+
61
66
  nil
62
67
  end
63
68
 
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'time'
4
5
 
@@ -29,11 +30,13 @@ module Pwnlib
29
30
 
30
31
  def timeout
31
32
  return @timeout || ::Pwnlib::Context.context.timeout unless started?
33
+
32
34
  @deadline == :forever ? :forever : [@deadline - Time.now, 0].max
33
35
  end
34
36
 
35
37
  def timeout=(timeout)
36
38
  raise "Can't change timeout when countdown" if started?
39
+
37
40
  @timeout = timeout
38
41
  end
39
42
 
@@ -41,13 +44,14 @@ module Pwnlib
41
44
  # NOTE(Darkpi): timeout = nil means default value for the first time, and nop after that.
42
45
  def countdown(timeout = nil)
43
46
  raise ArgumentError, 'Need a block for countdown' unless block_given?
47
+
44
48
  if started?
45
49
  return yield if timeout.nil?
50
+
46
51
  raise 'Nested countdown not permitted'
47
52
  end
48
53
 
49
- timeout ||= @timeout
50
- timeout ||= ::Pwnlib::Context.context.timeout
54
+ timeout ||= @timeout || ::Pwnlib::Context.context.timeout
51
55
 
52
56
  @deadline = timeout == :forever ? :forever : Time.now + timeout
53
57
 
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  module Pwnlib
4
5
  module Tubes
@@ -35,6 +36,7 @@ module Pwnlib
35
36
  else
36
37
  data = data.to_s.dup
37
38
  return if data.empty?
39
+
38
40
  @data << data
39
41
  end
40
42
  @size += data.size
@@ -53,6 +55,7 @@ module Pwnlib
53
55
  else
54
56
  data = data.to_s.dup
55
57
  return if data.empty?
58
+
56
59
  @data.unshift(data)
57
60
  end
58
61
  @size += data.size
@@ -61,7 +64,7 @@ module Pwnlib
61
64
 
62
65
  # Retrieves bytes from the buffer.
63
66
  #
64
- # @param [Integer] n
67
+ # @param [Integer?] n
65
68
  # Maximum number of bytes to fetch.
66
69
  #
67
70
  # @return [String]
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/errors'
4
5
  require 'pwnlib/tubes/tube'
@@ -140,6 +141,7 @@ module Pwnlib
140
141
  def recv_raw(size)
141
142
  o, = IO.select([@o], [], [], @timeout)
142
143
  return if o.nil?
144
+
143
145
  @o.readpartial(size)
144
146
  rescue Errno::EIO, Errno::EPIPE, IOError
145
147
  raise ::Pwnlib::Errors::EndOfTubeError
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'rubyserial'
4
5
 
@@ -69,6 +70,7 @@ module Pwnlib
69
70
  while @serial_timer.active?
70
71
  data += @conn.read(numbytes - data.length)
71
72
  break unless data.empty?
73
+
72
74
  sleep 0.1
73
75
  end
74
76
  # XXX(JonathanBeverley): should we reverse @convert_newlines here?
@@ -94,7 +96,7 @@ module Pwnlib
94
96
 
95
97
  data.gsub!(context.newline, "\r\n") if @convert_newlines
96
98
  begin
97
- return @conn.write(data)
99
+ @conn.write(data)
98
100
  rescue RubySerial::Error
99
101
  close
100
102
  raise ::Pwnlib::Errors::EndOfTubeError
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'socket'
4
5
 
@@ -42,6 +43,7 @@ module Pwnlib
42
43
  def close(direction = :both)
43
44
  if direction == :both
44
45
  return if @sock.closed?
46
+
45
47
  @closed[:read] = @closed[:write] = true
46
48
  @sock.close
47
49
  else
@@ -55,6 +57,7 @@ module Pwnlib
55
57
 
56
58
  def shutdown(direction)
57
59
  return if @closed[direction]
60
+
58
61
  @closed[direction] = true
59
62
 
60
63
  if direction.equal?(:read)
@@ -70,6 +73,7 @@ module Pwnlib
70
73
 
71
74
  def send_raw(data)
72
75
  raise ::Pwnlib::Errors::EndOfTubeError if @closed[:write]
76
+
73
77
  begin
74
78
  @sock.write(data)
75
79
  rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED
@@ -80,10 +84,12 @@ module Pwnlib
80
84
 
81
85
  def recv_raw(size)
82
86
  raise ::Pwnlib::Errors::EndOfTubeError if @closed[:read]
87
+
83
88
  begin
84
89
  rs, = IO.select([@sock], [], [], @timeout)
85
90
  return if rs.nil?
86
- return @sock.readpartial(size)
91
+
92
+ @sock.readpartial(size)
87
93
  rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ECONNABORTED, EOFError
88
94
  shutdown(:read)
89
95
  raise ::Pwnlib::Errors::EndOfTubeError
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pwnlib/context'
4
5
  require 'pwnlib/errors'
@@ -59,6 +60,7 @@ module Pwnlib
59
60
  # @!macro raise_timeout
60
61
  def recv(num_bytes = nil, timeout: nil)
61
62
  return '' if @buffer.empty? && !fillbuffer(timeout: timeout)
63
+
62
64
  @buffer.get(num_bytes)
63
65
  end
64
66
  alias read recv
@@ -99,8 +101,9 @@ module Pwnlib
99
101
  # @!macro raise_timeout
100
102
  def recvpred(timeout: nil)
101
103
  raise ArgumentError, 'Need a block for recvpred' unless block_given?
104
+
102
105
  @timer.countdown(timeout) do
103
- data = ''
106
+ data = +''
104
107
  begin
105
108
  until yield(data)
106
109
  return '' unless @timer.active?
@@ -108,6 +111,7 @@ module Pwnlib
108
111
  c = recv(1)
109
112
 
110
113
  return '' if c.empty?
114
+
111
115
  data << c
112
116
  end
113
117
  data.slice!(0..-1)
@@ -161,12 +165,13 @@ module Pwnlib
161
165
  max_len = delims.map(&:size).max
162
166
  @timer.countdown(timeout) do
163
167
  data = Buffer.new
164
- matching = ''
168
+ matching = +''
165
169
  begin
166
170
  while @timer.active?
167
171
  s = recv(1)
168
172
 
169
173
  return '' if s.empty?
174
+
170
175
  matching << s
171
176
 
172
177
  sidx = matching.size
@@ -174,6 +179,7 @@ module Pwnlib
174
179
  delims.each do |d|
175
180
  idx = matching.index(d)
176
181
  next unless idx
182
+
177
183
  if idx + d.size <= sidx + match_len
178
184
  sidx = idx
179
185
  match_len = d.size
@@ -265,6 +271,19 @@ module Pwnlib
265
271
  recvpred(timeout: timeout) { |data| data =~ regex }
266
272
  end
267
273
 
274
+ # Receives data until reaching EOF or a timeout is occurred.
275
+ #
276
+ # @!macro timeout_definition
277
+ #
278
+ # @return [String]
279
+ # Returns the data received.
280
+ def recvall(timeout: nil)
281
+ recvn(1 << 63, timeout: timeout)
282
+ rescue ::Pwnlib::Errors::EndOfTubeError, ::Pwnlib::Errors::TimeoutError
283
+ @buffer.get
284
+ end
285
+ alias readall recvall
286
+
268
287
  # Sends data.
269
288
  #
270
289
  # @param [String] data
@@ -323,8 +342,9 @@ module Pwnlib
323
342
  # #=> nil
324
343
  def puts(*objs)
325
344
  return write(context.newline) if objs.empty?
345
+
326
346
  objs = *objs.flatten
327
- s = ''
347
+ s = +''
328
348
  objs.map(&:to_s).each do |elem|
329
349
  s << elem
330
350
  s << context.newline unless elem.end_with?(context.newline)