IO_file attack

IO_FILE attack

IO_file struct 认识

FILE在linux的标准IO库中用于描述文件的结构,称为文件流。FILE结构在程序执行fopen等函数是才会创建,并将其分配到中。

我们通常定义一个指向FILE结构体的指针来接受这样一个返回值

FILE struct
struct _IO_FILE {
   
   
  int _flags;       /* 文件流的状态标志,包括控制、状态和错误信息等。高阶字包含魔数(_IO_MAGIC),其余字节包含其他标志。 */
#define _IO_file_flags _flags/*对 _flags 进行重命名,用于简化使用。*/

  /* 用于支持 C++ streambuf 协议的指针, */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* 表示当前读取位置、读取区域的结束和读取区域的起始位置。 */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* 用于支持备份和撤销的指针,表示非当前读取区域的起始位置、备份区域的起始位置和非当前读取区域的结束位置。 */

  struct _IO_marker *_markers;/*指向 _IO_marker 结构体的指针,用于支持标记操作。*/

  struct _IO_FILE *_chain;/*指向下一个文件流结构体的指针,用于构成一个链表。*/

  int _fileno;
#if 0
  int _blksize;
#else
  int _flags2;
#endif
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;/*虚函数表(vtable)的偏移量。*/
  char _shortbuf[1];/*一个字符的缓冲区,用于性能优化。*/

  /*  char* _save_gptr;  char* _save_egptr; */

  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
struct _IO_FILE_complete
{
   
   
  struct _IO_FILE _file;
#endif
#if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
  _IO_off64_t _offset;
# if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
  /* Wide character stream stuff.  */
  struct _IO_codecvt *_codecvt;
  struct _IO_wide_data *_wide_data;
  struct _IO_FILE *_freeres_list;
  void *_freeres_buf;
# else
  void *__pad1;
  void *__pad2;
  void *__pad3;
  void *__pad4;

