WannaCry勒索病毒分析

在WannaCry.exe的分析实战 里面我已经拿到了WannaCry.exe在资源文件中的PE文件,并且给它提了个名WannaCry_PE.exe文件。但在WannaCry.exe的分析实战,我通过动态分析WannaCry.exe释放了tasksche.exe(这个名字好拗口哦,我还百度了一下它中午是什么意思,塔斯克切),我这里就用它分析了,不用WannaCry_PE.exe分析了。

看一下服务程序和tasksche.exe时,发现mssecsvc2.0服务已上线,我在WannaCry.exe的分析实战,没有执行最后一步,为它获取进程,所以它不会启动。

#tasksche.exe的程序主体:

sub_401225是一个生成随机序号的函数

这段程序的流程:
if(_p_argc()== 2) -> if( _p_argv== ‘/i’)->if(sub_40185F)->if(copyFile,GetFileAttributesA)->if(sub_401F5D)->loc_40208E,然后正常退出。

_p_argc是返回主函数参数个数;_p_argv是返回参数;

当sub_401B5F返回创建目录成功则继续执行0x00402061。

CopyfileA()函数将现有文件复制到tasksche.exe,利用GetFileAttributesA()判断文件是否存在,存在则继续执行调用sub_401F50,不存在则跳转到loc_40208E。

如果 if( _p_argc() != 2) 或者 if ( _p_argv != ‘/i’) 或者 if ( !sub_40185F) 或者if(copyFile,GetFileAttributesA == -1) 或者 if ( !sub_401F5D)的时候,就跳转到 loc_40208E

strrchr(char*, ch); 用于匹配字符, ‘\’ 匹配到文件目录的最后一个 ‘\’ 停止,然后返回 ‘\’ 后面的字符,这里返回了\tasksche.exe,再调用strrchr()后,将bl(0x0)赋值给字符串\tasksche.exe后,返回tasksche.exe

sub_4010FD创建组成表项Software\WanaCrypt0r;
sub_401DAB释放资源到当前目录;
sub_401E9E读写c.wnry,将字符串拷贝到目标数组;
sub_401064创建要指定执行命令的进程;
sub_40170A加载Dll的函数API;
sub_4012FD构造函数;
sub_401437获取指定类型为三重DES的CSP,并且将密钥导入CSP;
sub_4014A6将t.wnry解密放到指定内存块中;
(篇幅太长了,剩下的我再续一篇)


sub_401225

Sub_401225通过GetComputerName()函数,让缓冲区Buffer接受检索本地计算机的 NetBIOS 名称。 当系统从注册表读取该名称时,会在系统启动时建立此名称。然后调用wcslen()返回NetBIOS的字符串长度,如果检索不到,返回为NULL,字符串长度也为空,然后就跳转到loc_4012A0。Pop ecx是将NetBIOS放到ecx中,JBE指令判断CF位和ZF位是否等于1。


这个循环过程是将主机号的每一个ASCII乘以项数再相加起来,(441)+(452)+(533)+…+(4AF)= 94F18000


将94F18000作为srand()的种子运算生成随机种子,然后再调用rand(),若不先调用srand()函数随机生成种子,直接调用rand()函数,rand()会自动设计种子是1,接下来产生的随机数也会相同。利用srand()函数生成的种子是026B05B8,rand()生成随机数0x6752。

Cdq指令是将eax的第31位(即最高位)填入edx里面,rand()返回的eax的最高位是0,edx也等于0。在call rand后,push一个8,然后pop ecx,又将8取出。我用VS写代码的时候都是直接将立即数放到寄存器里面,这里通过栈,我还是有点疑惑的。

Idiv ecx;使eax(rand()返回的随机数 6752)除以ecx(0x8),余数放到edx。将余数(0x2)+被除数(0x8),再test(实质是与运算)若小于等于0,则跳转到loc_4012D6,否则继续执行loc_4012C0。




将esi的值作为一个循环数,进入到loc_4012C0中,调用rand()函数,将rand()返回的值取余除以0x1A,余数+0x61反到新的局部变量中,然后偏移edi,使得局部变量组成字符串的形式。

