恶意代码的分类包括计算机病毒、蠕虫、特洛伊木马、后门程序、Rootkit、流氓软件、间谍软件、广告软件、bot、漏洞利用等。有些技术是经常使用的,有些是不可避免的。

恶意代码常见的功能技术有:进程遍历、文件遍历、击键记录、后门、桌面截屏、文件监控、自删除、u盘监控。知己知彼,百战不殆。这里的目的是为反病毒工程师提供参考。请绕过病毒作者。

进程遍历进程遍历获取计算机上所有进程(用户进程、系统进程)的信息,通常是为了检索受害进程,检测其是否运行在虚拟机中,是否存在软件查杀等。有时反调试技术也会检测进程名。所以进程遍历在恶意代码中很常见。

具体流程:

1、调用CreateToolhelp32Snapshot获取所有进程的快照信息。之所以称为快照,是因为保存了之前的信息,这个函数返回进程快照句柄。

2、调用Process32First获取第一个进程的信息,返回的进程信息保存在PROCESSENTRY32结构中。该函数的第一个参数是CreateToolhelp32Snapshot返回的快照句柄。

3、调用Process32Next从进程列表中获取下一个进程的信息,直到Process32Next函数返回FALSE且GetLastError的错误代码为ERROR_NO_MORE_FILES,则遍历结束。

4、关闭快照句柄并释放资源。

遍历线程和进程模块的步骤与上面类似。线程遍历使用Thread32First和Thread32Next,模块遍历使用Module32First和Module32Next。

源代码实现:

# include ' enum info . h ' void show error(char * lpszText){ char szErr[MAX _ PATH]={ 0 };* wsprintf(szErr,' %s错误[%d]'lpszText,GetLastError());#ifdef _DEBUG :MessageBox(NULL,szErr,' ERROR 'MB _ OK);# endif } BOOL enum process(){ process entry 32 pe32={ 0 };pe32 . dwsize=sizeof(process entry 32);//获取所有进程快照句柄HProcessSnap=:Create tool help 32 snapshot(th 32 cs _ snap process,0);if(INVALID _ HANDLE _ VALUE==hProcessSnap){ ShowError(' createtoolhelp 32 snapshot ');返回FALSE}//获取快照中的第一条信息BoolBret=:Process 32 first(HProcess snap,PE32);While (bRet) {//显示进程id printf ('[%d]'pe32 . th32 processid);//显示进程名printf('[%s]'pe32 . SZ exefile);//获取快照中的下一条信息bret=:process 32 next(HProcess snap,PE32);}//关闭句柄:Close handle(hProcessSnap);返回TRUE} BOOL enum thread(){ thread entry 32 te32={ 0 };te32 . dwsize=sizeof(thread entry 32);//获取所有线程快照句柄Hthread Snap=:Create tool help 32 Snapshot(th 32 cs _ Snap thread,0);if(INVALID _ HANDLE _ VALUE==hThreadSnap){ ShowError(' createtoolhelp 32 snapshot ');返回FALSE}//先获取快照BoolBret=: Thread 32中的第一条信息(Hthread Snap,Te32);While (bRet) {//显示所有者进程id printf ('[%d]'te32.th32所有者进程id);//显示线程ID printf ('[%d]'te32.th32线程ID);//获取快照中的下一条信息bret=:Thread 32 Next(Hthread Snap,Te32);}//关闭句柄:Close handle(hThreadSnap);返回TRUE} BOOL EnumProcessModule(DWORD dwProcessId){ moduleentry 32 me32={ 0 };me32 . dwsize=sizeof(moduleentry 32);//获取指定进程的所有模块的快照;handle h module Snap=:Create tool help 32 Snapshot(th 32 cs _ Snap module,dwprocessID);if(INVALID _ HANDLE _ VALUE==hModuleSnap){ ShowError(' createtoolhelp 32 snapshot ');返回FALSE}//先获取快照BoolBret=: Module 32中的第一条信息(HMODULE Snap,ME32);While (bRet) {//显示processid printf ('[%d]'me32 . th32 processid);//显示模块加载基址printf ('[0x% p]'me32 . modbase addr);//显示模块名称printf('[%s]'me32 . SZ module);//获取快照中的下一个信息。bret=:Module 32 Next(HMODULE Snap,ME32);}//关闭句柄:Close handle(hModuleSnap);返回TRUE}

