吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1372|回复: 12
收起左侧

[学习记录] 滴水三期 3.13号(节表)程序解析课后作业记录

[复制链接]
okboy 发表于 2023-3-15 23:55
大家好,第一次发帖,记录一下学习过程.
不知道大家入门是不是学的滴水三期的,我在pe结构里面折腾了很久,c语言还没到入门级别,写出来的代码一部分是参考网络上的,可能里面的代码写的不对,但是它还是奶牛能挤奶.希望得到各位大佬的拍砖
#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[256] = { '\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[9] = {};
    int j;
    for (j = 0; i < 9; i++) {
        name[i] =* PSEC->Name;
        printf("%c", name[i]);
    }*///草,不会写了

    //printf("%s", PSEC->Name);//成功打印,但是8个字节可能全都是字符,没有/0结尾.这样就有问题
//循环读取psec->name的值给一个数组,然后打印出来
    char name[8] = { 0 };
    int j;
    for (j = 0; j < 8; j++) {
        name[j] =PSEC->Name[j];//IMAGE_SECTION_HEADER结构体里面的Name数组的j元素
        //name =&*(PSEC->Name);
        printf("%c", name[j]);
    }
    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[j] = PSEC++->Name[j];
    //  printf("%c", name[j]);
    //}++可以跳转过去,但是给name的值不对.什么原因呢????
    //试试先++
    //memset(name, 0, 9);
    for (i = 0; i < 2; i++) {

        for (j = 0; j < 8; j++) {
            //复制上面的代码

            name[j] = PSEC->Name[j];
            printf("%c", name[j]);
        }

        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;
}

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
Abiu678 + 1 + 1 热心回复!
为之奈何? + 1 + 1 我很赞同!
crownyouyou + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xixicoco 发表于 2023-3-16 05:09
不错,坚持到底就是大牛
faxrain 发表于 2023-3-16 06:43
dmhyvip 发表于 2023-3-16 07:01
Moondevil 发表于 2023-3-16 08:09
坚持到底
ljl727ljl 发表于 2023-3-16 08:37

好主意,感谢分享
onlyougao 发表于 2023-3-16 08:47
惭愧,看不懂
wzbAwxl 发表于 2023-3-16 08:48
加油,坚持到底!!
头像被屏蔽
jinzhu160 发表于 2023-3-16 09:17
提示: 作者被禁止或删除 内容自动屏蔽
逆劫古修 发表于 2023-3-16 09:44
坚持就是胜利&#9996;
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 00:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表