heapinfo 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd09327165de603d3fa3350e9022d8bf642a1f7c
4
- data.tar.gz: 5c1dd70e46c5fad709e187c25a8347be8262586e
3
+ metadata.gz: e90a4db825f5e6b53989edc82441a0800d13aaa7
4
+ data.tar.gz: f638662fb165a7c884c5427b378cfac091ebe83a
5
5
  SHA512:
6
- metadata.gz: 6827c2c7129162b716046200e71cdba7475de9edad4a1880b0aec374c3e9a5649c6a2ae934566097794671bc1c30d255e4fed9142e6a1de4b95a914f3c8c5ee1
7
- data.tar.gz: 82bfd1db1bca104fa62d54e7c14a63ad91d2a208dfa346d8a23464141d9767e1f9d18dda21dfd106a840d2799c92c3d4dad2a78893b4bcbc224aa9c415f38692
6
+ metadata.gz: f2356a124a5a9480e2e170f6abb2ee782f671734d4e7edbe2f15f47f690609a40580ac1d3d8f027342d03a82901c996b32d9dc21dccb4473105f027814149503
7
+ data.tar.gz: 3e3df55aca650bf6c8277185afdf56bb3f9c4e3ded9ec444af64f6159302aa9eb5d001da0f3f7dac82d174348c5e8af5b4340abfa1a5cca6f205a7936fa640b0
@@ -3,22 +3,25 @@ module HeapInfo
3
3
  class Arena
4
4
  # @return [Array<HeapInfo::Fastbin>] Fastbins in an array.
5
5
  attr_reader :fastbin
6
- # @return [Array<HeapInfo::UnsortedBin>] The unsorted bin (only one).
6
+ # @return [HeapInfo::Chunk] Current top chunk.
7
+ attr_reader :top_chunk
8
+ # @return [HeapInfo::Chunk] Current last remainder.
9
+ attr_reader :last_remainder
10
+ # @return [Array<HeapInfo::UnsortedBin>] The unsorted bin (array size will always be one).
7
11
  attr_reader :unsorted_bin
8
12
  # @return [Array<HeapInfo::Smallbin>] Smallbins in an array.
9
13
  attr_reader :smallbin
10
- # @return [HeapInfo::Chunk] Current top chunk.
11
- attr_reader :top_chunk
14
+ # @return [Integer] The <tt>system_mem</tt>
15
+ attr_reader :system_mem
12
16
  # attr_reader :largebin, :last_remainder
13
17
 
14
18
  # Instantiate a <tt>HeapInfo::Arena</tt> object.
15
19
  #
16
20
  # @param [Integer] base Base address of arena.
17
- # @param [Integer] bits Either 64 or 32
21
+ # @param [Integer] size_t Either 8 or 4
18
22
  # @param [Proc] dumper For dump more data
19
- def initialize(base, bits, dumper)
20
- @base, @dumper = base, dumper
21
- @size_t = bits / 8
23
+ def initialize(base, size_t, dumper)
24
+ @base, @size_t, @dumper = base, size_t, dumper
22
25
  reload!
23
26
  end
24
27
 
@@ -26,16 +29,19 @@ module HeapInfo
26
29
  # Retrive data using <tt>@dumper</tt>, load bins, top chunk etc.
27
30
  # @return [HeapInfo::Arena] self
28
31
  def reload!
29
- top_ptr = Helper.unpack(size_t, @dumper.call(@base + 8 + size_t * 10, size_t))
32
+ top_ptr_offset = @base + 8 + size_t * 10
33
+ top_ptr = Helper.unpack(size_t, @dumper.call(top_ptr_offset, size_t))
30
34
  @fastbin = []
31
35
  return self if top_ptr == 0 # arena not init yet
32
36
  @top_chunk = Chunk.new size_t, top_ptr, @dumper
37
+ @last_remainder = Chunk.new size_t, top_ptr_offset + 8, @dumper
38
+ @system_mem = Helper.unpack(size_t, @dumper.call(top_ptr_offset + 258 * size_t + 16, size_t))
33
39
  @fastbin = Array.new(7) do |idx|
34
40
  f = Fastbin.new(size_t, @base + 8 - size_t * 2 + size_t * idx, @dumper, head: true)
35
41
  f.index = idx
36
42
  f
37
43
  end
