您的位置:首页 > 编程语言

恶意代码分析实战 Lab 9-1 习题笔记

2017-11-13 17:48 344 查看

Lab 9-1

问题

1.如何让这个恶意代码安装自身?

解答: 这个既然开始了动态调试的部分,我们就只用
OD
来进行操作了,因为这个版本的恶意代码都是针对
XP
的,所以我打算是把
OD
装到
XP
那台运行代码的机器上

这里我们还是跟这书上的步骤走走,先摸清摸清一下套路

我们先打开
OllyDbg
,我这个是从官网下载的,原版的
1.x
的东西,然后大概是这样



这里稍微说一下这个
OllyDbg
调整字体的方式

如果你用是吾爱破解版的话,字体应该没问题了(吾爱的插件比较多,懒得自己装插件的同学可以下一个)



我们打开这里,然后点第一个这个
Appearance
这个东西



就会打开一个这个界面,然后
Height adjust
这里可以调一下行高这个东西(第一个标黄的地方)

然后就是这个
Change
这个地方,这里可以调字体,把字体调成你喜欢的就行了

然后我们回归正题,继续按照书中的步骤一步一步调试

一般打开
OD
的时候,停在地方就是函数
main
开始的地方

我们可以看到我们停到了这里这个地方



这里对我们来说并不是什么重要的东西,我们可以按
F8(step-over)
往后慢慢一步一步走,其实这时候按
F7(step-into)
是最保险的,因为你不知道什么时候会调用到函数,然后如果你想回退到开始执行的地方,可以按
Ctrl+F2
来回溯到函数一开始执行的地方

然后我们边按边对照这
IDA
的汇编代码看,不然光看
OD
的代码会把人看傻的

我们先来到第一个
call
的地方



这里
OD
是标识了调用的是
kernel32.GetVersion
的函数

到现在这些函数都是程序执行前的初始化,这里是获取导入库的地址的



然后我们继续往下,忽略那些有的没的函数,来到第二个调用
CALL
这里,这里具体是什么我们可以进去看看

进去我们可以发现这里其实也是代码的初始化过程



这里是创建
Heap
也就堆,我们忽略,跳出来之后继续往下



然后我们来到这个
CALL
的地方,这个也是初始化的东西,但是我们注意到下面这个
CALL
的函数是
GetCommandLineA
,这个函数是获得用户输入的函数,说明这个程序需要用户提供一个参数

然后我们继续往下会发现



3915
这个地方,然后这里有个
CALL
,我们按
F7
进去看看

进去发现这个也是初始化的过程



调用了
GetEnvironmentStrings
这个函数来获取环境,这个函数为当前进程返回当前系统的环境变量

然后这个函数在里面一直比较什么,最后返回的
eax
是这样的



EAX 00900768 ASCII "=::=::\"


这个对我们没什么用处

下面就是这三个函数的
CALL




我们进去第一个调用
405E61
处,然后我们会发现这个函数其实就是调用模块的



我们退出,然后进入第二个调用



这也是获得模块文件名字的调用

这是第三个调用,我们可以发现



这里获得了当前进程的
ID
,这其实也是程序执行过程中,初始化的过程

然后我们继续往下分析



这里有三个
push
,是
Lab09-01.00402AF0
调用的三个入参,右边的注释已经帮我们标出来了

后面我们分析会发现,其实这个调用
Lab09-01.00402AF0
就是
main
函数

然后我们就进入这个函数看看

然后进入就找到第一个调用,熟悉我的人都知道我喜欢找
CALL
来分析代码



这是进入的第一个
CALL
,我们注意到这个
CALL
后面的一行的代码是

CMP DWORD PTR SS:[EBP+8], 1


这时候我们可以看看
IDA




IDA
里面,标黄那个
CALL
下面的
CMP
是不是很眼熟

我们看上面的定义,
argc
=
8
,转换一下这个语句就是
[ebp+8]


这就和
OD
对应上了

其实上面那个
OD
的第一个调用,就是
__alloca_probe
这个函数,这个函数是分配栈空间用的

于是我们就大概知道这是在比较你的有没有输入参数,如有有参数的话,
argc
就不会等于
1
,如果没有就是
1


现在我们没有输入任何参数,然后
[ebp+argc]
其实=
1
,所以
cmp
相减之后,结果为
0
,于是
ZF=1
,则
jnz
不跳转

我们可以会到
OD
里面一步一步看看有没有跳转

