上次整理FILE结构体的时候还说以后有空再慢慢想利用吧,结果这么快就遇到一道利用FLIE结构体的题,收了自己的flag。
FILE结构体的一些信息可以看我之前的文不对题的文章浅析stdout。这道题的难点就在于伪造出一个合适的FILE结构体。
在调用fclose()的时候会调用IO_jump的_IO_close,这点其实比较能懂,但是如果我要传参的话应该怎么办呢?
最先开始想的是_IO_close可能调用的是利用系统调用open打开的一个类似句柄的东西,但是用gdb跟进去的时候发现不是这样,传的参数是FILE结构体所在的地址,这个地方伪造的话只需要把FILE结构体的前面几位写成’/bin/sh\x00’就行了,关键是后面的东西。
在调用_IO_close的前面几句汇编有一句mov eax,[ebx+4*eax+0x94]
0x94是FILE结构体的大小,eax是FILE结构体中一个叫offest的东西,这时候ebx储存的是FILE结构体的地址,所以FILE结构体寻找调用表的时候是通过基址+0x94+偏移来寻找的,所以伪造FILE的时候也应该注意一下offest的值,有条件的话尽量搞成0,方便计算偏移。
在伪造的时候也需要注意其他的成员,我在构造的时候不知道为啥检查了struct _IO_marker *_markers这个成员,需要这个地方指向一个可读内存区域,然而我自己写程序调试的时候这个变量为0,不知道是不是和flag有些关系,不过改了之后能过,也就不想深究了。
最后还有一点,拿到shell之后发现并不能直接cat flag,而需要通过运行get_flag这个程序来获取flag,这个程序长这样:
#include <unistd.h>
#include <stdio.h>
int read_input(char *buf,unsigned int size){
int ret ;
ret = read(0,buf,size);
if(ret <= 0)
{
puts("read error");
exit(1);
}
if(buf[ret-1] == '\n')
buf[ret-1] = '\x00';
return ret ;
}
int main(){
char buf[100];
setvbuf(stdin,0,2,0);
setvbuf(stdout,0,2,0);
printf("Your magic :");
read_input(buf,40);
if(strcmp(buf,"Give me the flag")){
puts("GG !");
return 1;
}
FILE *fp = fopen("/home/seethefile/flag","r");
if(!fp){
puts("Open failed !");
}
fread(buf,1,40,fp);
printf("Here is your flag: %s \n",buf);
fclose(fp);
}
我一想:这tm不是很简单吗,直接输入Give me the flag就完事,结果一直出GG !让我有点怀疑人生,后来我用了一下:
p.sendline(‘Give me the flag\x00’)
结果就过了,这又是什么原理,难道shell读不了回车吗,真的不是很懂。。。。
想要大佬网页模版,吸口水中,啊
页面最下面有这个主题的广告2333
你shell输入的时候没有\x00结束符。。。
但是程序中有这么一段
if(buf[ret-1] == ‘\n’)
buf[ret-1] = ‘\x00’;
如果是正常情况的话是会把换行换成0x00的。
(大概