首页
社区
课程
招聘
[求助]Dll文件的code setcion (.text) 在pe文件中的数据和加载之后在进程空间的(.text数据)是一致的吗?
发表于: 2017-7-3 20:55 3193

[求助]Dll文件的code setcion (.text) 在pe文件中的数据和加载之后在进程空间的(.text数据)是一致的吗?

2017-7-3 20:55
3193

如题。 加密与解密第三版的里面可以通过这种方式校验PE文件代码段,但是发现对EXE有效, 对dll不生效。 求解。

写crc校验码:

/*******************************************************
 /*《加密与解密(第三版)》配套实例
 /*    14.3.3 内存映像校验
 /*  add2crc32.cpp -- 计算文件的CRC32值
/*    code by kanxue
/*(c)  看雪软件安全网站 www.pediy.com 2000-2008
********************************************************/
#include <windows.h>

int patch();
DWORD CRC32(BYTE*,DWORD);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
    
    patch();
    
    return 0;
}

//////////////////////////////////////////////////////////////////////



int patch()
{
    PIMAGE_DOS_HEADER        pDosHeader=NULL;
    PIMAGE_NT_HEADERS       pNtHeader=NULL;
    PIMAGE_SECTION_HEADER   pSecHeader=NULL;
    
    TCHAR szFileName[MAX_PATH ] ;
    DWORD szTemp;
    static OPENFILENAME ofn ;
    HANDLE hFile;    
    long FileSize;
    DWORD szCRC32;
    TCHAR  *pBuffer ;

    ZeroMemory(&ofn, sizeof(ofn));                             // 初始化OPENFILENAME结构

    static TCHAR szFilter[] =TEXT ("EXE Files (*.exe)\0*.exe\0") \
        TEXT ("All Files (*.*)\0*.*\0\0") ;
    
    szFileName[0] = '\0';                         
    ZeroMemory(&ofn, sizeof(ofn));                             // 初始化OPENFILENAME结构
    ofn.lStructSize       = sizeof (OPENFILENAME) ;
    ofn.lpstrFilter       = szFilter ;
    ofn.lpstrFile         = szFileName ;         
    ofn.nMaxFile          = MAX_PATH ;   
    ofn.nMaxFileTitle     = MAX_PATH ;
    ofn.Flags             = OFN_HIDEREADONLY | OFN_CREATEPROMPT ;           
    
    if(GetOpenFileName (&ofn))
    {
        
        hFile = CreateFile(
            szFileName,
            GENERIC_READ | GENERIC_WRITE, 
            FILE_SHARE_READ, 
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL);
        
        
        if( hFile != INVALID_HANDLE_VALUE )
        {
            FileSize=GetFileSize(hFile,&szTemp);  // 获取文件大小
            if (FileSize == 0xFFFFFFFF) return FALSE;
            pBuffer = new TCHAR [FileSize];     // 申请内存
            if(ReadFile(hFile, pBuffer, FileSize, &szTemp, NULL)==NULL) return FALSE;// 读取数据
            
        }
        else
        {
            MessageBox(NULL,"I can't access file!","CRC error",MB_ICONEXCLAMATION);
            return 0;
        }
        
    }
    else
        return 0;
    
    
    pDosHeader=(PIMAGE_DOS_HEADER)pBuffer;          
    pNtHeader=(PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHead-z>e_lfanew);
    pSecHeader=IMAGE_FIRST_SECTION(pNtHeader);   //得到第一个区块的起始地址  
    IMAGE_FILE_HEADER* pFileHeader =    &pNtHeader->FileHeader;
    for (int i = 0; i < pFileHeader->NumberOfSections;i++)
    {
        if((strcmp((char*)pSecHeader->Name,".text") == 0))
        {
            break;
        }
        pSecHeader++;
    }


    szCRC32=CRC32((BYTE*)(pBuffer+pSecHead-z>PointerToRawData),pSecHeader->Misc.VirtualSize);
    
    DWORD Writeadd=DWORD(pDosHeader->e_lfanew-4);//定位到PE文件头(即字串“PE\0\0”处)前4个字节处,准备在这写CRC-32值:
    SetFilePointer(hFile,Writeadd,NULL,FILE_BEGIN);//设置文件指针
    
    if(!WriteFile(hFile,&szCRC32,4,&szTemp,NULL))
    {
        MessageBox(NULL,"Error while patching !","Patch aborted",MB_ICONEXCLAMATION);
        CloseHandle(hFile);
        return 0;
    }
    
    
    delete pBuffer;  // 释放内存
    CloseHandle(hFile);    
    MessageBox(NULL,"Patch successfull !","Patch",MB_ICONINFORMATION);
    return 1;
    
}


////////////////////////////////////////////////////////////////
// 计算字符串的CRC32值
// 参数:欲计算CRC32值字符串的首地址和大小
// 返回值: 返回CRC32值

