已经加载到内存的文件,如何直接获取版本信息?

dibotiger 2010-11-29 05:21:24
通过 GetFileVersionInfoSizeA GetFileVersionInfoA VerQueryValueA
这3个API, 我们很容易获取一个硬盘上的文件的详细的版本信息.


现在,有一种特殊情况下:

这个文件不存在硬盘上,而是被某个进程的加载进虚拟内存里,我知道它的基地址和偏移大小,
如何在这段内存里, 找到对应的版本信息?

谁能告诉我版本信息在PE文件结构里大概的偏移.如何完整地取出上面3个API能够获取到的信息?

谢谢.
...全文
481 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenh7788 2010-12-01
  • 打赏
  • 举报
回复
http://blog.csdn.net/unsigned/archive/2008/10/14/3076212.aspx

哥们你看看这个链接

还有 PETools,LordPE, ImpREC
这几个工具 去下载个 看看
个人感觉
Stud_PE
这个很好用的

给分
sunlin7 2010-12-01
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 dibotiger 的回复:]
//理论上, 加载到内存里的数据,只要知道对应数据结构和偏移,也能获取出正确的对应信息.

//到了这步,看了半天PE资料,GOOGLE了一天,找了很久的资料,
//继续GOOGLE,VS_VERSIONINFO居然是个可变长结构体.到此彻底蒙了.[/Quote]

VersionInfo是一个类C的结构体,就是楼主讲的“可变长结构体”,需要按照MSDN里面描述的结构自行解析,我前面贴的代码就是做这个的,可以解析得到一个VersionInfo对象。
应该是VersionInfo::m_FixedFileInfo里面存储了楼主感兴趣的版本信息。以上代码里面还支持对象的修改和另存功能(修改PE中版本信息部分未贴出)。

希望楼主耐心阅读MSDN里面的描述,并实际动手仔细分析一个PE文件版本信息格式,结合上面给出的代码,才能深入的了解。
dibotiger 2010-12-01
  • 打赏
  • 举报
回复
呼唤PE帝, PE达人.

只懂用API的,还是继续看你的MSND去吧. 呵呵
dibotiger 2010-12-01
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 yangzhi000 的回复:]
这个问题貌似是比较蛋疼。
我也不怎么清楚是不是加载了全部信息到内存的。
是不是版本信息等不会加载到内存里?
就像文件的创建/修改时间等信息,都需要通过磁盘文件本身位置去查询磁盘表/索引去获得。

当然,文件自身肯定是带版本信息的,但是是否加载到内存,就不能肯定了。
如果加载了大家都不知道位置,难道楼主还搜索整个进程空间,进行试验对比啊?
还是通过读取磁盘上的PE文件,再到内存中找偏移……
[/Quote]

的确比较蛋疼,因为这些PE文件(DLL文件)根本就不打算让它在硬盘上出现, 它来之网络.
用完就打算让它消失的.但是我需要获取它的版本信息.

理论上,内存里的PE文件数据和硬盘上的PE文件数据时一样的.而且我上面的代码也找到了
资源数据里的版本信息,只是这个信息结构体是个可变的,我实在是搞不懂了.
yangzhi000 2010-12-01
  • 打赏
  • 举报
回复
这个问题貌似是比较蛋疼。
我也不怎么清楚是不是加载了全部信息到内存的。
是不是版本信息等不会加载到内存里?
就像文件的创建/修改时间等信息,都需要通过磁盘文件本身位置去查询磁盘表/索引去获得。

当然,文件自身肯定是带版本信息的,但是是否加载到内存,就不能肯定了。
如果加载了大家都不知道位置,难道楼主还搜索整个进程空间,进行试验对比啊?
还是通过读取磁盘上的PE文件,再到内存中找偏移?
或者跟踪GetFileVersionInfoSizeA GetFileVersionInfoA VerQueryValueA这三个函数,看他们是怎么实现的?
如果目的仅仅是查询版本信息,既然楼主都能得到内存映像了,何不去查询磁盘文件呢?
dibotiger 2010-12-01
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 lisunlin0 的回复:]
我知道你的意图,你上面的代码我也看过了,写得很好,可惜到了关键的地方却没有了代码,而我前面帖出的大段代码,正是解析VersionInfo的核心代码。
其实动手写的话,利用上面代码,半个小时就可以写好了。----这个时间却用来打字回帖了~~
[/Quote]

呵呵, 感谢一路回帖陪伴. 自己解决了.

解决的方法不是很理想,因为我对PE的资源数据结构还是很晕.

但解决的办法也很正规,因为MSDN里说了:
dwSignature
Contains the value 0xFEEFO4BD. This is used with the szKey member of the VS_VERSIONINFO structure when searching a file for the VS_FIXEDFILEINFO structure.

所以,只要有版本信息, 就有这个东西,剩下的就简单了.

sunlin7 2010-12-01
  • 打赏
  • 举报
回复
我知道你的意图,你上面的代码我也看过了,写得很好,可惜到了关键的地方却没有了代码,而我前面帖出的大段代码,正是解析VersionInfo的核心代码。
其实动手写的话,利用上面代码,半个小时就可以写好了。----这个时间却用来打字回帖了~~
dibotiger 2010-12-01
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 lisunlin0 的回复:]
引用 9 楼 dibotiger 的回复:
//理论上, 加载到内存里的数据,只要知道对应数据结构和偏移,也能获取出正确的对应信息.

//到了这步,看了半天PE资料,GOOGLE了一天,找了很久的资料,
//继续GOOGLE,VS_VERSIONINFO居然是个可变长结构体.到此彻底蒙了.

