2019-03-17 18:42:07 +03:00
|
|
|
#include "pe.h"
|
|
|
|
|
|
|
|
#include <QFile>
|
2019-03-18 10:33:03 +03:00
|
|
|
#include <QFileInfo>
|
2019-03-22 23:36:22 +03:00
|
|
|
#include <QVector>
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
bool PE::readSectionsHeaders(const LIB_META_INFO & info,
|
|
|
|
QVector<IMAGE_SECTION_HEADER> §ions,
|
|
|
|
QFile& file) {
|
|
|
|
|
|
|
|
if (!file.isOpen()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sections.clear();
|
|
|
|
|
|
|
|
if (static_cast<RunType>(info.type) == RunType::_32bit) {
|
|
|
|
if (!file.seek(info.PEIndex + SECTION_HEADER_32)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sections.resize(info.rawSectionCount);
|
|
|
|
file.read(reinterpret_cast<char*>(sections.data()),
|
|
|
|
sizeof (IMAGE_SECTION_HEADER) * info.rawSectionCount);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (static_cast<RunType>(info.type) == RunType::_64bit) {
|
|
|
|
|
|
|
|
if (!file.seek(info.PEIndex + SECTION_HEADER_64)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sections.resize(info.rawSectionCount);
|
|
|
|
file.read(reinterpret_cast<char*>(sections.data()),
|
|
|
|
sizeof (IMAGE_SECTION_HEADER) * info.rawSectionCount);
|
|
|
|
return true;
|
|
|
|
}
|
2019-03-21 13:22:18 +03:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
DWORD PE::readSectionAligment(const LIB_META_INFO &info, QFile& file) {
|
|
|
|
|
|
|
|
if (!file.isOpen()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!file.seek(info.PEIndex + SECTION_ALIGMENT_INDEX_32_64)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD sectionAlign;
|
|
|
|
|
|
|
|
file.read(reinterpret_cast<char*>(§ionAlign), sizeof (sectionAlign));
|
|
|
|
|
|
|
|
return sectionAlign;
|
2019-03-21 13:22:18 +03:00
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
unsigned short PE::findIndexPE(QFile &file) {
|
2019-03-20 18:05:14 +03:00
|
|
|
|
|
|
|
if (!file.isOpen()) {
|
2019-03-22 23:36:22 +03:00
|
|
|
return 0;
|
2019-03-20 18:05:14 +03:00
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
unsigned short limit = 0x400;
|
|
|
|
unsigned short currentSeeck = INDEX_PE_MAGIC;
|
|
|
|
unsigned short PE = 0x0;
|
2019-03-20 18:05:14 +03:00
|
|
|
|
2019-03-21 00:34:57 +03:00
|
|
|
while (currentSeeck <= limit) {
|
|
|
|
if (!file.seek(currentSeeck)) {
|
2019-03-22 23:36:22 +03:00
|
|
|
return 0;
|
2019-03-20 18:05:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
file.read(reinterpret_cast<char*>(&PE), sizeof (PE));
|
|
|
|
|
|
|
|
if (PE == PE_MAGIC) {
|
2019-03-21 00:34:57 +03:00
|
|
|
return currentSeeck;
|
2019-03-20 18:05:14 +03:00
|
|
|
}
|
|
|
|
|
2019-03-21 00:34:57 +03:00
|
|
|
currentSeeck++;
|
2019-03-20 18:05:14 +03:00
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
return 0;
|
2019-03-20 18:05:14 +03:00
|
|
|
}
|
|
|
|
|
2019-03-17 20:16:48 +03:00
|
|
|
bool PE::fillMetaInfo(LIB_META_INFO &info, const QString &file) {
|
2019-03-17 18:42:07 +03:00
|
|
|
QFile f(file);
|
|
|
|
|
2019-03-17 20:16:48 +03:00
|
|
|
#define SEEK(address) \
|
|
|
|
if (!f.seek(address)) { \
|
|
|
|
f.close(); \
|
|
|
|
return false; \
|
|
|
|
}
|
|
|
|
|
2019-03-17 18:42:07 +03:00
|
|
|
if (!f.open(QIODevice::ReadOnly)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
info.PEIndex = findIndexPE(f);
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
if (!info.PEIndex) {
|
2019-03-17 18:42:07 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
SEEK(info.PEIndex + sizeof (unsigned int));
|
|
|
|
f.read(reinterpret_cast<char*>(&info.mashine), sizeof (info.mashine));
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
SEEK(info.PEIndex +
|
|
|
|
sizeof (unsigned int) +
|
|
|
|
sizeof (info.mashine));
|
|
|
|
f.read(reinterpret_cast<char*>(&info.rawSectionCount),
|
|
|
|
sizeof (info.rawSectionCount));
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
SEEK(info.PEIndex + INDEX_MAGIC);
|
2019-03-17 20:16:48 +03:00
|
|
|
|
|
|
|
unsigned short magic = 0x0;
|
|
|
|
f.read(reinterpret_cast<char*>(&magic), sizeof (magic));
|
|
|
|
|
|
|
|
info.type = magic;
|
|
|
|
|
|
|
|
unsigned int importTableIndex = 0;
|
2019-03-21 00:34:57 +03:00
|
|
|
|
2019-03-17 20:16:48 +03:00
|
|
|
if (static_cast<RunType>(info.type) == RunType::_32bit) {
|
2019-03-22 23:36:22 +03:00
|
|
|
importTableIndex = info.PEIndex + INDEX_IMPORTS_32;
|
2019-03-21 00:34:57 +03:00
|
|
|
|
2019-03-17 20:16:48 +03:00
|
|
|
} else if (static_cast<RunType>(info.type) == RunType::_64bit) {
|
2019-03-22 23:36:22 +03:00
|
|
|
importTableIndex = info.PEIndex + INDEX_IMPORTS_64;
|
2019-03-17 20:16:48 +03:00
|
|
|
} else {
|
2019-03-17 18:42:07 +03:00
|
|
|
f.close();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-21 00:34:57 +03:00
|
|
|
SEEK(importTableIndex);
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-21 00:34:57 +03:00
|
|
|
IMAGE_DATA_DIRECTORY import = {};
|
2019-03-22 23:36:22 +03:00
|
|
|
f.read(reinterpret_cast<char*>(&import), sizeof (import));
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
QVector<IMAGE_SECTION_HEADER> sectionHeader;
|
|
|
|
if (!readSectionsHeaders(info, sectionHeader, f)) {
|
2019-03-21 13:22:18 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
ROW_CONVERTER converter(sectionHeader, readSectionAligment(info, f));
|
2019-03-21 13:22:18 +03:00
|
|
|
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-21 13:22:18 +03:00
|
|
|
info.addressImports = converter.convert(import.VirtualAddress);
|
2019-03-21 00:34:57 +03:00
|
|
|
info.sizeImportTable = import.Size;
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-17 18:42:07 +03:00
|
|
|
f.close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
bool PE::is32bit(const QString &file, const LIB_META_INFO * info) {
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
if (!info) {
|
|
|
|
LIB_META_INFO meta;
|
2019-03-17 20:16:48 +03:00
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
if (!fillMetaInfo(meta, file)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<RunType>(meta.type) == RunType::_32bit;
|
2019-03-17 20:16:48 +03:00
|
|
|
}
|
2019-03-17 18:42:07 +03:00
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
return static_cast<RunType>(info->type) == RunType::_32bit;
|
2019-03-17 20:16:48 +03:00
|
|
|
}
|
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
bool PE::dependecies(QStringList &list, const QString &file,
|
|
|
|
const LIB_META_INFO * info) {
|
|
|
|
|
|
|
|
|
2019-03-17 20:16:48 +03:00
|
|
|
LIB_META_INFO meta;
|
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
if (!info) {
|
|
|
|
|
|
|
|
if (!fillMetaInfo(meta, file)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
meta = std::move(*info);
|
2019-03-17 20:16:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
QFile f(file);
|
|
|
|
|
|
|
|
if (!f.open(QIODevice::ReadOnly)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!f.seek(meta.addressImports)) {
|
|
|
|
f.close();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
auto data = f.read(meta.sizeImportTable).split(char(0x0));
|
2019-03-17 20:16:48 +03:00
|
|
|
|
|
|
|
f.close();
|
|
|
|
|
|
|
|
if (data.isEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-18 10:33:03 +03:00
|
|
|
for (QString i : data) {
|
|
|
|
if (i.contains(".dll")) {
|
|
|
|
list.push_back(i);
|
|
|
|
}
|
|
|
|
}
|
2019-03-17 20:16:48 +03:00
|
|
|
|
|
|
|
return true;
|
2019-03-17 18:42:07 +03:00
|
|
|
}
|
|
|
|
|
2019-03-18 16:00:39 +03:00
|
|
|
PE::PE(): IGetLibInfo () {
|
2019-03-18 10:33:03 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-03-19 21:50:05 +03:00
|
|
|
bool PE::getLibInfo(const QString &lib, LibInfo &info) {
|
2019-03-18 10:33:03 +03:00
|
|
|
LIB_META_INFO meta;
|
|
|
|
|
|
|
|
if (!fillMetaInfo(meta, lib)) {
|
2019-03-19 21:50:05 +03:00
|
|
|
return false;
|
2019-03-18 10:33:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
info.name = QFileInfo(lib).fileName();
|
2019-03-19 22:51:24 +03:00
|
|
|
info.path = QFileInfo(lib).absolutePath();
|
2019-03-18 10:33:03 +03:00
|
|
|
|
|
|
|
if (static_cast<RunType>(meta.type) == RunType::_32bit) {
|
|
|
|
info.platform = Platform::Win32;
|
|
|
|
} else if (static_cast<RunType>(meta.type) == RunType::_64bit) {
|
|
|
|
info.platform = Platform::Win64;
|
|
|
|
} else {
|
|
|
|
info.platform = Platform::UnknownPlatform;
|
|
|
|
}
|
|
|
|
|
|
|
|
dependecies(info.dependncies, lib, &meta);
|
2019-03-17 18:42:07 +03:00
|
|
|
|
2019-03-19 21:50:05 +03:00
|
|
|
return info.isValid();
|
2019-03-17 18:42:07 +03:00
|
|
|
}
|
2019-03-18 17:12:40 +03:00
|
|
|
|
|
|
|
PE::~PE(){
|
|
|
|
|
|
|
|
}
|
2019-03-21 13:22:18 +03:00
|
|
|
|
|
|
|
int ROW_CONVERTER::defSection(DWORD rva) {
|
2019-03-22 23:36:22 +03:00
|
|
|
for (int i = 0; i < sections.size(); ++i) {
|
2019-03-21 13:22:18 +03:00
|
|
|
DWORD start = sections[i].VirtualAddress;
|
2019-03-22 23:36:22 +03:00
|
|
|
DWORD end = start + ALIGN_UP(sections[i].VirtualSize, sectionAligment);
|
2019-03-21 13:22:18 +03:00
|
|
|
if(rva >= start && rva < end)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD ROW_CONVERTER::rvaToOff(DWORD rva) {
|
|
|
|
int indexSection = defSection(rva);
|
|
|
|
if(indexSection != -1)
|
2019-03-22 23:36:22 +03:00
|
|
|
return rva - sections[indexSection].VirtualAddress +
|
|
|
|
sections[indexSection].PointerToRawData;
|
2019-03-21 13:22:18 +03:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-22 23:36:22 +03:00
|
|
|
ROW_CONVERTER::ROW_CONVERTER(QVector<IMAGE_SECTION_HEADER> sctions, DWORD align) {
|
2019-03-21 13:22:18 +03:00
|
|
|
sections = sctions;
|
|
|
|
sectionAligment = align;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD ROW_CONVERTER::convert(DWORD rva) {
|
|
|
|
return rvaToOff(rva);
|
|
|
|
}
|