DWORD CRC32(BYTE* ptr,DWORD Size)
{
    
    DWORD crcTable[256],crcTmp1;
    
    //动态生成CRC-32表
    for (int i=0; i<256; i++)
    {
        crcTmp1 = i;
        for (int j=8; j>0; j--)
        {
            if (crcTmp1&1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;
            else crcTmp1 >>= 1;
        }
        
        crcTable[i] = crcTmp1;
    }
    //计算CRC32值
    DWORD crcTmp2= 0xFFFFFFFF;
    while(Size--)
    {
        crcTmp2 = ((crcTmp2>>8) & 0x00FFFFFF) ^ crcTable[ (crcTmp2^(*ptr)) & 0xFF ];
        ptr++;
    }
    
    return (crcTmp2^0xFFFFFFFF);
}

获取映像文件crc码,然后进行校验

/*******************************************************
 /*《加密与解密(第三版)》配套实例
 /*    14.3.3 内存映像校验
 /*   memcrc32.cpp -- 内存映像校验,仅校验代码区块
/*    code by kanxue
/*(c)  看雪软件安全网站 www.pediy.com 2000-2008
********************************************************/
#include <windows.h>

DWORD CRC32(BYTE*,DWORD);
BOOL CodeSectionCRC32( );
    


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
    HMODULE hmodule  = LoadLibraryA("Test.dll");
    if(CodeSectionCRC32())
        MessageBox(NULL,TEXT ("CRC32 Check OK!"),TEXT ("OK"),MB_ICONEXCLAMATION);
    else
            MessageBox(NULL,"File corrupted! !","CRC error",MB_ICONEXCLAMATION);
    return 0;
}

////////////////////////////////////////////////////////////////
// 计算代码区块的CRC32值
//

BOOL CodeSectionCRC32( )
{

    PIMAGE_DOS_HEADER        pDosHeader=NULL;
    PIMAGE_NT_HEADERS       pNtHeader=NULL;
    PIMAGE_SECTION_HEADER   pSecHeader=NULL;

    DWORD                    ImageBase,OriginalCRC32;

    ImageBase=(DWORD)GetModuleHandle("Test.dll");//取基址,其实本例也可直接用0x4000000这个值
    //ImageBase=(DWORD)GetModuleHandle(NULL);//取基址,其实本例也可直接用0x4000000这个值

     pDosHeader=(PIMAGE_DOS_HEADER)ImageBase;          
     pNtHeader=(PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHead-z>e_lfanew);
     //定位到PE文件头(即字串“PE\0\0”处)前4个字节处,并读出储存在这里的CRC-32值:
     OriginalCRC32 =*((DWORD *)((DWORD)pNtHeader-4));

     pSecHeader=IMAGE_FIRST_SECTION(pNtHeader);   //得到第一个区块的起始地址  
     IMAGE_FILE_HEADER* pFileHeader =    &pNtHeader->FileHeader;
     for (int i = 0; i < pFileHeader->NumberOfSections;i++)
     {
         if((strcmp((char*)pSecHeader->Name,".text") == 0))
         {
             break;
         }
         pSecHeader++;
     }
     //假设第一个区块就是代码区块
     //是从磁盘文件得到代码块的地址和大小来计算CRC32值
     if(OriginalCRC32==CRC32((BYTE*) (ImageBase+pSecHead-z>VirtualAddress),pSecHeader->Misc.VirtualSize)) 
        return TRUE;
    else
        return FALSE;


    //如果程序从磁盘文件获取第一区块的数据,加壳后,数据将可能不准确,因此对于要加壳的程序来说,
    //直接填上代码区块的地址和大小,方法是先随便填一数据,编译后用PE工具查看生成文件的代码区块的RVA和大小,
    //再填进来重新编译
    /*
    if(OriginalCRC32==CRC32((BYTE*) 0x401000,0x36AE)) 
        return TRUE;
    else
        return FALSE;
*/

}



////////////////////////////////////////////////////////////////
// 计算字符串的CRC32值
// 参数:欲计算CRC32值字符串的首地址和大小
// 返回值: 返回CRC32值

DWORD CRC32(BYTE* ptr,DWORD Size)
{

    DWORD crcTable[256],crcTmp1;
    
    //动态生成CRC-32表
    for (int i=0; i<256; i++)
     {
        crcTmp1 = i;
        for (int j=8; j>0; j--)
         {
            if (crcTmp1&1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;
             else crcTmp1 >>= 1;
        }

         crcTable[i] = crcTmp1;
     }
    //计算CRC32值
    DWORD crcTmp2= 0xFFFFFFFF;
    while(Size--)
    {
        crcTmp2 = ((crcTmp2>>8) & 0x00FFFFFF) ^ crcTable[ (crcTmp2^(*ptr)) & 0xFF ];
        ptr++;
    }
        
    return (crcTmp2^0xFFFFFFFF);
}


exe一样, dll不一样, 但是二者不都是pe文件吗? 难道还有隐藏的规则吗?


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 7354
活跃值: (4060)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
因为DLL有重定位
2017-7-3 23:37
0
雪    币: 689
活跃值: (422)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
3

szCRC32=CRC32((BYTE*)(pBuffer+pSecHead-z&gt;PointerToRawData),pSecHeader-&gt;Misc.VirtualSize);
很明显应该用RawSize而不是用VirtualSize


--------------------------------------------

我去,发完就反应过来写错了。。。。。

确实是因为重定位的关系,dll的重定位导致一些数据引用数值发生了改变

2017-7-4 08:16
0
雪    币: 230
活跃值: (137)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢
2017-7-5 22:55
0
游客
登录 | 注册 方可回帖
返回
//