  size_t __pad5;
  int _mode;
  /* Make sure we don't get into trouble again.  */
  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
#endif
};

如注释所说,对于进程中的FILE结构,他会通过_chain域彼此链接将所有的FILE结构体连接成一个链表,链表头部是全局变量 _IO_LIST_ALL表示,并且可以依靠该变量来遍历整个链表中的所有FILE结构

在标准I/O库中,在每个程序启动时会有三个文件流是自动打开的,分别是 stdin,stdout,stderr。所以一开始_IO_list_all会指向这样一个拥有这些文件流的链表, 但是,这里我们需要注意的是文件流位于libc.so的数据段,而我们通过fopen函数创建的文件流是分配在堆上面的

在libc文件中我们可以找到stdin,stdout,stderr以及_IO_2_1_stderr_ IO_2_1_stdout _IO_2_1_stdin这些符号,而他们之间有分别是指向关系,stdin -> _IO_2_1_stdin(这才是真正的结构file)

事实上_IO_FILE结构外围还包裹着一层 _IO_FILE_plus结构:

struct _IO_FILE_plus
{
   
   
    _IO_FILE    file;
    IO_jump_t   *vtable;
}
/*其中*vtable的偏移在libc.2.23下:32位:偏移为0x94;64位:偏移为0xd8*/

可以看到*vtable指针被定义为IO_jump_t类型,其中保存了一些函数指针,在后面我们会看到一些标准IO函数调用这里面的的一些函数指针。

void * funcs[] = {
   
   
   1 NULL, // "extra word"
   2 NULL, // DUMMY
   3 exit, // finish
   4 NULL, // overflow
   5 NULL, // underflow
   6 NULL, // uflow
   7 NULL, // pbackfail
   
   8 NULL, // xsputn  #printf
   9 NULL, // xsgetn
   10 NULL, // seekoff
   11 NULL, // seekpos
   12 NULL, // setbuf
   13 NULL, // sync
   14 NULL, // doallocate
   15 NULL, // read
   16 NULL, // write
   17 NULL,
<think>我们遇到了一个错误:在尝试导入`deeprobust.graph.defense_pyg`模块时,在`__init__.py`的第10行调用了`warnings.warn`,但是`warnings`模块没有被导入,导致出现了`NameError: name 'warnings' is not defined`。 根据您提供的代码片段,这个`__init__.py`文件中有以下结构: ```python try: from .gcn import GCN from .gat import GAT from .appnp import APPNP from .sage import SAGE from .gpr import GPRGNN from .airgnn import AirGNN import warnings except ImportError as e: print(e) warnings.warn("Please install pytorch geometric if you " + "would like to use the datasets from pytorch " + "geometric. See details in https://pytorch-geom" + "etric.readthedocs.io/en/latest/notes/installation.html") __all__ = ["GCN", "GAT", "APPNP", "SAGE", "GPRGNN", "AirGNN"] ``` 问题分析: 在`try`块中,我们尝试导入一些模块,其中包括`import warnings`。但是,如果在导入这些模块的过程中发生了`ImportError`(例如,某个模块不存在),那么就会跳转到`except`块中执行。而在`except`块中,我们使用了`warnings.warn`,但是此时`warnings`模块只有在`try`块中成功执行到`import warnings`时才会被导入。如果`try`块中的导入在`import warnings`之前就失败了(比如前面的某个模块导入失败),那么`warnings`模块就不会被导入,因此在`except`块中尝试使用`warnings`就会导致`NameError`。 具体来说,如果前面的某个模块(例如`.gcn`)导入失败,那么就会触发`ImportError`,然后进入`except`块。此时,由于`import warnings`位于`try`块中失败的那个导入之后,它还没有被执行,所以`warnings`模块没有被导入,因此调用`warnings.warn`就会出错。 解决方案: 需要确保在`except`块中使用的任何模块都必须在`try`块之前就被导入,或者确保即使在导入失败时也能使用。一种简单的方法是将`import warnings`移到`try`块之前(即模块的最顶部),这样无论`try`块中的导入是否成功,`warnings`模块都是可用的。 修改后的代码: ```python import warnings # 在try之前先导入warnings,确保在except块中可用 try: from .gcn import GCN from .gat import GAT from .appnp import APPNP from .sage import SAGE from .gpr import GPRGNN from .airgnn import AirGNN except ImportError as e: print(e) warnings.warn("Please install pytorch geometric if you " + "would like to use the datasets from pytorch " + "geometric. See details in https://pytorch-geom" + "etric.readthedocs.io/en/latest/notes/installation.html") __all__ = ["GCN", "GAT", "APPNP", "SAGE", "GPRGNN", "AirGNN"] ``` 这样,无论`try`块中的导入是否成功,`warnings`模块都已经导入了,因此在`except`块中调用`warnings.warn`就不会出现`NameError`。 您需要修改的文件路径是:`E:\Anaconda\envs\chris_ergcn\lib\site-packages\deeprobust\graph\defense_pyg\__init__.py` 按照上述修改后,重新运行程序,应该可以解决这个错误。 §§相关问题§§ 1. 在Python的try-except块中,为什么要注意导入语句的顺序? 2. 除了在try块之前导入模块,还有哪些方法可以避免在异常处理中出现NameError? 3. 在编写Python库时,如何处理依赖库未安装的情况,以提供友好的用户提示? 4. 在导入多个模块时,如何设计try-except结构以提高代码的健壮性? </think>### 错误分析与解决方案 您提供的错误信息表明,在`deeprobust/graph/defense_pyg/__init__.py`中存在一个关键问题:**`import warnings`被放置在`try`块内部错误的位置**。具体分析如下: ```python try: from .gcn import GCN from .gat import GAT # ...其他导入... import warnings # ✘ 错误位置 except ImportError as e: print(e) warnings.warn("警告信息") # 此时warnings可能未定义 ``` ### 错误原因: 1. 当`from .gcn import GCN`等前面的导入失败时,程序直接跳转到`except`块 2. 此时`import warnings`尚未执行(位于失败导入之后) 3. 在`except`块中使用`warnings.warn()`触发`NameError` ### 正确修改方案: 将`import warnings`移至`try`块**之前**,确保它在任何情况下都被优先导入: ```python import warnings # ✔ 正确位置 try: from .gcn import GCN from .gat import GAT from .appnp import APPNP from .sage import SAGE from .gpr import GPRGNN from .airgnn import AirGNN except ImportError as e: print(e) warnings.warn("Please install pytorch geometric...") __all__ = ["GCN", "GAT", "APPNP", "SAGE", "GPRGNN", "AirGNN"] ``` ### 操作步骤: 1. 打开文件:`deeprobust/graph/defense_pyg/__init__.py` 2. 将`import warnings`移动到文件最顶部(在`try`语句之前) 3. 删除原`try`块内的`import warnings` 4. 保存文件并重新运行程序 ### 额外建议: 检查PyTorch Geometric是否已安装: ```bash # 在Anaconda环境中执行 pip list | grep torch-geometric # 若未安装,使用以下命令 pip install torch-geometric -f https://data.pyg.org/whl/torch-1.13.0+cu117.html ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值