VersionInfo是一个类C的结构体,就是楼主讲的“可变长结构体”,需要按照MSDN里面……
[/Quote]


你的C++代码我大概看了下,很奇怪居然没有PE结构的分析过程,你怎么直接获取到
资源数据段里的版本信息? 我想我们可能还是在讨论两个不同的事情.

如果你有兴趣,把那个我写的简单的C代码看看,就大概了解我的意图.

很多同学奇怪为何不用微软的 **RESouces** API来操作获取对应的资源信息.

有两点原因:

1. 这些数据不是本地的, 也不能存入磁盘. 只在内存里停留.
2. 我希望更了解PE的格式, 自己通过数据结构来解析出对应的资源信息.

dibotiger 2010-12-01
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wenh7788 的回复:]
http://blog.csdn.net/unsigned/archive/2008/10/14/3076212.aspx

哥们你看看这个链接

还有 PETools,LordPE, ImpREC
这几个工具 去下载个 看看
个人感觉
Stud_PE
这个很好用的

给分
[/Quote]

if(UpdateResource(hResource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), lpTranslate -> wLanguage, versioninfodata, versioninfosize)){

哥们,你没看到又是微软API作用的结果么?

我要的是自己通过PE结构分析出内存中PE文件的版本信息. 和这种思路无关!!!

另外,再多的工具有何用处? 我看不到其中获取得细节, 有啥用?

dibotiger 2010-11-30
  • 打赏
  • 举报
回复
感谢lisunlin0贴了这么多自己的代码,辛苦了.
我阅读了其中的部分代码, 感觉和自己的思路不太一样.

于是写了个验证程序来表达我目前的研究的思路和遇到的问题.如下:

//////////////////////////////////////////////////////////////////////////////////
/*
最近学习PE结构,想从已经读取到内存里的PE文件的数据里,直接从内存里解析出一些资源数据。
(当然,微软也已经提供了相关的API来直接操作,但为了加深PE结构了解,自己写了个蛋疼的程序来验证)

通过 GetFileVersionInfoSize GetFileVersionInfo VerQueryValue 这3个API, 我们很容易获取一个硬盘上的文件的详细的版本信息.

理论上, 加载到内存里的数据,只要知道对应数据结构和偏移,也能获取出正确的对应信息.
但是第一个想法就搁浅了,看了半天的PE的资源数据,居然就是不知道如何获取对应的版本信息。


所以特来请教各位PE帝,PE达人,如何从内存里直接获取对应的版本信息。请看下面的代码:

问题集中在GetVersionInfoFromMem函数中获取到对应的资源PIMAGE_RESOURCE_DIRECTORY_ENTRY后,
如果才能获取VS_VERSIONINFO这个数据结构是变长的版本信息呢?
*/
//////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>


DWORD RVA2Offset(void *pImage, DWORD dwRVA)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER )pImage;
PIMAGE_NT_HEADERS pNtHeads = (PIMAGE_NT_HEADERS)((DWORD)pDos + pDos->e_lfanew);

DWORD NumOfSection = pNtHeads->FileHeader.NumberOfSections;
PIMAGE_SECTION_HEADER pSectionHead = (PIMAGE_SECTION_HEADER )(sizeof(IMAGE_FILE_HEADER) + 4 + pNtHeads->FileHeader.SizeOfOptionalHeader + (DWORD)pNtHeads);
DWORD RawOfEntryPoint = 0;
DWORD RawinSection = 0;
WORD count=0;
while(count<NumOfSection)
{
if((dwRVA >= pSectionHead->VirtualAddress)
&&(dwRVA < pSectionHead->VirtualAddress+pSectionHead->Misc.VirtualSize))
{
RawinSection=dwRVA-pSectionHead->VirtualAddress;
RawOfEntryPoint=pSectionHead->PointerToRawData+RawinSection;
break;
}
pSectionHead++;
count++;
}
if (RawOfEntryPoint == 0)
{
return 0;
}
return RawOfEntryPoint;
}


DWORD CheckFileSize(char *filename)
{
HANDLE hFile=NULL;
WIN32_FIND_DATA wfd;

if((hFile=FindFirstFile(filename,&wfd))==INVALID_HANDLE_VALUE)
{
FindClose(hFile);
return 0;
}

FindClose(hFile);
return wfd.nFileSizeHigh*MAXDWORD+wfd.nFileSizeLow;
}