的确,
OD
里面并没有跳转,继续往下执行了



然后可能这时候有同学会问,这时候如果只看
OD
的数据,怎么知道
DWORD PTR SS:[EBP+8]
就是
argc
呢,如果你想这种硬分析的话,我们可以回到进入
main
函数之前



这里在吊用
Lab09-01.00402AF0
之前
push
入栈了三个参数,这个函数就是我们标记为
main
的函数,学过
C
语言的同学都知道
main
函数的一般三个入参

int main(int argc, char **argv, char **envp)




然后我们会发现这个
main
函数的三个入参都被
OD
标注了类型,然后还要我们清楚的一点就是这个每个参数的大小问题,不清楚的可以看看
OD
的标注,这里我们可以在
Arg1
Arg2
这里看出来每个参数的大小是多少

Arg1
的地址是
DS:[40EB84]
,然后
Arg2
的地址是
DS:[40EB80]
,从这里我们可以看出这个代码中,每个参数是占
4
个字节的大小

然后这里有个小的skill,在汇编函数调用中,我们压入这三个函数完之后,并不是马上就调用了这个函数,而是还要压入函数的返回地址

我们按照
param3
param2
param1
的次序依次在栈中压入参数,对应我们这里就是
Arg3
Arg2
Arg1
的次序



然后在压参数结束之后,我们还要压入返回地址



最后,准备调用函数的时候,再将
ebp
入栈,将
esp
的指赋值给
ebp




然后这时到了程序转移到被调用函数中执行,这个期间

地址
ebp+0
指向的是外面那个函数的
ebp
指针,
ebp+4
指向的是
RET返回地址
ebp+8
就是我们的第一个入参,也就是这里的
Arg1


所以这里为啥
EBP+8
对应
argc
就是这个道理

然后因为我们现在调试的时候并没有输入任何的入参,所以这里我们的
argc
是等于
1


所以我们这里并不会跳转



而是继续往下执行,然后从
00402B03
开始的话,就到了
IDA
的这里



这里的
Lab09-01.00401000
对应的就是
sub_401000
,然后我们看看这个函数是干什么的



这里调用了
RegOpenKeyExA
这个函数,然后
OD
已经帮我们标注好了这个入参的个个值,这里比
IDA
人性得很多



这里是打开一个注册表的键,位置是
HKEY_LOCAL_MACHINE
这个地方,然后具体位置是在
SOFTWARE\Microsoft \XPS
这里

然后调用完之后就是测试这个调用是否成功了



这里
test
了一下返回值,一般返回值是



成功就返回
0
,假设调用成功了,
and
之后,结果为
0
ZF
=
1
,那么
je
跳转

但是很不幸的是,我们
OD
调试的时候这个函数是返回失败的



函数的返回值在
EAX
中存储,这时候是
2


然后就是函数把
eax
置为
0
之后返回了,于是我们大概知道这个函数的一半是干什么的了

就是检测系统中是否存在那个注册表键,如果没有的话,就退出这个函数,并返回
0
,那如果成功呢,我们这里手动修改了一下
eax
看看

我们将这个
ZF
标志位手动置
1




然后执行

这里我们到了这个地方



这里调用了一个注册表查询的函数,将名为
Configuration
的值查出来

这里调用完成之后我们手动将返回值也置为
0
,因为这时候这个键都不存在,哪里会查询成功



然后就是一些返回值比较函数的作用,注意这里的
ebp-4
的位置,这里一般是属于临时空间

这里的
JE
其实和
JZ
是一样的,如果相等就跳转

这里其实如果调用失败之后,也会返回
0


如果两个函数都调用成功,就返回
1


然后这里我们为了节约分析时间,分析过后,其实这里的
sub_401000
如果调用失败,
jz
跳转之后,就会去执行一个
Lab09-01.00402410
的函数





其实也就是
IDA
中的
sub_402410




然后在这调用的最后,是这个



这里用
ShellExecuteA
打开了
cmd.exe
,这应该是这个恶意程序的一种伪造,如果用户没有输入任何的参数,或者没有发现那个注册表项,再或者查询注册表失败,就来执行这个
ShellExecuteA
通过
cmd.exe
来运行一些命令

关键现在我们要找出这个命令是什么,然后我们现在回到这个函数的开始,开始我们的分析



这里是开头的地方,一样的先是做了一些栈的初始化,将
ebp
压栈备份,然后把
ebp
指向
esp


