首页
社区
课程
招聘
[原创]PEedit
发表于: 2013-12-2 21:32 7712

[原创]PEedit

2013-12-2 21:32
7712

PEedit总结
                                                                               ——千里之行,始于足下

1.引言
        1.1编写目的                                       
               该工具模仿LoadPE,目的是通过做项目来了解PE结构。
        1.2背景
               说明:
               a.项目名称:PEedit
               b.任务提出者:A1pass,编写者:GhostDL
        1.3 开发工具
               VS2012 Update3、OllDbg
        1.4 参考资料
               a.LordPE结构说明
               b.《黑客免杀攻防》
               c.《Windows PE权威指南》
               d.网上相关资料
2.实际开发结果
        2.1产品结构图
        
       2.2版本
               当前版本为Bate1.0版
       2.3主要功能
               a.查看及编辑PE基本信息
               b.查看及编辑目录表结构信息
               c.查看区段基本信息
               d.查看输入表、输出表、资源表及重定位表信息
               e.可用16Edit定位编辑
               f.加密伪装壳
       2.4性能
               性能比较稳定,能够接受压力测试,可以抵御变态的PE文件
       2.5进度
               进度比较慢,以后慢慢完善。
3.开发
      3.1程序文件列表
      
      3.2相关代码
             a.工具函数类

/******************************************************************/
/* 函数功能:多字节转宽字节,使用后需要delete                         */
/* 参数: 多字节                                                    */
/* 返回值:WCHAR*                                                   */
/*******************************************************************/
WCHAR*  MultiByte2WideChar(CHAR* multiChar)
{
    DWORD dwNum = MultiByteToWideChar(CP_ACP,0,multiChar,-1,NULL,0);
    WCHAR  *wideChar = new WCHAR[dwNum];
    MultiByteToWideChar (CP_ACP, 0, multiChar, -1, wideChar, dwNum);
    return wideChar;
}
 
/*******************************************************************/
/* 函数功能:宽字节转多字节,使用后需要delete                        */
/* 参数: 多字节                                                    */
/* 返回值:CHAR*                                                    */
/*******************************************************************/
CHAR* WideChar2MultiByte(WCHAR *wcChar )
{
    //宽字节转换多字节
DWORD dwNum =     WideCharToMultiByte(CP_OEMCP,NULL,wcChar,-1,NULL,0,NULL,FALSE);
    char *psText;
    psText = new char[dwNum];
    WideCharToMultiByte (CP_OEMCP,NULL,wcChar,-1,psText,dwNum,NULL,FALSE);
    return psText;
}
 
 
/*******************************************************************/
/* 函数功能:判断是否为PE文件                                       */
/* 参数:lpImage文件映像基址、文件大小                               */
/* 返回值:TURE或FALSE                                              */
/*******************************************************************/
BOOL IsPE_File(PVOID lpImage)
{
    PIMAGE_DOS_HEADER pDos  = (PIMAGE_DOS_HEADER)lpImage;
    if ( pDos->e_magic != IMAGE_DOS_SIGNATURE )
        return FALSE;
 
    PIMAGE_NT_HEADERS32 pNT32 = (PIMAGE_NT_HEADERS32)((LONG)lpImage+pDos->e_lfanew);
    if ( pNT32->Signature != IMAGE_NT_SIGNATURE )
        return FALSE;
 
    return TRUE;
} 
 
 
 
 
 
/*******************************************************************/
/* 函数功能:获取真正内存地址                                       */
/* 参数:RVA相对虚地址、装入内存基址、PE文件头                      */
/* 返回值:真正内存地址                                             */
/*******************************************************************/
DWORD RVA2Offset( DWORD dwRVA, PVOID lpImage, PIMAGE_NT_HEADERS32 pNT32 )
{
    PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT32);
    for ( DWORD i=0; i<pNT32->FileHeader.NumberOfSections; i++ )
    {
        if ( dwRVA>=pSection[i].VirtualAddress && dwRVA<pSection[i].VirtualAddress+pSection[i].Misc.VirtualSize )
        {
            DWORD dwR_Offset = dwRVA - pSection[i].VirtualAddress;
            DWORD dwOffset   =(DWORD)lpImage+ dwR_Offset+ pSection[i].PointerToRawData;
            return dwOffset;
        }
    }
    return 0;
}
 
 
/*******************************************************************/
/* 函数功能:判断在哪个区段                                         */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:所在区段的RVA                                            */
/*******************************************************************/
DWORD GetRvaInWhitchSection( DWORD dwRVA,PVOID lpImage,PIMAGE_NT_HEADERS32 pNT32)
{
    PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT32);
    for (DWORD i=0; i<pNT32->FileHeader.NumberOfSections; i++)
    {
        if (dwRVA>=pSection[i].VirtualAddress && dwRVA<pSection[i].VirtualAddress+pSection[i].Misc.VirtualSize)
        {
            return (DWORD)&pSection[i];
        }
    }
    return 0;
}
 
 
 
 
 
/*******************************************************************/
/* 函数功能:获取PIMAGE_NT_HEADERS32                                */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:PIMAGE_NT_HEADERS32                                      */
/*******************************************************************/
PIMAGE_NT_HEADERS  GetNtHeaders(LPVOID lpImage)
{
    PIMAGE_DOS_HEADER   pDos  = (PIMAGE_DOS_HEADER)lpImage;
    PIMAGE_NT_HEADERS32 pNT32 = (PIMAGE_NT_HEADERS32)((LONG)lpImage+pDos->e_lfanew);
    return pNT32;
}
 
 
 
 
 
/*******************************************************************/
/* 函数功能:获取PIMAGE_FILE_HEADER                                 */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:PIMAGE_FILE_HEADER                                       */
/*******************************************************************/
PIMAGE_FILE_HEADER   GetFileHeader(LPVOID lpImage)
{
    if(!IsPE_File(lpImage))
        return NULL;
    PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
    PIMAGE_FILE_HEADER pImageHeader = &(pNT32->FileHeader);
    return pImageHeader;
}
 
 
 
 
 
/*******************************************************************/
/* 函数功能:获取文件扩展头                                         */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:PIMAGE_OPTIONAL_HEADER                                   */
/*******************************************************************/
PIMAGE_OPTIONAL_HEADER GetOptionalHeader(LPVOID lpImage)
{
    if(!IsPE_File(lpImage))
        return NULL;
    PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
    PIMAGE_OPTIONAL_HEADER pOH=&pNT32->OptionalHeader;
    return pOH;
}
 
 
 
 
 
/*******************************************************************/
/* 函数功能:获取数据目录表                                         */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:PIMAGE_DATA_DIRECTORY                                    */
/*******************************************************************/
PIMAGE_DATA_DIRECTORY GetDataDirctory(LPVOID lpImage)
{
    PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
    PIMAGE_DATA_DIRECTORY pDir = (PIMAGE_DATA_DIRECTORY)pNT32->OptionalHeader.DataDirectory;
    return pDir;
}
 
 
 
 
 
/*******************************************************************/
/* 函数功能:获取导入表                                             */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:PIMAGE_IMPORT_DESCRIPTOR                                 */
/*******************************************************************/
PIMAGE_IMPORT_DESCRIPTOR GetImportTable(LPVOID lpImage)
{
    PIMAGE_NT_HEADERS32 pNT32 = GetNtHeaders(lpImage);
    PIMAGE_DATA_DIRECTORY pDir = GetDataDirctory(lpImage);
    PIMAGE_DATA_DIRECTORY pImportDir = pDir+IMAGE_DIRECTORY_ENTRY_IMPORT;
    PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)RVA2Offset(pImportDir->VirtualAddress, lpImage, pNT32);
    return pImport;
}
 
 
/*******************************************************************/
/* 函数功能:获得第一个节头                                         */
/* 参数:lpImage文件映像基址                                        */
/* 返回值:PIMAGE_SECTION_HEADER                                    */
/*******************************************************************/
PIMAGE_SECTION_HEADER GetFirstSectionHeader(LPVOID lpImage)
{
    PIMAGE_NT_HEADERS pNtHeader=GetNtHeaders(lpImage);
    if (pNtHeader!=NULL)
    {
        return IMAGE_FIRST_SECTION(pNtHeader);  //根据NT头得到首个SECTION的宏
    }
    return NULL;
}
 
 
 
/*******************************************************************/
/* 函数功能:关闭打开的文件                                         */
/* 参数:MAP文件结构体                                              */
/* 返回值:无                                                       */
/*******************************************************************/
void UnLoadFile(PMAP_FILE_STRUCT pstMapFile)
{
    if(pstMapFile->ImageBase)
        UnmapViewOfFile(pstMapFile->ImageBase);
 
    if(pstMapFile->hMapping)
        CloseHandle(pstMapFile->hMapping);
 
    if(pstMapFile->hFile)
        CloseHandle(pstMapFile->hFile);
 
}
 
 
/*******************************************************************/
/* 函数功能:加载文件                                               */
/* 参数:文件绝对地址, MAP文件结构体                                */
/* 返回值:无                                                       */
/*******************************************************************/
BOOL  LoadFileR(LPTSTR lpFilename,PMAP_FILE_STRUCT pstMapFile)
{
 
    HANDLE hFile;
    HANDLE hMapping;
    LPVOID ImageBase;
 
    memset(pstMapFile,0,sizeof(MAP_FILE_STRUCT));
 
    hFile=CreateFile(lpFilename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL,0);
 
    if (!hFile)                                   
        return FALSE;
 
    hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
    if(!hMapping)
    {                                                                        
        CloseHandle(hFile);
        return FALSE;
    }
    ImageBase=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
    if(!ImageBase)
    {                                                                        
        CloseHandle(hMapping);
        CloseHandle(hFile);
        return FALSE;
    }
    pstMapFile->hFile=hFile;
    pstMapFile->hMapping=hMapping;
    pstMapFile->ImageBase=ImageBase;
    return TRUE;
}
LRESULT CALLBACK MainDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    switch (message) 
    {
    case WM_DROPFILES:
        {
            int FileNum = DragQueryFile((HDROP)wParam,-1,szFilePath,0);//得到拖动文件个数
            if(FileNum!=1)
                return FALSE;
            DragQueryFile((HDROP)wParam, 0, szFilePath, MAX_PATH);
            stMapFile.tFilePath = szFilePath; 
            SendDlgItemMessage(hWnd,IDC_FILEPATH_EDIT,WM_SETTEXT,MAX_PATH,(LPARAM)szFilePath);

            UnLoadFile(&stMapFile);
            if(!LoadFileR(szFilePath,&stMapFile))
            {
                MessageBox(hWnd,_T("Load file faild! :("),_T("PEInfo_Example"),MB_OK);
                EnableEditCtrl(hWnd,FALSE);
                return FALSE;
            }
            if(!IsPE_File(stMapFile.ImageBase))
            {
                MessageBox(hWnd,_T("Invalid PE Format file!:("),_T("PEInfo_Example"),MB_OK);
                UnLoadFile(&stMapFile);
                EnableEditCtrl(hWnd,FALSE);
                return FALSE;
            }
            EnableEditCtrl(hWnd,TRUE);      
            ShowFileHeaderInfo(hWnd);
            ShowOptionHeaderInfo(hWnd);
            return TRUE;
        }
    case WM_INITDIALOG:
        hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_SMALL));
        SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
        EnableEditCtrl(hWnd,FALSE);
        return TRUE;

    case WM_COMMAND:
        wmId    = LOWORD(wParam); 
        wmEvent = HIWORD(wParam); 

        switch (wmId)
        {
        // 打开文件
        case IDC_OPEN_BTN:
            OpenFileFun(hWnd);
            return TRUE;
        // 显示位置计算器
        case IDC_CLAC:
                DialogBox(hInst,MAKEINTRESOURCE(IDD_CALCPOS_DLG), hWnd, (DLGPROC)CalcPosDlgProc);
                return TRUE;
        // 保存主界面PE修改信息
        case IDC_SAVE_BTN:
                OnSavePE(hWnd);
                return TRUE;
        // 显示区段对话框
        case IDC_SHOWSHT:                        
            DialogBox(hInst, MAKEINTRESOURCE(IDD_SHT_DLG), hWnd, (DLGPROC)SectionTableDlgProc);
            return TRUE;
        // 显示数据目录表
        case IDC_SHOWDATADIR:  
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DATADIR_DLG), hWnd, (DLGPROC)DataDirDlgProc);
            return TRUE;
        //加壳操作
        case IDC_PACKER:
            Packing(hWnd);
            return TRUE;
        // 点击退出
        case IDC_EXIT:
            SendMessage(hWnd, WM_CLOSE,0,0);
            return TRUE;
        }
        break;
    case IDC_ABOUTBTN:
        DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About);
        return TRUE;
    //程序退出
    case WM_CLOSE:
        UnLoadFile(&stMapFile);
        EndDialog(hWnd, 0);
        return TRUE;
    }
    return FALSE;
}
/*******************************************************************/
/* 函数功能:显示目录表信息                                         */
/* 参数:HWND                                                       */
/* 返回值:无                                                       */
/*******************************************************************/
void ShowDataDirInfo(HWND hDlg)
{
    TCHAR   tcBuff[9];
    //获取PE扩展头
    PIMAGE_OPTIONAL_HEADERpOH=GetOptionalHeader(stMapFile.ImageBase);
    if(!pOH) return;
    //循环获取目录表信息并显示在对话框中
    for(int i=0;i<COUNT_OF_DATADIR;i++)
    {
   wsprintf(tcBuff,_T("%08lX"),pOH->DataDirectory[i].VirtualAddress);        
        SetDlgItemText(hDlg,EditID_Array[i].ID_RVA,cBuff);
 
        wsprintf(tcBuff, _T("%08lX"), pOH->DataDirectory[i].Size);
        SetDlgItemText(hDlg,EditID_Array[i].ID_SIZE,cBuff);
    }
}

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

收藏
免费 5
支持
分享
最新回复 (4)
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
看了后面哪四条,我还是建议楼主看看C++八大金刚里<<设计模式>>
2013-12-2 22:12
0
雪    币: 23
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
好的
2013-12-2 22:19
0
雪    币: 210
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这不是参考科锐的项目么, 今天什么日子啊. 你们班的人都出来宣传了吧 好多人发同样的帖子哦!
2013-12-3 11:36
0
雪    币: 23
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
::3这是我们班学PE结构做的小项目,写的文档总结,欢迎批评指正。本人小菜,和大家一起进步。
2013-12-3 14:17
0
游客
登录 | 注册 方可回帖
返回
//