pwntools 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -3
- data/lib/pwn.rb +1 -0
- data/lib/pwnlib/abi.rb +1 -0
- data/lib/pwnlib/asm.rb +83 -42
- data/lib/pwnlib/constants/constant.rb +4 -1
- data/lib/pwnlib/constants/constants.rb +3 -0
- data/lib/pwnlib/constants/linux/amd64.rb +2 -0
- data/lib/pwnlib/constants/linux/i386.rb +2 -0
- data/lib/pwnlib/context.rb +10 -1
- data/lib/pwnlib/dynelf.rb +7 -2
- data/lib/pwnlib/elf/elf.rb +79 -6
- data/lib/pwnlib/errors.rb +3 -2
- data/lib/pwnlib/ext/array.rb +2 -1
- data/lib/pwnlib/ext/helper.rb +3 -2
- data/lib/pwnlib/ext/integer.rb +2 -1
- data/lib/pwnlib/ext/string.rb +3 -2
- data/lib/pwnlib/logger.rb +21 -1
- data/lib/pwnlib/memleak.rb +1 -0
- data/lib/pwnlib/pwn.rb +5 -1
- data/lib/pwnlib/reg_sort.rb +5 -0
- data/lib/pwnlib/runner.rb +53 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/common.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/memcpy.rb +5 -1
- data/lib/pwnlib/shellcraft/generators/amd64/common/mov.rb +4 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/nop.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/popad.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr.rb +3 -1
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/ret.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +3 -2
- data/lib/pwnlib/shellcraft/generators/amd64/linux/cat.rb +3 -2
- data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/exit.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/linux.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/open.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +3 -2
- data/lib/pwnlib/shellcraft/generators/amd64/linux/sleep.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/helper.rb +11 -2
- data/lib/pwnlib/shellcraft/generators/i386/common/common.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/memcpy.rb +34 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/mov.rb +3 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/nop.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +3 -2
- data/lib/pwnlib/shellcraft/generators/i386/linux/cat.rb +3 -2
- data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/exit.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/linux.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/open.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +3 -2
- data/lib/pwnlib/shellcraft/generators/i386/linux/sleep.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/common.rb +5 -3
- data/lib/pwnlib/shellcraft/generators/x86/common/infloop.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/memcpy.rb +17 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/mov.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/pushstr.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/pushstr_array.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/setregs.rb +8 -6
- data/lib/pwnlib/shellcraft/generators/x86/linux/cat.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/execve.rb +3 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/exit.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/linux.rb +2 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/ls.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/open.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/sh.rb +1 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/sleep.rb +52 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/syscall.rb +10 -10
- data/lib/pwnlib/shellcraft/registers.rb +5 -1
- data/lib/pwnlib/shellcraft/shellcraft.rb +8 -3
- data/lib/pwnlib/timer.rb +6 -2
- data/lib/pwnlib/tubes/buffer.rb +4 -1
- data/lib/pwnlib/tubes/process.rb +2 -0
- data/lib/pwnlib/tubes/serialtube.rb +3 -1
- data/lib/pwnlib/tubes/sock.rb +7 -1
- data/lib/pwnlib/tubes/tube.rb +23 -3
- data/lib/pwnlib/ui.rb +21 -0
- data/lib/pwnlib/util/cyclic.rb +2 -0
- data/lib/pwnlib/util/fiddling.rb +37 -5
- data/lib/pwnlib/util/getdents.rb +1 -0
- data/lib/pwnlib/util/hexdump.rb +8 -5
- data/lib/pwnlib/util/lists.rb +3 -0
- data/lib/pwnlib/util/packing.rb +5 -2
- data/lib/pwnlib/util/ruby.rb +1 -0
- data/lib/pwnlib/version.rb +2 -1
- data/test/abi_test.rb +1 -0
- data/test/asm_test.rb +75 -85
- data/test/constants/constant_test.rb +1 -0
- data/test/constants/constants_test.rb +1 -0
- data/test/context_test.rb +1 -0
- data/test/data/assembly/aarch64.s +19 -0
- data/test/data/assembly/amd64.s +21 -0
- data/test/data/assembly/arm.s +9 -0
- data/test/data/assembly/i386.s +21 -0
- data/test/data/assembly/mips.s +16 -0
- data/test/data/assembly/mips64.s +6 -0
- data/test/data/assembly/powerpc.s +18 -0
- data/test/data/assembly/powerpc64.s +36 -0
- data/test/data/assembly/sparc.s +33 -0
- data/test/data/assembly/sparc64.s +5 -0
- data/test/data/assembly/thumb.s +37 -0
- data/test/data/echo.rb +1 -0
- data/test/dynelf_test.rb +3 -1
- data/test/elf/elf_test.rb +18 -0
- data/test/ext_test.rb +1 -0
- data/test/files/use_pwn.rb +1 -0
- data/test/files/use_pwnlib.rb +1 -0
- data/test/full_file_test.rb +6 -0
- data/test/logger_test.rb +24 -3
- data/test/memleak_test.rb +1 -0
- data/test/reg_sort_test.rb +1 -0
- data/test/runner_test.rb +32 -0
- data/test/shellcraft/infloop_test.rb +1 -0
- data/test/shellcraft/linux/cat_test.rb +1 -0
- data/test/shellcraft/linux/ls_test.rb +1 -0
- data/test/shellcraft/linux/sh_test.rb +1 -0
- data/test/shellcraft/linux/sleep_test.rb +68 -0
- data/test/shellcraft/linux/syscalls/execve_test.rb +1 -0
- data/test/shellcraft/linux/syscalls/exit_test.rb +1 -0
- data/test/shellcraft/linux/syscalls/open_test.rb +1 -0
- data/test/shellcraft/linux/syscalls/syscall_test.rb +1 -0
- data/test/shellcraft/memcpy_test.rb +20 -5
- data/test/shellcraft/mov_test.rb +1 -0
- data/test/shellcraft/nop_test.rb +1 -0
- data/test/shellcraft/popad_test.rb +1 -0
- data/test/shellcraft/pushstr_array_test.rb +1 -0
- data/test/shellcraft/pushstr_test.rb +1 -0
- data/test/shellcraft/registers_test.rb +1 -0
- data/test/shellcraft/ret_test.rb +1 -0
- data/test/shellcraft/setregs_test.rb +9 -8
- data/test/shellcraft/shellcraft_test.rb +1 -0
- data/test/test_helper.rb +28 -0
- data/test/timer_test.rb +2 -1
- data/test/tubes/buffer_test.rb +1 -0
- data/test/tubes/process_test.rb +8 -2
- data/test/tubes/serialtube_test.rb +1 -4
- data/test/tubes/sock_test.rb +1 -0
- data/test/tubes/tube_test.rb +10 -1
- data/test/ui_test.rb +18 -0
- data/test/util/cyclic_test.rb +1 -0
- data/test/util/fiddling_test.rb +8 -0
- data/test/util/getdents_test.rb +1 -0
- data/test/util/hexdump_test.rb +2 -1
- data/test/util/lists_test.rb +1 -0
- data/test/util/packing_test.rb +3 -2
- 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}" })
|
@@ -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
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
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
|
-
|
41
|
-
|
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
|
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
|
-
|
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
|
|
data/lib/pwnlib/timer.rb
CHANGED
@@ -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
|
|
data/lib/pwnlib/tubes/buffer.rb
CHANGED
@@ -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]
|
data/lib/pwnlib/tubes/process.rb
CHANGED
@@ -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
|
-
|
99
|
+
@conn.write(data)
|
98
100
|
rescue RubySerial::Error
|
99
101
|
close
|
100
102
|
raise ::Pwnlib::Errors::EndOfTubeError
|
data/lib/pwnlib/tubes/sock.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/pwnlib/tubes/tube.rb
CHANGED
@@ -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)
|