38
- @unsorted_bin = UnsortedBin.new(size_t, @base + 8 + size_t * 10, @dumper, head: true)
44
+ @unsorted_bin = UnsortedBin.new(size_t, top_ptr_offset, @dumper, head: true)
39
45
  @smallbin = Array.new(55) do |idx|
40
46
  s = Smallbin.new(size_t, @base + 8 + size_t * (26 + 2 * idx), @dumper, head: true)
41
47
  s.index = idx
@@ -61,6 +61,27 @@ module HeapInfo
61
61
  flag
62
62
  end
63
63
 
64
+ # Ask if chunk not belongs to main arena.
65
+ #
66
+ # @return [Boolean] <tt>true|false</tt> if chunk not belongs to main arena
67
+ def non_main_arena?
68
+ flags.include? :non_main_arena
69
+ end
70
+
71
+ # Ask if chunk is mmapped.
72
+ #
73
+ # @return [Boolean] <tt>true|false</tt> if chunk is mmapped
74
+ def mmapped?
75
+ flags.include? :mmapped
76
+ end
77
+
78
+ # Ask if chunk has set the prev-inuse bit.
79
+ #
80
+ # @return [Boolean] <tt>true|false</tt> if the <tt>prev_inuse</tt> bit has been set
81
+ def prev_inuse?
82
+ flags.include? :prev_inuse
83
+ end
84
+
64
85
  # Size of chunk
65
86
  # @return [Integer] The chunk size without flag masks
66
87
  def size