将cmp edi,esi+3,再通过次方法循环随机得到字符串的后三位数,后三位数由rand() % 0xA + 0x30决定,最后,字符串的最后一位以’\0’结束。



我猜测,因为我是单击直接执行tasksche.exe而不是通过命令行使用参数,所以_p_argc返回的是0x1,所以接下来会执行jnz short loc_40208E。

sub_401B5F

Sub_401B5F子程序,开辟三个缓冲区,一个Buffer、一个FileName,一个WideCharStr;
1)调用MultiByteToWideChar()函数,将字符串转换成宽字符(即UTF-16),由缓冲区WideCharStr接收。

2)调用GetWindowsDirectoryW()函数,索引Windows目录地址,由缓冲区Buffer接收。

3)swprintf():”C:\Windows\ProgramData”,将WideCharStr与Buffer里的一起打印,由缓冲区FileName接收。

4)调用GetFileAttributesW()函数索引”C:\Windows\ProgramData”如果目录或者文件存在则返回成功,否则返回失败就跳转到loc_401C40。

5)sub_401AF6函数调用包括了CreateDirectoryW()用来创建目录, SetCurrentDirectoryW()设置进程当前的目录,SetFileAttributesW()设置文件或目录的属性,GetFileAttributesW()获取当前进程所有在的目录。

6)loc_401C40处判断C:\Windows\Intel是否存在,再调用sub_401AF6创建目录。若成功退出程序,若失败则创建其它目录,Buffer缓冲区的内容作为目录的lpPathname, WideCharStr缓冲区内容作为目录的lpFileName,创建目录。


sub_401AF6

sub_401F5D

retn sub_401CE8 && sub_401EFF || sub_401064 && sub_401EFF;

sub_401CE8

打开服务管理器,启动服务路径cmd.exe /c “tasksche.exe的FullPathName”,设置开机自启动服务dwStartType = 0x2。dwServiceType = 0x10服务运行在独立进程。
如果服务创建失败则跳转到sub_401064,否则继续执行sub_401EFF。

sub_401EFF

Sub_401EFF创建互斥量名称Global\MsWinZonesCahceCounterMutexA0,dwDesireAccess= MUTEX_ALL_ACCESS = 0x00100000,bInheritHandle = True。休眠时间3E8秒。

sub_401064

创建进程,StartupInfo结构体作为CreateProcess的参数,StartupInfo初始化其cb = 0x44h(结构体大小);wShowWindow = 0x0(隐藏窗口);dwFlags = 0x1(应用窗口设置)。设置CreateProcessA的参数dwCreationFlags = 0x8000000(创建不带窗口)。创建成功继续执行,WaitForSingleObject等待对象返回,检查响应是否超时;TerminateProcess终止进程。If(CreateProcess) -> if(WaitForSingleObject) ->TerminateProcess() , if(lpExitCode)-> GetExitCodeProcess


sub_4010FD

wcscat函数将字符串Software\WanaCry0r凑接到了一起作为RegCreateKeyW的lpSubKey参数传入(创建的密钥的名称),因为var_8等于0、esi也等于0,所以jnz跳转不执行,执行0x40116E,hKey = 80000002h (HKEY_LOCAL_MACHINE )。

如果RegCreateKeyW()函数创建注册表项成功,将返回0x0(ERROR_SUCCESS),phkResult存放着已经打开的已经创建好的项指针,如果phkResult为空则跳转loc_40120D,loc_40120D将var_8加一后与2比较,如果小于2,则跳转回loc_40115C,创建hKey = 80000001h(HKEY_CURRENT_USER)的组策表项。


若RegCreateKeyW()函数创建注册表项成功后,进入0x401189做判断,argc_0 = 1(参数传入时等于1)。

如果argc_0与esi相等时,RegQueryValueExA(phkResult, “wd”, 1, 1, &Buffer, 0x207);检索与打开的注册表项关联的指定值名称的类型和数据;返回成功同样为0x0(ERROR_SUCCESS)则执行SetCurrentDirectoryA(Buffer);设置为当前进程的目录,跳转到 loc_401200关闭注册表项的句柄,判断esi是否为0,不是则结束判断var_8是否小于2,是则跳回继续创建注册表项;否则直接跳转到 loc_401200关闭注册表项的句柄,判断esi是否为1,是则结束,不是则进入判断var_8是否小于2。

