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.
- 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)
|