pwntools 1.0.1 → 1.1.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 +5 -5
- data/README.md +4 -3
- data/Rakefile +3 -1
- data/lib/pwnlib/asm.rb +172 -2
- data/lib/pwnlib/constants/constants.rb +10 -3
- data/lib/pwnlib/context.rb +1 -3
- data/lib/pwnlib/elf/elf.rb +3 -3
- data/lib/pwnlib/errors.rb +30 -0
- data/lib/pwnlib/ext/helper.rb +1 -1
- data/lib/pwnlib/logger.rb +140 -2
- data/lib/pwnlib/pwn.rb +3 -0
- data/lib/pwnlib/reg_sort.rb +1 -1
- data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +9 -3
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/amd64/linux/cat.rb +23 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +6 -4
- data/lib/pwnlib/shellcraft/generators/amd64/linux/exit.rb +23 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/amd64/linux/open.rb +23 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +6 -4
- data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +9 -3
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/i386/linux/cat.rb +23 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +8 -4
- data/lib/pwnlib/shellcraft/generators/i386/linux/exit.rb +23 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/i386/linux/open.rb +23 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +6 -2
- data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +8 -4
- data/lib/pwnlib/shellcraft/generators/x86/linux/cat.rb +53 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/exit.rb +33 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/open.rb +46 -0
- data/lib/pwnlib/shellcraft/shellcraft.rb +3 -2
- data/lib/pwnlib/timer.rb +5 -2
- data/lib/pwnlib/tubes/process.rb +153 -0
- data/lib/pwnlib/tubes/serialtube.rb +112 -0
- data/lib/pwnlib/tubes/sock.rb +24 -25
- data/lib/pwnlib/tubes/tube.rb +191 -39
- data/lib/pwnlib/util/packing.rb +3 -9
- data/lib/pwnlib/version.rb +1 -1
- data/test/asm_test.rb +85 -2
- data/test/constants/constants_test.rb +2 -2
- data/test/data/echo.rb +2 -7
- data/test/elf/elf_test.rb +10 -15
- data/test/files/use_pwn.rb +2 -6
- data/test/logger_test.rb +38 -0
- data/test/shellcraft/linux/cat_test.rb +86 -0
- data/test/shellcraft/linux/syscalls/exit_test.rb +56 -0
- data/test/shellcraft/linux/syscalls/open_test.rb +86 -0
- data/test/shellcraft/shellcraft_test.rb +5 -4
- data/test/test_helper.rb +22 -2
- data/test/timer_test.rb +19 -1
- data/test/tubes/process_test.rb +99 -0
- data/test/tubes/serialtube_test.rb +165 -0
- data/test/tubes/sock_test.rb +20 -21
- data/test/tubes/tube_test.rb +86 -16
- metadata +75 -13
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
require 'pwnlib/context'
|
6
|
+
require 'pwnlib/shellcraft/shellcraft'
|
7
|
+
|
8
|
+
class OpenTest < MiniTest::Test
|
9
|
+
include ::Pwnlib::Context
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@shellcraft = ::Pwnlib::Shellcraft::Shellcraft.instance
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_amd64
|
16
|
+
context.local(arch: 'amd64') do
|
17
|
+
assert_equal(<<-'EOS', @shellcraft.open('/etc/passwd'))
|
18
|
+
/* push "/etc/passwd\x00" */
|
19
|
+
push 0x1010101 ^ 0x647773
|
20
|
+
xor dword ptr [rsp], 0x1010101
|
21
|
+
mov rax, 0x7361702f6374652f
|
22
|
+
push rax
|
23
|
+
/* call open("rsp", "O_RDONLY", 0) */
|
24
|
+
push 2 /* (SYS_open) */
|
25
|
+
pop rax
|
26
|
+
mov rdi, rsp
|
27
|
+
xor esi, esi /* (O_RDONLY) */
|
28
|
+
cdq /* rdx=0 */
|
29
|
+
syscall
|
30
|
+
EOS
|
31
|
+
|
32
|
+
assert_equal(<<-'EOS', @shellcraft.open('/etc/passwd', 0x40, 0o750)) # O_CREAT = 0x40
|
33
|
+
/* push "/etc/passwd\x00" */
|
34
|
+
push 0x1010101 ^ 0x647773
|
35
|
+
xor dword ptr [rsp], 0x1010101
|
36
|
+
mov rax, 0x7361702f6374652f
|
37
|
+
push rax
|
38
|
+
/* call open("rsp", 64, 488) */
|
39
|
+
push 2 /* (SYS_open) */
|
40
|
+
pop rax
|
41
|
+
mov rdi, rsp
|
42
|
+
push 0x40
|
43
|
+
pop rsi
|
44
|
+
xor edx, edx
|
45
|
+
mov dx, 0x1e8
|
46
|
+
syscall
|
47
|
+
EOS
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_i386
|
52
|
+
context.local(arch: 'i386') do
|
53
|
+
assert_equal(<<-'EOS', @shellcraft.open('/etc/passwd'))
|
54
|
+
/* push "/etc/passwd\x00" */
|
55
|
+
push 0x1010101
|
56
|
+
xor dword ptr [esp], 0x1657672 /* 0x1010101 ^ 0x647773 */
|
57
|
+
push 0x7361702f
|
58
|
+
push 0x6374652f
|
59
|
+
/* call open("esp", "O_RDONLY", 0) */
|
60
|
+
push 5 /* (SYS_open) */
|
61
|
+
pop eax
|
62
|
+
mov ebx, esp
|
63
|
+
xor ecx, ecx /* (O_RDONLY) */
|
64
|
+
cdq /* edx=0 */
|
65
|
+
int 0x80
|
66
|
+
EOS
|
67
|
+
|
68
|
+
assert_equal(<<-'EOS', @shellcraft.open('/etc/passwd', 'O_CREAT', 0o750))
|
69
|
+
/* push "/etc/passwd\x00" */
|
70
|
+
push 0x1010101
|
71
|
+
xor dword ptr [esp], 0x1657672 /* 0x1010101 ^ 0x647773 */
|
72
|
+
push 0x7361702f
|
73
|
+
push 0x6374652f
|
74
|
+
/* call open("esp", "O_CREAT", 488) */
|
75
|
+
push 5 /* (SYS_open) */
|
76
|
+
pop eax
|
77
|
+
mov ebx, esp
|
78
|
+
push 0x40 /* (O_CREAT) */
|
79
|
+
pop ecx
|
80
|
+
xor edx, edx
|
81
|
+
mov dx, 0x1e8
|
82
|
+
int 0x80
|
83
|
+
EOS
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -15,14 +15,15 @@ class ShellcraftTest < MiniTest::Test
|
|
15
15
|
def test_respond
|
16
16
|
context.local(arch: 'amd64') do
|
17
17
|
# Check respond_to_missing? is well defined
|
18
|
-
assert
|
19
|
-
assert
|
18
|
+
assert(@shellcraft.respond_to?(:mov))
|
19
|
+
assert(@shellcraft.method(:sh))
|
20
20
|
end
|
21
|
-
refute
|
21
|
+
refute(@shellcraft.respond_to?(:linux))
|
22
22
|
assert_raises(NoMethodError) { @shellcraft.meow }
|
23
23
|
|
24
24
|
context.local(arch: 'arm') do
|
25
|
-
|
25
|
+
err = assert_raises(::Pwnlib::Errors::UnsupportedArchError) { @shellcraft.respond_to?(:mov) }
|
26
|
+
assert_equal("Can't use shellcraft under architecture \"arm\".", err.message)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'codeclimate-test-reporter'
|
2
1
|
require 'rainbow'
|
3
2
|
require 'simplecov'
|
4
3
|
|
5
4
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
6
|
-
[SimpleCov::Formatter::HTMLFormatter
|
5
|
+
[SimpleCov::Formatter::HTMLFormatter]
|
7
6
|
)
|
8
7
|
SimpleCov.start do
|
9
8
|
add_filter '/test/'
|
@@ -20,5 +19,26 @@ module MiniTest
|
|
20
19
|
# Default to disable coloring for easier testing.
|
21
20
|
Rainbow.enabled = false
|
22
21
|
end
|
22
|
+
|
23
|
+
# Methods for hooking logger,
|
24
|
+
# require 'pwnlib/logger' before using these methods.
|
25
|
+
|
26
|
+
def log_null(&block)
|
27
|
+
File.open(File::NULL, 'w') { |f| log_hook(f, &block) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def log_stdout(&block)
|
31
|
+
log_hook($stdout, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def log_hook(obj)
|
35
|
+
old = ::Pwnlib::Logger.log.instance_variable_get(:@logdev)
|
36
|
+
::Pwnlib::Logger.log.instance_variable_set(:@logdev, obj)
|
37
|
+
begin
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
::Pwnlib::Logger.log.instance_variable_set(:@logdev, old)
|
41
|
+
end
|
42
|
+
end
|
23
43
|
end
|
24
44
|
end
|
data/test/timer_test.rb
CHANGED
@@ -12,12 +12,30 @@ class TimerTest < MiniTest::Test
|
|
12
12
|
refute(t.started?)
|
13
13
|
refute(t.active?)
|
14
14
|
assert_equal('DARKHH QQ', t.countdown(0.1) { 'DARKHH QQ' })
|
15
|
+
|
15
16
|
exception = assert_raises(RuntimeError) { t.countdown(0.1) { t.countdown(0.1) {} } }
|
16
17
|
assert_equal('Nested countdown not permitted', exception.message)
|
18
|
+
|
17
19
|
t.timeout = 0.514
|
18
|
-
exception = assert_raises(RuntimeError)
|
20
|
+
exception = assert_raises(RuntimeError) do
|
21
|
+
t.countdown(0.1) { t.timeout = :forever }
|
22
|
+
end
|
19
23
|
assert_equal("Can't change timeout when countdown", exception.message)
|
24
|
+
|
20
25
|
t.countdown(0.1) { assert(t.started?) }
|
21
26
|
t.countdown(0.1) { assert(t.active?) }
|
27
|
+
|
28
|
+
assert_raises(::Pwnlib::Errors::TimeoutError) do
|
29
|
+
t.countdown(0.1) { sleep(0.2) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Check #115 fixed
|
34
|
+
def test_nested_countdown_false_positve_115
|
35
|
+
t = Timer.new
|
36
|
+
assert_raises(::Pwnlib::Errors::TimeoutError) do
|
37
|
+
t.countdown(0.01) { sleep(0.02) }
|
38
|
+
end
|
39
|
+
t.countdown(0.01) {}
|
22
40
|
end
|
23
41
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'tty-platform'
|
5
|
+
|
6
|
+
require 'test_helper'
|
7
|
+
|
8
|
+
require 'pwnlib/context'
|
9
|
+
require 'pwnlib/errors'
|
10
|
+
require 'pwnlib/tubes/process'
|
11
|
+
|
12
|
+
class ProcessTest < MiniTest::Test
|
13
|
+
include ::Pwnlib::Context
|
14
|
+
|
15
|
+
def setup
|
16
|
+
skip 'Skip on Windows' if TTY::Platform.new.windows?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_io
|
20
|
+
cat = ::Pwnlib::Tubes::Process.new('cat')
|
21
|
+
cat.puts('HAHA')
|
22
|
+
assert_equal("HAHA\n", cat.gets)
|
23
|
+
assert_raises(::Pwnlib::Errors::TimeoutError) { cat.gets(timeout: 0.1) }
|
24
|
+
cat.puts('HAHA2')
|
25
|
+
assert_equal("HAHA2\n", cat.gets)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_env
|
29
|
+
data = ::Pwnlib::Tubes::Process.new('env').read
|
30
|
+
assert_match('PATH=', data)
|
31
|
+
data = ::Pwnlib::Tubes::Process.new('env', env: { 'FOO' => 'BAR' }).read
|
32
|
+
assert_equal("FOO=BAR\n", data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_aslr
|
36
|
+
skip 'Only tested on linux' unless TTY::Platform.new.linux?
|
37
|
+
map1 = ::Pwnlib::Tubes::Process.new('cat /proc/self/maps', aslr: false).read
|
38
|
+
map2 = ::Pwnlib::Tubes::Process.new(['cat', '/proc/self/maps'], aslr: false).read
|
39
|
+
assert_match('/bin/cat', map1) # make sure it read something
|
40
|
+
assert_equal(map1, map2)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_eof
|
44
|
+
ls = ::Pwnlib::Tubes::Process.new(['ls', '-la'])
|
45
|
+
assert_match(/total/, ls.gets)
|
46
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { ls.write('anything') }
|
47
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { loop { ls.gets } }
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_shutdown
|
51
|
+
cat = ::Pwnlib::Tubes::Process.new('cat')
|
52
|
+
assert_raises(::Pwnlib::Errors::TimeoutError) { cat.recvn(1, timeout: 0.1) }
|
53
|
+
cat.shutdown(:write) # This should cause `cat` dead
|
54
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { cat.recvn(1, timeout: 0.1) }
|
55
|
+
cat.shutdown
|
56
|
+
|
57
|
+
cat = ::Pwnlib::Tubes::Process.new('cat')
|
58
|
+
cat.shutdown(:read)
|
59
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { cat.recvn(1) }
|
60
|
+
cat.shutdown
|
61
|
+
assert_raises(ArgumentError) { cat.shutdown(:zz) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_kill
|
65
|
+
cat = ::Pwnlib::Tubes::Process.new('cat')
|
66
|
+
cat.kill
|
67
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { cat.recvn(1) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_tty
|
71
|
+
tty_test = proc do |*args, raw: true|
|
72
|
+
in_, out = args.map { |v| v ? :pty : :pipe }
|
73
|
+
process = ::Pwnlib::Tubes::Process.new('ruby -e "p [STDIN.tty?, STDOUT.tty?]"',
|
74
|
+
in: in_, out: out, raw: raw)
|
75
|
+
process.gets
|
76
|
+
end
|
77
|
+
assert_equal("[false, false]\n", tty_test.call(false, false))
|
78
|
+
assert_equal("[true, false]\n", tty_test.call(true, false))
|
79
|
+
assert_equal("[false, true]\n", tty_test.call(false, true))
|
80
|
+
assert_equal("[false, true]\r\n", tty_test.call(false, true, raw: false))
|
81
|
+
|
82
|
+
cat = ::Pwnlib::Tubes::Process.new('cat', in: :pty, out: :pty, raw: false)
|
83
|
+
cat.puts('Hi')
|
84
|
+
# In cooked mode, tty should echo the input, so we can gets twice.
|
85
|
+
assert_equal("Hi\r\n", cat.gets)
|
86
|
+
assert_equal("Hi\r\n", cat.gets)
|
87
|
+
cat.close
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_interact
|
91
|
+
ls = ::Pwnlib::Tubes::Process.new('ls Gemfile*')
|
92
|
+
saved = $stdin
|
93
|
+
# prevents stdin being closed
|
94
|
+
$stdin = UDPSocket.new
|
95
|
+
assert_output("Gemfile\nGemfile.lock\n") { context.local(log_level: :fatal) { ls.interact } }
|
96
|
+
$stdin.close
|
97
|
+
$stdin = saved
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
require 'test_helper'
|
6
|
+
|
7
|
+
require 'pwnlib/tubes/serialtube'
|
8
|
+
|
9
|
+
module Pwnlib
|
10
|
+
module Tubes
|
11
|
+
class SerialTube
|
12
|
+
def break_encapsulation
|
13
|
+
@conn.close
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class SerialTest < MiniTest::Test
|
20
|
+
include ::Pwnlib::Tubes
|
21
|
+
|
22
|
+
def skip_windows
|
23
|
+
skip 'Not test tube/serialtube on Windows' if TTY::Platform.new.windows?
|
24
|
+
end
|
25
|
+
|
26
|
+
def open_pair
|
27
|
+
Open3.popen3('socat -d -d pty,raw,echo=0 pty,raw,echo=0') do |_i, _o, stderr, thread|
|
28
|
+
devs = []
|
29
|
+
2.times do
|
30
|
+
devs << stderr.readline.chomp.split.last
|
31
|
+
# First pattern matches Linux, second is macOS
|
32
|
+
raise IOError, 'Could not create serial crosslink' if devs.last !~ %r{^(/dev/pts/[0-9]+|/dev/ttys[0-9]+)$}
|
33
|
+
end
|
34
|
+
# To ensure socat have finished setup
|
35
|
+
stderr.gets('starting data transfer loop')
|
36
|
+
|
37
|
+
serial = SerialTube.new devs[1], convert_newlines: false
|
38
|
+
|
39
|
+
begin
|
40
|
+
File.open devs[0], 'r+' do |file|
|
41
|
+
file.set_encoding 'default'.encoding
|
42
|
+
yield file, serial, thread
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
::Process.kill('SIGTERM', thread.pid) if thread.alive?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def random_string(length)
|
51
|
+
Random.rand(36**length).to_s(36).rjust(length, '0')
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_raise
|
55
|
+
skip_windows
|
56
|
+
open_pair do |_file, serial, thread|
|
57
|
+
::Process.kill('SIGTERM', thread.pid)
|
58
|
+
# ensure the process has been killed
|
59
|
+
thread.value
|
60
|
+
assert_raises(Pwnlib::Errors::EndOfTubeError) { serial.puts('a') }
|
61
|
+
end
|
62
|
+
open_pair do |_file, serial|
|
63
|
+
serial.break_encapsulation
|
64
|
+
assert_raises(Pwnlib::Errors::EndOfTubeError) { serial.recv(1, timeout: 2) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_recv
|
69
|
+
skip_windows
|
70
|
+
open_pair do |file, serial|
|
71
|
+
# recv, recvline
|
72
|
+
rs = random_string 24
|
73
|
+
file.puts rs
|
74
|
+
result = serial.recv 8, timeout: 1
|
75
|
+
|
76
|
+
assert_equal(rs[0...8], result)
|
77
|
+
result = serial.recv 8
|
78
|
+
assert_equal(rs[8...16], result)
|
79
|
+
result = serial.recvline.chomp
|
80
|
+
assert_equal(rs[16..-1], result)
|
81
|
+
|
82
|
+
assert_raises(Pwnlib::Errors::TimeoutError) { serial.recv(1, timeout: 0.2) }
|
83
|
+
|
84
|
+
# recvpred
|
85
|
+
rs = random_string 12
|
86
|
+
file.print rs
|
87
|
+
result = serial.recvpred do |data|
|
88
|
+
data[-6..-1] == rs[-6..-1]
|
89
|
+
end
|
90
|
+
assert_equal rs, result
|
91
|
+
|
92
|
+
assert_raises(Pwnlib::Errors::TimeoutError) { serial.recv(1, timeout: 0.2) }
|
93
|
+
|
94
|
+
# recvn
|
95
|
+
rs = random_string 6
|
96
|
+
file.print rs
|
97
|
+
result = ''
|
98
|
+
assert_raises(Pwnlib::Errors::TimeoutError) do
|
99
|
+
result = serial.recvn 120, timeout: 1
|
100
|
+
end
|
101
|
+
assert_empty result
|
102
|
+
file.print rs
|
103
|
+
result = serial.recvn 12
|
104
|
+
assert_equal rs * 2, result
|
105
|
+
|
106
|
+
assert_raises(Pwnlib::Errors::TimeoutError) { serial.recv(1, timeout: 0.2) }
|
107
|
+
|
108
|
+
# recvuntil
|
109
|
+
rs = random_string 12
|
110
|
+
file.print rs + '|'
|
111
|
+
result = serial.recvuntil('|').chomp('|')
|
112
|
+
assert_equal rs, result
|
113
|
+
|
114
|
+
assert_raises(Pwnlib::Errors::TimeoutError) { serial.recv(1, timeout: 0.2) }
|
115
|
+
|
116
|
+
# gets
|
117
|
+
rs = random_string 24
|
118
|
+
file.puts rs
|
119
|
+
result = serial.gets 12
|
120
|
+
assert_equal rs[0...12], result
|
121
|
+
result = serial.gets.chomp
|
122
|
+
assert_equal rs[12..-1], result
|
123
|
+
|
124
|
+
assert_raises(Pwnlib::Errors::TimeoutError) { serial.recv(1, timeout: 0.2) }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_send
|
129
|
+
skip_windows
|
130
|
+
open_pair do |file, serial|
|
131
|
+
# send, sendline
|
132
|
+
rs = random_string 24
|
133
|
+
# rubocop:disable Style/Send
|
134
|
+
# Justification: This isn't Object#send, false positive.
|
135
|
+
serial.send rs[0...12]
|
136
|
+
# rubocop:enable Style/Send
|
137
|
+
serial.sendline rs[12...24]
|
138
|
+
result = file.readline.chomp
|
139
|
+
assert_equal rs, result
|
140
|
+
|
141
|
+
# puts
|
142
|
+
r1 = random_string 4
|
143
|
+
r2 = random_string 4
|
144
|
+
r3 = random_string 4
|
145
|
+
serial.puts r1, r2, r3
|
146
|
+
result = ''
|
147
|
+
3.times do
|
148
|
+
result += file.readline.chomp
|
149
|
+
end
|
150
|
+
assert_equal r1 + r2 + r3, result
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_close
|
155
|
+
skip_windows
|
156
|
+
open_pair do |_file, serial|
|
157
|
+
serial.close
|
158
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { serial.puts(514) }
|
159
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { serial.puts(514) }
|
160
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { serial.recv }
|
161
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { serial.recv }
|
162
|
+
assert_raises(ArgumentError) { serial.close(:hh) }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/test/tubes/sock_test.rb
CHANGED
@@ -9,46 +9,45 @@ require 'pwnlib/tubes/sock'
|
|
9
9
|
class SockTest < MiniTest::Test
|
10
10
|
include ::Pwnlib::Tubes
|
11
11
|
ECHO_FILE = File.expand_path('../data/echo.rb', __dir__)
|
12
|
-
BIND_PORT = 31_337
|
13
12
|
|
14
13
|
def popen_echo(data)
|
15
|
-
Open3.popen2("
|
16
|
-
o.gets
|
17
|
-
s = Sock.new('
|
14
|
+
Open3.popen2("ruby #{ECHO_FILE}") do |_i, o, _t|
|
15
|
+
port = o.gets.split.last.to_i
|
16
|
+
s = Sock.new('127.0.0.1', port)
|
18
17
|
yield s, data, o
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
21
|
+
def test_sock
|
23
22
|
popen_echo('DARKHH') do |s, data, _o|
|
24
|
-
s.
|
25
|
-
rs, = IO.select([s.
|
23
|
+
s.sock.puts(data)
|
24
|
+
rs, = IO.select([s.sock])
|
26
25
|
refute_nil(rs)
|
27
|
-
assert_equal(data, s.
|
26
|
+
assert_equal(data, s.sock.readpartial(data.size))
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
30
|
+
def test_eof
|
32
31
|
popen_echo('DARKHH') do |s, data, o|
|
33
32
|
s.puts(data)
|
34
33
|
assert_equal(data + "\n", s.gets)
|
35
34
|
o.gets
|
36
35
|
s.puts(514)
|
37
36
|
sleep(0.1) # Wait for connection reset
|
38
|
-
assert_raises(
|
39
|
-
assert_raises(
|
40
|
-
assert_raises(
|
41
|
-
assert_raises(
|
37
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.puts(514) }
|
38
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.puts(514) }
|
39
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.recv }
|
40
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.recv }
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
44
|
def test_close
|
46
45
|
popen_echo('DARKHH') do |s, _data, _o|
|
47
46
|
s.close
|
48
|
-
assert_raises(
|
49
|
-
assert_raises(
|
50
|
-
assert_raises(
|
51
|
-
assert_raises(
|
47
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.puts(514) }
|
48
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.puts(514) }
|
49
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.recv }
|
50
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.recv }
|
52
51
|
assert_raises(ArgumentError) { s.close(:hh) }
|
53
52
|
end
|
54
53
|
|
@@ -57,10 +56,10 @@ class SockTest < MiniTest::Test
|
|
57
56
|
3.times { s.close(:recv) }
|
58
57
|
3.times { s.close(:send) }
|
59
58
|
3.times { s.close(:write) }
|
60
|
-
assert_raises(
|
61
|
-
assert_raises(
|
62
|
-
assert_raises(
|
63
|
-
assert_raises(
|
59
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.puts(514) }
|
60
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.puts(514) }
|
61
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.recv }
|
62
|
+
assert_raises(::Pwnlib::Errors::EndOfTubeError) { s.recv }
|
64
63
|
3.times { s.close }
|
65
64
|
assert_raises(ArgumentError) { s.close(:shik) }
|
66
65
|
end
|