正文
在解析具体函数之前介绍一下
0)zend_parse_parameters函数 (GPT写的)
???? 函数原型
ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...);
参数说明:
|
|
num_args
|
PHP 调用时实际传入参数的数量,一般用
ZEND_NUM_ARGS()
|
type_spec
|
参数类型字符串,例如
"ll"
表示两个 long 类型
|
...
|
|
常见类型字符
|
|
|
l
|
|
zend_long
|
d
|
|
double
|
s
|
|
char *
|
b
|
|
zend_bool
|
z
|
|
zval *
|
a
|
|
zval *
|
o
|
|
zval *
|
|
|
|
1)zif_construct函数
还原结构体,大致如下
2)zif_allocate函数
3)zif_overwrite函数
同时汇编观察发现,zend_parse_parameters 函数的传入参数其实很多,修正一下。
这下对劲了。。
4)zif_clear函数
基本的需要利用的漏洞函数都已解析完毕。
注意到,本质是堆的UAF 任意地址写,同时overwrite函数没有检查init。
7. php源码 -> emalloc 和 efree 以及堆 大致粗略分析
从题目的docker容器中可以查找到对应的php版本
php --version
PHP 8.1.20 (cli) (built: Jun 13 2023 12:02:18) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.20, Copyright (c) Zend Technologies
下载它的源码
heap相关结构体
_zend_mm_heap
struct_zend_mm_heap {
#if ZEND_MM_CUSTOM
int use_custom_heap;
#endif
#if ZEND_MM_STORAGE
zend_mm_storage *storage;
#endif
#if ZEND_MM_STAT
size_t size;
size_t peak;
#endif
zend_mm_free_slot *free_slot[ZEND_MM_BINS];
#if ZEND_MM_STAT || ZEND_MM_LIMIT
size_t real_size;
#endif
#if ZEND_MM_STAT
size_t real_peak;
#endif
#if ZEND_MM_LIMIT
size_t limit;
int overflow;
#endif
zend_mm_huge_list *huge_list;
zend_mm_chunk *main_chunk;
zend_mm_chunk *cached_chunks;
int chunks_count;
int peak_chunks_count;
int cached_chunks_count;
double avg_chunks_count;
int last_chunks_delete_boundary;
int last_chunks_delete_count;
#if ZEND_MM_CUSTOM
union {
struct {
void *(*_malloc)(size_t);
void (*_free)(void*);
void *(*_realloc)(void*, size_t);
} std;
struct {
void *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
} debug;
} custom_heap;
HashTable *tracked_allocs;
#endif
};
_zend_mm_chunk
struct_zend_mm_chunk {
zend_mm_heap *heap;
zend_mm_chunk *next;
zend_mm_chunk *prev;
uint32_t free_pages;
uint32_t free_tail;
uint32_t num;
char reserve[64 - (sizeof(void*) * 3 + sizeof(uint32_t) * 3)];
zend_mm_heap heap_slot;
zend_mm_page_map free_map;
zend_mm_page_info map[ZEND_MM_PAGES];
};
注释写的还算比较好理解
emalloc
ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)