Module: Ronin::PostExploitation::IO

Includes:
Enumerable, File::Constants
Included in:
Command, File
Defined in:
lib/ronin/post_exploitation/io.rb

Overview

The IO module provides an API for communicating with controlled resources, that is still compatible with the standard IO class.

To utilize the IO class, simply extend it and define either #io_read and/or #io_write, to handle the reading and writting of data.

The #io_open method handles optionally opening and assigning the file descriptor for the IO stream. The #io_close method handles optionally closing the IO stream.

Since:

  • 1.0.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#eofObject (readonly)

The end-of-file indicator

Since:

  • 1.0.0


49
50
51
# File 'lib/ronin/post_exploitation/io.rb', line 49

def eof
  @eof
end

#fdObject (readonly)

The file descriptor

Since:

  • 1.0.0


52
53
54
# File 'lib/ronin/post_exploitation/io.rb', line 52

def fd
  @fd
end

#posObject Also known as: tell

The position within the IO stream

Since:

  • 1.0.0


46
47
48
# File 'lib/ronin/post_exploitation/io.rb', line 46

def pos
  @pos
end

Instance Method Details

#append_buffer(data) ⇒ Object (protected)

Appends data to the read buffer.

Since:

  • 1.0.0


921
922
923
924
925
926
# File 'lib/ronin/post_exploitation/io.rb', line 921

def append_buffer(data)
  @pos -= data.length

  @buffer ||= ''
  @buffer << data
end

#autoclose=(mode) ⇒ IO

Note:

For compatibility with IO.

Since:

  • 1.0.0


707
708
709
# File 'lib/ronin/post_exploitation/io.rb', line 707

def autoclose=(mode)
  self
end

#autoclose?true

Note:

For compatibility with IO.

Since:

  • 1.0.0


718
719
720
# File 'lib/ronin/post_exploitation/io.rb', line 718

def autoclose?
  true
end

#binmodeIO

Note:

For compatibility with IO.

Since:

  • 1.0.0


683
684
685
686
# File 'lib/ronin/post_exploitation/io.rb', line 683

def binmode
  @binmode = true
  return self
end

#binmode?Boolean

Note:

For compatibility with IO.

Since:

  • 1.0.0


695
696
697
# File 'lib/ronin/post_exploitation/io.rb', line 695

def binmode?
  @binmode == true
end

#clear_buffer!Object (protected)

Clears the read buffer.

Since:

  • 1.0.0


876
877
878
# File 'lib/ronin/post_exploitation/io.rb', line 876

def clear_buffer!
  @buffer = nil
end

#closeObject

Closes the IO stream.

Since:

  • 1.0.0


850
851
852
853
854
855
856
857
858
859
# File 'lib/ronin/post_exploitation/io.rb', line 850

def close
  io_close

  @fd = nil

  @read   = false
  @write  = false
  @closed = true
  return nil
end

#close_on_exec=(mode) ⇒ IO

Note:

For compatibility with IO.

Since:

  • 1.0.0


729
730
731
# File 'lib/ronin/post_exploitation/io.rb', line 729

def close_on_exec=(mode)
  self
end

#close_on_exec?true

Note:

For compatibility with IO.

Since:

  • 1.0.0


740
741
742
# File 'lib/ronin/post_exploitation/io.rb', line 740

def close_on_exec?
  true
end

#close_readObject

Closes the read end of a duplex IO stream.

Since:

  • 1.0.0


818
819
820
821
822
823
824
# File 'lib/ronin/post_exploitation/io.rb', line 818

def close_read
  if @write then @read = false
  else           close
  end

  return nil
end

#close_writeObject

Closes the write end of a duplex IO stream.

Since:

  • 1.0.0


829
830
831
832
833
834
835
# File 'lib/ronin/post_exploitation/io.rb', line 829

def close_write
  if @read then @write = false
  else          close
  end

  return nil
end

#closed?Boolean

Determines whether the IO stream is closed.

Since:

  • 1.0.0


843
844
845
# File 'lib/ronin/post_exploitation/io.rb', line 843

def closed?
  @closed == true
end

#each_block {|block| ... } ⇒ Enumerator

Iterates over each block within the IO stream.

