纵观
详细分析
打开程序观察堆栈发现并不是main函数入口点
利用ida分析main函数地址,并在od中断点
一步一步跟进调试
查看参数个数是否为1,继续向下直接call 401000
代码太长不好截图,直接放代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83.text:00402410 push ebp
.text:00402411 mov ebp, esp
.text:00402413 sub esp, 208h
.text:00402419 push ebx
.text:0040241A push esi
.text:0040241B push edi
.text:0040241C push 104h ; nSize
.text:00402421 lea eax, [ebp+Filename]
.text:00402427 push eax ; lpFilename
.text:00402428 push 0 ; hModule
.text:0040242A call ds:GetModuleFileNameA
.text:00402430 push 104h ; cchBuffer
.text:00402435 lea ecx, [ebp+Filename]
.text:0040243B push ecx ; lpszShortPath
.text:0040243C lea edx, [ebp+Filename]
.text:00402442 push edx ; lpszLongPath
.text:00402443 call ds:GetShortPathNameA
.text:00402449 mov edi, offset aCDel ; "/c del "
.text:0040244E lea edx, [ebp+Parameters]
.text:00402454 or ecx, 0FFFFFFFFh
.text:00402457 xor eax, eax
.text:00402459 repne scasb
.text:0040245B not ecx
.text:0040245D sub edi, ecx
.text:0040245F mov esi, edi
.text:00402461 mov eax, ecx
.text:00402463 mov edi, edx
.text:00402465 shr ecx, 2
.text:00402468 rep movsd
.text:0040246A mov ecx, eax
.text:0040246C and ecx, 3
.text:0040246F rep movsb
.text:00402471 lea edi, [ebp+Filename]
.text:00402477 lea edx, [ebp+Parameters]
.text:0040247D or ecx, 0FFFFFFFFh
.text:00402480 xor eax, eax
.text:00402482 repne scasb
.text:00402484 not ecx
.text:00402486 sub edi, ecx
.text:00402488 mov esi, edi
.text:0040248A mov ebx, ecx
.text:0040248C mov edi, edx
.text:0040248E or ecx, 0FFFFFFFFh
.text:00402491 xor eax, eax
.text:00402493 repne scasb
.text:00402495 add edi, 0FFFFFFFFh
.text:00402498 mov ecx, ebx
.text:0040249A shr ecx, 2
.text:0040249D rep movsd
.text:0040249F mov ecx, ebx
.text:004024A1 and ecx, 3
.text:004024A4 rep movsb
.text:004024A6 mov edi, offset aNul ; " >> NUL"
.text:004024AB lea edx, [ebp+Parameters]
.text:004024B1 or ecx, 0FFFFFFFFh
.text:004024B4 xor eax, eax
.text:004024B6 repne scasb
.text:004024B8 not ecx
.text:004024BA sub edi, ecx
.text:004024BC mov esi, edi
.text:004024BE mov ebx, ecx
.text:004024C0 mov edi, edx
.text:004024C2 or ecx, 0FFFFFFFFh
.text:004024C5 xor eax, eax
.text:004024C7 repne scasb
.text:004024C9 add edi, 0FFFFFFFFh
.text:004024CC mov ecx, ebx
.text:004024CE shr ecx, 2
.text:004024D1 rep movsd
.text:004024D3 mov ecx, ebx
.text:004024D5 and ecx, 3
.text:004024D8 rep movsb
.text:004024DA push 0 ; nShowCmd
.text:004024DC push 0 ; lpDirectory
.text:004024DE lea eax, [ebp+Parameters]
.text:004024E4 push eax ; lpParameters
.text:004024E5 push offset File ; "cmd.exe"
.text:004024EA push 0 ; lpOperation
.text:004024EC push 0 ; hwnd
.text:004024EE call ds:ShellExecuteA
.text:004024F4 push 0 ; int
.text:004024F6 call _exit
.text:004024F6 sub_402410 endp大体就是得到本地文件路径,拼凑字符串
在本地尝试可以看到此命令为删除指定路径的文件(怪不得每次点击exe文件就没了,还以为防火墙删了emm)
调用SHELL32的ShellExecute函数执行拼接的字符串,但由于已在od中打开,所以不会删除
接着往下看,传入参数-in后call 40380f
在main函数中找到__mbscmp相关调用(call的40380f),此函数是比较字符串是否相等的
此函数(40380f)的返回值为910000
可以看到参数-c -cc -re- in
参数 | 地址 | 功能 |
---|---|---|
-in | .text:00402600 | |
-c | ||
-cc | .text:0x401280 | |
-re |
接着往下看,添加-in参数后Ctrl+F2重新调试
可见跳过删除自身,push参数call 402510
分析402510函数,发现对传入参数进行是否为abcd的校验
校验失败,call 402410函数,就是之前删除自身的函数
改变参数为-in abcd,即可跳过
call 0040380,ida分析为_mbscmp函数
call 4025B0
该函数作用为获取文件名且返回result=0
接着往下走,call 402600 应该是最重要的对应参数函数
可以看到所传参数为4025B0的返回值(即当前文件文件名)
跟进后看到call了_alloca_probe(可能与注册内存有关,先不管)和4025b0(先前分析过为截取文件名)
接着跟进发现跳转到402632,发现此函数前部分是实现拼接字符串%SYSTEMROOT%\system32\Lab09-01.exe的操作,然后调用OpenScManagerA
可以OpenScManagerA传入参数为3个立即数,之前分析知道它返回一个服务控制管理器句柄,所有要和服务交互的代码会调用这个函数;
对于这种官方API函数可以跳过
接着调用OpenService函数,参数为自身文件名,可以判断开启一个自身服务
接着调用ChangeServiceConfigA和CloseService函数
其中ChangeServiceConfigA所传参数如下,hService为之前开启的自身服务
再往下发现就跳出了402600函数,因此可以推断-in参数为创建服务功能,ida F5伪代码如下
1 | int __cdecl sub_402600(LPCSTR lpServiceName) |
可以看到已启动自身服务
至此,-in参数分析结束
接着分析-re参数
修改参数为-re abcd
经过_mbscmp函数后eax返回值为1,跳转到-re参数
接着和-in参数一样call 40380f比较字符串,call 4025b0获取文件名
接着call 402900进入-re参数函数
反汇编查看代码,初步判断为删除服务的,od跟进看看
1 | int __cdecl sub_402900(LPCSTR lpServiceName) |
同样的流程,只不过open改为deleteService
跟进发现服务已禁用
接着deletefile
到此,对于-re参数功能的分析已经结束,我们知道这是删除服务功能;
下面分析-c参数
修改参数为-c abcd
进入调试执行,此处应该就是-c参数代码段
可以看到有2个jnz跳转(402cd9,402ccf)
因为参数为-c所以402cd9不跳转,接下来分析下402ccf,od中是跳转了的
简单反汇编一下可以看到,判断参数是否为7
如果不为7,则call 402410,之前分析过这个函数是删除自身
更改参数如图,实际指令为(xxxx.exe -c 111 222 333 444 abcd)共7个参数,后重新调试
可以看到进入401070函数,并对输入的参数111 222 333 444处理
参数入栈后调用401070,应该就是-c的函数了,进入看看
大概意思就是创建注册表key,然后设置value,一步一步跟进
打开注册表按照参数发现雀氏添加了所传入的参数
接着跳出main函数,结束
至此-c 参数分析完毕,即向指定注册表添加value
接着分析-cc abcd
有两个跳转,od跟进发现并没有跳转,先过。接着call 401280
反汇编查看代码
大概就是注册表查value
打开注册表,然后查值
跳出401280后call 402e74(感觉想printf函数)
发现将查询到的value打印出来,然后删除自身,结束
接下来分析无参,设置参数为abcd
跳转至此401000,
接着call 402360
发现是一个死循环,且通过401280和402020跳出循环
查看401280
猜测如果查询注册表中的value,则跳出循环
查看402020
代码较长不放了
先call了401e60
1 | signed int __cdecl sub_401E60(char *a1, signed int a2) |
其中401420中调用了401280,即-cc参数,就是查询value
接着call了401470,进去看到call了401280和402f6a
接着call了401d80
先获取了当前时间time
然后4030e0函数将40C180的值赋为time
接着call 401D10,跟进去看
返回一个不是数字&&不是小写字母&&不是大写字母的v1(此处返回的是54)
不满足条件接着一直循环
跳出,接着call 401AF0,参数如栈中所示
代码如下,和socket网络通信有关
1 | int __cdecl sub_401AF0(char *name, u_short hostshort, int a3, char *a4, int a5) |
纵观以上,可以得到401e60主要功能为以下
1 | int _cdecl sub_401E60(cahr *a1,signed int a2){ |
如果获取字符串成功,则进入40204C,可以看到类似于一个后门功能
1 | int __cdecl sub_402020(char *name) |
可以实现cmd,和upload