< 32) usage += ctx.usage_by_class[sc + 1];// try to drop to a lower count if the one found above// increases usage by more than 25%. these reduced counts// roughly fill an integral number of pages, just not a// power of two, limiting amount of unusable space.if (4 * cnt > usage && !nosmall) {if (0);else if ((sc & 3) == 1 && size * cnt > 8 * pagesize)cnt = 2;else if ((sc & 3) == 2 && size * cnt > 4 * pagesize)cnt = 3;else if ((sc & 3) == 0 && size * cnt > 8 * pagesize)cnt = 3;else if ((sc & 3) == 0 && size * cnt > 2 * pagesize)cnt = 5;}size_t needed = size * cnt + UNIT;needed += -needed & (pagesize - 1);// produce an individually-mmapped allocation if usage is low,// bounce counter hasn't triggered, and either it saves memory// or it avoids eagar slot allocation without wasting too much.if (!nosmall && cnt <= 7) {req += IB + UNIT;req += -req & (pagesize - 1);if (req < size + UNIT || (req >= 4 * pagesize && 2 * cnt > usage)) {cnt = 1;needed = req;}}p = mmap(0, needed, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);if (p == MAP_FAILED) {free_meta(m);return 0;}m->maplen = needed >> 12;ctx.mmap_counter++;active_idx = (4096 - UNIT) / size - 1;if (active_idx > cnt - 1) active_idx = cnt - 1;if (active_idx < 0) active_idx = 0;}
如果所需内存不超过页大小的一半则在再申请一个所需大小的 chunk,然后在其中构造 group。与正常申请不同的是这里直接调用获取 chunk 的下标,不过和正常申请实际是一样的 。在申请的 chunk 的头部要打上标记(p[-3] = (p[-3] & 31) | (6< 48。之后调用函数触发。
uint32_t self = 1u << i;int sc = g->sizeclass;uint32_t mask = g->freed_mask | g->avail_mask;if (mask + self == (2u << g->last_idx) - 1 && okay_to_free(g)) {// any multi-slot group is necessarily on an active list// here, but single-slot groups might or might not be.if (g->next) {assert(sc < 48);int activate_new = (ctx.active[sc] == g);dequeue(&ctx.active[sc], g);if (activate_new && ctx.active[sc])activate_group(ctx.active[sc]);}return free_group(g);}
之后进入函数后为了减小伪造难度不再调用要保证不为零 。
static struct mapinfo free_group(struct meta *g) {struct mapinfo mi = {0};int sc = g->sizeclass;if (sc < 48) {ctx.usage_by_class[sc] -= g->last_idx + 1;}if (g->maplen) {step_seq();record_seq(sc);mi.base = g->mem;mi.len = g->maplen * 4096UL;} else {void *p = g->mem;struct meta *m = get_meta(p);int idx = get_slot_index(p);g->mem->meta = 0;// not checking size/reserved here; it's intentionally invalidmi = nontrivial_free(m, idx);}free_meta(g);return mi;}
poc 如下:
#include
- android 打包混淆,debug可以正常使用,混淆正式包就一点就崩
- 榆钱树怎么吃
- Chrome 调试工具【DevTools】详解
- vscode调试HTML的js文件
- 使用Instrument调试界面卡顿
- 客所思声卡调试 客所思声卡调试qq号
- 射频放大器-低噪声放大器
- hbuildX运行uniapp项目到andiord真机调试
- 微信公众号开发调试之内网穿透
- Vue的学习笔记二:万里长征第一步~Vue调试工具安装