Module: Pwnlib::Util::HexDump
- Included in:
- Pwn
- Defined in:
- lib/pwnlib/util/hexdump.rb
Overview
TODO:
Control coloring by context.
Method for output a pretty hexdump. Since this may be used in log module, to avoid cyclic dependency, it is put in a separate module as Fiddling
Constant Summary collapse
- MARKER =
"\u2502"
- HIGHLIGHT_STYLE =
->(s) { Rainbow(s).bg(:red) }
- DEFAULT_STYLE =
{ 0x00 => ->(s) { Rainbow(s).red }, 0x0a => ->(s) { Rainbow(s).red }, 0xff => ->(s) { Rainbow(s).green }, marker: ->(s) { Rainbow(s).dimgray }, printable: ->(s) { s }, unprintable: ->(s) { Rainbow(s).dimgray } }.freeze
Class Method Summary collapse
-
.hexdump(str, width: 16, skip: true, offset: 0, style: {}, highlight: '') ⇒ String
Returns a hexdump-dump of a string.
-
.hexdump_iter(io, width: 16, skip: true, offset: 0, style: {}, highlight: '') ⇒ Enumerator<String>
Yields lines of a hexdump-dump of a string.
Class Method Details
.hexdump(str, width: 16, skip: true, offset: 0, style: {}, highlight: '') ⇒ String
Returns a hexdump-dump of a string.
Color is provided using rainbow
gem and only when output is a tty. To force enable/disable coloring, call Rainbow.enabled = true / false
.
142 143 144 145 146 |
# File 'lib/pwnlib/util/hexdump.rb', line 142 def hexdump(str, width: 16, skip: true, offset: 0, style: {}, highlight: '') hexdump_iter(StringIO.new(str), width: width, skip: skip, offset: offset, style: style, highlight: highlight).to_a.join("\n") end |
.hexdump_iter(io, width: 16, skip: true, offset: 0, style: {}, highlight: '') ⇒ Enumerator<String>
Yields lines of a hexdump-dump of a string. Unless you have massive amounts of data you probably want to use hexdump. Returns an Enumerator if no block given.
Color is provided using rainbow
gem and only when output is a tty. To force enable/disable coloring, call Rainbow.enabled = true / false
.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/pwnlib/util/hexdump.rb', line 66 def hexdump_iter(io, width: 16, skip: true, offset: 0, style: {}, highlight: '') Enumerator.new do |y| style = DEFAULT_STYLE.merge(style) highlight.bytes.each { |b| style[b] = HIGHLIGHT_STYLE } (0..255).each do |b| next if style.key?(b) style[b] = (b.chr =~ /[[:print:]]/ ? style[:printable] : style[:unprintable]) end styled_bytes = (0..255).map do |b| left_hex = format('%02x', b) c = b.chr right_char = (c =~ /[[:print:]]/ ? c : "\u00b7") [style[b].call(left_hex), style[b].call(right_char)] end marker = style[:marker].call(MARKER) spacer = ' ' byte_index = offset skipping = false last_chunk = +'' loop do # We assume that chunk is in ASCII-8BIT encoding. chunk = io.read(width) break unless chunk chunk_bytes = chunk.bytes start_byte_index = byte_index byte_index += chunk_bytes.size # Yield * once for repeated lines. if skip && last_chunk == chunk y << '*' unless skipping skipping = true next end skipping = false last_chunk = chunk hex_bytes = +'' printable = +'' chunk_bytes.each_with_index do |b, i| left_hex, right_char = styled_bytes[b] hex_bytes << left_hex printable << right_char if i % 4 == 3 && i != chunk_bytes.size - 1 hex_bytes << spacer printable << marker end hex_bytes << ' ' end if chunk_bytes.size < width padded_hex_length = 3 * width + (width - 1) / 4 hex_length = 3 * chunk_bytes.size + (chunk_bytes.size - 1) / 4 hex_bytes << ' ' * (padded_hex_length - hex_length) end y << format("%08x %s #{MARKER}%s#{MARKER}", start_byte_index, hex_bytes, printable) end y << format('%08x', byte_index) end end |