@@ -0,0 +1,11 @@
1
+ module HeapInfo
2
+ module Glibc
3
+ # @abstract Exceptions raised by HeapInfo inherit from Error
4
+ class Error < StandardError; end
5
+ # Exception raised in malloc.c(malloc, free, etc.) methods.
6
+ class MallocError < Error; end
7
+ def malloc_assert(condition)
8
+ raise MallocError.new(yield) unless condition
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,77 @@
1
+ # Implment glibc's free-related functions
2
+ # [Reference](https://code.woboq.org/userspace/glibc/malloc/malloc.c.html)
3
+ module HeapInfo
4
+ module Glibc
5
+ # Implmentation of <tt>void __libc_free(void *mem)</tt>.
6
+ # [Source](https://code.woboq.org/userspace/glibc/malloc/malloc.c.html#__libc_free)
7
+ # @param [Integer] mem Memory address to be free.
8
+ def libc_free(mem)
9
+ # TODO: free_hook
10
+ mem = ulong mem
11
+ return if mem == 0 # free(0) has no effect
12
+ ptr = mem2chunk(mem)
13
+ return munmap_chunk(ptr) if chunk_is_mmapped(ptr)
14
+ av = arena_for_chunk(ptr)
15
+ int_free(av, ptr)
16
+ end
17
+ alias :free :libc_free
18
+
19
+ private
20
+ # Implmentation of <tt>void _int_free (mstate av, mchunkptr p, [int have_lock])</tt>.
21
+ # [Source](https://code.woboq.org/userspace/glibc/malloc/malloc.c.html#_int_free)
22
+ #
23
+ # The original method in C is too long, split to multiple methods to match ruby convention.
24
+ # @param [HeapInfo::Arena] av
25
+ # @param [Integer] ptr Use <tt>ptr</tt> instead of <tt>p</tt> to prevent confusing with ruby native method.
26
+ def int_free(av, ptr) # is have_lock important?
27
+ chunk = dumper.call(ptr, size_t * 2).to_chunk
28
+ size = ulong chunk.size
29
+ invalid_pointer(ptr, size)
30
+ invalid_size(size)
31
+ # check_inuse_chunk # off
32
+ if size <= get_max_fast
33
+ int_free_fast(av, ptr, size)
34
+ elsif !chunk_is_mmapped(ptr) # Though this has been checked in #libc_free
35
+ int_free_small(av, ptr, size)
36
+ else
37
+ munmap_chunk(ptr)
38
+ end
39
+ end
40
+
41
+ def int_free_fast(av, ptr, size)
42
+ invalid_next_size(:fast, av, ptr, size)
43
+ true
44
+ end
45
+
46
+ def int_free_small(av, ptr, size)
47
+ true
48
+ end
49
+
50
+ def munmap_chunk(ptr)
51
+ # TODO: check page alignment and... page exists?
52
+ true
53
+ end
54
+
55
+ # Start of checkers
56
+
57
+ def invalid_pointer(ptr, size)
58
+ errmsg = "free(): invalid pointer\n"
59
+ # unsigned compare
60
+ malloc_assert(ptr <= ulong(-size)) { errmsg + "ptr(0x%x) > -size(0x%x)" % [ptr, ulong(-size)] }
61
+ malloc_assert(ptr % (size_t * 2) == 0) { errmsg + "ptr(0x%x) %% %d != 0" % [ptr, size_t * 2] }
62
+ end
63
+
64
+ def invalid_size(size)
65
+ errmsg = "free(): invalid size\n"
66
+ malloc_assert(size >= min_chunk_size) { errmsg + "size(0x%x) < min_chunk_size(0x%x)" % [size, min_chunk_size] }
67
+ malloc_assert(aligned_ok size) { errmsg + "alignment error: size(0x%x) %% 0x%x != 0" % [size, size_t * 2] }
68
+ end
69
+
70
+ def invalid_next_size(type, av, ptr, size)
71
+ errmsg = "free(): invalid next size (#{type})\n"
72
+ nxt_chk = dumper.call(ptr + size, size_t * 2).to_chunk(base: ptr + size)
73
+ malloc_assert(nxt_chk.size > 2 * size_t) { errmsg + "next chunk(0x%x) has size(#{nxt_chk.size}) <= 2 * #{size_t}" % nxt_chk.base }
74
+ malloc_assert(nxt_chk.size < av.system_mem) { errmsg + "next chunk(0x%x) has size(0x%x) >= av.system_mem(0x%x)" % [nxt_chk.base, nxt_chk.size, av.system_mem] }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ module HeapInfo
2
+ module Glibc
3
+ attr_accessor :size_t
4
+ private
5
+ attr_accessor :main_arena
6
+ attr_accessor :dumper
7
+ end
8
+ end
9
+ require 'heapinfo/glibc/error.rb'
10
+ require 'heapinfo/glibc/helper.rb'
11
+ require 'heapinfo/glibc/free.rb'
@@ -0,0 +1,44 @@
1
+ module HeapInfo
2
+ module Glibc
3
+ private
4
+ def mem2chunk(mem)
5
+ ulong(mem - 2 * size_t)
6
+ end
7
+
8
+ # @return [Boolean]
9
+ def chunk_is_mmapped(ptr)
10
+ # TODO: handle memory not accessible
11
+ dumper.call(ptr, size_t * 2).to_chunk.mmapped?
12
+ end
13
+
14
+ def get_max_fast
15
+ size_t * 16
16
+ end
17
+
18
+ # The minimal chunk size.
19
+ # Not the real implmentation, maybe wrong some day?
20
+ # @return [Integer] The size.
21
+ def min_chunk_size
22
+ size_t * 4
23
+ end
24
+
25
+ # Not the real implmentation, maybe wrong some day?
26
+ # @return [Boolean]
27
+ def aligned_ok(size)
28
+ size & (2 * size_t - 1) == 0
29
+ end
30
+
31
+ # @return [Integer]
32
+ def ulong(n)
33
+ n % 2 ** (size_t * 8)
34
+ end
35
+
36
+ # @return [HeapInfo::Arena]
37
+ def arena_for_chunk(ptr)
38
+ # not support arena other than initial main_arena
39
+ return if dumper.call(ptr, size_t * 2).to_chunk.non_main_arena?
40
+ main_arena
41
+ end
42
+
43
+ end
44
+ end
@@ -93,6 +93,16 @@ module HeapInfo
93
93
  data.unpack(size_t == 4 ? 'L*' : 'Q*')[0]
94
94
  end
95
95
 
96
+ # Convert number in hex format
97
+ #
98
+ # @param [Integer] num Non-negative integer.
99
+ # @return [String] number in hex format.
100
+ # @example
101
+ # HeapInfo::Helper.hex(1000) # => '0x3e8'
102
+ def self.hex(num)
103
+ '0x' + num.to_s(16)
104
+ end
105
+
96
106
  # Retrieve pure class name(without module) of an object
97
107
  # @param [Object] obj Any instance
98
108
  # @return [String] Class name of <tt>obj</tt>
data/lib/heapinfo/libc.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module HeapInfo
2
2
  # Record libc's base, name, and offsets.