//从内存里获取版本资源信息
//lpFileData: 存放dll数据的内存缓冲区
//nDataLength: dll文件的长度
BOOL GetVersionInfoFromMem(void* lpFileData, int nDataLength)
{
PIMAGE_DOS_HEADER m_pDosHeader;
PIMAGE_NT_HEADERS m_pNTHeader;
PIMAGE_SECTION_HEADER m_pSectionHeader;

//检查长度
if (nDataLength < sizeof(IMAGE_DOS_HEADER))
{
return FALSE;
}
m_pDosHeader = (PIMAGE_DOS_HEADER)lpFileData; // DOS头
//检查dos头的标记
if (m_pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return FALSE; //0x5A4D : MZ
}

//检查长度
if ((DWORD)nDataLength < (m_pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)))
{
return FALSE;
}
//取得pe头
m_pNTHeader = (PIMAGE_NT_HEADERS)((PBYTE)lpFileData + m_pDosHeader->e_lfanew); // PE头
//检查pe头的合法性
if (m_pNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
return FALSE; //0x00004550 : PE00
}
if ((m_pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) //0x2000 : File is a DLL
{
return FALSE;
}
if ((m_pNTHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0) //0x0002 : 指出文件可以运行
{
return FALSE;
}
if (m_pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
{
return FALSE;
}

//取得节表(段表)
m_pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)m_pNTHeader + sizeof(IMAGE_NT_HEADERS));
//验证每个节表的空间
for (int i=0; i< m_pNTHeader->FileHeader.NumberOfSections; i++)
{
if ((m_pSectionHeader[i].PointerToRawData + m_pSectionHeader[i].SizeOfRawData) > (DWORD)nDataLength)
{
return FALSE;
}
}

if(m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress != 0 &&m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0 )
{
int nEntries;
DWORD dwOffset = RVA2Offset(lpFileData,m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
PIMAGE_RESOURCE_DIRECTORY pResRootDir = (PIMAGE_RESOURCE_DIRECTORY )((LPBYTE)lpFileData+dwOffset);
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResTypeDirEnt = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)pResRootDir+sizeof(IMAGE_RESOURCE_DIRECTORY));

nEntries = pResRootDir->NumberOfNamedEntries+pResRootDir->NumberOfIdEntries;

for (i = 0; i < nEntries; i++)
{
if(!pResTypeDirEnt->NameIsString&&pResTypeDirEnt->Id==16)
{
//VS_FIXEDFILEINFO FixedInfo;
printf("\r\nFound Version Resouce\r\n");

//通过 GetFileVersionInfoSize GetFileVersionInfo VerQueryValue 这3个API, 我们很容易获取一个硬盘上的文件的详细的版本信息.
//理论上, 加载到内存里的数据,只要知道对应数据结构和偏移,也能获取出正确的对应信息.

//到了这步,看了半天PE资料,GOOGLE了一天,找了很久的资料,
//继续GOOGLE,VS_VERSIONINFO居然是个可变长结构体.到此彻底蒙了.

//该如何从内存里取出对应的版本信息? 就如同使用上面的3个API?

/*
?????????????????????????????????????????????
*/

}
// Reference next entry in directory entries array.
pResTypeDirEnt++;
}
}

return TRUE;
}


void main(int argc, char *argv[])
{
//输入一个PE文件,读取到内存,根据PE结构,尝试解析出资源数据里的版本信息
if(argc==2)
{
char* pFileMemBuffer;
DWORD dFileSize=CheckFileSize(argv[1]);

if(dFileSize)
{
pFileMemBuffer=new char[dFileSize];
if (!pFileMemBuffer)
{
return;
}
else
{
FILE* fp = fopen(argv[1], "rb");
int nLen = static_cast<int>(fread(pFileMemBuffer, 1, dFileSize, fp));
fclose(fp);
}
GetVersionInfoFromMem(pFileMemBuffer,dFileSize);
}
}
}
这不是鸭头 2010-11-30
  • 打赏
  • 举报
回复
顶楼上~~
sunlin7 2010-11-30
  • 打赏
  • 举报
回复


const WCHAR *Var::s_szKey = L"Translation";

int Var::FromBuffer(LPVOID pVerBuffer, int nBufLen)
{
if(pValue)
{
delete []pValue;
pValue = NULL;
}

int nOffset = 0;
nOffset = VerHead::FromBuffer(pVerBuffer, nBufLen - nOffset);
if(nOffset)
{
nOffset = AlignOffset(nOffset);
if(wValueLength)
{
pValue = new BYTE[wValueLength];
memmove(pValue, ((LPBYTE)pVerBuffer) + AlignOffset(nOffset), wValueLength);
}
nOffset = wLength;
}
return nOffset;
}

int Var::SaveToBuffer(LPVOID pVerBuffer, int nBufLen)
{
int nLen = UpdateSize();
int nOffset = 0;
if(wLength <= nBufLen)
{
nOffset = 0;
nOffset = VerHead::SaveToBuffer(pVerBuffer, nBufLen);
nOffset = AlignOffset(nOffset);
if(pValue)
{
memmove((LPBYTE)pVerBuffer + AlignOffset(nOffset), pValue, wValueLength);
}
nOffset += wValueLength;
}
assert(nLen == nOffset);
UNREFERENCED_PARAMETER(nLen);
return nOffset;
}

int Var::UpdateSize(void)
{
const int nItemCount = 1; // waring: the language array size, here assume a value
wValueLength = sizeof(DWORD) * nItemCount;
wLength = (WORD)(AlignOffset(VerHead::UpdateSize()) + wValueLength);
return wLength;
}

const WCHAR *VarFileInfo::s_szKey = L"VarFileInfo";

int VarFileInfo::FromBuffer(LPVOID pVerBuffer, int nBufLen)
{
std::vector<Var *>::iterator pStart = m_vVar.begin();
for(; pStart != m_vVar.end(); ++pStart)
{
delete *pStart;
}
m_vVar.clear();

int nOffset = 0;
nOffset = VerHead::FromBuffer(pVerBuffer, nBufLen - nOffset);
if(nOffset)
{
int nLen = 0;
nOffset = AlignOffset(nOffset);
do
{
Var *pVar = new Var;
nLen = pVar->FromBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
if(0 == nLen)
{
delete pVar;
pVar = NULL;
break;
}
nOffset += AlignOffset(nLen);
m_vVar.push_back(pVar);
}while(nOffset < (int)wLength);
}
return nOffset;
}

int VarFileInfo::SaveToBuffer(LPVOID pVerBuffer, int nBufLen)
{
int nLen = UpdateSize();
int nOffset;
nOffset = VerHead::SaveToBuffer(pVerBuffer, nBufLen);
std::vector<Var *>::iterator pStart = m_vVar.begin();
for(; pStart != m_vVar.end(); ++pStart)
{
nOffset = AlignOffset(nOffset);
nOffset += (*pStart)->SaveToBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
}
assert(nLen == nOffset);
UNREFERENCED_PARAMETER(nLen);
return nOffset;
}

