pwnable.tw-seethefile笔记

上次整理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读不了回车吗,真的不是很懂。。。。

4 thoughts on “pwnable.tw-seethefile笔记

    1. 但是程序中有这么一段
      if(buf[ret-1] == ‘\n’)
      buf[ret-1] = ‘\x00’;
      如果是正常情况的话是会把换行换成0x00的。
      (大概

YNkTP进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注