文章转载:pt007@vip.sina.com
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
文章的原文地址及代码地址在http://forum.eviloctal.com/thread-43020-1-1.html
注:文章首发I.S.T.O信息安全团队,后由作者友情提交到邪恶八进制信息安全团队技术讨论组。
出处:部分内容整理自网络
前置知识:PE WINDOWS-API
作者:Zaroty
KeyWords :捆绑 EXE PE 资源
想做文件捆绑器,于是去搜了下文件捆绑的一些原理,大致上就三种方法吧,
如果你有其他的方法,希望您能告诉我,谢谢!
1.两个EXE直接合并的方法:
一个 WIN32的可执行文件(PE)的格式,是以数据流型排列的.
在PE文件的头部第3个字节处有一个4字节长的数值.这个数值用来告诉PE装载器PE header的位置.
也就是说.这个4字节的数值是一个真正可执行文件的起始偏移量.装载器就会跳到这个偏移量指的地方,
读取数据并将数据印射到内存并执行.
再说个例子:
有三个PE格式文件(A,B,C)
将A和B合并写入C里(C=A & B)
C执行的过程大致为:
PE装载器检查C的PE header偏移量--> 跳到这个位置,读取PE header里的节表结构-->将数据印射至内存--->处理(执行)
再说一个节表的概念,节表好比一个目录,用来告诉装载器.这个PE文件里面在哪个位置放了哪些数据,
并且这些数据是何种属性.
A和B合并写入C,虽然是两个可执行文件,但C的节表其实就是A的节表,
在C的节表里并没有加入B的任何东西.所以.执行C只是相当于执行了A的代码.
那么如何让执行C的同时,可以让这两个PE体都执行呢?大体思路是这样的:
1、A和B合并写入C里(咱们已经做好了)
2、修改C的PE偏移量,使这个值指向C里面所包含的B程序的PE header。(这样就使PE装载器首先跳到B代码处执行B程序体)
3、现在就要想办法使A也运行起来。这就要首先在B程序体里面(B程序要自己写的)加入一个跳转指令,
重新让PE装载器装入A程序,因为A程序的PE偏移量的数据已经被咱们修改了。
所以,必须你自己告诉装载器A的PE header的起始位置。
2.资源释放的方法:
这种方法需要你首先做好一个捆绑模板,用来装载需要捆绑的文件。
比如:A 、B、C三个文件
C为模板,我们要在C里面写入释放资源的源码,然后将A、B作为资源,利用BeginUpdateResource 、
UpdateResource、EndUpdateResource的API函数实现对资源内容的更新替换。
替换完之后,我们运行C,C就会释放他所包含的A和B,并且运行,这样做的优点是在C运行A和B的时候,
我们可以选择隐藏运行。
==
或者你也可以不用资源,直接把文件A、B加到文件C的边,然后文件C读取参数得到文件A、B的大小,
然后写出文件A、B,运行之。
3.WINRAR压缩包捆绑法
这个不是原理。。只是一种方法,,简单易用的,相关内容可以点击下面链接查看:
完美的WINRAR自解压绑马(没有右键菜单)
下面是EXE中资源的导入与导出:
代码:
// UpdateResource_Console.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
//including the file & Updating the resource data
void ImportFile(void)
{
HANDLE hFile;
DWORD dwFileSize,
dwBytesRead;
LPBYTE lpBuffer;
hFile = CreateFile("C://WINDOWS//system32//calc.exe", GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
dwFileSize = GetFileSize(hFile, NULL);
lpBuffer = new BYTE[dwFileSize];
if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
{
// do something with lpBuffer here //Updating the resource data
HANDLE hResource;
hResource = BeginUpdateResource("C://Documents and Settings//mjs//"
"桌面//资料//RightNowDoing//UpdateResource_MFC//"
"Debug//UpdateResource_MFC.exe", FALSE);
if (NULL != hResource)
{
char* p = MAKEINTRESOURCE(104);
if (UpdateResource(hResource,
RT_RCDATA,
MAKEINTRESOURCE(104),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //使用系统缺省语言
(LPVOID) lpBuffer,
dwFileSize) != FALSE)
{
EndUpdateResource(hResource, FALSE);
}
}
}
delete [] lpBuffer;
CloseHandle(hFile);
}
}
//Extracting the data & Saving the data to a file
void ExtractFile(void)
{
HMODULE hLibrary;
HRSRC hResource;
HGLOBAL hResourceLoaded;
LPBYTE lpBuffer;
hLibrary = LoadLibrary("C://Documents and Settings//mjs//"
"桌面//资料//RightNowDoing//UpdateResource_Console//"
"Debug//UpdateResource_Console.exe");
if (NULL != hLibrary)
{
char* p = MAKEINTRESOURCE(104);
hResource = FindResource(hLibrary, MAKEINTRESOURCE(104), RT_RCDATA);
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(), //获得错误代码
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, //错误代码对应的文字描述
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
if (NULL != hResource)
{
hResourceLoaded = LoadResource(hLibrary, hResource);
if (NULL != hResourceLoaded)
{
lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
if (NULL != lpBuffer)
{
// do something with lpBuffer here
DWORD dwFileSize,dwBytesWritten;
HANDLE hFile;
dwFileSize = SizeofResource(hLibrary, hResource);
hFile = CreateFile("C://WINNT//TEMP//calc2.exe",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
WriteFile(hFile, lpBuffer, dwFileSize, &dwBytesWritten, NULL);
CloseHandle(hFile);
}
}
}
}
FreeLibrary(hLibrary);
}
}
int main(int argc, char* argv[])
{
ImportFile();
ExtractFile();
return 0;
}
转载于:https://blog.51cto.com/3135888/1202953