int VarFileInfo::UpdateSize(void)
{
wLength = 0;
wValueLength = 0;
if(!m_vVar.empty())
{
int nValueLen = 0;
std::vector<Var *>::iterator pStart = m_vVar.begin();
for(; pStart != m_vVar.end(); ++pStart)
{
nValueLen = AlignOffset(nValueLen);
nValueLen += (*pStart)->UpdateSize();
}
wLength = (WORD)(AlignOffset(GetVerHeadSize()) + nValueLen);
}
return wLength;
}


const WCHAR *VersionInfo::s_szKey = L"VS_VERSION_INFO";

int VersionInfo::FromBuffer(LPVOID pVerBuffer, int nBufLen)
{
VS_FIXEDFILEINFO fixedFileInfo = {0};
m_FixedFileInfo = fixedFileInfo;

int nOffset = 0;
nOffset = VerHead::FromBuffer(pVerBuffer, nBufLen - nOffset);

if(nOffset) // got VerHead correctly
{
if(wValueLength) // VS_FIXEDFILEINFO exsit
{
nOffset = AlignOffset(nOffset);
m_FixedFileInfo = *(VS_FIXEDFILEINFO *)((LPBYTE)pVerBuffer + nOffset);
nOffset += wValueLength;
if(m_FixedFileInfo.dwSignature != s_dwFixedFileInfoSignature) // invalide signature
{
m_FixedFileInfo = fixedFileInfo;
VerHead::FromBuffer(NULL, 0);
nOffset = 0;
return nOffset;
}
}

int nLen = 0;
VerHead verHead;

nOffset = AlignOffset(nOffset);
do
{
nLen = verHead.FromBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
if(0 == nLen)
{
m_strFileInfo.FromBuffer(NULL, 0);
m_varFileInfo.FromBuffer(NULL, 0);
nOffset = 0;
break;
}
if(0 == m_strFileInfo.Is_szKey(verHead.pszKey))
{
nLen = m_strFileInfo.FromBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
}
else if(0 == m_varFileInfo.Is_szKey(verHead.pszKey))
{
nLen = m_varFileInfo.FromBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
}
nOffset += AlignOffset(nLen);
}
while(nOffset < (int)wLength);
}
return nOffset;
}

int VersionInfo::SaveToBuffer(LPVOID pVerbuffer, int nBufLen)
{
int nLen = UpdateSize();
if(nBufLen < nLen)
{
return 0;
}
memset(pVerbuffer, 0, nLen);
int nOffset = 0;
nOffset = VerHead::SaveToBuffer(pVerbuffer, nBufLen);
if(wValueLength)
{
nOffset = AlignOffset(nOffset);
*(VS_FIXEDFILEINFO *)((LPBYTE)pVerbuffer + nOffset) = m_FixedFileInfo;
nOffset += wValueLength;
}
nOffset = AlignOffset(nOffset);
nOffset += m_strFileInfo.SaveToBuffer((LPBYTE)pVerbuffer + nOffset, nBufLen - nOffset);
nOffset = AlignOffset(nOffset);
nOffset += m_varFileInfo.SaveToBuffer((LPBYTE)pVerbuffer + nOffset, nBufLen - nOffset);
nOffset = AlignOffset(nOffset);
assert(nLen == nOffset);
return nOffset;
}

BOOL VersionInfo::AddString(LPCWSTR pszKeyName, LPCWSTR pszValue)
{
return m_strFileInfo.AddString(pszKeyName, pszValue);
}

int VersionInfo::UpdateSize(void)
{
int wLen = 0;
if(m_FixedFileInfo.dwSignature == s_dwFixedFileInfoSignature)
{
wValueLength = sizeof(m_FixedFileInfo);
wLen = AlignOffset(GetVerHeadSize()) + wValueLength;
}
wLen = AlignOffset(wLen);
wLen += m_strFileInfo.UpdateSize();
wLen = AlignOffset(wLen);
wLen += m_varFileInfo.UpdateSize();
wLength = (WORD)AlignOffset(wLen);

return wLength;
}


int Test_VerInfo(void)
{
int nRet = 0;
const int nBufLen = 1024 * 8;
char verBuffer_1[nBufLen] = {0};
char verBuffer_2[nBufLen] = {0};

VersionInfo *pVerInfo = new VersionInfo;

HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
int nResSize = SizeofResource(NULL, hRsrc);
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
LPVOID lpVersion = LockResource(hGlobal);
//memmove(verBuffer_1, lpVersion, nResSize);

//DWORD dwHandle = 0;
////ULONG uVerLen = GetFileVersionInfoSizeEx(0, 0, &dwHandle);
////GetFileVersionInfoEx(0, argv[0], dwHandle, nBufLen, verBuffer_2);
//ULONG uVerLen = GetFileVersionInfoSize(argv[0], &dwHandle);
//GetFileVersionInfo(argv[0], dwHandle, uVerLen, verBuffer_2);

nRet = pVerInfo->FromBuffer(lpVersion, nBufLen);
nRet = pVerInfo->SaveToBuffer(verBuffer_1, nBufLen);
//nRet = pVerInfo->FromBuffer(verBuffer_1, nBufLen);
////nRet = pVerInfo->GetLength();
////nRet = pVerInfo->SaveToBuffer(verBuffer_1, nBufLen);

memcpy(verBuffer_2, lpVersion, nResSize);
int a = 0;
for(int i = 0; i < nRet; ++i)
{
if(verBuffer_1[i] != verBuffer_2[i])
{
++a;
}
}
UnlockResource(lpVersion);
FreeResource(hGlobal);
pVerInfo->AddString(L"Comments", L"hello");
//pVerInfo->RemoveString(L"Comments");
delete pVerInfo;

_CrtDumpMemoryLeaks();

return 0;
}
sunlin7 2010-11-30
  • 打赏
  • 举报
