heapinfo 0.0.5 → 0.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 +4 -4
- data/README.md +1 -0
- data/lib/heapinfo.rb +8 -8
- data/lib/heapinfo/arena.rb +47 -45
- data/lib/heapinfo/cache.rb +12 -13
- data/lib/heapinfo/chunk.rb +23 -23
- data/lib/heapinfo/chunks.rb +16 -5
- data/lib/heapinfo/dumper.rb +55 -44
- data/lib/heapinfo/ext/string.rb +2 -2
- data/lib/heapinfo/glibc/error.rb +2 -1
- data/lib/heapinfo/glibc/free.rb +29 -16
- data/lib/heapinfo/glibc/glibc.rb +5 -1
- data/lib/heapinfo/glibc/helper.rb +9 -6
- data/lib/heapinfo/helper.rb +22 -26
- data/lib/heapinfo/libc.rb +18 -17
- data/lib/heapinfo/nil.rb +14 -8
- data/lib/heapinfo/process.rb +34 -25
- data/lib/heapinfo/process_info.rb +15 -14
- data/lib/heapinfo/segment.rb +10 -9
- data/lib/heapinfo/tools/get_arena.c +0 -1
- data/lib/heapinfo/version.rb +1 -1
- metadata +75 -31
- data/spec/cache_spec.rb +0 -46
- data/spec/chunk_spec.rb +0 -40
- data/spec/chunks_spec.rb +0 -25
- data/spec/dumper_spec.rb +0 -105
- data/spec/files/32bit_maps +0 -23
- data/spec/files/64bit_maps +0 -29
- data/spec/files/victim.cpp +0 -33
- data/spec/helper_spec.rb +0 -73
- data/spec/libc_spec.rb +0 -75
- data/spec/nil_spec.rb +0 -15
- data/spec/process_spec.rb +0 -201
- data/spec/spec_helper.rb +0 -98
- data/spec/string_spec.rb +0 -18
data/spec/cache_spec.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
require 'heapinfo'
|
3
|
-
describe HeapInfo::Cache do
|
4
|
-
before(:all) do
|
5
|
-
@prefix = 'testcx1dd/'
|
6
|
-
end
|
7
|
-
after(:each) do
|
8
|
-
FileUtils.rm_rf File.join(HeapInfo::Cache::CACHE_DIR, @prefix)
|
9
|
-
end
|
10
|
-
it 'handle unwritable' do
|
11
|
-
org = HeapInfo::Cache::CACHE_DIR
|
12
|
-
HeapInfo::Cache.send :remove_const, :CACHE_DIR
|
13
|
-
no = '/tmp/no_permission'
|
14
|
-
FileUtils.mkdir_p no
|
15
|
-
File.chmod 0444, no # no write permission
|
16
|
-
HeapInfo::Cache.const_set :CACHE_DIR, no + '/.cache'
|
17
|
-
HeapInfo::Cache.send :load
|
18
|
-
expect(HeapInfo::Cache::CACHE_DIR).to eq HeapInfo::TMP_DIR + '/.cache/heapinfo'
|
19
|
-
HeapInfo::Cache.send :remove_const, :CACHE_DIR
|
20
|
-
HeapInfo::Cache.const_set :CACHE_DIR, org
|
21
|
-
FileUtils.rm_rf no
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'write' do
|
25
|
-
expect(HeapInfo::Cache::write @prefix + '123', {a: 1}).to be true
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'read' do
|
29
|
-
expect(HeapInfo::Cache::read @prefix + 'z/zzz').to be nil
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'write and read' do
|
33
|
-
key = @prefix + 'fefw/z/zz/xdddd'
|
34
|
-
object = {a: {b: 'string', array: [3, '1', 2]}, 'd' => 3}
|
35
|
-
expect(HeapInfo::Cache::read key).to be nil
|
36
|
-
expect(HeapInfo::Cache::write key, object).to be true
|
37
|
-
expect(HeapInfo::Cache::read key).to eq object
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'file corrupted' do
|
41
|
-
key = @prefix + 'corrupted'
|
42
|
-
HeapInfo::Cache::write key, 'ok'
|
43
|
-
IO.binwrite(File.join(HeapInfo::Cache::CACHE_DIR, key), 'not ok')
|
44
|
-
expect(HeapInfo::Cache::read key).to be nil
|
45
|
-
end
|
46
|
-
end
|
data/spec/chunk_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
require 'heapinfo'
|
3
|
-
describe HeapInfo::Chunk do
|
4
|
-
describe '32bit' do
|
5
|
-
before(:all) do
|
6
|
-
@fast = [0, 0x47, 0x1337].pack("L*").to_chunk(bits: 32)
|
7
|
-
@small = [0, 0x48, 0xabcdef].pack("L*").to_chunk(bits: 32)
|
8
|
-
end
|
9
|
-
it 'basic' do
|
10
|
-
expect(@fast.size_t).to be 4
|
11
|
-
expect(@fast.size).to be 0x40
|
12
|
-
expect(@fast.flags).to eq [:non_main_arena, :mmapped, :prev_inuse]
|
13
|
-
expect(@fast.bintype).to eq :fast
|
14
|
-
expect(@fast.data).to eq [0x1337].pack("L*")
|
15
|
-
expect(@small.bintype).to eq :small
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'to_s' do
|
19
|
-
expect(@small.to_s).to eq "\e[38;5;155m#<HeapInfo::Chunk:0>\n\e[0mflags = []\nsize = \e[38;5;12m0x48\e[0m (small)\nprev_size = \e[38;5;12m0\e[0m\ndata = \e[38;5;1m\"\\xEF\\xCD\\xAB\\x00\"\e[0m...\n"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '64bit' do
|
24
|
-
before(:all) do
|
25
|
-
@fast = [0, 0x87, 0x1337].pack("Q*").to_chunk # default 64bits
|
26
|
-
@small = [0, 0x90, 0xdead].pack("Q*").to_chunk
|
27
|
-
end
|
28
|
-
it 'basic' do
|
29
|
-
expect(@fast.size_t).to be 8
|
30
|
-
expect(@fast.size).to be 0x80
|
31
|
-
expect(@fast.flags).to eq [:non_main_arena, :mmapped, :prev_inuse]
|
32
|
-
expect(@fast.bintype).to eq :fast
|
33
|
-
expect(@fast.data).to eq [0x1337].pack("Q*")
|
34
|
-
expect(@small.bintype).to eq :small
|
35
|
-
end
|
36
|
-
it 'to_s' do
|
37
|
-
expect(@small.to_s).to eq "\e[38;5;155m#<HeapInfo::Chunk:0>\n\e[0mflags = []\nsize = \e[38;5;12m0x90\e[0m (small)\nprev_size = \e[38;5;12m0\e[0m\ndata = \e[38;5;1m\"\\xAD\\xDE\\x00\\x00\\x00\\x00\\x00\\x00\"\e[0m...\n"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/spec/chunks_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
require 'heapinfo'
|
3
|
-
describe HeapInfo::Chunks do
|
4
|
-
before(:each) do
|
5
|
-
@chunks = HeapInfo::Chunks.new
|
6
|
-
@chunks << 0; @chunks << 1; @chunks << 2
|
7
|
-
end
|
8
|
-
it '<<' do
|
9
|
-
expect(@chunks.size).to be 3
|
10
|
-
@chunks << ("\x00"*16).to_chunk
|
11
|
-
expect(@chunks.size).to be 4
|
12
|
-
end
|
13
|
-
it 'each' do
|
14
|
-
@chunks.each_with_index{|c, idx|
|
15
|
-
expect(c).to be idx
|
16
|
-
}
|
17
|
-
end
|
18
|
-
it 'to_s' do
|
19
|
-
expect(@chunks.to_s).to eq @chunks.instance_variable_get(:@chunks).map(&:to_s).join("\n")
|
20
|
-
end
|
21
|
-
it 'size' do
|
22
|
-
expect(@chunks.size).to eq @chunks.instance_variable_get(:@chunks).size
|
23
|
-
expect(@chunks.length).to eq @chunks.instance_variable_get(:@chunks).length
|
24
|
-
end
|
25
|
-
end
|
data/spec/dumper_spec.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
require 'heapinfo'
|
3
|
-
describe HeapInfo::Dumper do
|
4
|
-
before(:all) do
|
5
|
-
@self_maps = IO.binread('/proc/self/maps').lines.map do |seg|
|
6
|
-
s = seg.split(/\s/)
|
7
|
-
s[0] = s[0].split('-').map { |addr| addr.to_i(16) }
|
8
|
-
[s[0][0], s[0][1], s[1], s[-1]] # start, end, perm, name
|
9
|
-
end
|
10
|
-
|
11
|
-
@get_elf_base = ->() do
|
12
|
-
exe = File.readlink('/proc/self/exe')
|
13
|
-
@self_maps.find { |arr| arr[3] == exe }[0]
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe 'dump' do
|
18
|
-
before(:each) do
|
19
|
-
@mem_filename = '/proc/self/mem'
|
20
|
-
@elf_base = @get_elf_base.call
|
21
|
-
end
|
22
|
-
it 'simple' do
|
23
|
-
dumper = HeapInfo::Dumper.new(nil, @mem_filename)
|
24
|
-
expect(dumper.dump(@elf_base, 4)).to eq "\x7fELF"
|
25
|
-
end
|
26
|
-
it 'segment' do
|
27
|
-
class S;def initialize(base);@base = base;end; def elf; HeapInfo::Segment.new(@base, 'elf'); end; end
|
28
|
-
dumper = HeapInfo::Dumper.new(S.new(@elf_base), @mem_filename)
|
29
|
-
expect(dumper.dump(:elf, 4)).to eq "\x7fELF"
|
30
|
-
end
|
31
|
-
it 'invalid' do
|
32
|
-
dumper = HeapInfo::Dumper.new(HeapInfo::Nil.new, @mem_filename)
|
33
|
-
expect {dumper.dump(:zzz, 1)}.to raise_error ArgumentError
|
34
|
-
expect(dumper.dump(0x12345, 1)).to be nil
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'dumpable?' do
|
39
|
-
dumper = HeapInfo::Dumper.new(HeapInfo::Nil.new, '/proc/self/mem')
|
40
|
-
expect(dumper.send(:dumpable?)).to be true
|
41
|
-
# a little hack
|
42
|
-
dumper.instance_variable_set(:@filename, '/proc/1/mem')
|
43
|
-
expect(dumper.send(:dumpable?)).to be false
|
44
|
-
expect(dumper.dump).to be nil # show need permission
|
45
|
-
dumper.instance_variable_set(:@filename, '/proc/-1/mem')
|
46
|
-
expect {dumper.send(:dumpable?)}.to raise_error ArgumentError
|
47
|
-
end
|
48
|
-
|
49
|
-
describe 'find' do
|
50
|
-
before(:all) do
|
51
|
-
@elf_base = @get_elf_base.call
|
52
|
-
class S; def bits; 64; end; end
|
53
|
-
@dumper = HeapInfo::Dumper.new(S.new(@elf_base), '/proc/self/mem')
|
54
|
-
@end_of_maps = ->() do
|
55
|
-
@self_maps.find.with_index do |seg, i|
|
56
|
-
seg[2].include?('r') and seg[1] != @self_maps[i][0] # incontinuously segment
|
57
|
-
end[1]
|
58
|
-
end
|
59
|
-
end
|
60
|
-
it 'simple' do
|
61
|
-
expect(@dumper.find("ELF", :elf, 4)).to eq @elf_base + 1
|
62
|
-
expect(@dumper.find("ELF", :elf, 3)).to be nil
|
63
|
-
end
|
64
|
-
it 'regexp' do
|
65
|
-
addr = @dumper.find(/lin.x/, :elf, 0x1000)
|
66
|
-
expect(@dumper.dump(addr, 5) =~ /lin.x/).to eq 0
|
67
|
-
end
|
68
|
-
it 'invalid' do
|
69
|
-
expect(@dumper.find(nil, :elf, 1)).to be nil
|
70
|
-
end
|
71
|
-
it 'parser' do
|
72
|
-
expect(@dumper.find("ELF", ':elf + 1', 3)).to eq @elf_base + 1
|
73
|
-
end
|
74
|
-
it 'reach end' do
|
75
|
-
mem = @end_of_maps.call
|
76
|
-
# check dumper won't return nil when remain readable memory less than one page
|
77
|
-
expect(@dumper.find("\x00", mem - 0xff0, 0x1000).nil?).to be false
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe 'parse_cmd' do
|
82
|
-
it 'normal' do
|
83
|
-
expect(HeapInfo::Dumper.parse_cmd [0x30]).to eq [0x30, 0, 8]
|
84
|
-
expect(HeapInfo::Dumper.parse_cmd [0x30, 3]).to eq [0x30, 0, 3]
|
85
|
-
expect(HeapInfo::Dumper.parse_cmd [0x30, 2, 3]).to eq [0x30, 2, 3]
|
86
|
-
end
|
87
|
-
it 'symbol' do
|
88
|
-
expect(HeapInfo::Dumper.parse_cmd [:heap]).to eq [:heap,0 , 8]
|
89
|
-
expect(HeapInfo::Dumper.parse_cmd [:heap, 10]).to eq [:heap,0 , 10]
|
90
|
-
expect(HeapInfo::Dumper.parse_cmd [:heap, 3, 10]).to eq [:heap,3 , 10]
|
91
|
-
end
|
92
|
-
it 'string' do
|
93
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap']).to eq [:heap, 0, 8]
|
94
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap, 10']).to eq [:heap, 0, 10]
|
95
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap, 0x33, 10']).to eq [:heap, 51, 10]
|
96
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap+0x15, 10']).to eq [:heap, 0x15, 10]
|
97
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap + 0x15, 10']).to eq [:heap, 0x15, 10]
|
98
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap + 0x15']).to eq [:heap, 0x15, 8]
|
99
|
-
end
|
100
|
-
it 'mixed' do
|
101
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap+ 0x10', 10]).to eq [:heap, 0x10, 10]
|
102
|
-
expect(HeapInfo::Dumper.parse_cmd ['heap', 10]).to eq [:heap, 0, 10]
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
data/spec/files/32bit_maps
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
08048000-08049000 r-xp 00000000 ca:01 464143 /home/heapinfo/examples/uaf/uaf
|
2
|
-
08049000-0804a000 r--p 00000000 ca:01 464143 /home/heapinfo/examples/uaf/uaf
|
3
|
-
0804a000-0804b000 rw-p 00001000 ca:01 464143 /home/heapinfo/examples/uaf/uaf
|
4
|
-
f73d4000-f73d7000 rw-p 00000000 00:00 0
|
5
|
-
f73d7000-f73f3000 r-xp 00000000 ca:01 160460 /usr/lib32/libgcc_s.so.1
|
6
|
-
f73f3000-f73f4000 rw-p 0001b000 ca:01 160460 /usr/lib32/libgcc_s.so.1
|
7
|
-
f73f4000-f7438000 r-xp 00000000 ca:01 402366 /lib32/libm-2.19.so
|
8
|
-
f7438000-f7439000 r--p 00043000 ca:01 402366 /lib32/libm-2.19.so
|
9
|
-
f7439000-f743a000 rw-p 00044000 ca:01 402366 /lib32/libm-2.19.so
|
10
|
-
f743a000-f75df000 r-xp 00000000 ca:01 463662 /lib32/libc-2.19.so
|
11
|
-
f75df000-f75e1000 r--p 001a5000 ca:01 463662 /lib32/libc-2.19.so
|
12
|
-
f75e1000-f75e2000 rw-p 001a7000 ca:01 463662 /lib32/libc-2.19.so
|
13
|
-
f75e2000-f75e5000 rw-p 00000000 00:00 0
|
14
|
-
f75e5000-f76c1000 r-xp 00000000 ca:01 137147 /usr/lib32/libstdc++.so.6.0.19
|
15
|
-
f76c1000-f76c5000 r--p 000dc000 ca:01 137147 /usr/lib32/libstdc++.so.6.0.19
|
16
|
-
f76c5000-f76c6000 rw-p 000e0000 ca:01 137147 /usr/lib32/libstdc++.so.6.0.19
|
17
|
-
f76c6000-f76ce000 rw-p 00000000 00:00 0
|
18
|
-
f76db000-f76dd000 rw-p 00000000 00:00 0
|
19
|
-
f76dd000-f76de000 r-xp 00000000 00:00 0 [vdso]
|
20
|
-
f76de000-f76fe000 r-xp 00000000 ca:01 463655 /lib32/ld-2.19.so
|
21
|
-
f76fe000-f76ff000 r--p 0001f000 ca:01 463655 /lib32/ld-2.19.so
|
22
|
-
f76ff000-f7700000 rw-p 00020000 ca:01 463655 /lib32/ld-2.19.so
|
23
|
-
ffdd7000-ffdf8000 rw-p 00000000 00:00 0 [stack]
|
data/spec/files/64bit_maps
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
00400000-00401000 r-xp 00000000 ca:01 464143 /home/heapinfo/examples/uaf/uaf
|
2
|
-
00600000-00601000 r--p 00000000 ca:01 464143 /home/heapinfo/examples/uaf/uaf
|
3
|
-
00601000-00602000 rw-p 00001000 ca:01 464143 /home/heapinfo/examples/uaf/uaf
|
4
|
-
7f65ac7b8000-7f65ac7ce000 r-xp 00000000 ca:01 402137 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
5
|
-
7f65ac7ce000-7f65ac9cd000 ---p 00016000 ca:01 402137 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
6
|
-
7f65ac9cd000-7f65ac9ce000 rw-p 00015000 ca:01 402137 /lib/x86_64-linux-gnu/libgcc_s.so.1
|
7
|
-
7f65ac9ce000-7f65acad3000 r-xp 00000000 ca:01 401788 /lib/x86_64-linux-gnu/libm-2.19.so
|
8
|
-
7f65acad3000-7f65accd2000 ---p 00105000 ca:01 401788 /lib/x86_64-linux-gnu/libm-2.19.so
|
9
|
-
7f65accd2000-7f65accd3000 r--p 00104000 ca:01 401788 /lib/x86_64-linux-gnu/libm-2.19.so
|
10
|
-
7f65accd3000-7f65accd4000 rw-p 00105000 ca:01 401788 /lib/x86_64-linux-gnu/libm-2.19.so
|
11
|
-
7f65accd4000-7f65ace8f000 r-xp 00000000 ca:01 402326 /lib/x86_64-linux-gnu/libc-2.19.so
|
12
|
-
7f65ace8f000-7f65ad08e000 ---p 001bb000 ca:01 402326 /lib/x86_64-linux-gnu/libc-2.19.so
|
13
|
-
7f65ad08e000-7f65ad092000 r--p 001ba000 ca:01 402326 /lib/x86_64-linux-gnu/libc-2.19.so
|
14
|
-
7f65ad092000-7f65ad094000 rw-p 001be000 ca:01 402326 /lib/x86_64-linux-gnu/libc-2.19.so
|
15
|
-
7f65ad094000-7f65ad099000 rw-p 00000000 00:00 0
|
16
|
-
7f65ad099000-7f65ad17f000 r-xp 00000000 ca:01 13857 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
|
17
|
-
7f65ad17f000-7f65ad37e000 ---p 000e6000 ca:01 13857 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
|
18
|
-
7f65ad37e000-7f65ad386000 r--p 000e5000 ca:01 13857 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
|
19
|
-
7f65ad386000-7f65ad388000 rw-p 000ed000 ca:01 13857 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19
|
20
|
-
7f65ad388000-7f65ad39d000 rw-p 00000000 00:00 0
|
21
|
-
7f65ad39d000-7f65ad3c0000 r-xp 00000000 ca:01 402319 /lib/x86_64-linux-gnu/ld-2.19.so
|
22
|
-
7f65ad5aa000-7f65ad5af000 rw-p 00000000 00:00 0
|
23
|
-
7f65ad5bc000-7f65ad5bf000 rw-p 00000000 00:00 0
|
24
|
-
7f65ad5bf000-7f65ad5c0000 r--p 00022000 ca:01 402319 /lib/x86_64-linux-gnu/ld-2.19.so
|
25
|
-
7f65ad5c0000-7f65ad5c1000 rw-p 00023000 ca:01 402319 /lib/x86_64-linux-gnu/ld-2.19.so
|
26
|
-
7f65ad5c1000-7f65ad5c2000 rw-p 00000000 00:00 0
|
27
|
-
7fff3d1e8000-7fff3d209000 rw-p 00000000 00:00 0 [stack]
|
28
|
-
7fff3d309000-7fff3d30b000 r-xp 00000000 00:00 0 [vdso]
|
29
|
-
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
|
data/spec/files/victim.cpp
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
#include <cstdlib>
|
2
|
-
#include <cstdio>
|
3
|
-
#include <unistd.h>
|
4
|
-
int main(int argc, char **argv) {
|
5
|
-
if(argc <= 1) alarm(10);
|
6
|
-
void *v, *u;
|
7
|
-
int *i, *j;
|
8
|
-
|
9
|
-
void *mmap = malloc(0x20000);
|
10
|
-
|
11
|
-
// normal
|
12
|
-
v = malloc(24); u = malloc(24);
|
13
|
-
free(v); free(u);
|
14
|
-
|
15
|
-
// invalid fd
|
16
|
-
i = (int*)malloc(40);
|
17
|
-
free(i);
|
18
|
-
*i = 0xdeadbeef;
|
19
|
-
|
20
|
-
// loop
|
21
|
-
v = malloc(56); u = malloc(56);
|
22
|
-
free(v); free(u); free(v);
|
23
|
-
|
24
|
-
v = malloc(136);
|
25
|
-
void** others = (void**)malloc(72); // also prevent small bin merge with top_chunk
|
26
|
-
*others = mmap; // hack for test can get address of mmap
|
27
|
-
free(v);
|
28
|
-
v = malloc(152); // let 136 put into smallbin
|
29
|
-
malloc(200); // to prevent merge with top_chunk
|
30
|
-
free(v); // put into unsorted bin
|
31
|
-
char dummy;
|
32
|
-
read(0, &dummy, 1); // function which not use heap
|
33
|
-
}
|
data/spec/helper_spec.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
require 'heapinfo'
|
3
|
-
describe HeapInfo::Helper do
|
4
|
-
describe 'unpack' do
|
5
|
-
it '32bit' do
|
6
|
-
expect(HeapInfo::Helper.unpack(4, "\x15\xCD\x5b\x07")).to eq 123456789
|
7
|
-
end
|
8
|
-
it '64bit' do
|
9
|
-
expect(HeapInfo::Helper.unpack(8, "\xEF\xCD\xAB\xEF\xBE\xAD\xDE\x00")).to eq 0xdeadbeefabcdef
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'proc' do
|
14
|
-
expect { HeapInfo::Helper.exe_of 0 }.to raise_error ArgumentError
|
15
|
-
end
|
16
|
-
|
17
|
-
describe 'parse_maps' do
|
18
|
-
before(:all) do
|
19
|
-
@files_dir = File.expand_path('../files', __FILE__)
|
20
|
-
end
|
21
|
-
it '32bit' do
|
22
|
-
maps = IO.binread(@files_dir + '/32bit_maps')
|
23
|
-
expect(HeapInfo::Helper.parse_maps maps).to eq [
|
24
|
-
[0x8048000, 0x8049000, 'r-xp', '/home/heapinfo/examples/uaf/uaf'],
|
25
|
-
[0x8049000, 0x804a000, 'r--p', '/home/heapinfo/examples/uaf/uaf'],
|
26
|
-
[0x804a000, 0x804b000, 'rw-p', '/home/heapinfo/examples/uaf/uaf'],
|
27
|
-
[0xf73d7000, 0xf73f3000, 'r-xp', '/usr/lib32/libgcc_s.so.1'],
|
28
|
-
[0xf73f3000, 0xf73f4000, 'rw-p', '/usr/lib32/libgcc_s.so.1'],
|
29
|
-
[0xf73f4000, 0xf7438000, 'r-xp', '/lib32/libm-2.19.so'],
|
30
|
-
[0xf7438000, 0xf7439000, 'r--p', '/lib32/libm-2.19.so'],
|
31
|
-
[0xf7439000, 0xf743a000, 'rw-p', '/lib32/libm-2.19.so'],
|
32
|
-
[0xf743a000, 0xf75df000, 'r-xp', '/lib32/libc-2.19.so'],
|
33
|
-
[0xf75df000, 0xf75e1000, 'r--p', '/lib32/libc-2.19.so'],
|
34
|
-
[0xf75e1000, 0xf75e2000, 'rw-p', '/lib32/libc-2.19.so'],
|
35
|
-
[0xf75e5000, 0xf76c1000, 'r-xp', '/usr/lib32/libstdc++.so.6.0.19'],
|
36
|
-
[0xf76c1000, 0xf76c5000, 'r--p', '/usr/lib32/libstdc++.so.6.0.19'],
|
37
|
-
[0xf76c5000, 0xf76c6000, 'rw-p', '/usr/lib32/libstdc++.so.6.0.19'],
|
38
|
-
[0xf76dd000, 0xf76de000, 'r-xp', '[vdso]'],
|
39
|
-
[0xf76de000, 0xf76fe000, 'r-xp', '/lib32/ld-2.19.so'],
|
40
|
-
[0xf76fe000, 0xf76ff000, 'r--p', '/lib32/ld-2.19.so'],
|
41
|
-
[0xf76ff000, 0xf7700000, 'rw-p', '/lib32/ld-2.19.so'],
|
42
|
-
[0xffdd7000, 0xffdf8000, 'rw-p', '[stack]']]
|
43
|
-
end
|
44
|
-
it '64bit' do
|
45
|
-
maps = IO.binread(@files_dir + '/64bit_maps')
|
46
|
-
expect(HeapInfo::Helper.parse_maps maps).to eq [
|
47
|
-
[0x400000, 0x401000, 'r-xp', '/home/heapinfo/examples/uaf/uaf'],
|
48
|
-
[0x600000, 0x601000, 'r--p', '/home/heapinfo/examples/uaf/uaf'],
|
49
|
-
[0x601000, 0x602000, 'rw-p', '/home/heapinfo/examples/uaf/uaf'],
|
50
|
-
[0x7f65ac7b8000, 0x7f65ac7ce000, 'r-xp', '/lib/x86_64-linux-gnu/libgcc_s.so.1'],
|
51
|
-
[0x7f65ac7ce000, 0x7f65ac9cd000, '---p', '/lib/x86_64-linux-gnu/libgcc_s.so.1'],
|
52
|
-
[0x7f65ac9cd000, 0x7f65ac9ce000, 'rw-p', '/lib/x86_64-linux-gnu/libgcc_s.so.1'],
|
53
|
-
[0x7f65ac9ce000, 0x7f65acad3000, 'r-xp', '/lib/x86_64-linux-gnu/libm-2.19.so'],
|
54
|
-
[0x7f65acad3000, 0x7f65accd2000, '---p', '/lib/x86_64-linux-gnu/libm-2.19.so'],
|
55
|
-
[0x7f65accd2000, 0x7f65accd3000, 'r--p', '/lib/x86_64-linux-gnu/libm-2.19.so'],
|
56
|
-
[0x7f65accd3000, 0x7f65accd4000, 'rw-p', '/lib/x86_64-linux-gnu/libm-2.19.so'],
|
57
|
-
[0x7f65accd4000, 0x7f65ace8f000, 'r-xp', '/lib/x86_64-linux-gnu/libc-2.19.so'],
|
58
|
-
[0x7f65ace8f000, 0x7f65ad08e000, '---p', '/lib/x86_64-linux-gnu/libc-2.19.so'],
|
59
|
-
[0x7f65ad08e000, 0x7f65ad092000, 'r--p', '/lib/x86_64-linux-gnu/libc-2.19.so'],
|
60
|
-
[0x7f65ad092000, 0x7f65ad094000, 'rw-p', '/lib/x86_64-linux-gnu/libc-2.19.so'],
|
61
|
-
[0x7f65ad099000, 0x7f65ad17f000, 'r-xp', '/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19'],
|
62
|
-
[0x7f65ad17f000, 0x7f65ad37e000, '---p', '/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19'],
|
63
|
-
[0x7f65ad37e000, 0x7f65ad386000, 'r--p', '/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19'],
|
64
|
-
[0x7f65ad386000, 0x7f65ad388000, 'rw-p', '/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19'],
|
65
|
-
[0x7f65ad39d000, 0x7f65ad3c0000, 'r-xp', '/lib/x86_64-linux-gnu/ld-2.19.so'],
|
66
|
-
[0x7f65ad5bf000, 0x7f65ad5c0000, 'r--p', '/lib/x86_64-linux-gnu/ld-2.19.so'],
|
67
|
-
[0x7f65ad5c0000, 0x7f65ad5c1000, 'rw-p', '/lib/x86_64-linux-gnu/ld-2.19.so'],
|
68
|
-
[0x7fff3d1e8000, 0x7fff3d209000, 'rw-p', '[stack]'],
|
69
|
-
[0x7fff3d309000, 0x7fff3d30b000, 'r-xp', '[vdso]'],
|
70
|
-
[0xffffffffff600000, 0xffffffffff601000, 'r-xp', '[vsyscall]']]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/spec/libc_spec.rb
DELETED
@@ -1,75 +0,0 @@
|
|
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
|
-
|
53
|
-
it 'double free (fastop)' do
|
54
|
-
expect { @h.libc.free(@h.heap.base + 0x30) }.to raise_error "double free or corruption (fasttop)\ntop of fastbin[0x20]: 0x602020=0x602020"
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'success' do
|
58
|
-
expect(@h.libc.free(@h.heap.base + 0x10)).to be true
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe 'munmap' do
|
63
|
-
it 'success' do
|
64
|
-
mmap_addr = HeapInfo::Helper.unpack(8, @h.dump(:heap, 0x190, 8)) # backdoor of victim.cpp
|
65
|
-
expect(@h.libc.free(mmap_addr)).to be true
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe 'small' do
|
70
|
-
it 'success' do
|
71
|
-
expect(@h.libc.free(@h.heap.base + 0x280)).to be true
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|