如果argc_0与esi不相等,GetCurrentDirectoryA(0x207, Buffer);RegSetValueExA(phkResult, “wd”, 0, 1, Buffer, strlen(Buffer) + 1);设置注册表项下指定值的数据类型和类型。将返回值赋值给esi,esi按位取反+1,sbb esi,esi,esi再加1;也就是当返回值=0时,esi=1;返回值=非0时,esi=0。随之跳转到loc_401200,关闭注册表句柄,判断esi是否等于1,等于1则结束,等于0则跳转至判断var_8是否小于等于2。

sub_401DAB

sub_401DAB传入参数WNcry@2o17和hModule = 0;

FindResourceA(0, 80Ah, “XIA”);返回XIA的句柄,LoadResource(0, esi);esi是XIA的句柄、返回指向资源第一个字节的句柄,LockResource(eax);Win XP留下的、将LoadResource返回的句柄转换成地址。


SizeofResource(hModule, hResInfo);返回Resource的大小,hModule是LoadResource()返回来的包含资源的模块句柄;
str:WNcry@2ol7; eax : 资源的大小; hFile : 资源的地址。sub_4074A4返回了一个地址,地址里存放着0x1,大概的作用不是很能确定(我都觉得我太菜了)

已知sub_4075AD返回0x1,如果不是0x1,则不在执行loc_401E0E,然后退出函数,所有,sub_4075AD的大概作用会不会是检索是否能解析资源。接着memset(Str1, 0, 0x44h * 4); sub_4075C4(Src、0xFFFFFFFF、1);在跳转指令jle short loc_401E8F前的test ebx, ebx;可以猜测sub_4075C4是否达到目的会通过Src存放的值判断。

sub_4075C4(Src、0xFFFFFFFF、1)调用后,Src存放了0x24h,则接下来不跳转到loc_401E8F。

再次调用sub_4075C4(Src, 0, 0x24),接着调用strcmp(Str1, c.wnry);所以,sub_4075C4会改变Str1,由局部变量分配地址紧挨着的原则来看,Str1在Src的地址+4(IDA识别出Src=dword ptr -12C,Str1=Byte ptr -128)。

sub_4075C4(Src, 0, 0x24); Src=0, Str1 = b.wnry;

如果Str1=c.wnry,则执行GetFileAttributesA(Str1);判断c.wnry的文件是否存在,不存在则返回-1跳转到不执行jnz short loc_401E8A,存在则执行jnz short loc_401E8A。

但目前Str1=b.wnry,所以将执行jnz short loc_401E79,调用sub_40763D(Str1, 0, 1);

若sub_40763D(Str1, 0, 1); 返回的edi + 1后,小于ebx(ebx是Src原来的值,0x24)则回到loc_401E41继续执行,

sub_40763D(b.wnry, 0, 1);调用后,返回了ecx=0x2501080、edx=0x02500000,不改变edi的值,所以继续执行,循环次数为0x24次。

在改变了edi=1后,回到loc_401E41,调用sub_4075C4(0, 1, 1);返回的Str1=c.wnry;Src=0x0,于是将会调用GetFileAttributesA(c.wnry); 返回0xFFFFFFFF,然后调用sub_40763D(c.wnry, 1, 1);返回值与调用sub_40763D(b.wnry, 0, 1)一样的效果。



跟踪过程中,发现它有多个语言标识的wnry。

当执行完最后一次

这个循环的作用是将这些文件从资源中释放到当前目录,解压密码是调用函数前传参的WNcry@2ol7。在当前目录有8个文件,在目录msg中,有28个文件,总共36个文件=0x24h,所以sub_4075C4的作用应该是匹配文件,sub_40763D释放文件到当前目录。

执行完循环后,调用sub_407656(1),sub_407656的作用应该是释放使用资源的堆。

sub_401E9E

sub_401E9E将c.wnry读写入Buffer里,字符串拷贝到destination里。

调用函数sub_401000(1, Buffer);如果调用返回0x0,执行jz short loc_401011退出函数。