回复

// Temp06.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
//#include "resource.h"

//#define _CRTDBG_MAP_ALLOC
//#include <stdlib.h>
//#include <crtdbg.h>
#include <windows.h>
#include <assert.h>

#include "VersionInfo.h"

#pragma comment(lib, "Version.lib")

int VerHead::FromBuffer(PVOID pVerHead, int nBufLen)
{
if(pszKey)
{
delete []pszKey;
pszKey = NULL;
}

if(NULL == pVerHead) // zero the structure
{
wLength = GetVerHeadSize();
wValueLength = 0;
wType = 0;
pszKey = NULL;
return 0;
}

int nOffset = 0;
wLength = *(PWORD)((LPBYTE)pVerHead + nOffset);
if((wLength <= nBufLen)
&& (wLength > sizeof(wLength) + sizeof(wValueLength) + sizeof(wType) + sizeof(WCHAR)))
{
nOffset += sizeof(wLength);
wValueLength = *(PWORD)((LPBYTE)pVerHead + nOffset);
nOffset += sizeof(wValueLength);
wType = *(PWORD)((LPBYTE)pVerHead + nOffset);
nOffset += sizeof(wValueLength);
int nKeyLen = lstrlenW((LPCWSTR)((LPBYTE)pVerHead + nOffset)) + 1;
pszKey = new WCHAR[nKeyLen];
lstrcpyW(pszKey, (LPCWSTR)((LPBYTE)pVerHead + nOffset));
nOffset += nKeyLen * sizeof(WCHAR);
}
if(0 == nOffset)
{
wLength = GetVerHeadSize();
wValueLength = 0;
wType = 0;
pszKey = NULL;
}
return nOffset;
};

int VerHead::SaveToBuffer(PVOID pVerHead, int nBufLen)
{
UpdateSize();
int nOffset = 0;
int nKeyLen = lstrlenW(pszKey) + 1;
if((UINT)nBufLen >= sizeof(wLength) + sizeof(wValueLength) + sizeof(wType) + nKeyLen * sizeof(WCHAR))
{
nOffset = 0;
*(PWORD)((LPBYTE)pVerHead + nOffset) = wLength;
nOffset += sizeof(wLength);
*(PWORD)((LPBYTE)pVerHead + nOffset) = wValueLength;
nOffset += sizeof(wValueLength);
*(PWORD)((LPBYTE)pVerHead + nOffset) = wType;
nOffset += sizeof(wType);
lstrcpyW((LPWSTR)((LPBYTE)pVerHead + nOffset), pszKey);
nOffset += nKeyLen * sizeof(WCHAR);
}
return nOffset;
}
//
//String::String(LPCWSTR pszKeyName) : pValue(NULL)
//{
// WORD wKeyLen = (WORD)(lstrlenW(pszKeyName) + 1);
// pszKey = new WCHAR[wKeyLen];
// lstrcpyW(pszKey, pszKeyName);
// wLength += wKeyLen * sizeof(WCHAR);
//}

String::String(LPCWSTR pszKeyName, LPCWSTR pszValue) : pValue(NULL)
{
WORD wKeyLen = (WORD)(lstrlenW(pszKeyName) + 1);
WORD wValueLen = (WORD)(lstrlenW(pszValue) + 1);
pszKey = new WCHAR[wKeyLen];
lstrcpyW(pszKey, pszKeyName);
pValue = (LPWORD)new WCHAR[wValueLen];
lstrcpyW((LPWSTR)pValue, pszValue);
UpdateSize();
}

int String::FromBuffer(LPVOID pVerBuffer, int nBufLen)
{
if(pValue)
{
delete []pValue;
pValue = NULL;
}

int nOffset = 0;
nOffset = VerHead::FromBuffer(pVerBuffer, nBufLen - nOffset);
if(nOffset) // got the VerHead correctly
{
nOffset = AlignOffset(nOffset);
if(wValueLength)
{
pValue = new WORD[wValueLength];
memmove(pValue, ((LPBYTE)pVerBuffer) + nOffset, wValueLength * sizeof(WCHAR));
}
nOffset = wLength;
}
return nOffset;
}

int String::SaveToBuffer(LPVOID pVerBuffer, int nBufLen)
{
int nLen = UpdateSize();
int nOffset = 0;
if(wLength <= nBufLen)
{
nOffset = 0;
nOffset = VerHead::SaveToBuffer(pVerBuffer, nBufLen);
if(pValue)
{
nOffset = AlignOffset(nOffset);
memmove((LPBYTE)pVerBuffer + nOffset, pValue, wValueLength * sizeof(WCHAR));
}
nOffset = wLength;
}
assert(nLen == nOffset);
UNREFERENCED_PARAMETER(nLen); // for toggole the warring message when release
return nOffset;
}

int String::UpdateSize(void)
{
wLength = 0;
wValueLength = 0;
if(pValue)
{
wValueLength = (WORD)((lstrlen((LPCWSTR)pValue) + 1));
wLength = (WORD)(AlignOffset(GetVerHeadSize()) + wValueLength * sizeof(WCHAR));
}
return wLength;
}