Yields:

  • (block)

    The given block will be passed each block of data from the IO stream.

Yield Parameters:

  • block (String)

    A block of data from the IO stream.

Raises:

  • (IOError)

    The stream is closed for reading.

Since:

  • 1.0.0


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ronin/post_exploitation/io.rb', line 86

def each_block
  return enum_for(__method__) unless block_given?

  unless @read
    raise(IOError,"closed for reading")
  end

  # read from the buffer first
  yield read_buffer unless empty_buffer?

  until @eof
    begin
      # no data currently available, sleep and retry
      until (block = io_read)
        sleep(1)
      end
    rescue EOFError
      break
    end

    unless block.empty?
      @pos += block.length
      yield block
    else
      # short read
      @eof = true
    end
  end
end

#each_byte {|byte| ... } ⇒ Enumerator Also known as: bytes

Iterates over each byte in the IO stream.

Yields:

  • (byte)

    The given block will be passed each byte in the IO stream.

Yield Parameters:

  • byte (Integer)

    A byte from the IO stream.

Since:

  • 1.0.0


375
376
377
378
379
# File 'lib/ronin/post_exploitation/io.rb', line 375

def each_byte(&block)
  return enum_for(__method__) unless block

  each_block { |chunk| chunk.each_byte(&block) }
end

#each_char {|char| ... } ⇒ Enumerator Also known as: chars

Iterates over each character in the IO stream.

Yields:

  • (char)

    The given block will be passed each character in the IO stream.

Yield Parameters:

  • char (String)

    A character from the IO stream.

Since:

  • 1.0.0


395
396
397
398
399
# File 'lib/ronin/post_exploitation/io.rb', line 395

def each_char(&block)
  return enum_for(__method__) unless block

  each_block { |chunk| chunk.each_char(&block) }
end

#each_codepoint {|ord| ... } ⇒ Enumerator Also known as: codepoints

Note:

Only available on Ruby > 1.9.

Passes the Integer ordinal of each character in the stream.

Yields:

  • (ord)

    The given block will be passed each codepoint.

Yield Parameters:

  • ord (String)

    The ordinal of a character from the stream.

Since:

  • 1.0.0


419
420
421
422
423
# File 'lib/ronin/post_exploitation/io.rb', line 419

def each_codepoint
  return enum_for(__method__) unless block_given?

  each_char { |c| yield c.ord }
end

#each_line(separator = $/) {|line| ... } ⇒ Enumerator Also known as: each, lines

Iterates over each line in the IO stream.

Yields:

  • (line)

    The given block will be passed each line in the IO stream.

Yield Parameters:

  • line (String)

    A line from the IO stream.

See Also:

Since:

  • 1.0.0


442
443
444
445
446
447
448
449
450
451
452
453
454
# File 'lib/ronin/post_exploitation/io.rb', line 442

def each_line(separator=$/)
  return enum_for(__method__,separator) unless block_given?

  loop do
    begin
      line = gets(separator)
    rescue EOFError
      break
    end

    yield line
  end
end

#empty_buffer?Boolean (protected)

Determines if the read buffer is empty.

Since:

  • 1.0.0


886
887
888
# File 'lib/ronin/post_exploitation/io.rb', line 886

def empty_buffer?
  @buffer.nil?
end

#eof?Boolean

Determines if end-of-file has been reached.

Since:

  • 1.0.0


64
65
66
# File 'lib/ronin/post_exploitation/io.rb', line 64

def eof?
  @eof == true
end

#fcntl(command, argument) ⇒ Object

Raises:

Since:

  • 1.0.0


757
758
759
# File 'lib/ronin/post_exploitation/io.rb', line 757

def fcntl(command,argument)
  raise(NotImplementedError,"#{self.class}#fcntl was not implemented")
end

#filenoInteger? Also known as: to_i

The number of the file descriptor.

Since:

  • 1.0.0


563
564
565
# File 'lib/ronin/post_exploitation/io.rb', line 563

def fileno
  @fd if @fd.kind_of?(Integer)
end

#flushIO

Note:

For compatibility with IO.

Since:

  • 1.0.0


803
804
805
# File 'lib/ronin/post_exploitation/io.rb', line 803