当sub_401000返回成功,则调用函数strcpy(Destination, source[rand() % 3] )
随机取密钥字符串,
当rand() % 3 = 0时,:13AM4VW2dhxYgXeQepoHkHSQuy6NgaEb94。
当rand() % 3 = 1时,:12t9YDPgwueZ9NyMgw519p7AA8isjr6SMw。
当rand() % 3 = 2时,:115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn。


将115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn拷贝到局部变量Destination。


再次调用sub_401000时,参数改变成sub_401000(Buffer, 0), 调用的函数fopen(c.wnry, “wb”)和fwrite(Buffer, 30Ch, 1, fopen返回的指针); 然后跳出程序,fclose(fopen返回来的指针);

sub_401000

从这里,可以看出sub_401000是代码节的开始,它的参数arg_4 = 1和Buffer,因为arg_4 !=0,调用fopen(c.wnry, “rb”);对文件c.wnry以二进制方式读取,若读取不成功则返回NULL,结束函数。
若读取成功,则执行jnz short loc_40102D,再判断一次arg_4是否等于0,当arg_4 = 1是则调用fread(Buffer, 30C, 1, fopen返回的文件地址);写入失败返回NULL。当arg_4 = 0是则调用fwrite(Buffer, 30C, 1, fopen返回的文件地址);写入失败返回NULL。

sub_401064

调用了两次sub_401064, sub_401064(0, 0, attrib +h .);和sub_401064(0, 0, icacls . /grant Everyone:F /T /C /Q);

指定lpCommandLine创建进程的时候执行命令attrib +h .和icacls . /grant Everyone:F /T /C /Q。
atttib +h指的是文件/进程加以隐藏属性;
icacls . /grant Everyone:F /T /C /Q指的是为Everyone授予完全访问权限,并且对当前目录及其子目录中的所有指定文件执行操作、尽管存在任何文件错误,仍继续操作、禁止显示成功消息。

sub_40170A

sub_40170A的调用不带参数,然后判断返回值是否为0,为0则退出程序,不为空则继续执行并且调用sub_4012FD, sub_4012FD是一个构造函数,this指针通过ecx传参,返回值也为this;同时在调用sub_4012FD后还继续执行构造函数sub_401437。

sub_40170A调用了sub_401A45, 返回成功则加载kernel32.dll,加载成功后便获取添加文件、写文件、读文件、移动文件、删除文件、关闭操作句柄,的地址。并且判断它们是否全部创建成功,否则退出。


sub_401A45加载advapi32.dll, 并且获取:获取CSP、导入密钥、销毁密钥、加密、解密、随机加密密钥或公钥/私钥对,的地址。并且判断它们是否全部创建成功,否则退出。

sub_4012FD

sub_4012FD是一个构造函数,this指针通过ecx传参;
内部调用函数sub_4017D0,他同样也是构造函数,将this + 4通过ecx传参。
再将this + 2C通过ecx传参,调用sub_4017D0

将this + 0x54通过ecx传参,调用sub_402A46。将this+1C8、this+4CC、this+4D0、this+4D4都赋值0。将esi+0处赋值4081D8。

sub_4017D0

在esi = this + 4, 为其赋值4081EC,调用InitializeCriticalSection()初始化对象。


在esi = this + 2C, 为其赋值4081EC,调用InitializeCriticalSection()初始化对象。

sub_402A46

在eax = this + 0x58, 为其赋值0,在eax = this + 0x54,为其赋值40BC7C。

sub_401437

sub_401437同样也为构造函数,this同样通过ecx传参,ebx=0传入。如果sub_401437返回非0则继续往下执行。

在sub_401437里,调用了构造函数sub_401861(esi+4, lpFileName);由sub_4012FD返回得,esi+4 = 4081EC, lpFileName = 0。如果sub_401861返回值是非0,则继续执行,否则退出程序。

当sub_401861返回非0后继续判断lpFileName是否 = 0,若lpFileName = 0则直接跳转到loc_40145D调用GlobalAlloc(100000, 0);从堆中分配0x100000字节, 将分配成功后返回的指针放到this + 4C8处,若分配不成功则退出函数。

再次调用GlobalAlloc(100000, 0);将分配成功返回的指针放到this + 4CC处,并且跳转至loc_4014B9处,将this + 4D4和this + 4D0都置为0。最后eax=1,退出函数。