LPWORD String::SetValue(LPCWSTR pszValue)
{
WORD wNewValueLen = 0;
if(pValue)
{
delete []pValue;
}
wNewValueLen = (WORD)(lstrlenW(pszValue) + 1);
pValue = new WORD[wNewValueLen];
lstrcpyW((LPWSTR)pValue, pszValue);
wLength += -wValueLength + wNewValueLen;
wValueLength = wNewValueLen;
return pValue;
}

int StringTable::FromBuffer(LPVOID pVerBuffer, int nBufLen)
{
std::vector<String *>::iterator pStart = m_vString.begin();
for(; pStart != m_vString.end(); ++pStart)
{
delete *pStart;
}
m_vString.clear();

int nOffset = 0;
nOffset = VerHead::FromBuffer(pVerBuffer, nBufLen - nOffset);
if(nOffset)
{
int nLen = 0;
nOffset = AlignOffset(nOffset);
do
{
String *pString = new String;
nLen = pString->FromBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
if(0 == nLen)
{
delete pString;
pString = NULL;
break;
}
nOffset += AlignOffset(nLen);
m_vString.push_back(pString);
}while(nOffset < (int)wLength);
}
return nOffset;
}

int StringTable::SaveToBuffer(LPVOID pVerBuffer, int nBufLen)
{
int nLen = UpdateSize();
int nOffset;
nOffset = VerHead::SaveToBuffer(pVerBuffer, nBufLen);
nOffset = AlignOffset(nOffset);
std::vector<String *>::iterator pStart = m_vString.begin();
for(; pStart != m_vString.end(); ++pStart)
{
nOffset = AlignOffset(nOffset);
nOffset += (*pStart)->SaveToBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
}
assert(nLen == nOffset);
UNREFERENCED_PARAMETER(nLen);
return wLength;
}

int StringTable::UpdateSize(void)
{
wLength = 0;
wValueLength = 0;
int nValueLen = 0;
if(!m_vString.empty())
{
std::vector<String *>::iterator pStart = m_vString.begin();
for(; pStart != m_vString.end(); ++pStart)
{
nValueLen = AlignOffset(nValueLen);
nValueLen += (*pStart)->UpdateSize();
}
wLength = (WORD)(AlignOffset(GetVerHeadSize()) + nValueLen);
}
return wLength;
}

String *StringTable::FindStringByName(LPCWSTR pszStrName)
{
String *pStrRet = NULL;
std::vector<String *>::iterator pStart = m_vString.begin();
for(; pStart != m_vString.end(); ++pStart)
{
if(0 == lstrcmpiW((*pStart)->pszKey, pszStrName))
{
pStrRet = *pStart;
break;
}
}
return pStrRet;
}

//String *StringTable::FindStringByValue(LPCWSTR pszValue)
//{
// String *pStrRet = NULL;
// std::vector<String *>::iterator pStart = m_vString.begin();
// for(; pStart != m_vString.end(); ++pStart)
// {
// if(0 == lstrcmpiW((LPCWSTR)(*pStart)->pValue, pszValue))
// {
// pStrRet = *pStart;
// break;
// }
// }
// return pStrRet;
//}

BOOL StringTable::AddString(LPCWSTR pszKeyName, LPCWSTR pszValue)
{
BOOL bRet = FALSE;
std::vector<String *>::iterator pStart = m_vString.begin();
for(; pStart != m_vString.end(); ++pStart)
{
if(0 == lstrcmpiW((*pStart)->pszKey, pszKeyName))
{
(*pStart)->SetValue(pszValue);
bRet = TRUE;
break;
}
}
if(!bRet)
{
String *pStr = new String(pszKeyName, pszValue);
m_vString.push_back(pStr);
bRet = TRUE;
}
return bRet;
}
//
//BOOL StringTable::RemoveString(LPCWSTR pszKeyName)
//{
// std::vector<String *>::iterator pStart = m_vString.begin();
// for(; pStart != m_vString.end(); ++pStart)
// {
// if(0 == lstrcmpiW((*pStart)->pszKey, pszStrName))
// {
// pStrRet = *pStart;
// break;
// }
// }
//}
//
const WCHAR *StringFileInfo::s_szKey = L"StringFileInfo";
//
int StringFileInfo::FromBuffer(LPVOID pVerBuffer, int nBufLen)
{
std::vector<StringTable *>::iterator pStart = m_vStrTable.begin();
for(; pStart != m_vStrTable.end(); ++pStart)
{
delete *pStart;
}
m_vStrTable.clear();

int nOffset = 0;
nOffset = VerHead::FromBuffer(pVerBuffer, nBufLen - nOffset);
if(nOffset)
{
nOffset = AlignOffset(nOffset);;
do
{
int nLen = 0;
StringTable *pStrTable = new StringTable;
nLen = pStrTable->FromBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
if(0 == nLen)
{
delete pStrTable;
pStrTable = NULL;
break;
}

m_vStrTable.push_back(pStrTable);
nOffset += nLen;
}while(nOffset < (int)wLength);
}
return wLength;
}

int StringFileInfo::SaveToBuffer(LPVOID pVerBuffer, int nBufLen)
{
int nLen = UpdateSize();
int nOffset;
nOffset = VerHead::SaveToBuffer(pVerBuffer, nBufLen);
nOffset = AlignOffset(nOffset);
std::vector<StringTable *>::iterator pStart = m_vStrTable.begin();
for(; pStart != m_vStrTable.end(); ++pStart)
{
nOffset = AlignOffset(nOffset);
nOffset += (*pStart)->SaveToBuffer((LPBYTE)pVerBuffer + nOffset, nBufLen - nOffset);
}
assert(nLen == nOffset);
UNREFERENCED_PARAMETER(nLen);
return nOffset;
}