然后做完这些后把
esp
相减
208
,将
esp
往低地址的地方偏移了
208
个地址,4个地址存储一个字节,有
52
个字节的存储空间

这里稍微讲一下这个怎么看一个栈空间存储多少字节,一个
EAX
多少字节这个问题



就是上图画圈圈这么一个空间占多少字节,你可能会说,这里只要看旁边的地址差是多少就知道了,对,但是并不是所有的栈都是图片中这样相差
4


我们先看看一个栈空间可以存储多少的字节



这是地址空间的
OD
里面的
stack


这里的用
4
个地址空间的空间,存储了
8
个十六进制的数字,

然后一个字节等于
2
个十六进制字符,这里有
8
个,所以相当于
4
个字节,也就是一个地址指向一个字节,每个栈空间是
4
的地址差,为什么要用上面的
208
/
4
得出可以存储多少个数据节,就是这么来的

一个栈的空间,刚好可以存储进去一个
EAX
或者
EBX
(因为也是
8
位十六进制的,
4
字节)

我们继续回到汇编代码中



这里一共分配了
52
个空间了,然后下面
push
了四个参数进入栈中,这四个参数并不是占这些分配的空间,他们是在
esp
的基础上往低地址的地方堆砌,注意,这里是从
esp
开始,而不是
ebp




然后最后通过

LEA EAX, DWORD PTR SS:[EBP-208]


将通过
sub esp, 208
后的
esp
值返回给
eax




IDA
中已经帮我们把这个变量标注为了
Filename
这个名称,然后这个代码片段到最后的就是删除那个可执行程序本身(刚刚写了一下午的分析,,,一关全没了,,,所以这里简写了。。。)

其实之类这些各种比较字符串长度的操作,主要是为了在赋值字符串的时候,不覆盖原来的字符串,所以才要求计算偏移也就是字符串的长度,这点看懂了这部分基本没啥问题了,最后那个用
cmd.exe
执行的指令,有个入参就是这个拼接后的字符串

如果我们手动修改这个
cmp
的结果值



让这个程序以为我们输入了一个参数,然后看看



然后这里将我们的
argv
(也就是
ebp+8
)赋值给
eax
,然后就是把
argv
(也就是
ebp+c
)赋值给了
ecx
,然后这个代码

MOV EDX, DWORD PTR DS:[ECX+EAX*4-4]


的作用就是取
argv
里面的最后一个参数的值,放入
edx
中又放入
eax


然后就开始调用这个
Lab09-01.00402510
的这个函数

也就是
IDA
中的
sub_402510
这个



进来之后



前面的两句是函数栈的初始化

2515
处的地方,将我们的获取到的
argv
的最后一个函数(
ebp+8
)赋值给了
edi
这个地方

下一句将
ecx
置为
-1


然后
repne scas edi
这个其实是计算
edi
指向的字符串的长度

然后
not ecx
是全部长度,包括字符串最后的结束符
\0


然后下面的
ecx + -1
就是去除这个结束符之后的长度

最后将这个长度和
4
进行比较,这里剧透一下,如果长度不是
4
,函数就直接返回
0


我们这里肯定不能让他就这么返回了,改~



这里的意思就是将那个字符的第一个字符,通过指针赋值给了
cl
,然后又给了
edx


然后最后和
61
比较,
61
其实是
a
ASCII
编码

然后我们这里也是改~

让他一直执行下去



这是将那个字符串的第二个字符(
eax+1
)赋值给了
cl
,然后这里的代码算是比较复杂的了,主要集中在这里

SUB AL, BYTE PTR DS:[EDX]


al
是字符串的第二个字符,
[edx]
是字符串的第一个字符,如果能想清这里,这里就理解了

这里的意思是,如果字符串的第二个字符,比第一个字符大
1
(也就是第二个字符如果是
b
),就跳转继续,否则和上面一样,直接返回
0
(这里说的字符串,是指
main
入参的
argv
最后一个参数)

然后下面就是这个代码



这里的
[ebp-4]
是字符串的上面字符串相减之后的值,是上一个代码片段遗传下来的

这里的
IMUL DL
意思就是将
dl
al
相乘,然后将结果放在
ax
中(因为
ax
的一半就是
al
,而
eax
1/4
就是al)

因为
al
上一代码片段曾经计算过了,是
0x01h
这个值,所以最后和
dl
相乘之后,就还是
dl
的值,也就是
63


这里注意考虑
[ebp-4]
的时候,和上下文结合起来看

