• 逆向 stdio.h 函数库 fseek 函数(调试版本)


    0x01 fseek 函数

    • 函数原型int fseek(FILE *stream, long int offset, int whence)
    • 函数功能:设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数
    • 动态链接库ucrtbased.dll
    • CC++ 实现
    #define _CRT_SECURE_NO_WARNINGS // 抛弃安全警告
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    	FILE* fp;
    
    	fp = fopen("D:\1.txt", "w+");
    	fputs("This is runoob.com", fp);
    
    	fseek(fp, 7, SEEK_SET);
    	fputs(" C Programming Langauge", fp);
    	fclose(fp);
    
    	return(0);
    }
    
    • 上述程序的功能主要是打开 D:1.txt 文件,之后调整文件流的偏移,最后关闭文件
    • 调试工具:x32dbg 调试器
    • 逆向分析:首先利用定位字符串的方式找到 fseek 函数
      在这里插入图片描述
    • fseek(一级函数)中调用了两个子函数:ucrtbased.sub_625FF510 负责将传入的参数一(文件句柄)赋值到局部变量 [ebp-4] 中,之后压入文件句柄调用 ucrtbased.sub_6261C940
      在这里插入图片描述
    • ucrtbased.sub_6261C940(二级函数)函数内部首先判断传入的第一个参数(文件句柄)是否存在,不存在的话就调用 _CrtDbgReportW_error 进行错误处理
      在这里插入图片描述
    • 之后判断传入的第四个参数(SEEK_SET)是否为 0、1、2 中的一个
      在这里插入图片描述
    SEEK_SET: 文件开头 0
    SEEK_CUR: 当前位置 1
    SEEK_END: 文件结尾 2
    
    • 然后调用 ucrtbased.sub_ 625EC550 获取文件句柄,文件句柄的类型为 FILE。紧接着调用 _lock_file 锁住文件。既然锁住了文件,那么肯定要解锁文件,如图所示:解锁文件的函数 _unlock_file 在结尾处调用
      在这里插入图片描述
    • 最后压入参数调用 ucrtbased.sub_6261CCE0(三级函数),参数如下图注释所示
      在这里插入图片描述
    • 进入 ucrtbased.sub_6261CCE0(三级函数) 函数单步调试:首先会调用 ucrtbased.sub_62616B10ucrtbased.sub_626168F0_flag 进行判断
      在这里插入图片描述
    • 注:_flag_iobuf 结构体的成员,而 FILE 结构体指针指向的原型就是 _iobuf。结构体示意图如下图所示:
      在这里插入图片描述
    • ucrtbased.sub_62616B10:判断(_flag & 2000)是否大于 0,若等于 0,则函数直接返回。因为查阅不到 _flag 成员的有关资料,所以暂时不知道这一步操作是什么目的
      在这里插入图片描述
    • ucrtbased.sub_626168F0 判断方式:先循环比较 _flag(_flag & FFFFFFF7) 是否相等,然后比较 _flag & 8 是否等于 0 。这里有两个 bug,假如 _flag204e 的话,就变成死循环了。而且通过观察 ucrtbased.sub_626168F0 的返回值,发现没有对返回值做任何处理,也就是说这个判断 _flag 的函数没有任何作用
      在这里插入图片描述
    • 然后压入 4 个参数后,调用 ucrtbased.sub_6261CB00(四级函数)
      在这里插入图片描述
    • 进入 ucrtbased.sub_6261CB00(四级函数)函数进行分析:首先这个函数判断传入的第四个参数(SEEK_SET)是否为指向文件结尾,如果指向文件结尾此函数返回 0,之后调用 ucrtbased.sub_62615130ucrtbased.sub_62615150 对 _flag 进行判断
      在这里插入图片描述
    • ucrtbased.sub_62615130 的判断方式:(_flag & 4c0) 是否等于 0,若不等于 0,返回 1
      在这里插入图片描述
    • ucrtbased.sub_62615150 的判断方式:在 (_flag & 4c0) 是不等于 0 的前提下判断 (_flag & 6) 是否等于 0,若不等于 0,返回 1
      在这里插入图片描述
    • ucrtbased.sub_62615150 判断完成之后直接清空 eaxucrtbased.sub_6261CB00(四级函数)返回
      在这里插入图片描述
    • 返回之后判断传入的第四个参数(SEEK_SET)是否为当前文件位置,由于不是当前文件位置,故发生了跳转
      在这里插入图片描述
    • 之后调用 ucrtbased.sub_625EC550 获取文件句柄,把文件句柄做为参数压入,接着调用 ucrtbased.sub_62619070
      在这里插入图片描述
    • ucrtbased.sub_62619070(四级函数) 这个函数主要是对 _iobuf->cnt_iobuf->*_ptr 进行操作,进入这个函数看看:首先会调用 ucrtbased.sub_625FF510 将文件句柄赋值到局部变量 [ebp-4] 当中,接着调用 ucrtbased.sub_62615070 将取出 _iobuf->_flag 取出
      在这里插入图片描述
    • 注:ucrtbased.sub_62619010 是对 _iobuf->_flag 进行判断
      在这里插入图片描述
    • 判断方式:
    	if((_flag & 3 == 2) && (_flag & C0 == 0))
    	{
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    
    • 判断完成之后,将 _iobuf->*_ptr - _iobuf->_cnt
      在这里插入图片描述
    • 接着调用 ucrtbased.sub_62618EA0,该函数的主要功能:_iobuf->*ptr = iobuf->cnt,并将 _iobuf->*_base 赋值为 0
      在这里插入图片描述
    • 之后在 _iobuf->*ptr - _iobuf->_cnt 大于 0 的前提下调用 _fileno_write 函数
      在这里插入图片描述
    • 之后再判断写入的字节和_iobuf->*ptr - _iobuf->_cnt 相等的前提下调用 ucrtbased.sub_62618FA0,该函数的主要功能就是判断 _iobuf->_flag & 44 是否相等,eax 返回 1 表示相等
      在这里插入图片描述
      在这里插入图片描述
    • 最后调用 ucrtbased.sub_62618FA0 判断 _flag & 8 是否等于 0ucrtbased.sub_62619070(四级函数)返回 0
    • 接着向下调试,发现会将 _iobuf->*ptr 赋值为 iobuf->cnt_iobuf->*_base 设置为 0,并且判断 _iobuf->flag & 44 是否相等, 再相等的前提下判断 _flag & 8 是否为 0
      在这里插入图片描述
    • 最后调用 ucrtbased.sub_62619070(四级函数)
      在这里插入图片描述
    • 进入这个函数看看:首先会使用 _get_osfhandle 检索与指定文件描述符关联的操作系统文件句柄,如果函数调用失败则进入错误处理
      在这里插入图片描述
    • 之后调用 ucrtbased.sub_62619070
      在这里插入图片描述
    • 这个函数的功能是利用 SetFilePointerEx 函数移动指定文件的文件指针,并配合 GetLastError 函数进行错误处理 在这里插入图片描述
    • 接着将返回值放入局部变量中
      在这里插入图片描述
    • 最后返回
      在这里插入图片描述
      在这里插入图片描述
    • ucrtbased.sub_6261ccE0 的结尾对这两个返回值进行比较,如图所示跳转实现,故返回值为 0
      在这里插入图片描述
    • 最后使用 _unlock_file 对文件进行解锁,fseek 函数调用结束
      在这里插入图片描述

    逆向 stdio.h 库的 fseek 函数到此结束,如有错误,欢迎指正

  • 相关阅读:
    串口数据字节位的理解
    【转】arm-none-linux-gnueabi-gcc下载
    【转】网络排错全面详解
    【转】VMware虚拟机三种网络模式详解
    【转】vi编辑只读文档无法保存的解决办法
    【转】关于在linux下清屏的几种技巧
    【转】64位Ubuntu 16.04搭建嵌入式交叉编译环境arm-linux-gcc过程图解
    ELF文件
    UCOSII内核代码分析
    vmware安装win7提示No CD-ROM drive to use:GCDROM not loaded
  • 原文地址:https://www.cnblogs.com/csnd/p/11800500.html
Copyright © 2020-2023  润新知