3
3
  class Libc < Segment
4
-
4
+ include HeapInfo::Glibc
5
5
  # Instantiate a <tt>HeapInfo::Libc</tt> object.
6
6
  #
7
7
  # @param [Mixed] args See <tt>#HeapInfo::Segment.initialize</tt> for more information.
@@ -24,21 +24,25 @@ module HeapInfo
24
24
  return @main_arena.reload! if @main_arena
25
25
  off = main_arena_offset
26
26
  return if off.nil?
27
- @main_arena = Arena.new(off + self.base, process.bits, process.method(:dump))
27
+ @main_arena = Arena.new(off + self.base, size_t, dumper)
28
28
  end
29
29
 
30
30
  # @param [Array] maps See <tt>#HeapInfo::Segment.find</tt> for more information.
31
31
  # @param [String] name See <tt>#HeapInfo::Segment.find</tt> for more information.
32
- # @param [HeapInfo::Process] process The process.
32
+ # @param [Integer] bits Either 64 or 32.
33
+ # @param [String] ld_name The loader's realpath, will be used for running subprocesses.
34
+ # @param [Proc] dumper The memory dumper for fetch more information.
33
35
  # @return [HeapInfo::Libc] libc segment found in maps.
34
- def self.find(maps, name, process)
36
+ def self.find(maps, name, bits, ld_name, dumper)
35
37
  obj = super(maps, name)
36
- obj.send(:process=, process)
38
+ obj.size_t = bits / 8
39
+ obj.send(:ld_name=, ld_name)
40
+ obj.send(:dumper=, dumper)
37
41
  obj
38
42
  end
39
43
 
40
44
  private
41
- attr_accessor :process
45
+ attr_accessor :ld_name
42
46
  # only for searching offset of main_arena now
43
47
  def exhaust_search(symbol)
44
48
  return false if symbol != :main_arena
@@ -58,9 +62,9 @@ module HeapInfo
58
62
  tmp_elf = HeapInfo::TMP_DIR + "/get_arena"
59
63
  libc_file = HeapInfo::TMP_DIR + "/libc.so.6"
60
64
  ld_file = HeapInfo::TMP_DIR + "/ld.so"