这段代码的意思就是将第三个字符和
c
(也就是
63
)比较

这里其实是要注意这个
MOVSX
这个指令,这个指令是带符合操作的

然后下一个字符



这里的
al
这时候是
63
,上一步计算后的结果最后还存在
al
中,于是
al
=
1
之后就是
64
也就是
ASCII
d


然后这些计算都通过之后,就会将
eax
赋值为
1
然后返回了

这里的代码有点变态,因为各个参数之间不是独立的,后面的比较参数是根据前面的计算结果来的,如果写出伪C代码的话,大概如下

int sub_402510(const char *argv_last_string)
{
char *ptmp = NULL;
len_argv_string = strlen(argv_last_string);
if (len_argv_string != 4)
{
return 0;
}

ptmp = &argv_last_string[0];
int a_value = 61;
if (*ptmp != a_value)
{
return 0;
}

int ntmp = (int)(*(ptmp+1)) - a_value;
if (ntmp != 1)
{
return 0;
}

int c_value = 63 * ntmp;
if (*(ptmp + 2) != c_value)
{
return 0;
}

int d_value = c_value + 1;
if (*(ptmp + 3) != d_value)
{
return 0;
}

return 1;
}


大概就是上面这个样子的一个函数,很变态,不是直接比较
a
,
b
,
c
,
d
,而是根据前一个计算的结果推倒后面的要比较的字符串

然后函数出来之后就是一个检测返回值是否是
1




然后下面的地方是对应
IDA
的这里



这个
argv
如果你输入的是
abcd
话就是
abcd
,如果没输入就是这个可执行文件的绝对路径

然后我们这里看见这个函数
__mbscmp
,这个函数在
MSDN
中的解释就是



比较字符串的东西,这个函数其实和
strcmp
差不多



所以这里
2B56
地址的这个函数其实就是
__mbscmp
,我们这里可以标记一下

然后我们看看他
push
进去的参数有哪些



第一个
push
进去的是
byte_40C170
,这个好像是个字符串的,第二个
push
进去的是
eax






很可惜的就是
IDA
中并没有很明确的标注这个参数,
IDA
这里的
2Dh
并没有翻译成
ASCII
2Dh
就是
-


这里第一个
push
的参数我们知道了,是
-in
,然后我们看看第二个
push
的参数是什么



这里将
[EBP-1820]
位置的值赋值给了
eax


而这个
[EBP-1820]
是从
edx
来的



EDX
是从
[ECX+4]
来的,这里注意一下就是
[ECX+4]
这里读数据的时候要从倒着读,这里的
[ECX=4]
=
00900AE4






内存中是
380B9000
但是在栈中是
00900B38
这样

然后现在我们也知道了第二个参数是
abcd
,这里是将
abcd
这个字符串和
-in
进行比较

这里因为我们现在是不等于的,所以返回值不会为
0
,这里我们返回了
1




test
and
逻辑的运算,
and
之后还是
1
ZF
=
0
JNZ
就会跳转



就会跳右边这条绿线

然后这里的结构其实和上面这里是一样的



也是比较这个入参和
-re
是否相同,我们这里依旧不相同

我们还是顺着绿色这个线继续走



下面的这里还是一个
test
比较之后
JNZ
跳转



这里是比较是否和
-c
相同,我们依旧不相同,然后我们继续往下



然后我们这里走的是左边这条绿色的线

这里和上面一样,是比较
-cc
选项的

我们依旧不等于,然后继续走
jnz
绿线



到这里我们就会调用这个
sub_402410
的函数

然后这个函数我们上面曾经遇到过,就是没输入任何密码的时候调用的那个删除自身函数



这条线走完之后我们去看看那些个分支是干什么的

一开始是如果我们输入了参数
abcd
之后,第一个比较的是
-in
选项,我们进去看看是什么



如果当时输入了
-in
这个参数,就会跳到这里,对应
IDA
就是



这里的
[EBP+8]
其实就是调用这个函数时的输入也就是
argc
这个参数

这里会比较参数的个数是否为
3
,如果相等的话,
ZF
=
1
,就走红线,如果不相等就走绿线

我们先看红线是啥

相等之后就会调用这些函数



对应
IDA
也就是这里



这里我们可以结合这
IDA
来看,
IDA
已经表明了这个
ecx
是将
ServiceName
赋值给它

我们可以看看这个值是多少



IDA
中标识是一段地址空间,我们这时候就可以看
OD
的了

