首页
社区
课程
招聘
未解决 [求助]小白求教写的程序访问内存冲突
发表于: 2021-3-14 10:39 3054

未解决 [求助]小白求教写的程序访问内存冲突

2021-3-14 10:39
3054

// PE解析器.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

 

#include <iostream>

 

#include<Windows.h>

 

#include<malloc.h>

 

#include<string.h>

 

using namespace std;

 

LPCSTR VAR = "C:\Windows\System32\notepad.exe";

 

LPVOID ReadPEFile(LPCSTR lpszFile) //阅读PE文件函数
{
FILE *pFile = NULL; //定义一个文件指针 指向NULL
DWORD fileSize = 0;
LPVOID pFileBuffer = NULL; //定义一个文件映像指针 指向NULL

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
//打开文件
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);//申请一块新的内存空间作为新文件映像
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;          //返回文件映像的内存空间指针 

}

 

VOID PrintfNTHeaders() //自定义打印NT头函数
{
LPVOID pFileBuffer = NULL; //自定义文件映像指针
PIMAGE_DOS_HEADER pDosHeader = NULL; //自定义DOS头指针
PIMAGE_NT_HEADERS pNTHeader = NULL; //自定义NT头指针
PIMAGE_FILE_HEADER pPEHeader = NULL; //自定义指向PE头指针
PIMAGE_OPTIONAL_HEADER32 pOPtionHeader = NULL; //自定义指向可选PE头指针(32位)
PIMAGE_SECTION_HEADER pSectionHeader = NULL; //自定义指向可选PE头指针

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
pFileBuffer = ReadPEFile(VAR);
if (!pFileBuffer)
{
    printf("文件读取失败\n");
    return ;
}
 
 
//判断是否是有效的MZ标识
if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)  //判断pFileBuffer指针取值是不是MZ标识(4D5A
{
    printf("不是有效的MZ标识\n");                  //若不是有效的MZ标识,若不是则打印失败信息
    free(pFileBuffer);                             //释放申请的文件映像内存空间
    return;
}
 
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;     //将文件映像指针数据类型强制转换为PIMAGE_DOS_HEADER 既DOS头
//打印DOS头相关信息
printf("******************************DOC头*******************************\n");
printf("MZ标志:%x\n", pDosHeader->e_magic);
printf("PE偏移:%x\n", pDosHeader->e_lfanew);
//判断是否是有效的PE标志
 
