zoukankan      html  css  js  c++  java
  • Python解析器源码加密系列之(一):标准c的tmpfile()、tmpfile_s()生成的临时文件究竟放在哪里了?

    这两天由于修改python解释器的需求,需要用到tmpfile()来生成临时文件的FILE*,但是又担心这个临时文件是否存在于磁盘的某个地方,终究会被人找到,所以就简单做了以下几点实验,看看是否可以找到tmpfile临时文件的路径。

    实验环境:Win7 + VS2010

    一、实验一:跟踪调试

    写了一小段简单的tmpfile调用,然后跟踪调试,在tmpfile_s内部也没能发现这个临时文件的路径,当然,通过stream->_tmpfname,可以看到一个临时文件的名称,但是看不到路径;根据这个名称到WINDOWSTEMP(或者C:UsersxxxAppDataLocalTemp)路径下去查找,也没有找到类似名称的文件。

    void TesttempfileFunc()
    {
        FILE *stream;
        char tempstring[] = "String to be written";
        // Create temporary files.
        for(int i = 1; i <= 3; i++ )
        {
            errno_t err = tmpfile_s(&stream);
            fwrite(tempstring, 1, strlen(tempstring), stream);
            if( err )
                perror( "Could not open new temporary file
    " );
            else
                printf( "Temporary file %d was created
    ", i );
        }
        // Remove temporary files.
        printf( "%d temporary files deleted
    ", _rmtmp() );
    }

    二、实验二,通过api提取FILE*的路径

    是否可以通过FILE*,然后通过某种API的调用,找到对应的文件名称,bing搜了一把,有一篇类似的文章(通过文件句柄获得文件路径http://www.bkjia.com/cjjc/498250.html),但是这里是通过HANDLE来获取文件路径,而我需要的是从FILE*获取文件路径,想到下午了解到有一个函数(_get_osfhandle)可以将FILE*转换为文件句柄,所以写了如下代码来验证:

    1)首先来尝试针对普通文件的FILE*来提取他的路径,提取成功,代码如下:

    BOOL GetFileNameFromHandle(HANDLE hFile)  
    {  
        TCHAR  pszFileName[MAX_PATH];  
        HANDLE hFileMap;  
        PVOID  pMem;  
    
        //获取文件大小  
        DWORD  dwFileSizeHigh = 0;  
        DWORD  dwFileSizeLow = 5;//GetFileSize(hFile, &dwFileSizeHigh);  
        if (dwFileSizeLow == 0 && dwFileSizeHigh == 0)  
        {  
            printf("不能map文件大小为0的文件.
    ");  
            return FALSE;  
        }  
    
        //创建Mapping对象  
        hFileMap = CreateFileMapping(hFile,  
            NULL,  
            PAGE_READONLY,  
            0,  
            1,  
            NULL);  
        if (!hFileMap)  
        {  
            printf("CreateFileMapping error: %d", GetLastError());  
            return FALSE;  
        }  
    
        pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);  
        if (!pMem)  
        {  
            printf("MapViewOfFile error: %d", GetLastError());  
            return FALSE;  
        }  
    
        //从Mapping对象获得文件名  
        if (0 == GetMappedFileName(GetCurrentProcess(),  
            pMem,  
            pszFileName,  //以设备名的形式获得文件路径,运行时设个断点查看即可  
            MAX_PATH))  
        {  
            printf("GetMappedFileName error: %d", GetLastError());  
            return FALSE;  
        }  
    
        TCHAR szTemp[MAX_PATH] = {0};  
        //获取电脑上的所有驱动器,如"C:"  "D:"等,连续放置的  
        if (0 == GetLogicalDriveStrings(BUFSIZE-1, szTemp))  
        {  
            printf("GetLogicalDriveStrings error: %d", GetLastError());  
            return FALSE;  
        }  
    
        TCHAR  szName[MAX_PATH];  
        TCHAR  szDrive[3] = {0};  
        BOOL   bFound = FALSE;  
        //通过指针p的移动来顺序访问所有的驱动器目录  
        TCHAR* p = szTemp;  
        do  
        {  
            CopyMemory(szDrive, p, 2*sizeof(TCHAR));   
            //通过路径查找设备名,如"C:"  
            if (!QueryDosDevice(szDrive, szName, BUFSIZE))  
            {  
                printf("QueryDosDrive error: %d", GetLastError());  
                return FALSE;  
            }  
            UINT uNameLen = lstrlen(szName);  
            if (uNameLen < MAX_PATH)  
            {  
                //比较驱动器的设备名文件名与文件设备名是否匹配  
                bFound = _tcsnccmp(pszFileName, szName, uNameLen) == 0;  
                if (bFound)  
                {  
                    //如果匹配,说明已找到,构造路径  
                    TCHAR szTempFile[MAX_PATH];  
                    wsprintf(szTempFile,  
                        TEXT("%s%s"),  
                        szDrive,  
                        pszFileName+uNameLen);  
                    lstrcpy(pszFileName, szTempFile);  
                }  
            }  
            //这里不理解的话可以去看看GetLogicalDriveStrings  
            while (*p++);  
        }while (!bFound && *p);  
    
        UnmapViewOfFile(pMem);  
        CloseHandle(hFileMap);     
        std::wcout<<_T("File Path is: ")<<pszFileName<<std::endl;
        //printf("File Path is %s
    ", pszFileName);      
        return TRUE;  
    }  
    
    void GetFileNameFromFILEPtr(FILE* pFile)
    {    
        HANDLE hFile = (HANDLE)_get_osfhandle(fileno(pFile));
        GetFileNameFromHandle(hFile);
    }
    
    void TestGetFilePathFromNormalFILEPtr()
    {
        FILE* fd = fopen("D:\TestMemMapFile.txt", "r");
        char c = fgetc(fd);
        GetFileNameFromFILEPtr(fd);
    }

    2)然后尝试对tmpfile生成的FILE* 提取文件路径,提取失败,因为这种临时文件在获取文件长度(GetFileSize)时就会失败,无法转换为内存映射文件,我怀疑可能是因为这个临时文件本来就不在磁盘上,所以去做映射的时候就失败了,相关代码如下:

    void TestGettempfilePath()
    {
        FILE *stream;
        char tempstring[] = "String to be written";
        errno_t err = tmpfile_s(&stream);        
        if( err )
        {
            perror( "Could not open new temporary file
    " );
            return;
        }
        else
            printf( "Temporary file was created
    ");
    
        fwrite(tempstring, 1, strlen(tempstring), stream);
        GetFileNameFromFILEPtr(stream);
        fclose(stream);
    }

    三、结论

    综上,tmpfile()、tmpfile_s()生成的临时文件没有放在磁盘上,或者是没有出现在文件系统中,或者至少是在一个非常隐蔽的地方,我暂时没有办法找到。

    有了这层保障,后续使用tmpfile的时候,就不用太担心泄密的问题了。

  • 相关阅读:
    node lesson2
    二级联动(list对象中存list对象)
    Spring的注解@Qualifier注解
    @Service(value = "aaaa") 和@Service( "a")的区别
    oracle分页
    Oracle数据导入导出imp/exp
    oracle截取某个字符前面的字符串
    oracle中截取某个字符前面和后面的值
    解决Eclipse启动报错Failed to create the Java Virtual Machine
    成功秘诀就是拿出勇气和坚定的信念去做自己喜欢并且擅长的事情
  • 原文地址:https://www.cnblogs.com/strinkbug/p/where_is_the_filepath_which_created_by_tmpfile_of_c.html
Copyright © 2011-2022 走看看