heapinfo 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|