int StringFileInfo::UpdateSize(void)
{
wLength = 0;
int nValueLen = 0;
if(!m_vStrTable.empty())
{
wValueLength = 0;
std::vector<StringTable *>::iterator pStart = m_vStrTable.begin();
for(; pStart != m_vStrTable.end(); ++pStart)
{
nValueLen = AlignOffset(nValueLen);
nValueLen += (*pStart)->UpdateSize();
}
wLength = (WORD)(AlignOffset(GetVerHeadSize()) + nValueLen);
}
return wLength;
}

BOOL StringFileInfo::AddString(LPCWSTR pszKeyName, LPCWSTR pszValue)
{
BOOL bRet = FALSE;
std::vector<StringTable *>::iterator pStart = m_vStrTable.begin();
for(; pStart != m_vStrTable.end(); ++pStart)
{
String *pStr = (*pStart)->FindStringByName(pszKeyName);
if(pStr)
{
bRet = (*pStart)->AddString(pszKeyName, pszValue);
break;
}
}
if(!bRet && !m_vStrTable.empty()) // not found and string table not empty
{
bRet = m_vStrTable[0]->AddString(pszKeyName, pszValue);
}
return bRet;
}

sunlin7 2010-11-30
  • 打赏
  • 举报
回复
VersionInfo是一个类C结构的数据,在MSDN里面有简单描述。以下为本人根据MSDN以及PE coffe和耐心分析得出的代码:

// VersionInfo.h
#pragma once

#include <vector>

class VerHead // common head for version structure
{
public:
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR *pszKey;
protected:
static const UINT uAlignBoundary = 4; // 32-bit boundary
ULONG AlignOffset(ULONG uOffset){ULONG u = (uOffset / uAlignBoundary) * uAlignBoundary; if(u < uOffset){u += uAlignBoundary;} return u;}
public:
VerHead() : wLength(sizeof(VerHead)), wValueLength(0), wType(0), pszKey(NULL){}
virtual ~VerHead(){ if(pszKey) delete []pszKey;};
virtual int FromBuffer(PVOID pVerHead, int nBufLen);
virtual int SaveToBuffer(PVOID pVerHead, int nBufLen);
virtual int UpdateSize(void){ return GetVerHeadSize();}
virtual WORD GetVerHeadSize(void){int nLen = 0; if(pszKey) nLen = lstrlenW(pszKey) + 1; return (WORD)(sizeof(wLength) + sizeof(wValueLength) + sizeof(wType) + nLen * sizeof(WCHAR));}
};

class String : public VerHead
{
public:
LPWORD pValue;
public:
String() : pValue(NULL){}
//String(LPCWSTR pszKeyName);
String(LPCWSTR pszKeyName, LPCWSTR pszValue);
virtual ~String(){if(pValue) delete []pValue;}
virtual int FromBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int SaveToBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int UpdateSize(void);
//virtual int GetLength(void){return AlignOffset(VerHead::GetLength()) + (lstrlenW((LPCWSTR)pValue) + 1) * sizeof(WCHAR); };
LPWORD SetValue(LPCWSTR pszValue);
};

class StringTable : public VerHead
{
public:
std::vector<String *> m_vString;
public:
StringTable(){}
virtual ~StringTable(){while(!m_vString.empty()){delete m_vString.back(); m_vString.pop_back();}}
virtual int FromBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int SaveToBuffer(LPVOID pVerBuffer, int nBufLen);
//virtual int GetLength(void);
virtual int UpdateSize(void);
String *FindStringByName(LPCWSTR pszStrName);
//String *FindStringByValue(LPCWSTR pszValue);
BOOL AddString(LPCWSTR pszKeyName, LPCWSTR pszValue);
BOOL RemoveString(LPCWSTR pszKeyName);
};

class StringFileInfo : public VerHead
{
public:
static const WCHAR *s_szKey;
std::vector<StringTable *> m_vStrTable;
public:
StringFileInfo(){}
virtual ~StringFileInfo(){while(!m_vStrTable.empty()){delete m_vStrTable.back(); m_vStrTable.pop_back();}};
virtual int FromBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int SaveToBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int Is_szKey(WCHAR *pszKey){return lstrcmpW(s_szKey, pszKey);}
virtual int UpdateSize(void);
BOOL AddString(LPCWSTR pszKeyName, LPCWSTR pszValue);
BOOL RemoveString(LPCWSTR pszKey);
};

class Var : public VerHead
{
public:
static const WCHAR *s_szKey;
virtual int Is_szKey(WCHAR *pszKey){return lstrcmpW(s_szKey, pszKey);}
public:
LPBYTE pValue;
public:
Var() : pValue(NULL) {}
virtual ~Var(){if(pValue) delete []pValue;};
virtual int FromBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int SaveToBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int UpdateSize(void);
};

class VarFileInfo : public VerHead
{
public:
std::vector<Var *> m_vVar;
public:
static const WCHAR *s_szKey;
virtual int Is_szKey(WCHAR *pszKey){return lstrcmpW(s_szKey, pszKey);}
public:
VarFileInfo(){}
virtual ~VarFileInfo(){while(!m_vVar.empty()){delete m_vVar.back(); m_vVar.pop_back();}};
virtual int FromBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int SaveToBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int UpdateSize(void);
};