61
- flags = "-w #{@process.bits == 32 ? '-m32' : ''}"
65
+ flags = "-w #{size_t == 4 ? '-m32' : ''}"
62
66
  %x(cp #{self.name} #{libc_file} && \
63
- cp #{@process.ld.name} #{ld_file} && \
67
+ cp #{ld_name} #{ld_file} && \
64
68
  gcc #{flags} #{File.expand_path('../tools/get_arena.c', __FILE__)} -o #{tmp_elf} 2>&1 > /dev/null && \
65
69
  #{ld_file} --library-path #{HeapInfo::TMP_DIR} #{tmp_elf} && \
66
70
  rm #{tmp_elf} #{libc_file} #{ld_file}).to_i(16)
@@ -21,6 +21,17 @@ module HeapInfo
21
21
  return unless load?
22
22
  end
23
23
 
24
+ # Reload a new process with same program name
25
+ #
26
+ # @return [HeapInfo::Process] return <tt>self</tt> for chainable.
27
+ # @example
28
+ # puts h.reload!
29
+ def reload!
30
+ @pid = nil
31
+ load!
32
+ self
33
+ end
34
+
24
35
  # Use this method to wrapper all HeapInfo methods.
25
36
  #
26
37
  # Since <tt>::HeapInfo</tt> is a tool(debugger) for local usage,
@@ -164,7 +175,7 @@ module HeapInfo
164
175
  def load! # try to load
165
176
  return true if @pid
166
177
  @pid = fetch_pid
167
- return false if @pid.nil? # still can't load
178
+ return clear_process if @pid.nil? # still can't load
168
179
  load_info!
169
180
  true
170
181
  end
@@ -179,6 +190,13 @@ module HeapInfo
179
190
  pid
180
191
  end
181
192
 
193
+ def clear_process
194
+ ProcessInfo::EXPORT.each do |m|
195
+ self.class.send(:define_method, m) {Nil.new}
196
+ end
197
+ false
198
+ end
199
+
182
200
  def load_info!
183
201
  @info = ProcessInfo.new(self)
184
202
  ProcessInfo::EXPORT.each do |m|
@@ -32,8 +32,8 @@ module HeapInfo
32
32
  @stack = Segment.find(maps, '[stack]')
33
33
  # well.. stack is a strange case because it will grow in runtime..
34
34
  # should i detect stack base growing..?
35
- @libc = Libc.find(maps, match_maps(maps, options[:libc]), process)
36
35
  @ld = Segment.find(maps, match_maps(maps, options[:ld]))
36
+ @libc = Libc.find(maps, match_maps(maps, options[:libc]), @bits, @ld.name, ->(*args){ process.dump(*args) })
37
37
  end
38
38
 
39
39
  # Heap will not be mmapped if the process not use heap yet, so create a lazy loading method.
@@ -1,3 +1,3 @@
1
1
  module HeapInfo
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.3'.freeze
3
3
  end
data/lib/heapinfo.rb CHANGED
@@ -63,6 +63,7 @@ require 'heapinfo/cache'
63
63
  require 'heapinfo/process_info'
64
64
  require 'heapinfo/process'
65
65
  require 'heapinfo/segment'
66
+ require 'heapinfo/glibc/glibc'
66
67
  require 'heapinfo/libc'
67
68
  require 'heapinfo/chunk'
68
69
  require 'heapinfo/chunks'
data/spec/libc_spec.rb ADDED
@@ -0,0 +1,54 @@
1
+ # encoding: ascii-8bit
2
+ require 'heapinfo'
3
+ describe HeapInfo::Libc do
4
+ describe 'free' do
5
+ before(:all) do
6
+ HeapInfo::Cache.send :clear_all # force cache miss, to make sure coverage
7
+ @victim = HeapInfo::TMP_DIR + '/victim'
8
+ %x(g++ #{File.expand_path('../files/victim.cpp', __FILE__)} -o #{@victim} 2>&1 > /dev/null)
9
+ pid = fork
10
+ # run without ASLR
11
+ exec "setarch `uname -m` -R /bin/sh -c #{@victim}" if pid.nil?
12
+ loop until `pidof #{@victim}` != ''
13
+ @h = HeapInfo::Process.new(@victim, ld: '/ld')
14
+ @fake_mem = 0x13371000
15
+ @set_memory = ->(str) do
16
+ @h.libc.send(:dumper=, ->(ptr, len){
17
+ if ptr.between?(@fake_mem, @fake_mem + 0x1000)
18
+ str[ptr - @fake_mem, len]
19
+ else
20
+ @h.dump(ptr, len)
21
+ end
22
+ })
23
+ end
24
+ end
25
+ after(:all) do
26
+ `killall #{@victim}`
27
+ FileUtils.rm(@victim)
28
+ end
29
+
30
+ describe 'invalid' do
31
+ it 'invalid pointer' do
32
+ @set_memory.call [0, 0x21, 0x21, 0x0, 0x0].pack("Q*")
33
+ expect {@h.libc.free(@fake_mem + 24)}.to raise_error "free(): invalid pointer\nptr(#{HeapInfo::Helper.hex(@fake_mem + 8)}) % 16 != 0"
34
+ expect {@h.libc.free(@fake_mem + 32)}.to raise_error "free(): invalid pointer\nptr(#{HeapInfo::Helper.hex(@fake_mem + 16)}) > -size(0x0)"
35
+ end
36
+
37
+ it 'invalid size' do
38
+ @set_memory.call [0, 0x11].pack("Q*")
39
+ expect {@h.libc.free(@fake_mem + 16)}.to raise_error "free(): invalid size\nsize(0x10) < min_chunk_size(0x20)"
40
+ @set_memory.call [0, 0x38].pack("Q*")
41
+ expect {@h.libc.free(@fake_mem + 16)}.to raise_error "free(): invalid size\nalignment error: size(0x38) % 0x10 != 0"
42
+ end
43
+ end
44
+
45
+ describe 'fast' do
46
+ it 'invalid next size' do
47
+ @set_memory.call [0, 0x21, 0, 0, 0, 0xf].pack("Q*")
48
+ expect {@h.libc.free(@fake_mem + 16)}.to raise_error "free(): invalid next size (fast)\nnext chunk(#{HeapInfo::Helper.hex(@fake_mem + 32)}) has size(8) <= 2 * 8"
49
+ @set_memory.call [0, 0x21, 0, 0, 0, 0x21000].pack("Q*")
50
+ expect {@h.libc.free(@fake_mem + 16)}.to raise_error "free(): invalid next size (fast)\nnext chunk(#{HeapInfo::Helper.hex(@fake_mem + 32)}) has size(0x21000) >= av.system_mem(0x21000)"
51
+ end
52
+ end
53
+ end
54
+ end
data/spec/process_spec.rb CHANGED
@@ -38,7 +38,7 @@ describe HeapInfo::Process do
38
38
  @io = Cio.new
39
39
  end
40
40
  after(:all) do
41
- %x(killall #{@victim})
41
+ `killall #{@victim}`
42
42
  FileUtils.rm(@victim)
43
43
  end
44
44
 
@@ -84,6 +84,19 @@ describe HeapInfo::Process do
84
84
  end
85
85
  end
86
86
 
87
+ describe 'reload' do
88
+ it 'monkey' do
89
+ prog = File.readlink('/proc/self/exe')
90
+ @h = HeapInfo::Process.new(prog)
91
+ expect(@h.pid.is_a? Integer).to be true
92
+ pid = @h.pid
93
+ @h.instance_variable_set(:@prog, 'NO_THIS')
94
+ expect(@h.reload!.pid).to be nil
95
+ @h.instance_variable_set(:@prog, prog)
96
+ expect(@h.reload!.pid).to be pid
97
+ end
98
+ end
99
+
87
100
  describe 'fastbin' do
88
101
  it 'normal' do
89
102
  expect(@h.libc.main_arena.fastbin[0].list).to eq [0x602020, 0x602000, nil]
@@ -154,5 +167,9 @@ describe HeapInfo::Process do
154
167
  it 'nil chain' do
155
168
  expect(@h.dump(:heap).no_such_method.xdd.nil?).to be true
156
169
  end
170
+
171
+ it 'info methods' do
172
+ expect(@h.libc.base.nil?).to be true
173
+ end
157
174
  end
158
175
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heapinfo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-21 00:00:00.000000000 Z
11
+ date: 2016-12-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: create an interactive memory info interface while pwn / exploiting
14
14
  email:
@@ -25,6 +25,10 @@ files:
25
25
  - lib/heapinfo/chunks.rb
26
26
  - lib/heapinfo/dumper.rb
27
27
  - lib/heapinfo/ext/string.rb
28
+ - lib/heapinfo/glibc/error.rb
29
+ - lib/heapinfo/glibc/free.rb
30
+ - lib/heapinfo/glibc/glibc.rb
31
+ - lib/heapinfo/glibc/helper.rb
28
32
  - lib/heapinfo/helper.rb
29
33
  - lib/heapinfo/libc.rb
30
34
  - lib/heapinfo/nil.rb
@@ -41,6 +45,7 @@ files:
41
45
  - spec/files/64bit_maps
42
46
  - spec/files/victim.cpp
43
47
  - spec/helper_spec.rb
48
+ - spec/libc_spec.rb
44
49
  - spec/nil_spec.rb
45
50
  - spec/process_spec.rb
46
51
  - spec/spec_helper.rb
@@ -65,20 +70,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
70
  version: '0'
66
71
  requirements: []
67
72
  rubyforge_project:
68
- rubygems_version: 2.4.8
73
+ rubygems_version: 2.5.2
69
74
  signing_key:
70
75
  specification_version: 4
71
76
  summary: HeapInfo - interactive heap exploitation helper
72
77
  test_files:
73
- - spec/chunk_spec.rb
74
78
  - spec/files/32bit_maps
75
- - spec/files/64bit_maps
76
79
  - spec/files/victim.cpp
77
- - spec/helper_spec.rb
80
+ - spec/files/64bit_maps
78
81
  - spec/cache_spec.rb
82
+ - spec/dumper_spec.rb
83
+ - spec/process_spec.rb
84
+ - spec/chunk_spec.rb
85
+ - spec/chunks_spec.rb
79
86
  - spec/string_spec.rb
80
87
  - spec/spec_helper.rb
88
+ - spec/helper_spec.rb
81
89
  - spec/nil_spec.rb
82
- - spec/chunks_spec.rb
83
- - spec/dumper_spec.rb
84
- - spec/process_spec.rb
90
+ - spec/libc_spec.rb