def flush
  self
end

#fsync0 Also known as: fdatasync

Note:

For compatibility with IO.

Since:

  • 1.0.0


768
769
770
771
# File 'lib/ronin/post_exploitation/io.rb', line 768

def fsync
  fflush
  return 0
end

#getbyteInteger

Note:

Only available on Ruby > 1.9.

Reads a byte from the IO stream.

Since:

  • 1.0.0


184
185
186
187
188
# File 'lib/ronin/post_exploitation/io.rb', line 184

def getbyte
  if (c = read(1))
    c.bytes.first
  end
end

#getcString

Reads a character from the IO stream.

Since:

  • 1.0.0


198
199
200
201
202
# File 'lib/ronin/post_exploitation/io.rb', line 198

def getc
  if (c = read(1))
    c[0]
  end
end

#gets(separator = $/) ⇒ String

Reads a string from the IO stream.

Since:

  • 1.0.0


281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/ronin/post_exploitation/io.rb', line 281

def gets(separator=$/)
  # increment the line number
  @lineno += 1

  # if no separator is given, read everything
  return read if separator.nil?

  line = ''

  while (c = read(1))
    line << c

    break if c == separator # separator reached
  end

  if line.empty?
    # a line should atleast contain the separator
    raise(EOFError,"end of file reached")
  end

  return line
end

#inspectString

Inspects the IO stream.

Since:

  • 1.0.0


867
868
869
# File 'lib/ronin/post_exploitation/io.rb', line 867

def inspect
  "#<#{self.class}: #{@fd.inspect if @fd}>"
end

#io_closeObject (protected)

This method is abstract.

Place holder method used to close the IO stream.

Since:

  • 1.0.0


1013
1014
# File 'lib/ronin/post_exploitation/io.rb', line 1013

def io_close
end

#io_initializeObject (protected)

Initializes the IO stream.

Since:

  • 1.0.0


961
962
963
964
965
966
967
968
969
# File 'lib/ronin/post_exploitation/io.rb', line 961

def io_initialize
  @lineno = 0

  @read   = true
  @write  = true
  @closed = true

  open
end

#io_openfd (protected)

This method is abstract.

Place holder method used to open the IO stream.

Since:

  • 1.0.0


979
980
# File 'lib/ronin/post_exploitation/io.rb', line 979

def io_open
end

#io_readString (protected)

This method is abstract.

Place holder method used to read a block from the IO stream.

Raises:

  • (EOFError)

    The end of the stream has been reached.

Since:

  • 1.0.0


993
994
# File 'lib/ronin/post_exploitation/io.rb', line 993

def io_read
end

#io_write(data) ⇒ Object (protected)

This method is abstract.

Place holder method used to write data to the IO stream.

Since:

  • 1.0.0


1004
1005
1006
# File 'lib/ronin/post_exploitation/io.rb', line 1004

def io_write(data)
  0
end

#ioctl(command, argument) ⇒ Object

Raises:

Since:

  • 1.0.0


749
750
751
# File 'lib/ronin/post_exploitation/io.rb', line 749

def ioctl(command,argument)
  raise(NotImplementedError,"#{self.class}#ioctl was not implemented")
end

#isattyfalse

Note:

For compatibility with IO.

Since:

  • 1.0.0


592
593
594
# File 'lib/ronin/post_exploitation/io.rb', line 592

def isatty
  false
end

#linenoInteger

