Final
0.
我们首先对这个程序做一下初步的静态分析,string查看一下,发现这里出现了一个URL,还有一些导入函数的名称,但是在这里分析这些导入函数并不是很方便,我们打开dependency walker,这里有很多这个程序使用了很多函数,通过它调用函数的内容,就可以初步判断它的行为。可以发现这里有一个创建文件的函数createfile,接着还有创建远程线程的函数CreateRemoteThread、下面还有findresourse、loadresource这样子的操作,
还进行了文件移动,文件执行的操作,接下来就是一些调整权限的操作
资源节里面是什么东西呢?可以用resourse hacker打开看一看,通常的资源都是图标阿之类的,在这里有一个资源,这里的可以看到有MZ头和PE标识符,可以看出这是一个PE文件。先导出这个资源,命名为clues.exe,用于接下来的分析
1.
接着我们用IDA和OD打开这个程序,动态分析一下程序的行为。首先看到这里,程序的开始部分进行了这样一个操作:从psapi.dll里面连续调用了三个函数EnumProcessModules、GetModuleBaseNameA、EnumProcesses,这里可以把这三个函数的地址进行一下重命名的操作
2.
接着函数就会检查这三个函数能否调用成功,调用成功(返回结果都不为零),程序才开始调用EnumProcesses用于枚举当前的进程,这个函数有三个参数
一般我们可以到微软官网查,但是因为翻译的原因有一些意思还是比较晦涩难懂,那怎么办呢?就像这里我在查的时候就分不清The size of、The number of的区别,那怎么办呢,这个时候就可以用OD调试来看一下这些参数到底是什么
我们回来看一下这个函数大致是在401423的位置,在OD中找到这个位置,可以看到这里就是调用了403124也就是EnumProcesses,在这里设一个断点,然后跳到它的其中一个参数,当前EAX所指向的地址中去,然后运行一下这条调用函数,这里就是返回数组的字节数,相隔4个字节的位置就是ECX的值,也就是返回列表的起始地址。
这里第一个参数:数组的起始地址。第二个参数:数组的大小,第三个参数:数组返回了多少个字节(运行过程中是88)
3.
前面是一些赋值的操作 mov mov
接着可以看到这里有一个比较特别的地方,就是这个箭头比较多的情况都是上往下指的,这里有一个下往上指的情况,说明这里经历了一个循环,这个循环就是将我们获取到的pid表进行遍历,并通过这样的一个公式取出每一个pid值,作为参数传递到子函数401000中。
加油来OD中调试一下这一段,这个还是我们之前停止的位置,我们来看一下这个公式,这里的ebp加后面的这一串,IDA中解析的是ProcessId就是这个pid列表的起始地址,接着这个eax乘4这里的eax是累加器,记录的是循环的次数,当我们第一次进入这个循环的时候eax是1,那么eax乘4就是4,刚好列表开始地址+4的位置就是我们第一次取出来的值,下一次循环的时候eax是2,eax乘4就是8,这个位置刚好就是我们下一次要取出的值
4.
接着就是进入401000
40100有一个参数,是主函数传递过来的processid
这里是一些初始化的操作
接着就是将数据节403010附近的数据转移到了内存中,也就是函数运行的过程中变量str1和str2的值,选中这里,让IDA帮我们解析一下这里的内容,我们看这里的内容时候要从左到右看,这里winl ogon .exe 就是str2的内容,这里not r eal就是str1的内容
接下来就是rep store 进行一段内存初始化的操作,从ebp+var10D的地方对3E大小的区域进行置零的操作
接着可以看到程序将dwprocessID,作为openprocess的一个参数,以来打开这个进程。可以看到这个函数没有out,都是in,
所以函数返回值就默认是在eax里面,接着这个eax赋值给了hObject,双击一下hObject,往下看可以看到下面hObject又作为了我们手动改名的EnumProcessModules的参数,这个函数又两个输出,一个是句柄列表的开始地址hObject,另外一个是数组的大小eax,
目前我们不知道这两个东西究竟有什么用,可以看到下面的这个函数,这两个函数其实是配合使用的,从这里可以看到下面一个函数的参数其实需要用到上面函数的返回值,他们两个配合使用的目的是得到当前processid对应的进程名,返回值存到了str1中
【OD】
下面就是将str1和str2进行比较,也就是当前pid的名称与我们要找的目标winlogon.exe进行比较,如果两者相同,就走我图中标注的1号路径。1号路径和2号路径的区别在于成功就将eax置1,失败就将eax置零。值得注意的一点是_stricmp比较时,两者相同是0不同是1,但是经过这里处理后就变成了两者相同返回值置1,不同置0
5.
分析完401000,回到我们的主函数
jumpzero,如果是0(找不到也可以理解成str1、str2两者不同)的话就进入这一条分支到4014cf的位置,继续下一次循环,如果是1(找到winlogon也可以理解成str1、str2两者相同)的话就进行右边这一条分支
右边的话又将processID的值,也就是winlogon.exe的pid,传递给了401174
ADD
修改完成后是这样子的
回到IDA中,继续分析程序的主函数
加油来OD中调试一下这一段,这个还是我们之前停止的位置,我们来看一下这个公式,这里的ebp加后面的这一串,IDA中解析的是ProcessId就是这个pid列表的起始地址,接着这个eax乘4这里的eax是累加器,记录的是循环的次数,当我们第一次进入这个循环的时候eax是1,那么eax乘4就是4,刚好列表开始地址+4的位置就是我们第一次取出来的值,下一次循环的时候eax是2,eax乘4就是8,这个位置刚好就是我们下一次要取出的值
6.401174?
我们进入401174这个函数看一下,这个函数只有一个参数,就是找到的winlogon的pid
可以看到刚开始就有一个调用了函数4010fc。这个函数4010fc里面是做什么的呢?可以从它调用的函数判断一下它的行为
可以看到4010fc里面先是GetCurrentProcess、OpenProcessToken这两个函数配合使用,打开了winlogon的令牌,然后通过LookupPrivilegeValueA寻找了权限值,然后AdjustTokenPrivileges,调整了权限,恶意程序一般都是通过调高权限,从而开展恶意行为
接着我们回到上一级函数
可以看到这里的双call和双call的这两个函数和我们前面分析到的结构非常相像,除了相同之处,他们还存在着细微的差别:前面这个是按照函数名来调用的,现在这里是通过函数的序号来调用的,这里调用了sfc_os.dll的第二个函数。我又想起了我们课程刚开始的时候学习的导入表,导入表的桥一和桥二,其中桥一是按照函数名字导入的,桥二是按照函数序号导入的。为什么这里不通过函数名称来调用呢,这里我用stuPE打开一下,可以看到sfc_os.dll的第二个函数竟然没有名称,所以他不能通过名称只能通过序号来调用函数。
我找了一下这个函数,资料是这样子说的,这个2号函数就是终止SFC(System File Checker)监视线程,也就是破坏Windows系统文件保护功能,我看了一下其他的函数,好像没有恢复系统文件保护功能的这个函数,那么你不幸被这个病毒的变种感染了怎么办呢?后面我会介绍一下处理的方法
回到程序中,这里获取到了这个编号为2函数的地址,存到了【】lpStartAddress中,下面又调用Openprocess利用这个子函数的参数PID作为输入获取到了winlogon.exe的句柄,并存到了【】hProcess中,我们看到这个资料有这样一个提醒:使用这个函数有一个警告:它必须在创建SFC监视线程:winlogon的进程中调用。这里CreateRemoteThread就实现了这个条件,传入的第一个参数是winlogon.exe的句柄,第四个参数是sfc_os.dll编号为2函数的地址
到这里401174就分析完了
7.
回到主
前面的功能主要实现的是找到winlogon的pid,它们调用函数的时候大多数都有一个关键的链条:processid,找到winlogon之后关闭系统文件保护,
如果成功地关闭了系统文件保护,
接下来是获取系统中windows目录的路径GetWindowsDirectoryA,接着就是将windows目录作为一个参数,\system32\wupdmgr.exe作为另外一个参数,调用_snprintf对它们进行拼接,保存到了ExistingFileName中
接下来就调用了GetTempPathA获取了系统的临时文件夹的路径,将这个作为一个参数,\winup.exe作为另外一个参数,将他们拼接,保存到了第一个参数NewFileName中
从这个变量名就可以判断出是从那给位置移动到了哪个位置:从ExistingFile移动到了NewFile中,也就是windows目录下的\system32\wupdmgr.exe的内容移动到了temp目录下的\winup.exe中
8.
movefile的下一行call 4011FC表明程序调用了子函数4011fc,进一下4011fc
前面这一部分是对栈帧进行调整,接着对一些变量赋初值,从[ebp+var_11B处开始,送43h个0,这些对我们目前的分析都不重要,都是一些初始化的操作
这个函数刚刚就出现过,其实我感觉这个地方是在做重复的事情,是不是可以让filename直接等于ExistingFileName会不会更好一些。
接着调用了GetModuleHandleA,这个函数的唯一一个参数:进程的信息,如果为空,那么返回用于创建调用进程的句柄(目前正在执行的程序的句柄,哪个程序调用了这个函数,那么返回的句柄就指向这个程序的起始地址),在程序运行的过程中中返回值是400000(lab01-04的入口地址是400000,可以到40000来调用lab01-04)
LoadResource,顾名思义,就是找到纯资源节的位置把资源区给加载出来
SizeofResource,返回值为纯资源节的大小,此程序中返回值是4000
通过下面的createFileA和WriteFile可以知道是将这些资源进行了写入,写到哪里了呢?CreateFileA有写入的位置也就是这个filename存的路径中,本来wupdmgr.exe是属于系统保护的文件,但是由于之前以及调用了SfcTerminateWatcherThread终止SFC(System File Checker)监视线程函数,文件保护机制被破坏,于是wupdmgr.exe就能被此程序进行资源节写入的操作,等一下的验证环节我们来验证一下运行后资源节是不是写入了wupdmgr
最后调用了winexec,执行什么呢?执行了filename这个路径的文件也就是windows目录下的\system32\wupdmgr.exe。以隐藏窗口的方式运行了这个程序"C:\WINDOWS\system32\wupdmgr.exe",激活另一个窗口(IE浏览器)
回到主函数,4011fc完就是函数的结束部分了
验证环节
接着我们分析一下从资源节释放的这个wupdmgr,先将资源节导出重命名为101.bin,然后我们运行一下lab01-04,得到wupdmgr,将这两个东西做一下摘要,发现两者的摘要相同,说明这两个是同一个文件,
运行了lab01-04会开启一个更新的网址,在运行这个程序之后我提出了三个猜想,结合前面的分析,目前明确的是这一点:程序快要结束的地方,子函数4011FC里面调用WinExec运行了windows目录下的那个通过资源节写入的wupdmgr("C:\WINDOWS\system32\wupdmgr.exe"),接下来再分析一下这个从程序中释放的wupdmgr到底在做什么
IDA打开这个,可以看到程序一开始就获取了临时文件夹的路径,并将这个路径与winup.exe调用snprintf进行拼接,接着就用WinExec,来执行了这个目录下的程序,然后可以看到这个程序获取了windows目录,并且将这个目录与\system32\wupdmgrd.exe进行组合,可以看到这里与我们之前看到的wupdmgr相比多出了一个D,可以看到下面调用了有下载功能的函数URLDownloadToFileA,顾名思义,就是从url下载文件,这里这个函数的一个参数就是一个网站,然后把下载的内容存在第三个参数DEST中,也就是拼接好的这个路径中,我们来验证一下是不是我们分析的这样
由于这个网址已经失效,我就自己在本地搭一个网站,网站中放置一些下载的资源;修改一下lab01-04运行后的下载地址,可以看到这次运行完lab01-04后多出来了一个wupdmgrd,做一下摘要,就是我们在网站中上线的资源
接着我讲解一下windows文件保护机制被破坏,wupdmgr被恶意篡改以后的解决方法,关于文件保护机制被破坏,这里给出了针对这种攻击的解决方式,CreateRemoteThread和WFP将被禁用,直到winlogon进程重启(计算机重启)。首先把这个wupdmgr删除掉,一般重启,之后就能解决,如果还是不能解决,可以使用sfc scannow进行系统文件的检查。这里我演示的是在虚拟机中的处理情况,需要提前下载好一个相应版本的镜像文件,下载之后要让虚拟机载入这个镜像文件,看到这个画面就说明镜像文件载入成功。接着在命令行中运行sfc/scannow,这里运行的时间很长啊,我就做一个加速的处理了。完成上述两个步骤后,问题就被修复了
运行完成后发现wupdmgr变成了原来的图标,程序也变成了原来的程序,我的演示到此结束。