文件遍历操作几乎是所有恶意代码的必备功能。木马病毒窃取机密文件,然后打开秘密端口。(之前看到有人问怎么识别卡莉渗透组的木马。其实有一个简单的方法。几乎所有的木马都要和攻击者的主机进行通信。这是一种检查打开了哪些陌生端口的方法。).

即使在R0下,也经常创建读写文件,经常使用file函数。文件搜索功能主要通过调用FindFirstFile和FindNextFile来实现。

特定过程

1、调用FindFirstFile函数,该函数接收文件路径,第二个参数指向WIN32_FIND_DATA结构的指针。如果函数成功,则返回搜索句柄。该结构包含文件的名称、创建日期、属性、大小和其他信息。

当返回结构中的成员dwFileAttributes为FILE_ATTRIBUTE_DIRECTORY时,表示返回一个目录;否则为文件,根据cFileName获取被搜索文件的名称。如果需要再次搜索目录中的所有子目录文件,则需要判断文件属性。如果文件属性是directory,则继续递归搜索以搜索其目录下的目录和文件。

2、调用FindNextFile搜索下一个文件,根据返回值判断是否搜索到文件。如果没有,文件遍历结束。

3、搜索完成后,调用FindClose函数关闭搜索句柄并释放资源缓冲区中的资源。

源代码实现:

# include ' STD afx . h ' # include ' file Search . h ' void Search file(char * PSZ directory){//搜索指定类型的文件DWORD dwBufferSize=2048char * pszFileName=NULLchar * pTempSrc=NULLWIN32_FIND_DATA文件数据={ 0 };BOOL bRet=FALSE//申请动态内存PSZ filename=new char[dw buffer size];pTempSrc=new char[dw buffer size];//构造一个搜索文件类型字符串,*。*表示搜索所有文件类型:wsprintf (pszfilename,' % s \ *。*,PSZ directory);//搜索第一个文件handle file=:FindFirst file(PSZ filename,file data);if (INVALID_HANDLE_VALUE!=hFile) {do {//过滤出当前目录“.”和前一个目录''否则将继续进入无限循环来遍历if(' ')==file data . cfilename[0]){ continue;}//拼接文件路径:wsprintf (ptemp src,' % s \% s 'pszdirectory,file data . cfilename);//判断是目录还是文件if (filedata。dwfile attributes file _ attribute _ directory){//目录,继续向下递归遍历文件search file(pTempSrc);} else {//file printf('%s 'pTempSrc);}//搜索下一个文件} while (:Findnextfile (hfile,filedata));}//关闭文件句柄:FindClose(hFile);//释放内存delete[]pTempSrc;pTempSrc=NULL删除[]PSZ filename;pszFileName=NULL}击键记录收集用户所有的击键信息,区分哪些关键信息类似于账号、密码等。并窃取密码。这里,原始输入模型用于直接从输入设备获取数据并记录击键信息。

为了接收设备原始输入WM_INPUT消息,应用程序必须首先向RegisterRawInputDevice注册原始输入设备,因为默认情况下,应用程序不接受原始输入。

特定过程

1、注册原始输入设备

应用程序必须首先创建一个RAWINPUTDEVICE结构,该结构指示它要接受的设备类型,然后调用RegisterRawInputDevices来注册原始输入设备。将RAWINPUTDEVICE结构的成员dwFlags的值设置为RIDEV_INPUTSINK,这样即使程序不在焦点窗口中,它仍然可以接收原始输入。

2、获取原始输入数据

在消息流程中调用GetInputRawData来获取设备的原始输入数据。在WM_INPUT消息处理函数中,参数lParam存储原始输入的句柄。这个时候可以直接打电话。

GetInputRawData函数,根据句柄获取RAWINPUT结构数据。

DwType表示原始输入的类型,RIM_TYPEKEYBOARD表示键盘的原始输入,Message表示对应的窗口消息。WM_KEYBOARD表示普通按键消息,WM_SYSKEYDOWN表示系统按键消息,VKey存储键盘按键数据。

3、保存关键信息

GetForegroundWindow获取关键窗口的标题,然后调用GetWindowText根据窗口句柄获取标题并保存在本地文件中。

源代码实现:

恶意代码的存在并不是因为黑客等手段,主要是我们在开发过程中很多情况下会用到这种技术,所以请用技术做正确的事情!

另外,对于编程学习伙伴来说,如果想更好的提升自己的编程核心能力(内功),不妨现在就开始!

原标题:C/C恶意代码盘点(一):进程遍历木马病毒和密码记录。

文章来源:【微信微信官方账号:C语言编程学习基地】欢迎添加关注!请注明文章出处。

审计彭静