The current line-number (how many times #gets has been called).

Raises:

  • (IOError)

    The stream was not opened for reading.

Since:

  • 1.0.0


634
635
636
637
638
639
640
# File 'lib/ronin/post_exploitation/io.rb', line 634

def lineno
  unless @read
    raise(IOError,"not opened for reading")
  end

  return @lineno
end

#lineno=(number) ⇒ Integer

Manually sets the current line-number.

Raises:

  • (IOError)

    The stream was not opened for reading.

Since:

  • 1.0.0


654
655
656
657
658
659
660
# File 'lib/ronin/post_exploitation/io.rb', line 654

def lineno=(number)
  unless @read
    raise(IOError,"not opened for reading")
  end

  return @lineno = number.to_i
end

#openIO (protected)

Opens the IO stream.

Since:

  • 1.0.0


934
935
936
937
938
939
940
941
942
943
# File 'lib/ronin/post_exploitation/io.rb', line 934

def open
  @pos = 0
  @eof = false

  clear_buffer!

  @fd = io_open
  @closed = false
  return self
end

#pidObject

Raises:

  • (NotImplementedError)

    #pid is not implemented.

Since:

  • 1.0.0


573
574
575
# File 'lib/ronin/post_exploitation/io.rb', line 573

def pid
  raise(NotImplementedError,"#{self.class}#pid is not implemented")
end

#prepend_buffer(data) ⇒ Object (protected)

Prepends data to the front of the read buffer.

Since:

  • 1.0.0


910
911
912
913
# File 'lib/ronin/post_exploitation/io.rb', line 910

def prepend_buffer(data)
  @buffer ||= ''
  @buffer.insert(0,data)
end

Prints data to the IO stream.

Since:

  • 1.0.0


521
522
523
524
# File 'lib/ronin/post_exploitation/io.rb', line 521

def print(*arguments)
  arguments.each { |data| write(data) }
  return nil
end

#printf(format_string, *arguments) ⇒ nil

Prints a formatted string to the IO stream.

Since:

  • 1.0.0


550
551
552
553
# File 'lib/ronin/post_exploitation/io.rb', line 550

def printf(format_string,*arguments)
  write(format_string % arguments)
  return nil
end

#putc(data) ⇒ String, Integer

Writes a byte or a character to the IO stream.

Since:

  • 1.0.0


503
504
505
506
507
508
509
510
511
# File 'lib/ronin/post_exploitation/io.rb', line 503

def putc(data)
  char = case data
         when String then data.chr
         else             data
         end

  write(char)
  return data
end

#puts(*arguments) ⇒ nil

Prints data with new-line characters to the IO stream.

Since:

  • 1.0.0


534
535
536
537
# File 'lib/ronin/post_exploitation/io.rb', line 534

def puts(*arguments)
  arguments.each { |data| write("#{data}#{$/}") }
  return nil
end

#read(length = nil, buffer = nil) ⇒ String Also known as: sysread, read_nonblock

Reads data from the IO stream.

Since:

  • 1.0.0


129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ronin/post_exploitation/io.rb', line 129

def read(length=nil,buffer=nil)
  remaining = (length || (0.0 / 0))
  result = ''

  each_block do |block|
    if remaining < block.length
      result << block[0...remaining]
      append_buffer(block[remaining..-1])
      break
    else
      result << block
      remaining -= block.length
    end

    # no more data to read
    break if remaining == 0
  end

  unless result.empty?
    buffer << result if buffer
    return result
  end
end

#read_bufferString (protected)

Reads data from the read buffer.

Since:

  • 1.0.0


896
897
898
899
900
901
902
# File 'lib/ronin/post_exploitation/io.rb', line 896

def read_buffer
  chunk = @buffer
  @pos += @buffer.length

  clear_buffer!
  return chunk
end

#readbyteInteger

Reads a byte from the IO stream.

Raises:

  • (EOFError)

    The end-of-file has been reached.

Since:

  • 1.0.0


332
333
334
335
336
337
338
# File 'lib/ronin/post_exploitation/io.rb', line 332

def readbyte
  unless (c = read(1))
    raise(EOFError,"end of file reached")
  end

  return c.bytes.first
end

#readcharInteger

Reads a character from the IO stream.

Raises:

  • (EOFError)

    The end-of-file has been reached.

See Also:

Since:

  • 1.0.0


315
316
317
318
319
320
321
# File 'lib/ronin/post_exploitation/io.rb', line 315

def readchar
  unless (c = getc)
    raise(EOFError,"end of file reached")
  end

  return c
end

#readline(separator = $/) ⇒ String

Reads a line from the IO stream.

Raises:

  • (EOFError)

    The end-of-file has been reached.

See Also:

Since:

  • 1.0.0


355
356
357
358
359
360
361
# File 'lib/ronin/post_exploitation/io.rb', line 355

def readline(separator=$/)
  unless (line = gets(separator))
    raise(EOFError,"end of file reached")
  end

  return line
end

#readlines(separator = $/) ⇒ Array<String>

Reads every line from the IO stream.

See Also:

Since:

  • 1.0.0


467
468
469
# File 'lib/ronin/post_exploitation/io.rb', line 467

def readlines(separator=$/)
  enum_for(:each_line,separator).to_a
end

#readpartial(length, buffer = nil) ⇒ String

Reads partial data from the IO stream.

See Also:

Since:

  • 1.0.0


170
171
172
# File 'lib/ronin/post_exploitation/io.rb', line 170

def readpartial(length,buffer=nil)
  read(length,buffer)
end

#reopen(*arguments) ⇒ Object

Raises:

  • (NotImplementedError)

    #reopen is not implemented.

Since:

  • 1.0.0


811
812
813
# File 'lib/ronin/post_exploitation/io.rb', line 811

def reopen(*arguments)
  raise(NotImplementedError,"#{self.class}#reopen is not implemented")
end

#rewindIO

Note:

For compatibility with IO.

See Also:

Since:

  • 1.0.0


671
672
673
674
# File 'lib/ronin/post_exploitation/io.rb', line 671

def rewind
  @lineno = 0
  seek(0,SEEK_SET)
end

#seek(new_pos, whence = SEEK_SET) ⇒ Object

Raises:

  • (NotImplementedError)

    #seek is not implemented.

Since:

  • 1.0.0


607
608
609
# File 'lib/ronin/post_exploitation/io.rb', line 607

def seek(new_pos,whence=SEEK_SET)
  raise(NotImplementedError,"#{self.class}#seek is not implemented")
end

#statObject

Raises:

  • (NotImplementedError)

    #stat is not implemented.

Since:

  • 1.0.0


581
582
583
# File 'lib/ronin/post_exploitation/io.rb', line 581

def stat
  raise(NotImplementedError,"#{self.class}#stat is not implemented")
end

#synctrue

Returns true for compatibility with IO.

Since:

  • 1.0.0


780
781
782
# File 'lib/ronin/post_exploitation/io.rb', line 780

def sync
  true
end

#sync=(mode) ⇒ Boolean

Returns the sync mode, for compatibility with IO.

Since:

  • 1.0.0


792
793
794
# File 'lib/ronin/post_exploitation/io.rb', line 792

def sync=(mode)
  mode
end

#sysseek(offset, whence = SEEK_SET) ⇒ Object

See Also:

Since:

  • 1.0.0


614
615
616
# File 'lib/ronin/post_exploitation/io.rb', line 614

def sysseek(offset,whence=SEEK_SET)
  seek(new_pos,whence)
end

#to_ioIO (protected)

Note:

For compatibility with IO.

Since:

  • 1.0.0


952
953
954
# File 'lib/ronin/post_exploitation/io.rb', line 952

def to_io
  self
end

#tty?Boolean

See Also:

Since:

  • 1.0.0


599
600
601
# File 'lib/ronin/post_exploitation/io.rb', line 599

def tty?
  isatty
end

#ungetbyte(byte) ⇒ nil

Note:

Only available on Ruby > 1.9.

Un-reads a byte from the IO stream, append it to the read buffer.

Since:

  • 1.0.0


228
229
230
231
232
233
234
235
236
# File 'lib/ronin/post_exploitation/io.rb', line 228

def ungetbyte(byte)
  byte = case byte
         when Integer then byte.chr
         else              byte.to_s
         end

  prepend_buffer(byte)
  return nil
end

#ungetc(char) ⇒ nil

Un-reads a character from the IO stream, append it to the read buffer.

Since:

  • 1.0.0


250
251
252
253
# File 'lib/ronin/post_exploitation/io.rb', line 250

def ungetc(char)
  prepend_buffer(char.chr)
  return nil
end

#write(data) ⇒ Integer Also known as: syswrite, write_nonblock, <<

Writes data to the IO stream.

Raises:

  • (IOError)

    The stream is closed for writting.

Since:

  • 1.0.0


483
484
485
486
487
488
489
# File 'lib/ronin/post_exploitation/io.rb', line 483

def write(data)
  unless @write
    raise(IOError,"closed for writting")
  end

  io_write(data.to_s) if @write
end