OD
里面标识是
[EBP-404]
的地址上的值,计算出来就是
0012FB7C
也就是

这里就相当于
sub_4025B0(0012FB7C, 400)
这样的函数调用,然后我们进去这个函数看看



这里我们注意到有个调用是
GetModuleFileNameA
这个函数,这个函数会将返回值放在
OD
标注的
PathBuffer
这里,所以我们查看返回值要查看这个地址上的值是多少

这里的
PathBuffer
是=
0012E344


我们查看一下就是这样的



也就是我们当前这个可执行文件的绝对路径

然后就是一个
test




这里如果成功是返回这个绝对路径的长度,这里
test
之后,
ZF
=
0
,所以
jnz
会跳转过去

跳转过来就是这样的函数



这里有个调用函数

IDA
中标注的是



也就是
__splitpath
这个函数

这个函数在
MSDN
里面貌似查不到,我们直接看执行结果是什么

最后我们可以得出调用顺序是这样的
__splitpath(0012E344, 0, 0, 0012FB7C, 0)


其中
0012E344
这个地址是存着上一部返回的绝对路径



这个函数执行之后的寄存器变化



可以看出来这个函数的返回值
EAX
貌似是个地址,或者说就是个指针,但是这个指针指向的地址都是乱码,这个不知道是什么东西



然后我们看看传进去的两个入参,发现,函数执行之后,
0012FB7C
原本没有值的,现在存着这个感觉是像被分割之后的字符串



值是
Lab09-01
,注意我们要看
\00
字符串结束符,所以我们大概知道了这个函数就将那个绝对路径分割成为
Lab09-01
这个字符串

然后这个函数如果调用成功返回的是
0
,失败返回
1




然后我们从函数中返回之后就是来到了这里,这有个
test
,我们成功了,所以返回值是
0
,然后
test
之后
ZF
=
0
JE
跳转

如果这里不是返回
0
,那么整个这个函数会跳转之后结束并返回
-1


跳转之后来到这里



OD
中是这样的



这里有调用一个函数,还是按上面那种写法就是这样的
sub_402600(edx)
,我们可以执行
OD
来看看这个
EDX
的值是多少



我们可以大概看出来,这个
EDX
其实就是刚刚上面那个函数处理后的返回结果
Lab09-01


函数进来之后的是这样的(这个函数很大)



对应
IDA
中就是这样的



现在我是处于判断
-in
成功之后那条线进入的一个函数

这里的
call __alloca_probe
就是函数初始化栈的东西,这个我们可以不用管



这个写简单点就是
sub_4025B0(EAX, 400)
(这个函数就是那个__split什么那个函数)

这里函数就有这么几个入参,执行看看

然后这时候的
EAX
返回值就是
0


也就是这里



这里的
eax
=
0
,然后
test
之后
ZF
=
1
,然后
JZ
就绿线跳转了,红线是结束这个函数并返回
1


绿线之后就是来到这里



对应
IDA
的这里



这里有个字符串我们注意到
%SYSTEMROOT%\\system32\\




这里显示是的计算
[EDI]
的字符长度也就是上面那个字符串的长度

这么一串指令到最后的



都是为了调用
OpenSCManagerA
这个函数,这个函数是
在指定的计算机上建立与服务控制管理器的连接,并打开指定的服务控制管理器数据库。


前两个参数为
0
说明这个服务控制器是在本地上

这时候的寄存器



可以看出上面那个操作就是把这个字符串拼接成
EDX
所示的样子

然后这里将返回值放在
[EBP-404]
里面

然后和
0
比较,如果返回值
EAX
等于
0
ZF
=
1
JNZ
不跳转,继续执行就是结束并返回
1




然后我们这里并不等于
0
,于是跳转

也就是来到这里



OD
的这里



这里的第一个
push
入栈的
eax
IDA
中标注是
lpServiceName
,然后第二个
push
入栈的
ecx
hSCManager




这里的
eax
的值是
Lab09-01
,也就是要打开的服务的名称,如果调用成功,返回一个指针

然后我们这里是第一次调用这个函数,所以这个函数会返回
0
作为返回值

0
执行
cmp
之后
ZF
=
1
,则
JE
跳转



执行之后就会跳转到绿色的线那里,如果调用成功了,就重新配置一下这个服务的参数



然后这个函数就是创建一个叫
Lab09-01
的服务

这里调用成功之后,返回值肯定不为
0
,所以和
0
执行
cmp
之后,
ZF
=
0
,之后
JNZ
肯定就会跳转了