class VersionInfo : public VerHead
{
private:
static const WCHAR *s_szKey;
virtual int Is_szKey(WCHAR *pszKey){return lstrcmpW(s_szKey, pszKey);}
public:
static const DWORD s_dwFixedFileInfoSignature = 0xFEEF04BD;
VS_FIXEDFILEINFO m_FixedFileInfo;

StringFileInfo m_strFileInfo;
VarFileInfo m_varFileInfo;
public:
VersionInfo(){VS_FIXEDFILEINFO vs_info = {0}; m_FixedFileInfo = vs_info;}
virtual ~VersionInfo(){};
virtual int FromBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int SaveToBuffer(LPVOID pVerBuffer, int nBufLen);
virtual int UpdateSize(void);
BOOL AddString(LPCWSTR pszKeyName, LPCWSTR pszValue);
BOOL RemoveString(LPCWSTR pszKeyName);
};
dibotiger 2010-11-30
  • 打赏
  • 举报
回复
感谢回复. 这段代码读取的好像是图标资源的大小和信息?
比较汗的是, 我的编译器居然一堆的API都找不到. 难道是VS2010? 看来我的VC6真得老了.

其实我的意思就是:
我把一个PE文件读取到内存里, 我就想在内存里直接找到版本信息.
PE结构是否指定了版本信息的偏移位置呢?
sunlin7 2010-11-29
  • 打赏
  • 举报
回复
可以获取:
LRESULT PutIconVerInfo(HMODULE hModuleOrg , LPCTSTR pszIconFile, VersionInfo &verInfo)
{
LRESULT lRes = ERROR_SUCCESS;
BOOL bRet;

std::vector<std::pair<RESDIR, LPVOID>> vOrgFistIconGroudData;
std::vector<std::pair<RESDIR, LPVOID>> vSrcFistIconGroudData;

std::vector<std::pair<RESDIR, LPVOID>> vIconGroudData;

LPCTSTR pszFirstIconName = NULL;

/*bRet = */GetFirstIconGroupData(pszTargetFile, &pszFirstIconName, vOrgFistIconGroudData); // Origion file may not contain icon.
if(NULL == pszFirstIconName)
{
pszFirstIconName = MAKEINTRESOURCE(1);
}

bRet = GetFirstIconGroupData(pszIconFile, NULL, vSrcFistIconGroudData); // source icon

if(bRet) // got the source icons
{
USHORT uNewIconId = 0; // if insert an new icon, give it an ordered name
std::vector<std::pair<RESDIR, LPVOID>>::iterator pSrcStart = vSrcFistIconGroudData.begin();
for(; pSrcStart != vSrcFistIconGroudData.end(); ++pSrcStart)
{
RESDIR &srcResDir = pSrcStart->first;
std::vector<std::pair<RESDIR, LPVOID>>::iterator pOrgStart = vOrgFistIconGroudData.begin();
for(; pOrgStart != vOrgFistIconGroudData.end(); ++pOrgStart)
{
RESDIR &orgResDir = pOrgStart->first;
if(orgResDir.ResInfo.Icon.ColorCount == srcResDir.ResInfo.Icon.ColorCount // replace an exist icon
&& orgResDir.ResInfo.Icon.Height == srcResDir.ResInfo.Icon.Height
&& orgResDir.ResInfo.Icon.Width == srcResDir.ResInfo.Icon.Width)
{
orgResDir.BytesInRes = srcResDir.BytesInRes;
free(pOrgStart->second);
pOrgStart->second = pSrcStart->second;
pSrcStart->second = NULL;
break;
}
}
if(pSrcStart->second) // then insert it
{
while(++uNewIconId < (USHORT)-1 && FindResource(hModuleOrg, MAKEINTRESOURCE(uNewIconId), RT_ICON));
srcResDir.IconCursorId = uNewIconId;
vOrgFistIconGroudData.push_back(*pSrcStart);
pSrcStart->second = NULL;
}
}
}
else // no source icon found, clear vOrgFistIconGroudData, cause UpdatePeIcon() function take no effect.
{ // here we transplant vOrgFistIconGroudData to vSrcFistIconGroudData, the follow code will releas all data
vSrcFistIconGroudData = vOrgFistIconGroudData;
vOrgFistIconGroudData.clear();
}

if(hModuleOrg)
{
FreeLibrary(hModuleOrg); // free the target module first, the follow update resource need write the file.
hModuleOrg = NULL;
}

HANDLE hUpdate = ::BeginUpdateResource(pszTargetFile, FALSE);
if(hUpdate) // update resource data
{
if(!vOrgFistIconGroudData.empty())
bRet = bRet && UpdatePeIcon(hUpdate, pszFirstIconName, vOrgFistIconGroudData);
if(verInfo.UpdateSize())
bRet = bRet && UpdatePeVersionInfo(hUpdate, verInfo);
bRet = bRet && ::EndUpdateResource(hUpdate, FALSE);
}

for(std::vector<std::pair<RESDIR, LPVOID>>::iterator pStart = vOrgFistIconGroudData.begin(); // release data
pStart != vOrgFistIconGroudData.end();
++pStart)
{
if(pStart->second)
free(pStart->second);
}
for(std::vector<std::pair<RESDIR, LPVOID>>::iterator pStart = vSrcFistIconGroudData.begin();
pStart != vSrcFistIconGroudData.end();
++pStart)
{
if(pStart->second)
free(pStart->second);
}
return lRes;
}
dibotiger 2010-11-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jason176374 的回复:]
在内存中只能是一段数据,而非文件。
版本信息这个应该是只针对磁盘保存的文件而言的吧。
[/Quote]

汗一个
读到内存里的PE文件, 和硬盘里的文件的数据难道有差别?


谁知道PE文件版本信息偏移和结构呢?

jason176374 2010-11-29
  • 打赏
  • 举报
回复
在内存中只能是一段数据,而非文件。
版本信息这个应该是只针对磁盘保存的文件而言的吧。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