这个题目有问题,但是重要的是利用思想:可以把源码贴出来帮助理解:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
char buf[128]; /*值得注意的是这几个全局变量在bss段是紧挨着排列的*/
char *ptr[8];
char *cmd; //fake_chunk要把这个包含进去,这样的话就可以利用fgets实现任意地址写入
int size;
int n = 0;
void sh(char *c)
{
system(c);
}
int main()
{
setvbuf(stdout,0,_IONBF,0);
memset(ptr,0,sizeof(ptr));
cmd = buf;
while(1)
{
fgets(cmd,sizeof(buf),stdin);
if(!strncmp(cmd,"push",4)) //strncmp意思是只比较前4个
{
if(n<8)
{
scanf("%d%*c",&size); //这里可以写入size 进而伪造next_chunk_size
ptr[n] = malloc(size);
fgets(ptr[n],size,stdin);
n++;
}
else
{
puts("stack is full");
}
}
else if(!strncmp(cmd,"pop",3))
{
if(n>=0)
{
n--;
puts(ptr[n]);
free(ptr[n]);
ptr[n] = 0;
}
else
{
puts("stack is empty");
}
}
else{
puts("unkonwn command");
}
}
}
file得知是64位动态链接程序,那么看看ida分析 (push指针共有8个,图里面写错了)
那么我们的第一步就是伪造chunk ,这一点需要注意的就是地址要16位对齐,否则free的时候无法绕过检查,我们可以把size写入为next_chunk_size来躲过检查,然后把伪造的chunk free掉,然后就是malloc写入把cmd给溢出指向fgets@got,然后fgets把strncmp@got给覆盖了(因为下一个执行的就是strncmp,然后fgets@got的最后2个byte地方可以放参数/bin/sh,其它的可以用00填充 ),下次调用就直接getshell