sub_401861

在sub_401861处调用了构造函数sub_40182C,如果返回值非0则继续往下执行。

在sub_30182C返回值=1时,函数执行到0x0040186D,判断lpFileName是否为0,不为0则跳转到loc_401890,否则跳转到0x00401875; 由于lpFileName是作为参数传入,并且为0,所以接着执行0x00401875。

在sub_401861中调用dword_40E898时传入参数:
BOOL CryptImportKey(
[in] HCRYPTPROV hProv,
[in] const BYTE *pbData,
[in] DWORD dwDataLen,
[in] HCRYPTKEY hPubKey,
[in] DWORD dwFlags,
[out] HCRYPTKEY *phKey
);

hProv : this + 0x8; 密钥导入到CSP容器。

pbData : 40EBF8; 包含 PUBLICKEYSTRUC BLOB 标头的 BYTE 数组,后跟加密密钥。

dwDataLen : 0x494; 包含密钥BLOB的长度。

hPubKey : 0; 使用CSP容器中的密钥加密,则hPubKey设置为0。

dwFlags : NULL; 在以 PRIVATEKEYBLOB 的形式将公钥/私钥对导入 CSP 时才设置dwFlags。

phKey : this + 0xC; 指向接收导入密钥句柄的 HCRYPTKEY 值的指针。


sub_4018F9也大致看了一下,它创建了文件,文件名为lpFileName,然后读文件和文件大小,并且调用dword_40E898。

当调用dword_40E898导入密钥成功后,跳转至loc_4018B2便可退出函数。

sub_4018B9是当导入密钥失败后,拿来销毁密钥而使用的,在OD里面可以识别出是CryptDestroyKey(),我在IDA里面替它更名了。

sub_40182C

判断eax是否等于负数,如果等于复数则调用40F894时将字符串Microsoft Enhanced RSA and AES Cryptogrneg eax作为参数,否则eax=0作为参数。neg eax将eax里面的值按位取反再加1,sbb eax, eax将eax自己减自己然后再减ZF位。

BOOL CryptAcquireContextA(
[out] HCRYPTPROV *phProv,
[in] LPCSTR szContainer,
[in] LPCSTR szProvider,
[in] DWORD dwProvType,
[in] DWORD dwFlags
);
phProv : this + 8; 获得指向 CSP 密钥容器的指针

szContainer : NULL;当 dwFlags 设置为CRYPT_VERIFYCONTEXT时, pszContainer 必须设置为 NULL;

szProvider : NULL; 使用用户默认提供程序;

dwProvType : 0x18; 指定获取类型PROV_DH_SCHANNEL 即DESTriple,三重DES加密;

dwFlags : 0xF0000000; CRYPT_VERIFYCONTEXT, 使用临时密钥。


返回成功将获取的CSP放于this + 8; eax = 1。

sub_4014A6

sub_4014A6是构造函数,this通过ecx传参,同样传参的有字符串t.wnry,这个函数可以猜想为利用this放入的密钥去解密t.wnry。

CreateFileA(t.wnry, 80000000, 1, 0, 3, 0, 0);其中dwCreationDisposition指的是文件存在时才能打开,不存在时返回打开失败。

当CreateFileA()返回成功后,调用GetFileSizeEx(hFile, lpFileSize); hFile是打开t.wnry后返回来的句柄,lpFileSize是个LARGE_INTEGER类型的结构体,它接收着getFileSizeEx()返回来的文件大小,(LARGE_INTEGER类型是一个联合体,它通过定义高32位和低32位来表示64位有符号整数),所以指令cmp dword ptr [ebp+FileSize+4], ebx; 来检查高32位是否有值,如果大于0或者小于0,则跳转至loc_4016D0然后退出函数。

再判断FileSize低32位也就是返回来的文件大小与0x0640000比较,如果大于0x06400000则退出函数;

调用函数dword_40F880(edi(句柄), Buf1, 8, var_1C, 0); 从OD中识别出是ReadFile,Buf1接收文件的前8字节,如果返回0,则退出程序;

