滴水三期 3.13号(节表)程序解析课后作业记录
大家好,第一次发帖,记录一下学习过程.不知道大家入门是不是学的滴水三期的,我在pe结构里面折腾了很久,c语言还没到入门级别,写出来的代码一部分是参考网络上的,可能里面的代码写的不对,但是它还是奶牛能挤奶.希望得到各位大佬的拍砖
```cpp
#define _CRT_SRCURE_NO_DEPRECATE
#pragma warning(disable:4996)
#include <Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
//获取文件的大小,返回文件的大小
//打开文件到内存
//打印信息
// 1.获取文件的路径,返回文件指针
FILE* file_path() {
printf("请输入文件的路径\n");
char file_name = { '\0' };
scanf("%s", file_name);
FILE* fp = fopen(file_name, "rb");
if (!fp) {
printf("打开文件失败啦~~~~");
return NULL;
}
return fp;
}
//1.获取文件的大小
unsigned int getsize(FILE*fp) {
if (fp==NULL) {
return 0;
}
fseek(fp, 0, SEEK_END);
unsigned int file_length = ftell(fp);
fseek(fp, 0, SEEK_SET);
return file_length;
}
//2:打开文件,传入文件字节数,然后根据这个大小申请内存空间,然后读到内存中,返回一个内存地址空间
PVOID mem_adress(unsigned int file_length,FILE*fp) {
if (file_length == 0) {
printf("申请内存空间失败啦~~~~");
return NULL;
}
PVOID adress = malloc(file_length);
if (adress == NULL) {
printf("申请内存空间失败!!!!");
}
memset(adress, 0, file_length);
fread(adress, file_length, 1, fp);
//把getsize的文件关闭掉
fclose(fp);
printf("内存地址为**********%p**************\n", adress);
return adress;
}
/*
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
#define IMAGE_OS2_SIGNATURE 0x454E // NE
#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
#define IMAGE_VXD_SIGNATURE 0x454C // LE
#define IMAGE_NT_SIGNATURE 0x00004550// PE00
这是系统自带的define 在winnt.h里面
*/
//用windows 自带的结构体 打印dos文件的信息
void pe_DOS_info(char* adress) {
PIMAGE_DOS_HEADER pdos = NULL;//dos头结构体指针,这是一个结构体指针
pdos = (PIMAGE_DOS_HEADER)adress;
printf("%x", pdos->e_magic);
printf("%08x", pdos->e_lfanew);
}
//用偏移的方法打印pe标志符
void pe_NT_info(char* adress) {
PIMAGE_NT_HEADERS32 pnt = (PIMAGE_NT_HEADERS32)(adress + 0xE0);
printf("%08x", pnt->Signature);
//IMAGE_NT_SIGNATURE
}
//不通过偏移的方法打印pe fileheader的内容
void pe_FILEHEADER_info(char* adress) {
PIMAGE_FILE_HEADER pfile = (PIMAGE_FILE_HEADER)(adress + 0xe0 + 0x4);
printf("********machine机器码为(word):\n");
printf("%04x\n", pfile->Machine);
printf("********numberofsections节的数量为(word):\n");
printf("%04x\n", pfile->NumberOfSections);
printf("********time of stamp时间戳为(dword):\n");
printf("%08x\n", pfile->TimeDateStamp);
printf("********pointer to symbol table未知为(dword):\n");
printf("%08x\n", pfile->PointerToSymbolTable);
printf("********numberofstmbols未知为(dword):\n");
printf("%08x\n", pfile->NumberOfSymbols);
printf("********size of optional header可选pe头的大小为(word):\n");
printf("%04x\n", pfile->SizeOfOptionalHeader);//可选pe头的大小
printf("********character ristics文件属性为(word):\n");
printf("%04x\n", pfile->Characteristics);
if (pfile->SizeOfOptionalHeader != 0xE0) {
printf("是32位的软件\n");
}
//printf("%x", sizeof(_IMAGE_FILE_HEADER));
printf("%p\n", &(pfile->Characteristics) + 1);//良字节的地址,加1,就是过去两个字节
PIMAGE_OPTIONAL_HEADER32 pop = (PIMAGE_OPTIONAL_HEADER32)((&pfile->Characteristics) + 0x1);
printf("%04x\n", pop->Magic);
printf(" sizeOfCode\n");
printf("%x\n", pop->SizeOfCode);
printf(" BaseOfCode\n");
printf("%x\n", pop->BaseOfCode);
}
//3.打印节表的内容.adress+ifanew的内容+4字节+file_header+结构体fileheader中的sizeofoptionalheader =节表的
//开始位置
void pe_section_iofo(PVOID adress) {
//先把adress的地址偏移到section节表的位置
//读取ifanew (4字节)的内容,然后和adress相加,就到了pe标志了
//不用上面的结构体来.定义一个dword 的变量,从第60位开始读取
/*DWORD ifanew = DWORD( * (adress + 60));
printf("%08x", ifanew);*/
//printf("%08x",(DWORD)( * ((char*)adress + 64)));
DWORD i = 0;//定义一个dword类型的变量,接收ifanew的内容
i = *((DWORD*)adress + 15);//把void星 强制类型转换成ulong*,加15个long长度(4字节)就是60字节
//
PVOID pe_section_adress = NULL;
pe_section_adress = (BYTE*)adress + i;//把void*类型的adress,强制转换成byte*,然后加上ifanew,.现在指针
//1.指到了pe标志
//printf("%x", *(DWORD*)pe_section_adress);//强制转换成dword*类型,然后读取pe的四字节标志
//2.看一下sizeof(IMAGE_FILE_HEADER)的大小
//printf("%d", sizeof(IMAGE_FILE_HEADER));
//把adress强转为一个FILE_HEADER的结构体变量
PIMAGE_FILE_HEADER PFILE = (PIMAGE_FILE_HEADER)((BYTE*)pe_section_adress + 4);//可以获取到optionalheader的大小
//printf("%x",PFILE->SizeOfOptionalHeader);//大小为E0(32位程序)
//pe_section_adress = (DWORD)pe_section_adress + PFILE->SizeOfOptionalHeader)+4+20;
pe_section_adress = ((DWORD*)pe_section_adress + 1);//指到FILE_HEADER
pe_section_adress = (DWORD*)pe_section_adress + 5;//指到option_header
pe_section_adress = (BYTE*)pe_section_adress +PFILE->SizeOfOptionalHeader ;
PIMAGE_SECTION_HEADER PSEC = NULL;
PSEC=(PIMAGE_SECTION_HEADER)pe_section_adress;
/*BYTE name = {};
int j;
for (j = 0; i < 9; i++) {
name =* PSEC->Name;
printf("%c", name);
}*///草,不会写了
//printf("%s", PSEC->Name);//成功打印,但是8个字节可能全都是字符,没有/0结尾.这样就有问题
//循环读取psec->name的值给一个数组,然后打印出来
char name = { 0 };
int j;
for (j = 0; j < 8; j++) {
name =PSEC->Name;//IMAGE_SECTION_HEADER结构体里面的Name数组的j元素
//name =&*(PSEC->Name);
printf("%c", name);
}
printf("\n节的数据实际大小(没有对齐)\n");
printf("virtual size:\t%x\n", PSEC->Misc);
printf("节的数据开始的地方相对于imagebase的偏移量(必须是内存对齐的整数\n");
printf("virtual adress:\t%x\n", PSEC->VirtualAddress);
printf("节在文件中对齐的后的大小\n");
printf("sizeof rawdata:\t%x\n", PSEC->SizeOfRawData);
printf("在文件中的偏移\n");
printf("pointertorawdata:\t%x\n\n\n", PSEC->PointerToRawData);
//再来一个循环遍历整个节表内容.用第一个节表去偏移,获取下一个节表
//有没有一种可能使用SECTION_HEADER结构体指针来获取呢?????
//试试,先把section_adress指向第一个SECTION_HEADER结构体,然后结构体自增
//等等,好像上面已经定义了一个PIMAGE_SECTION_HEADER结构体指针.把他加1会怎么样
//for (j = 0; j < 4; j++) {
// //复制上面的代码
// name = PSEC++->Name;
// printf("%c", name);
//}++可以跳转过去,但是给name的值不对.什么原因呢????
//试试先++
//memset(name, 0, 9);
for (i = 0; i < 2; i++) {
for (j = 0; j < 8; j++) {
//复制上面的代码
name = PSEC->Name;
printf("%c", name);
}
printf("\n节的数据实际大小(没有对齐)\n");
printf("virtual size:\t%x\n", PSEC->Misc);
printf("节的数据开始的地方相对于imagebase的偏移量(必须是内存对齐的整数\n");
printf("virtual adress:\t%x\n", PSEC->VirtualAddress);
printf("节在文件中对齐的后的大小\n");
printf("sizeof rawdata:\t%x\n", PSEC->SizeOfRawData);
printf("在文件中的偏移\n");
printf("pointertorawdata:\t%x\n\n\n", PSEC->PointerToRawData);
memset(name, 0, 8);
PSEC++;
}
}
int main()
{
PVOID adress = NULL;
FILE* FP = NULL;
FP = file_path();
adress = mem_adress(getsize(FP), FP);//传入函数getsize的返回值
//pe_NT_info(adress);//打印nt头信息
//printf("文件大小为=%u字节", i);
//pe_FILEHEADER_info(adress);
pe_section_iofo(adress);
free(adress);
return 0;
}
``` 不错,坚持到底就是大牛
不错,坚持到底就是大牛 好主意,感谢分享 坚持到底{:1_921:}
好主意,感谢分享 惭愧,看不懂 加油,坚持到底!! 坚持就是胜利✌
页:
[1]
2