cutePE:自己写的PE文件结构查看器

(代码略搓,大神请飘走~~~)

cutePE基于Qt5.5开发,可以查看PE文件结构。开发过程如下:

0x01 读取文件

要【通过signature判断是否为PE文件】其实是件简单的事,but,首先得需要读取文件呀。所以第一步,实现Qt读取文件,以Hex形式打印:

#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QByteArray raw_bytes;
    QFile file("E:/myCode/binary_file_rw/notepad.exe");
    if(file.open(QIODevice::ReadOnly))
    {
        raw_bytes = file.readAll();
        string byte_string;
        for(int i=0;i<raw_bytes.count();i++){
            byte_string=QString::number(raw_bytes[i]&0x000000000000ff, 16).toUpper().toStdString();
            if(byte_string.length()==1){
                byte_string="0"+byte_string;
            }
            if(!(i%4) && (i%16))
                cout<<"\t";
            if(!(i%16))
                cout<<"\n";
            cout<<byte_string<<" ";
        }
        file.close();
    }

    return a.exec();
}

效果如图:
这里写图片描述

0x02 识别PE文件

不管是变形还是没变形的PE,起始两个byte肯定是 “MZ”,DOS Header结尾的4个byte肯定指向PE Header处,而PE Header起始两个byte肯定是 “PE\0\0”。以此可判断PE文件。
这里对之前的代码做了一丢丢改进,把读取到的byte_string通通存储到全局变量raw_bytes_string里,方便后续处理。bytes_string是一个以string为元素的容器。
同时增加了两个函数,便于对数据进行处理。

#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <iostream>
#include <vector>

using namespace std;

vector <string> raw_bytes_string;

//获取raw_bytes_string中addr起始的bytes_length字节。is_reversed指定是否逆序输出字节
string getBytesFromRAW(long long addr,long long bytes_length,bool is_reversed){
    string bytes_string;
    if(is_reversed){//小端机逆序输出地址,方便后续操作
        for(int i=addr+bytes_length-1;i>addr-1;i--){
            bytes_string.append(raw_bytes_string[i]);
        }
    }else{
        for(int i=addr;i<addr+bytes_length;i++){
            bytes_string.append(raw_bytes_string[i]);
        }
    }

    return bytes_string;
}

long long hexString2LongLong(string& hexStr)
{
    hexStr=hexStr.erase(0,hexStr.find_first_not_of("0"));//去掉000000E0前面的000000
    return strtoll(hexStr.c_str(),NULL,16);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QByteArray raw_bytes;
    QFile file("C:/Windows/system32/notepad.exe");
    if(file.open(QIODevice::ReadOnly))
    {
        raw_bytes = file.readAll();
        string byte_string;
        for(int i=0;i<raw_bytes.count();i++){
            byte_string=QString::number(raw_bytes[i]&0x000000000000ff, 16).toUpper().toStdString();
            if(byte_string.length()==1){
                byte_string="0"+byte_string;
            }
            raw_bytes_string.push_back(byte_string);

            //打印整个文件
            //            if(!(i%4) && (i%16))
            //                cout<<"\t";
            //            if(!(i%16))
            //                cout<<"\n";
            //            cout<<byte_string<<" ";
        }
        file.close();

        //判断是否为PE文件
        if(raw_bytes_string[0]=="4D" && raw_bytes_string[1]=="5A"){//MZ
            string pe_header_offset_string=getBytesFromRAW(0x3c,4,true);
            long long pe_header_offset=hexString2LongLong(pe_header_offset_string);
            string pe_header_first_4_bytes=getBytesFromRAW(pe_header_offset,4,false);
            if(pe_header_first_4_bytes=="50450000"){//PE\0\0
                cout<<"it is a PE file!\n";
            }else{
                cout<<"Ops,it is NOT a PE file!\n";
            }
        }else{
            cout<<"Ops,it is NOT a PE file!\n";
        }
    }

    return a.exec();
}

把file路径替换成任何PE文件,exe或者dll,执行效果都是:
这里写图片描述

0x03 读取 & 显示PE文件结构

cutePE里,界面左的内容都是固定的,界面右的内容根据实际PE文件内容变化。涉及到的主要的Qt控件是QTreeWidget(对应图左)、QTableWidget(对应图右)。
总的来说,实现过程有点像写八股文,照着PE文件结构来写就好了~当然具体的SectionTable定位等问题需要自己根据实际的SizeOfOptionlHeader和PE Header offset进行计算,不能照着一般PE文件来写,具体定位还得自己计算,毕竟万一是个变形PE呢。实现效果如下图:
这里写图片描述

代码放在这里了,其实程序还有很多可以优化的地方。现在程序对于PE文件的处理性能不是很理想,随便碰到一个稍微大点的PE就会崩溃。因为我在PE文件初始加载过程中(加载过程有好几道处理工序),把PE文件所有字节都赋给了栈上的变量。。。所以,你懂的……我比较懒,基本功能实现后,也没再进行优化。界面嘛,,本人审美有限,也没怎么调。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值