当ReadFile返回非0时,调用memcmp(Buf1, “WANACRY!”, 8);将Buf1的前8字节与"WANACRY!"匹配,匹配成功返回0;

然后调用一次ReadFile(edi(句柄), Size, 4, var_1C, 0);

第一次调用完dword_40F880(edi(句柄), Buf1, 8, var_1C, 0);

调用memcmp(Buf1, “WANACRY!”, 8);匹配字符串

第二次调用ReadFile(edi(句柄), Size, 4, var_1C, 0);用Size再接收文件4字节;接着将Size和0x100比较,不相等则退出函数。


第三次调用ReadFile(edi(句柄), esi + 4C8, eax(0x100), var_1C, 0);利用this + 4C8再从文件中接收0x100字节的。

第四次调用ReadFile(edi(句柄), var_240, 4, var_1C, 0);利用var_240再从文件中接收4字节的。
0019F590是Size接收的,0019F594是var_240接收的,0019F598是Buf1接收的。

接着第五次调用ReadFile(edi(句柄), dwBytes, 8, var_1C, 0);利用dwBytes再从文件中接收8字节的。

dwBytes是qword类型,有4个word,将dwBytes + 4取其高32位,拿来判断高32位是否等于0,同时低32位不能大于0x06400000,否则退出函数。

接着调用构造函数sub_4019E1(this + 4, this + 4C8, Size, var_22C, var_2C)

调用sub_4019E1将解密工作和拷贝工作、赋值工作都正常执行后,退出返回1,接着就会继续执行调用sub_402A76和GlobalAlloc。

同样,从this通过ecx传参可看出,sub_402A76是构造函数,它的调用sub_402A76(this + 54, var_22C, Src, var_2C, 0x10h);其中,var_22C是我们调用sub_4019E1后解密返回来可读的0x10字节文本,var_2C是0x10h,Src是一个void* 类型的指针。

同时,这里还会调用GlobalAlloc(dwBytes, 0); dwBytes是0x10000h, 调用成功后,将会返回一块0x10000字节的内存地址,然后将内存地址放到var_20里,再判断它是否为0,如果为0则退出函数。

sub_4019E1

判断this + C上是否等于0,若等于0则退出函数,否则继续执行。
EnterCriticalSection将在调用this + 0x14的线程所有权时返回。EnterCriticalSection和LeaveCriticalSection是成对出现的。

接着调用dword_40F8A4(this + 0xC, 0, 1, 0, this + 0x4C8, Size);OD将dword_40F8A4识别出是CryptDecrypt;
BOOL CryptDecrypt(
[in] HCRYPTKEY hKey,
[in] HCRYPTHASH hHash,
[in] BOOL Final,
[in] DWORD dwFlags,
[in, out] BYTE *pbData,
[in, out] DWORD *pdwDataLen
);

hKey : this + 0xC; 用于解密的句柄

hHash : 0; 未执行过Hash

Final : 1; 一个布尔值,该值指定是否是正在解密的序列中的最后一节。 如果此值是最后一个或唯一块,则此值为 TRUE 。

dwFlags : 0;

pbData : this + 0x4C8; 解密存放在this + 0x4C8的那0x100字节。

pdwDataLen : Size; 解密长度0x100字节。调用CryptDecrype之前,pdwDatalen为要解密的字节数。 调用后, Size为包含解密的纯文本的字节数。

这是解密0x100字节后的数据。

dword_40F8A4解密后,返回成功,则跳转到loc_401A1D

由于调用CryptDecrypt后Size返回了解密后可读的文本字节数,所以Size不再是原来的0x100h,从OD里可以跟踪到是10, Src是this + 4C8,var_8是var_22C。调用memcpy(var_22C, this + 4C8, 0x10), 将this +4C8解密后可读文本的0x10h拷贝到var_22C。

再将arg_C赋值为Size的0x10h, arg_C就是var_2C。eax返回1。