if (*((PWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
    printf("不是有效的PE标志\n");
    free(pFileBuffer);
    return;
}
 
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
 
 
//打印NT头相关信息
printf("******************************NT头*******************************\n");
printf("NT:%x\n", pNTHeader->Signature);
pPEHeader = ((PIMAGE_FILE_HEADER)((DWORD)pNTHeader) + 4);
//打印PE头相关信息
printf("******************************PE头*******************************\n");
printf("PE:%x\n", pPEHeader->Machine);
printf("节的数量:%x\n", pPEHeader->NumberOfSections);
printf("可选PE头大小%x\n", pPEHeader->SizeOfOptionalHeader);
//打印可选PE头相关信息
pOPtionHeader = (PIMAGE_OPTIONAL_HEADER32((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER));
printf("******************************OPTION  PE头*******************************\n");
printf("OPTION_PE:%x\n", pOPtionHeader->Magic);
//释放内存
free(pFileBuffer);

}

 

int main()
{

1
2
3
ReadPEFile(VAR);
PrintfNTHeaders();
getchar();

}

 

调试了很多次,每次都会出现冲突。
在下面这行的地方中断。实在没辙了,还请各位内行的大佬们解答
/(ㄒoㄒ)/~~

1
2
3
4
5
6
if (*((PWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
    printf("不是有效的PE标志\n");
    free(pFileBuffer);
    return;
}

还有第二个问题。昨天重新写了一遍,第二次出现的问题是,一样的代码,这个却一直显示不是有效的MZ标记。用的是同一个文件路径,但是显示出来的结果跟有问题这个截然不同。。

 

#include<iostream>

 

#include<stdio.h>

 

#include<Windows.h>

 

#include<malloc.h>
using namespace std;

 

//这里是我自己用脑子写的PE解析器

 

LPCSTR LUJIN = "C:\Windows\System32\notepad.exe";

 

LPVOID READPe(LPCSTR str)
{
LPVOID BUFF = NULL;
FILE *pfile = NULL;
DWORD sizee = 0;

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
pfile = fopen( str ,"rb");
if (!pfile)
{
    printf("文件路径打开失败\n");
    fclose(pfile);
    return NULL;
}
 
fseek(pfile, 0, SEEK_END);
sizee = ftell(pfile);
fseek(pfile, 0, SEEK_SET);
 
BUFF = malloc(sizee);
if (!BUFF)
{
    printf("申请的BUFF空间失败\n");
    fclose(pfile);
    return NULL;
}
size_t x = fread(BUFF, sizee, 1, pfile); //fread函数:fread(要读取的对象指针,每个对象的大小单位为DWORD,读取对象个数,输入流)
if (!x)
{
    printf("读取数据失败了\n");
    free(BUFF);
    fclose(pfile);
    return NULL;
}
 
fclose(pfile);   //此次需要注意,无论成功与否,均要关闭文件路径流
return BUFF;   //返回申请的ImageBuffer 的指针

}

 

//以上,读取PE文件的函数就算是搞定了

 

VOID PNT()//这个是打印用函数
{
LPVOID BUFF = NULL;
PIMAGE_DOS_HEADER pdos = NULL;
PIMAGE_NT_HEADERS pnt = NULL;
PIMAGE_FILE_HEADER pfiles = NULL;
PIMAGE_OPTIONAL_HEADER pope = NULL;
PIMAGE_SECTION_HEADER pjiebiao = NULL;

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
BUFF = READPe(LUJIN);
if (!BUFF)
{
    printf("文件读取失败\n");
    return;
}
 
if (*((PDWORD)BUFF) != IMAGE_DOS_SIGNATURE)
{
    printf("无效的MZ标志\n");
    free(BUFF);
    return;
}
else
{
    printf("有效的MZ标志,开始将 BUFF转化为 pdos头\n");
}
pdos = (PIMAGE_DOS_HEADER)BUFF; //非常要注意,这里是PIMAGE_DOS_HEADER 而不是IMAGE_DOS_HEADER  要非常注意是否带有P
 
printf("DOS头\n");
printf("MZ标记=%x", pdos->e_magic);
printf("垃圾数据后偏移=%x", pdos->e_lfanew);
 
pnt = (PIMAGE_NT_HEADERS)(((PIMAGE_DOS_HEADER)BUFF + (pdos->e_lfanew) + 4));//使指针指向NT头
printf("NT头\n");
printf("NT头标记=%x ", pnt->Signature);
 
pfiles = (PIMAGE_FILE_HEADER)((PIMAGE_FILE_HEADER)BUFF +(DWORD)pnt + 4);//不理解;
printf("PE=%x \n", pfiles->Machine);
printf("可选PE头大小=%x \n", pfiles->SizeOfOptionalHeader);
printf("节的数量=%x \n", pfiles->NumberOfSections);
 
pope = (PIMAGE_OPTIONAL_HEADER)((PIMAGE_OPTIONAL_HEADER)BUFF + pfiles->SizeOfOptionalHeader);
printf("OPE=%x :\n", pope->Magic);
printf("OPE内的OEP=%x \n", pope->AddressOfEntryPoint);
 
free(BUFF);
 
printf("ALL OVER\n");

}

 

int main()
{
READPe(LUJIN);
PNT();
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 4516
活跃值: (4493)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
先抄别人的代码.然后自己写.  你目前的代码杂乱无章.

比如那一个个的结构体指针 你也不填进去.   访问也没有使用结构体指针访问. 非得用加加减减PDWORD去访问一个结构体定义的东西.  显得那么生硬的转换.

照别人的代码写几次就可以了  论坛 很多PE结构的代码.比如这个 https://bbs.pediy.com/thread-266268.htm
2021-3-14 13:37
0
雪    币: 345
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
谢谢老兄O(∩_∩)O,因为我是跟着滴水逆向的教程自学的,上面第一份代码我是抄课件的代码,第二份是我自己理解后跟着记忆打出来的。因为一直调试不通过所以卡在这里没学后面的课程了,我试试看能不能理解后用其他方式仿造这个PE解析器,毕竟找的课程15年,你说的加加减减PDWORD就是课程教的哈哈哈。谢谢老兄的指点,谢谢O(∩_∩)O
2021-3-15 09:26
0
游客
登录 | 注册 方可回帖
返回
//