Python解析器源碼加密系列之(一):標准c的tmpfile()、tmpfile_s()生成的臨時文件究竟放在哪里了?


這兩天由於修改python解釋器的需求,需要用到tmpfile()來生成臨時文件的FILE*,但是又擔心這個臨時文件是否存在於磁盤的某個地方,終究會被人找到,所以就簡單做了以下幾點實驗,看看是否可以找到tmpfile臨時文件的路徑。

實驗環境:Win7 + VS2010

 

一、實驗一:跟蹤調試

寫了一小段簡單的tmpfile調用,然后跟蹤調試,在tmpfile_s內部也沒能發現這個臨時文件的路徑,當然,通過stream->_tmpfname,可以看到一個臨時文件的名稱,但是看不到路徑;根據這個名稱到WINDOWS\TEMP(或者C:\Users\xxx\AppData\Local\Temp)路徑下去查找,也沒有找到類似名稱的文件。

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\n" );
        else
            printf( "Temporary file %d was created\n", i );
    }
    // Remove temporary files.
    printf( "%d temporary files deleted\n", _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的文件.\n");  
        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\n", 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\n" );
        return;
    }
    else
        printf( "Temporary file was created\n");

    fwrite(tempstring, 1, strlen(tempstring), stream);
    GetFileNameFromFILEPtr(stream);
    fclose(stream);
}

三、結論

綜上,tmpfile()、tmpfile_s()生成的臨時文件沒有放在磁盤上,或者是沒有出現在文件系統中,或者至少是在一個非常隱蔽的地方,我暫時沒有辦法找到。

有了這層保障,后續使用tmpfile的時候,就不用太擔心泄密的問題了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM