首页
社区
课程
招聘
[求助]PE文件操作生成EXE后不能执行
发表于: 2023-2-27 14:53 6271

[求助]PE文件操作生成EXE后不能执行

2023-2-27 14:53
6271

滴水逆向教程作业

作业内容:

编写一段代码,代码作用:

1、将notepad.exe读取到内存中,然后将内存中硬盘状态的notepad.exe拉伸到到运行状态,放一段新开辟的内存里;(FileBuffer转换成ImageBuffer)
2、将内存中拉伸后的notepad.exe恢复成硬盘文件状态,放一段新开辟的内存里;(ImageBuffer转换成FileBuffer)
3、将在内存中的硬盘文件状态的notepad.exe保存为新的notepad11.exe文件。

遇到的问题:

生成了新的exe文件之后无法运行,运行就报错,报错截图如下:

 

图片描述

解决思路:

1、直接丢PE_TOOL里看看结构全不全,截图如下:

 

图片描述

 

图片描述

 

图片描述

 

发现结构都是全的;
2、看看错误报告,截图如下:
图片描述
发现可能是签名的问题;
这就很难受了,我看视频课里也没说关于签名的问题啊,嘎,请大佬看看怎么办,有没有可能是我的代码出了问题,或者说是真的需要把所有节复制完了,再复制一下后面的数据。
注意:请在32位XP系统中使用vc6.0运行,win10也可以但是需要操作SysWoW文件夹中的notepad.exe这个是32位的
以下是C语言代码:

 

读取文件函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <string.h>
#include <windows.h>
 
 
LPVOID ReadPEFile(LPSTR lpszFile)
{
    FILE* pFile = NULL;
    DWORD fileSize = 0;
    LPVOID pFileBuffer = NULL;
 
    //打开文件
    pFile = fopen(lpszFile, "rb");
    if (!pFile)
    {
        printf(" 无法打开 EXE 文件! ");
        return NULL;
    }
    //读取文件大小
    fseek(pFile, 0, SEEK_END);
    fileSize = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);
    //分配缓冲区
    pFileBuffer = malloc(fileSize);
    memset(pFileBuffer, 0, fileSize);
    if (!pFileBuffer)
    {
        printf(" 分配空间失败! ");
        fclose(pFile);
        return NULL;
    }
    //将文件数据读取到缓冲区
    size_t n = fread(pFileBuffer, fileSize, 1, pFile);
    if (!n)
    {
        printf(" 读取数据失败! ");
        free(pFileBuffer);
        fclose(pFile);
        return NULL;
    }
    //关闭文件   
    fclose(pFile);
    return pFileBuffer;
}

判断文件大小函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DWORD File_size(LPSTR lpszFile)
{
    FILE* pFile = NULL;
    DWORD fileSize = 0;
    LPVOID pFileBuffer = NULL;
 
    //打开文件
    pFile = fopen(lpszFile, "rb");
    if (!pFile)
    {
        printf(" 无法打开 EXE 文件! ");
        return 0;
    }
    //读取文件大小
    fseek(pFile, 0, SEEK_END);
    fileSize = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);
    fclose(pFile);
    return fileSize;
}

拉伸文件函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
LPVOID ExpentPE_File()
//拉伸文件
{
    int memSize = 0;
    int headerSize = 0;
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeaders = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    LPVOID sectionSource;
    LPVOID sectionDestinaton;
    LPVOID memcopycheck;
    LPVOID pFileBuffer = NULL;
    LPVOID pImageBuffer = NULL;
    int Filesize = 0;
 
    //读取文件
    pFileBuffer = ReadPEFile((LPSTR)"C:\\notepad.exe");
    Filesize = File_size((LPSTR)"C:\\notepad.exe");
    if (!pFileBuffer)
    {
        printf("文件读取失败\n");
        return NULL;
    }
 
    //判断是否是有效的MZ标志   
    if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
    {
        printf("不是有效的MZ标志\n");
        free(pFileBuffer);
        return NULL;
    }
    //DOS头地址,类型为结构体指针
    pDosHeader = (PIMAGE_DOS_HEADER)((DWORD)pFileBuffer);
    //NT头地址,类型为结构体指针
    pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    //printf("%x\n",*pNTHeaders);
    //标准PE头地址,类型为结构体指针
    pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeaders + 4);
    //可选PE头地址,类型为结构体指针
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
    //定位可选PE头中ImageBuffer的大小,即拉伸后PE文件的大小
    memSize = pOptionHeader->SizeOfImage;
    //printf("%d",memSize);
    //开辟相应的地址空间,定义开辟空间的首地址
    pImageBuffer = malloc((int)memSize);
    //将开辟的空间全部置零
    memset(pImageBuffer, 0, (int)memSize);
    if (!pImageBuffer)
    {
        printf("内存分配失败!");
        return NULL;
    }
    headerSize = pOptionHeader->SizeOfHeaders;
    //将FileBuffer的头文件复制到ImageBuffer中
    memcopycheck = memcpy(pImageBuffer, pFileBuffer, (int)headerSize);
    if (!memcopycheck)
    {
        printf("内存复制失败!");
        free(pImageBuffer);
        return NULL;
    }
    //定位第一个节表头位置,数据类型为结构体指针
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
    //printf("%d\n",pPEHeader->NumberOfSections);
    //循环定位所有的节表
    for (int i = 0; i < (int)(pPEHeader->NumberOfSections); i++)
    {
        //printf("%s\n",pSectionHeader->Name);
        //printf("%d\n",i);
        //定位所有的节所在ImageBuffer的位置
        sectionDestinaton = (LPVOID)((DWORD)pImageBuffer + pSectionHeader->VirtualAddress);
        //定位所有的节所在FileBuffer的位置
        sectionSource = (LPVOID)((DWORD)pFileBuffer + pSectionHeader->PointerToRawData);
        //将所有在FileBuffer中的节循环复制到ImageBuffer中去
        memcopycheck = memcpy(sectionDestinaton, sectionSource, (int)(pSectionHeader->SizeOfRawData));
        if (!memcopycheck)
        {
            printf("内存复制失败!");
            free(pImageBuffer);
            return NULL;
        }
        //定位到下一个节表位置
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + (DWORD)IMAGE_SIZEOF_SECTION_HEADER);
    }
    //释放内存
    free(pFileBuffer);
    pFileBuffer = NULL;
    return pImageBuffer;
}

