exe程序捆绑运行的设计实现

#程序拼接软件研究与实现

第一作者:李松 第二作者:薛野

##研究背景
近些年病毒程序越来越猖狂,各种病毒更是和普通的安装程序绑定在一起,让一般用户(特指一般不去官网下载而且不验证MD5的用户),很容易在安装一般程序的时候顺手运行了黑客设计的病毒程序。这种用户主动运行病毒程序的方式让整个的入侵过程防不胜防。作为一个信息安全学习人员,我们在这里就研究一下怎么绑定程序自动后台运行两个程序。

##材料准备
普通安装程序 1;
模拟病毒程序
1;
Visual Studio IDE 1;
Visual Studio 程序序列号
1;
MS提供的c#编程语言

##程序设计

###开始阶段
开始的时候,我的小组程序设计是这样的。
1,肢解正常的安装程序;
2,在原来的安装程序资源中加入病毒程序;
3,用一些不知道怎么方法的方法运行起来病毒程序。
后来经过各种尝试和研究,发现第三步出了问题。虽然我们可以很容易的把正常安装程序肢解并且把病毒程序打包到安装程序中,而且外观上看不出什么问题来。但是悲剧的是运行安装程序的时候也没有什么问题(病毒程序根本不会运行)。这里也是我自己基础知识太薄弱。程序的最开始引导部分根本就不会有运行后边病毒的指令,怎么会运行病毒程序呢。

###程序设计
后来的时候,我们小组有重新设计了新的程序;
1,提取正常安装程序的图标;
2,把病毒程序拼接到正常程序后边;
3,重新写一个新的控制程序,运行的时候让他拆开后边两个程序(正常安装程序以及病毒程序)并且相互独立运行;
4,把控制程序拼接到程序的最前端;
5,替换这个控制程序的图标。
总体来说就是这样的。
pic1
后来发现控制程序根本很难知道正常程序的起始位置和病毒程序的起始位置。在此之后我曾经很想让控制程序自动找到正常运行程序的起始特征标识以及病毒程序的特征标识,后来失败了。最终采取了另外的策略,在捆绑程序的时候,我们算好了正常程序和病毒程序的大小。然后把它们记录好了,放在病毒程序的后边,一共8个字节,记录了两个int,也就是病毒程序和正常程序起始位置相对于程序开始的偏移量。这样通过读取最后的两个位置,我们就可以直接找到正常程序和病毒程序的起始位置了。图示如下:
pic2

###代码编写
写代码的时候问题最多。

####拼接程序:
1,各种按键,各种头文件,各种界面设计代码一律省略;
2, CBoundTryDlg::OnBnClickedOk()
这个东西是捆绑过程的核心,在这个里边实现了程序的大小检测,程序的拼接以及最 后的大小记录。关键代码贴出来看看就好:

1
2
3
4
5
6
7
8
9
10
11
12
VirusFile.Read(pbyVirusFile, dwVirusFileLength);
//就像上边这样把程序文件读进内存,然后记录程序大小。
DWORD dwInfectFilePos = dwContralFileLength;
DWORD dwInfectFilePos1 = dwContralFileLength + dwInfectFileLength;
//像这样记录好程序的起始位置,这里contral竟然拼写错了。
//这里dwInfectFilePos 就是正常程序的偏移量,也就是control(控制程序)的大小。
//dwInfectFilePos1 就是病毒程序的偏移量,也就是control + 正常程序的大小。
TargetFile.Write(pbyContralFile, dwContralFileLength);
TargetFile.Write(pbyInfectFile, dwInfectFileLength);
TargetFile.Write(pbyVirusFile, dwVirusFileLength);
TargetFile.Write(FileInfo, sizeof(FileInfo));
//上边就是写入文件的过程了。

3,更换图标
这一块难度很大。想了很多代码。过程如下:
1,可以通过图标句柄制造出一个图标,然后按到程序里边;
2,可以扫描程序图标造出一个新的图标,然后按到程序里边;
3,直接在程序中查找图标,按到新的程序里边。
前两个方案经过一整天的实验宣告失败。可能是由于对于程序句柄以及图标处理了解 太少。后来从网上找到了第三种方案的代码,读懂之后稍作修改,实现了该功能。
控制程序:
这个东西技术含量比较大。最大的问题就是:程序运行的时候很难测试
这个程序的核心在于,拆解这个程序后边的部分,把一个大的程序拆解然后运行。
需要在这个控制程序本身的末尾找到标明正常程序和病毒程序偏移量的两个int。
问题是写代码的时候根本没办法调试啊!程序一跑起来,怎么可能在debug的时候在自己本身的最后边找到这两个int呢。因为写入这两个int以及把整个最后的程序组装起来的试前边说的拼接程序,写这部分代码的时候根本没有后边的程序啊。
详细说明如下:
pic2
在控制程序编写过程中,debug生成的程序仅仅是控制程序部分。一旦运行起来,他就要去找最后的“正常程序和病毒程序的位置”,然后现在还没拼接呢,根本不存在啊。接下来去找偏移量肯定会报错了。因为这一块内存已经不归控制程序管了。
最后我机智的用了另外一个小程序代替控制程序,先运行前边的拼接程序,组成一个用于实验的结构完整的拼接好的程序。然后把代码写成这样:
exeFullPath = “E:\res.exe”;
也就是试验中控制程序控制的目标是这个结构完成的虚拟程序,而不是自己。调试好各个拆分点等等,最后在改成控制本身就可以了。
关键代码如下:

1
2
3
4
5
LogFile.Seek(-8,CFile::end);
CString strBuf,strBuf2;
LogFile.Read(strBuf.GetBufferSetLength(4),4);
LogFile.Seek(-4, CFile::end);
LogFile.Read(strBuf2.GetBufferSetLength(4), 4);

在程序的结尾读出8字节的记录信息,然后存储好当做位置用。

1
2
3
4
5
strExecFilename1= "1.exe";
strExecFilename2= "2.exe";
strEncrypt=strBuf.Mid(0,8);
memcpy(&dwFirstLength,strBuf.GetBuffer(4),4);
memcpy(&dwSecondLength,strBuf2.GetBuffer(4),4);

根据上边得到的偏移量信息,找到拆分点。
然后拆分运行就可以了。

###程序隐藏
程序隐藏部分按说是比较容易处理的。直接开启隐藏进程就可以了。但是不知道为什么,一旦开起了隐藏,直接程序就不能正常跑了。全部程序都隐藏起来了。这里代码有一点问题,还在调试过程中。

##最后的收获
1,老师说得对啊,自己做的才最有收获,自己研究的才最能提升;
2,设计程序的时候一定要基于在对本程序机理的理解的前提下设计,贸然动手只会浪费时间;
3,对于很多东西自己上网查找很靠谱,按照自己设计的路线有时候根本行不通;
4,这下算是对于exe格式的程序有了更多的了解。知道了怎么写出来捆绑安装的程序了。而且是静默的捆绑安装,不是简单的程序打包。
5,团队给了我无限的创意和力量!
6,程序隐藏真心任重而道远,接下来的程序加壳脱壳更是难以设计。这方面知识欠缺的太多了,急需要补充一下。

Contents
,