跳转之后的绿线就是执行一写关闭操作,来关闭打开的
Handle


之后就是调用了



这里的入参我们可在在
OD
里面查看

这里的入参
edx
等于



然后我们看看调用后的结果,存放在
ecx
指向的地址



这里把
%SYSTEMROOT%
这个变量替换成了环境变量然后就成了
0012DF44
这个地址上的字符串

调用成功之后继续往下走



我们直接看看这个入参和结果

这是执行之后的返回值,存在
eax
指向的地址



然后执行成功之后继续往下



这里两个入参,
edx
ecx




lpNewFileName
的值是
ecx
,然后
lpExistingFileName
也就是
edx
也是上面我们刚刚的返回值

这里要将这个可执行文件赋值到
system32
下面

执行成功之后就会跳到这里



我们看看这个函数的入参是多少

也就是这个
system32
下面的可执行文件



进入这个函数之后,我们第一个要执行的函数是这个



这个函数在
MSDN
里面的解释就是
检索系统目录的路径。 系统目录包含系统文件,如动态链接库和驱动程序。


我们看看返回值,返回值
eax
是字符长度,真正的字符被赋值到了
lpbuf
里面

lpBuffer
的值是



这是返回值



如果函数返回成功了,就会跳转到绿线继续执行,否则返回
1




调用
sub_4014E0
这个函数的时候,入参是
ecx
eax




然后就调用了
sub_4014E0


进入这个函数之后是这样的



我们还是按照先看入参然后看返回值的做法看看

这个函数的入参是
eax
,这个的值是



这也就是创建这个文件叫
C:\WINDOWS\system32\kernel32.dll


这里我们执行后会发现返回值不是
0
,然后就是和
0
就行
cmp
ZF
=
0
,则
JNZ
跳转,走绿线

也就是这里



我们还是用
OD
来看参数,这个函数的意思就是
检索文件或目录创建,上次访问和上次修改的日期和时间。


我们看看参数



hfile
的值是
5c
也就是上面那个函数的返回值

然后这个函数会把返回值放到
lpCreationTime
lpLastAccessTime
lpLastWriteTime
这里

我们看看
CreationTime
的返回值好像是乱码的东西

调用成功之后就会调用这个



这里先关闭上面那个
Handle


然后就是
CreateFileA


入参
ecx
的值



然后设置这个文件的时间和
kernel32.dll
的一样

然后就是关闭这个
Handle
然后返回

这个函数成功返回
0
,失败返回
1


然后接着上面一层这个函数也会返回,从这里返回之后就会来到这里



这里开始调用
sub_401070
这个函数

这里入参有个网址,我们进去这个函数看看

这个函数的一连串的指令之后是这个函数



这里看函数名是创建一个注册表的键值

是在
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft \\XPS
这里创建



然后设置一个键叫
Configuration


然后就是在关闭之后返回

然后上面一层的函数也会返回,这里成功返回
0
,失败返回
1


现在我们知道了这个
-in
参数会干什么了,这个参数会让函数安装自己为一个服务,然后把
Lab09-01.exe
复制到
system32
下面

我们试试下一个参数
-re
这个参数



这里我们将入参设置为
-re


然后来到
OD
的这里



然后这里相同之后,
ZF
=
1
JNZ
不会跳转,走红线

然后这里会比较我们的入参是不是三个

我们的入参就是三个,所以这里走红线

然后就会来到这里



然后这里有个函数
sub_4025B0
这个东东

进去看看就会发现这个

我们进去看看



GetModuleFileNameA
函数的返回值是



然后就开始退出这个函数了



然后就是分离出这个值之后返回

2.这个恶意代码的命令行选项是什么?它要求的密码是什么?

解答: 这个代码分析太长时间了哈哈哈,密码是
abcd


3.如何利用OllyDbg永久修补这个恶意代码,使其不需要指定的命令行密码?

解答: 修改特定的地址上的代码,然后不跳转就ok

4.这个恶意代码基于系统的特征是什么?

解答: 恶意代码创建了一个注册表项,然后一个名为
XYZ
的服务

5.这个恶意代码通过网络执行了哪些不同操作?

解答:
SLEEP
,
UPLOAD
,
DOWNLOAD
,
CMD
NOTHING
之类的指令

6.这个恶意代码是否有网络特征?

解答: 有,对对应网址的资源有个一个
GET
请求

本文完
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  代码分析 病毒