还原文件函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
LPVOID CompressPE_File(LPVOID pImageBuffer)
//还原文件
{
 
    DWORD memSize = 0;
    DWORD fileSize = 0;
    WORD check = 0;
    LPVOID pFileBuffer = NULL;
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeaders = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    LPVOID sectionSource;
    LPVOID sectionDestinaton;
    LPVOID memCheck;
 
    //获取原文件FileBuffer状态下的大小
    fileSize = File_size((LPSTR)"C:\\notepad.exe");
    //printf("%d\n",fileSize);
    //根据大小开辟相应空间
    pFileBuffer = malloc(fileSize);
    //将开辟的内存空间置零
    memset(pFileBuffer, 0, fileSize);
    if (!pFileBuffer)
    {
        printf("内存分配失败!");
        free(pImageBuffer);
        pImageBuffer = NULL;
        return NULL;
    }
    //各种定位头文件
    pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
    pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pNTHeaders + 4 + IMAGE_SIZEOF_FILE_HEADER);
    //定位所有头的大小
    memSize = pOptionHeader->SizeOfHeaders;
    //将所有的头从ImageBuffer复制到FileBuffer中
    memCheck = memcpy(pFileBuffer, pImageBuffer, memSize);
    //printf("%x",pOptionHeader->Magic);
    if (!memCheck)
    {
        printf("内存复制失败!");
        free(pFileBuffer);
        free(pImageBuffer);
        pFileBuffer = NULL;
        pImageBuffer = NULL;
        return NULL;
    }
    //定位头文件
    pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeaders + 4);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
    //定位目的地址与源地址
    sectionDestinaton = (LPVOID)((DWORD)pFileBuffer + pSectionHeader->PointerToRawData);
    sectionSource = (LPVOID)((DWORD)pImageBuffer + pSectionHeader->VirtualAddress);
    //循环复制节信息
    for (int i = 0; i < (int)(pPEHeader->NumberOfSections); i++)
    {
        printf("%s\n", pSectionHeader->Name);
        memCheck = memcpy(sectionDestinaton, sectionSource, (int)(pSectionHeader->SizeOfRawData));
        if (!memCheck)
        {
            printf("内存复制失败!");
            free(pFileBuffer);
            free(pImageBuffer);
            pFileBuffer = NULL;
            pImageBuffer = NULL;
            return NULL;
        }
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER);
    }
    free(pImageBuffer);
    pImageBuffer = NULL;
    return pFileBuffer;
}

将还原的文件数据存盘到exe文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void MemToFile(LPVOID pFileBuffer)
//将新的FileBuffer存档到文件中
{
    DWORD fileSize = 0;
    //char* pinputData = NULL;
 
    fileSize = File_size((LPSTR)"C:\\notepad.exe");
    //char inputData[fileSize];
    //pinputData = inputData;
    FILE* fp = NULL;
    fp = fopen("C:\\Notpad11.exe", "wb+");
    fseek(fp, 0, SEEK_SET);
    //pinputData = (char*)pFileBuffer;
    fwrite(pFileBuffer, (int)fileSize, 1, fp);
    free(pFileBuffer);
    fclose(fp);
}

main函数

1
2
3
4
5
6
7
8
9
int main()
{
    LPVOID pImageBuffer = NULL;
    LPVOID pFileBuffer = NULL;
    pImageBuffer = ExpentPE_File();
    pFileBuffer = CompressPE_File(pImageBuffer);
    MemToFile(pFileBuffer);
    return(0);
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 236
活跃值: (96)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

各位大佬这是问题相关的附件,请下载检阅

上传的附件:
2023-2-27 14:55
0
雪    币: 364
活跃值: (1716)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
PE 基础没学好。重定位。
2023-2-27 15:08
0
雪    币: 236
活跃值: (96)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
wujimaa PE 基础没学好。重定位。
这就是在学习中呀大侠
2023-2-27 15:47
0
游客
登录 | 注册 方可回帖
返回
//