WannaCry勒索病毒分析 **下**相关推荐

  1. WannaCry勒索病毒分析过程**中**

    WannaCry勒索病毒分析 中 为了分析WannaCry.exe有着什么样的行为,以及它是如何释放WannaCry_PE.exe程序的,在IDA中打开WannaCry.exe 我们可以发现它的头是W ...

  2. WannaCry勒索病毒分析过程**中**(注)

    WannaCry勒索病毒分析 中(注) 我犯了一个很大的错误,就是在做分析的时候没有确定函数的作用,在分析过程中有捉不到重点的毛病. 在WannaCry.exe的分析中,它在判断打开它的URL后,如果 ...

  3. WannaCry勒索病毒分析过程**上**

    WannaCry勒索如何分析实战 上 我的第一篇博客文章 作为一名大四的网络工程应届毕业生,发自内心的感谢网上的每一位博主,感谢网上的每一位大佬愿意分享自己的经验.我才可以在网上学到如此多的知识.我在 ...

  4. [系统安全] 二十六.WannaCry勒索病毒分析 (2)MS17-010漏洞利用及蠕虫解析

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  5. [系统安全] 二十七.WannaCry勒索病毒分析 (3)蠕虫传播机制解析及IDA和OD逆向

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  6. [系统安全] 二十八.WannaCry勒索病毒分析 (4)全网“最“详细的蠕虫传播机制解读

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  7. WannaCry 勒索病毒复现及分析,蠕虫传播机制全网源码详细解读 | 原力计划

    作者 | 杨秀璋,责编 | 夕颜 来源 | CSDN博客 头图 | CSDN 下载自东方 IC 出品 | CSDN(ID:CSDNnews) 这篇文章将详细讲解WannaCry蠕虫的传播机制,带领大家 ...

  8. WannaCry勒索病毒复现及分析,蠕虫传播机制全网源码详细解读 | 原力计划

    作者 | 杨秀璋 编辑 | 夕颜 题图 | 东方 IC 出品 | CSDN(ID:CSDNnews) 这篇文章将详细讲解WannaCry蠕虫的传播机制,带领大家详细阅读源代码,分享WannaCry勒索 ...

  9. [网络安全自学篇] 七十.WannaCry勒索病毒复现及分析(三)蠕虫传播机制分析及IDA和OD逆向

    这是作者网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您们喜欢,一起进步.前文分享了宏病毒相关知识,包括宏病毒基础原理.防御措施.自发邮件及APT28样本分 ...

最新文章

  1. ISA SERVER使用指南
  2. UITextField的属性与程序启动后一系列方法
  3. linux-centerOs6.8安装nginx与配置
  4. php5.5 mysql网站空间_PHP环境配置IIS5.0+PHP5.23+MYSQL5+phpMyAdmin
  5. 【数据结构与算法】常用算法
  6. [html] html的开始与结束标签嵌套错误会导致哪些问题?
  7. Beta 冲刺 (4/7)
  8. python 多进程 每个进程做不同功能实例_Python 多进程并发操作中进程池Pool的实例...
  9. Design Pattern: Adapter 模式 - Object Adapter
  10. fail-fast机制
  11. 拓端tecdat|r语言中如何进行两组独立样本秩和检验
  12. 8种排序算法(Java实现)
  13. html文件是fla,FLASH 全屏、按ESC 退出全屏模式Fla及HTML源文件
  14. 拓扑排序算法C++实现
  15. 基于CNN-LSTM的手写数字识别与应用实现(附tensorflow代码讲解)
  16. 根据前序序列和中序序列重建二叉树
  17. N-BaIoT-Network-based-Detection-of-IoT-Botnet-Attacks
  18. P1228 地毯填补问题(Java语言实现)
  19. Groovy脚本基础全攻略
  20. OracleTechnologyNetwork

热门文章

  1. 面试到了“IT大佬”,怼得我哑口无言…
  2. c++常用的 math 函数讲解
  3. 数字化转型中基于交付价值数据治理的6大原则
  4. Ubuntu18.04 同一个程序显示两个图标,收藏夹图标不合并问题解决
  5. USB 为什么一般选择48MHz
  6. mysql中selec sum返回null的解决方法
  7. [解决问题]注册表修改windows用户名后,vscode以前的扩展消失
  8. [工具]利用EasyRTSPClient工具检查摄像机RTSP流不能播放原因以及排查音视频数据无法播放问题...
  9. 如何禁止电脑随便修改IP?
  10. 合并两个工作表怎么做?