如果对glibc内存管理的逻辑比较了解,在学习各种堆漏洞利用的方法时,就会更顺畅一些,而且glibc内存管理的代码,本身也很值得看一看,好几次决定写点总结,都是咬咬牙又放弃了,现在,我觉得已经不能再拖了。
在刚入门C语言编程时就知道:为了使用一块堆内存,要先分配。随着接触编程一段时间后,慢慢开始意识到:分配,就是底层代码把正在使用的内存区域记录下来,从而保证程序始终知道哪些空间是正在使用的,哪些空间当前是空闲的,进一步保证每次获取的内存,不会与正在使用的内存重叠。
刚才已经说了,CPU的权限是支持调节的,最高权限时,可以执行所有指令,包括将权限调低,但低权限向高权限调节,就需要接受额外的条件(否则权限如果可以随意调高,那么权限设计的意义就没了),那就是必须穿过“门”进行提升,而在穿过“门”的同时,也要求执行一次代码跳转(这种要求,以及“门”的设计,也是硬件层实现的),而内核代码是在CPU刚上电时就开始执行了,相比用户程序,内核具有设置这个跳转地址的先机,所以当然会将其设置为内核代码的地址。这样,内核代码就总能在最高权限执行,而用户代码总是在低权限执行,同时又有路径从用户态(低CPU权限下执行用户代码的状态)回到内核态(最高CPU权限下执行内核代码的状态)。很多特权指令,只在CPU高权限状态时有效,比如CR3寄存器的读/写指令,从而“强制”用户程序使用内核接口,对进程本身的虚拟空间和占用的物理内存,进行管理。
这块内容是参考《Glibc内存管理--Ptmalloc2源代码分析.pdf》学习的,这份pdf文件总共129页,分析过程非常详细、深刻,为了防止遗忘,我整理了一个主要过程出来,并且为有些部分添加了配图和个人的理解。
《Glibc内存管理--ptmalloc2源代码分析》博客系列:https://www.iteye.com/blog/user/mqzhuang
/
/
32
位系统
*
(char
*
)
0x9d08008
=
0
;
/
/
32
位系统
*
(char
*
)
0x9d08008
=
0
;
jmpcall@ubuntu:test$ .
/
a.out
Segmentation fault
jmpcall@ubuntu:test$ .
/
a.out
Segmentation fault
int
main()
{
80483c3
:
55
push
%
ebp
80483c4
:
89
e5 mov
%
esp,
%
ebp
*
(char
*
)
0x9d08008
=
0
;
80483c6
: b8
08
80
d0
09
mov $
0x9d08008
,
%
eax
80483cb
: c6
00
00
movb $
0x0
,(
%
eax)
return
0
;
80483ce
: b8
00
00
00
00
mov $
0x0
,
%
eax
}
int
main()
{
80483c3
:
55
push
%
ebp
80483c4
:
89
e5 mov
%
esp,
%
ebp
*
(char
*
)
0x9d08008
=
0
;
80483c6
: b8
08
80
d0
09
mov $
0x9d08008
,
%
eax
80483cb
: c6
00
00
movb $
0x0
,(
%
eax)
return
0
;
80483ce
: b8
00
00
00
00
mov $
0x0
,
%
eax
}
struct malloc_state {
/
*
Serialize access.
*
/
mutex_t mutex;
/
*
Flags (formerly
in
max_fast).
*
/
int
flags;
/
*
Statistics
for
locking. Only used
if
THREAD_STATS
is
defined.
*
/
long
stat_lock_direct, stat_lock_loop, stat_lock_wait;
/
*
Fastbins
*
/
mfastbinptr fastbinsY[NFASTBINS];
/
*
Base of the topmost chunk
-
-
not
otherwise kept
in
a
bin
*
/
mchunkptr top;
/
*
The remainder
from
the most recent split of a small request
*
/
mchunkptr last_remainder;
/
*
Normal bins packed as described above
*
/
mchunkptr bins[NBINS
*
2
-
2
];
/
*
Bitmap of bins
*
/
unsigned
int
binmap[BINMAPSIZE];
/
*
Linked
list
*
/
struct malloc_state
*
next
;
/
*
Linked
list
for
free arenas.
*
/
struct malloc_state
*
next_free;
/
*
Memory allocated
from
the system
in
this arena.
*
/
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};
struct malloc_state {
/
*
Serialize access.
*
/
mutex_t mutex;
/
*
Flags (formerly
in
max_fast).
*
/
int
flags;
/
*
Statistics
for
locking. Only used
if
THREAD_STATS
is
defined.
*
/
long
stat_lock_direct, stat_lock_loop, stat_lock_wait;
/
*
Fastbins
*
/
mfastbinptr fastbinsY[NFASTBINS];
/
*
Base of the topmost chunk
-
-
not
otherwise kept
in
a
bin
*
/
mchunkptr top;
/
*
The remainder
from
the most recent split of a small request
*
/
mchunkptr last_remainder;
/
*
Normal bins packed as described above
*
/
mchunkptr bins[NBINS
*
2
-
2
];
/
*
Bitmap of bins
*
/
unsigned
int
binmap[BINMAPSIZE];
/
*
Linked
list
*
/
struct malloc_state
*
next
;
/
*
Linked
list
for
free arenas.
*
/
struct malloc_state
*
next_free;
/
*
Memory allocated
from
the system
in
this arena.
*
/
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};
typedef struct _heap_info {
mstate ar_ptr;
/
*
Arena
for
this heap.
*
/
struct _heap_info
*
prev;
/
*
Previous heap.
*
/
size_t size;
/
*
Current size
in
bytes.
*
/
size_t mprotect_size;
/
*
Size
in
bytes that has been mprotected
PROT_READ|PROT_WRITE.
*
/
/
*
Make sure the following data
is
properly aligned, particularly
that sizeof (heap_info)
+
2
*
SIZE_SZ
is
a multiple of
MALLOC_ALIGNMENT.
*
/
char pad[
-
6
*
SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
typedef struct _heap_info {
mstate ar_ptr;
/
*
Arena
for
this heap.
*
/
struct _heap_info
*
prev;
/
*
Previous heap.
*
/
size_t size;
/
*
Current size
in
bytes.
*
/
size_t mprotect_size;
/
*
Size
in
bytes that has been mprotected
PROT_READ|PROT_WRITE.
*
/
/
*
Make sure the following data
is
properly aligned, particularly
that sizeof (heap_info)
+
2
*
SIZE_SZ
is
a multiple of
MALLOC_ALIGNMENT.
*
/
char pad[
-
6
*
SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
struct malloc_chunk {
INTERNAL_SIZE_T prev_size;
/
*
Size of previous chunk (
if
free).
*
/
INTERNAL_SIZE_T size;
/
*
Size
in
bytes, including overhead.
*
/
struct malloc_chunk
*
fd;
/
*
double links
-
-
used only
if
free.
*
/
struct malloc_chunk
*
bk;
/
*
Only used
for
large blocks: pointer to
next
larger size.
*
/
struct malloc_chunk
*
fd_nextsize;
/
*
double links
-
-
used only
if
free.
*
/
struct malloc_chunk
*
bk_nextsize;
};
struct malloc_chunk {
INTERNAL_SIZE_T prev_size;
/
*
Size of previous chunk (
if
free).
*
/
INTERNAL_SIZE_T size;
/
*
Size
in
bytes, including overhead.
*
/
struct malloc_chunk
*
fd;
/
*
double links
-
-
used only
if
free.
*
/
struct malloc_chunk
*
bk;
/
*
Only used
for
large blocks: pointer to
next
larger size.
*
/
struct malloc_chunk
*
fd_nextsize;
/
*
double links
-
-
used only
if
free.
*
/
struct malloc_chunk
*
bk_nextsize;
};
(((((unsigned
long
)(sz)) >>
6
) <
=
38
)?
56
+
(((unsigned
long
)(sz)) >>
6
): \
((((unsigned
long
)(sz)) >>
9
) <
=
20
)?
91
+
(((unsigned
long
)(sz)) >>
9
): \
((((unsigned
long
)(sz)) >>
12
) <
=
10
)?
110
+
(((unsigned
long
)(sz)) >>
12
): \
((((unsigned
long
)(sz)) >>
15
) <
=
4
)?
119
+
(((unsigned
long
)(sz)) >>
15
): \
((((unsigned
long
)(sz)) >>
18
) <
=
2
)?
124
+
(((unsigned
long
)(sz)) >>
18
): \
126
)
(((((unsigned
long
)(sz)) >>
6
) <
=
38
)?
56
+
(((unsigned
long
)(sz)) >>
6
): \
((((unsigned
long
)(sz)) >>
9
) <
=
20
)?
91
+
(((unsigned
long
)(sz)) >>
9
): \
((((unsigned
long
)(sz)) >>
12
) <
=
10
)?
110
+
(((unsigned
long
)(sz)) >>
12
): \
((((unsigned
long
)(sz)) >>
15
) <
=
4
)?
119
+
(((unsigned
long
)(sz)) >>
15
): \
((((unsigned
long
)(sz)) >>
18
) <
=
2
)?
124
+
(((unsigned
long
)(sz)) >>
18
): \
126
)
1
2
|
/ / 32 位系统
* (char * ) 0x9d08008 = 0 ;
|
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!