DotNet程序的判断依据

前言

今天看到一个Demo,可以为DotNet程序生成调试用的ini.
这个资料在MSDN上有 : https://msdn.microsoft.com/en-us/library/9dd8z24x(v=vs.110).aspx
我好奇的是Demo如何判断指定程序是否为DotNet程序.
特意做了一个vc的测试程序,Demo判断这不是DotNet程序,看来不是为所有程序都生成ini, 而是真的判断了指定程序是否为DotNet程序…
好奇心来了,去偷偷的看看Demo怎么实现这个功能的:)

试验结论

看导入表中是否存在mscoree.dll(程序是否依赖mscoree.dll), 作为DotNet程序的判断依据

还原的工程

// hw.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stddef.h>
#include <Dbghelp.h>
#pragma comment(lib, "Dbghelp.lib")

#define TMP_FILE_NAME "myTmpFileForDirCommand.bin"
#define DOT_NET_PROG_DEPEND_DLL "mscoree.dll"

BOOL DotNetProgProc(const char* pcFilename);
BOOL IsDotNetProg(const char* pcFilename);
BOOL IsAppDependDll(const char* pcFilename, const char* pcDllname); // 程序是否依赖指定的Dll
void MakeIniFileForDotNetProgDebug(const char* pcFilename);

int main(int argc, char* argv[])
{
    int iProcCnt = 0; // 处理的DotNet程序数量
    int iTmp = 0;
    FILE* pFile = NULL;
    char szBuf[MAX_PATH] = {'\0'};
    sprintf(szBuf, "dir /aa /s /b > %s", TMP_FILE_NAME);
    system(szBuf);
    pFile = fopen(TMP_FILE_NAME, "r+"); // not rb+

    if (NULL != pFile) {
        ZeroMemory(szBuf, sizeof(szBuf));

        while (fgets(szBuf, sizeof(szBuf), pFile)) {
            iTmp = strlen(szBuf);

            // 文本中读进来的行尾有一个'\n'
            if ((iTmp > 0) && (szBuf[iTmp - 1] == '\n')) {
                szBuf[iTmp - 1] = '\0'; ///< ! 过滤掉 文件中传来的\n
            }

            if (DotNetProgProc(szBuf)) {
                printf("%s\r\n", szBuf);
                iProcCnt++;
            }

            ZeroMemory(szBuf, sizeof(szBuf));
        }

        fclose(pFile);
        DeleteFileA(TMP_FILE_NAME);
    }

    printf("process DotNet file numbers = %d\r\n", iProcCnt);
    system("pause");
    return 0;
    /** run result
    D:\test\testCSharp.exe
    process DotNet file numbers = 1
    请按任意键继续. . .
    */
}

BOOL DotNetProgProc(const char* pcFilename)
{
    BOOL bRc = FALSE;

    if (NULL != pcFilename) {
        if ((NULL != strstr(pcFilename, ".exe")) || (NULL != strstr(pcFilename, ".dll"))) {
            bRc = IsDotNetProg(pcFilename);

            if (bRc) {
                MakeIniFileForDotNetProgDebug(pcFilename);
            }
        }
    }

    return bRc;
}

BOOL IsDotNetProg(const char* pcFilename)
{
    // 看导入表中是否存在mscoree.dll(程序是否依赖mscoree.dll), 作为DotNet程序的判断依据
    return IsAppDependDll(pcFilename, DOT_NET_PROG_DEPEND_DLL);
}

BOOL IsAppDependDll(const char* pcFilename, const char* pcDllname)
{
    BOOL bRc = FALSE;
    int i = 0;
    HANDLE hMap = INVALID_HANDLE_VALUE;
    HANDLE hFile = INVALID_HANDLE_VALUE;
    char* pImportDllFileName = NULL;
    int iPos = 0;
    PIMAGE_NT_HEADERS NtHeaders = NULL;
    IMAGE_IMPORT_DESCRIPTOR importDescEmpty = {0}; // 空的引入表描述符
    IMAGE_IMPORT_DESCRIPTOR* pImportDescCur = NULL; // 当前的引入表描述符指针
    PVOID lpBaseAddress = NULL;
    DWORD dwVA = 0;
    DWORD dwRVA = 0;

    do {
        hFile = CreateFileA(pcFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

        if (INVALID_HANDLE_VALUE == hFile) {
            break;
        }

        hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);

        if (NULL == hMap) {
            break;
        }

        lpBaseAddress = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);

        if (NULL == lpBaseAddress) {
            break;
        }

        if (IMAGE_DOS_SIGNATURE != *(WORD*)lpBaseAddress) {
            break;
        }

        NtHeaders = (PIMAGE_NT_HEADERS)((int)lpBaseAddress
                                        + * ((DWORD*)((int)lpBaseAddress + offsetof(IMAGE_DOS_HEADER, e_lfanew))));
        dwRVA = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

        if ((0 == dwRVA) || (0xffffffff == dwRVA)) {
            break;
        }

        dwVA = (int)ImageRvaToVa(NtHeaders, lpBaseAddress, dwRVA, 0);

        for (i = 0; ; i++) {
            pImportDescCur = (IMAGE_IMPORT_DESCRIPTOR*)(dwVA + sizeof(IMAGE_IMPORT_DESCRIPTOR) * i);

            if (0 == memcmp(pImportDescCur, &importDescEmpty, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
                break;
            }

            pImportDllFileName = (char*)ImageRvaToVa(
                                     NtHeaders,
                                     lpBaseAddress,
                                     *(DWORD*)((int)pImportDescCur + offsetof(IMAGE_IMPORT_DESCRIPTOR, Name)),
                                     0);

            if (0 == _strcmpi(pImportDllFileName, pcDllname)) {
                bRc = TRUE;
                break;
            }
        }
    } while (0);

    if (lpBaseAddress) {
        UnmapViewOfFile(lpBaseAddress);
        lpBaseAddress = NULL;
    }

    if (hMap) {
        CloseHandle(hMap);
        hMap = NULL;
    }

    if (INVALID_HANDLE_VALUE != hFile) {
        CloseHandle(hFile);
        hFile = NULL;
    }

    return bRc;
}

void MakeIniFileForDotNetProgDebug(const char* pcFilename)
{
    char szBuf[MAX_PATH] = {'\0'};
    char* p = NULL;

    if (NULL != pcFilename) {
        strcpy(szBuf, pcFilename);
        p = strrchr(szBuf, '.');

        if (NULL != p) {
            strcpy(p + 1, "ini");
            WritePrivateProfileStringA(".NET Framework Debugging Control", "GenerateTrackingInfo", "1", szBuf);
            WritePrivateProfileStringA(".NET Framework Debugging Control", "AllowOptimize", "0", szBuf);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值