能力值:
( LV15,RANK:340 )
26 楼
感谢分享!
检测仿真环境那段,感觉它直接调用 gethostbyname 检查LastError是否为10093不稳妥。确实正常情况中没有调用WSAStartup前gethostbyname,会返回10093,不过VM虚拟个系统来跑这个代码,也能得到这个值。或者sandbox关注了网络方面的实现,也有可能过不了。
不过以前真没想过 gethostbyname 还能用来检测仿真环境。以前看到bot中清空DNS缓存然后查询服务器的IP,以为只是为了防止固定IP被封。现在想来对付没有网络的启发扫描环境,可以查询一个自己注册的域名,比较返回的IP是否正确... (当然,没网络的机器也就无法发作了
)
总之先把文章收下了。写得很详细,回头结合源码对照着看看。
Win32.Anunnaki by Dark Prophet/EOF
http://vx.eof-project.net/viewtopic.php?pid=2065
能力值:
( LV6,RANK:90 )
27 楼
好文章,谢谢楼主分享。
能力值:
( LV2,RANK:140 )
28 楼
几个问题,多谢LZ!!
0040171C |. 64:A1 34000000 mov eax,dword ptr fs:[34] ; 从teb中读取GetLastError数值给eax
00401722 |. 69C0 01000100 imul eax,eax,10001
00401728 |. 35 58862413 xor eax,13248658
0040172D |. 3D 35A14934 cmp eax,3449A135 ; 校验返回值
00401732 |. 74 24 je short Anunnaki.00401758
00401734 |. 6A 00 push 0
00401736 |. 68 65737300 push 737365
0040173B |. 68 50726F63 push 636F7250
00401740 |. 68 45786974 push 74697845
00401745 |. 54 push esp ; esp->ExitProcess
00401746 |. E8 50FEFFFF call Anunnaki.0040159B
0040174B |. 50 push eax
0040174C |. E8 37FDFFFF call <Anunnaki.my_getprocaddress>
00401751 |. 83C4 0C add esp,0C
00401754 |. 6A 00 push 0
00401756 |. FFD0 call eax ;
00401758 |> 61 popad
00401759 \. C3 retn
正常都会到0x00401756直接退出线程?错了反倒正常返回?
push_au macro au, fstr
local pvar, cnt, es, cn, idx1, idx2, len, ln
local hex, dcm, hid
es = 0
len = 0
irpc c1, <fstr>
len = len+1
if es eq 1
if (("&c1" ge "0") and ("&c1" le "9")) or ("&c1" eq "x") or ("&c1" eq "X")
len = len-3
啥语言?看着像脚本。
1 -- 解析代码段,寻找跳向最后一个节的call,记录建立栈帧的地址addr_s
1 -- 执行call后寄存器中出现小于addr_s的数值
这个addr_s啥含义?
能力值:
( LV15,RANK:340 )
29 楼
[QUOTE=nkspark;790004]几个问题,多谢LZ!!
00401716 |. 54 push esp ;esp->"google.com"
00401717 |. FFD7 call edi ;call - > gethostbyname("google.com")
00401719 |. 83C4 10 add esp,10
0040171C |. 64:A1 34000000 mov eax,dword ptr fs:[34] ; 从teb中读取GetLastError数值给eax
00401722 |. 69C0 01000100 imul eax,eax,10001
00401728 |. 35 58862413 xor eax,13248658
0040172D |. 3D 35A14934 cmp eax,3449A135 ; 校验返回值
00401732 |. 74 24 je short Anunnaki.00401758
00401734 |. 6A 00 push 0
00401736 |. 68 65737300 push 737365
0040173B |. 68 50726F63 push 636F7250
00401740 |. 68 45786974 push 74697845
00401745 |. 54 push esp ; esp->ExitProcess
00401746 |. E8 50FEFFFF call Anunnaki.0040159B
0040174B |. 50 push eax
0040174C |. E8 37FDFFFF call <Anunnaki.my_getprocaddress>
00401751 |. 83C4 0C add esp,0C
00401754 |. 6A 00 push 0
00401756 |. FFD0 call eax ;
00401758 |> 61 popad
00401759 \. C3 retn
[/QUOTE]
不要被GetLastError给迷惑了。这一段是通过没有 WSAStartup 前调用 gethostbyname 会返回10093错误来检测的:
0040171C |. 64:A1 34000000 mov eax,dword ptr fs:[34] ; 从teb中读取GetLastError数值给eax
00401722 |. 69C0 01000100 imul eax,eax,10001
00401728 |. 35 58862413 xor eax,13248658
0040172D |. 3D 35A14934 cmp eax,3449A135 ; 校验返回值
10093 这样乘出来正好是 0x3449A135。实际机器中直接gethostbyname会因为没有初始化而返回这个错误值,而虚拟环境中可能因为是个stub而GetLastError为0。
能力值:
( LV9,RANK:410 )
30 楼
ls 的木桩兄弟已经说第一个了,我说后面的吧。
push_au 不是脚本语言,是用masm定义的字符串压栈的宏操作。
里面用了一些不太常用的伪指令fstr等。
他有两个版本,一个asc ,一个unicode 版。
push_sz macro fstr
push_au 0, <fstr>
endm
push_uz macro fstr
push_au 1, <fstr>
endm
主要是为了不再堆栈中产生明文的字符串, anti 动态仿真。
addr_s 是从检测的方面记录的值,
比如一个被感染的文件的入口,
00401000 push 0
00401002 call kifilter.00401008
00401007 int3
00401008 call kifilter.00404644 -->被感染,跳向最后一个节 00404644 push ebp 记录此处建立占帧地址addr_s,也就是addr_s == 0x00404644
00404645 mov ebp,esp
00404647 push 6F25393D
0040464C pop edi
0040464D call kifilter.00404652
00404652 pop eax
00404653 add eax,FFBFB9AE ---->运算解密的首地址eax== 0x404643,一定小于addr_s
00404659 add eax,kifilter.00404643
0040465F push 25F0 此处就是产生解密循环计数
00404664 pop edx
00404665 xor dword ptr ds:[eax],edi
00404667 sub edi,B382A492
0040466D dec eax
0040466E dec edx
0040466F test edx,edx
00404671 jnz short kifilter.00404665
被它感染后的文件都具有该特点,所以我们记录addr_s ,当发现解密首地址值eax小于addr_s时,可作为检测依据进行标记。
能力值:
( LV2,RANK:140 )
31 楼
[QUOTE=木桩;790008]不要被GetLastError给迷惑了。这一段是通过没有 WSAStartup 前调用 gethostbyname 会返回10093错误来检测的:
0040171C |. 64:A1 34000000 mov eax,dword ptr fs:[3...[/QUOTE] 多谢了.
又看了一下, 前面几个je Anunnaki.00401758应该是如果出错,就放弃Anti。
能力值:
( LV2,RANK:140 )
32 楼
收到。理解错了,以为是你用来做启发式检测的。
能力值:
( LV2,RANK:10 )
33 楼
有点长.慢慢看吧
能力值:
( LV2,RANK:10 )
34 楼
非常不错 LZ很用心
能力值:
( LV2,RANK:10 )
35 楼
详细!值得赞!
能力值:
( LV12,RANK:390 )
36 楼
菜鸟提问!!!!
为啥patch ExitProcess()的调用时 在整个代码里搜索 ff 15/ff 25?不是应该搜索0xE8么?
希望大牛讲解一下,我初学,这个地方看了好长时间没看懂。。。。
能力值:
( LV12,RANK:390 )
37 楼
我又问愚蠢问题了。。。ff25是绝对Jmp的机器码 ff15是绝对call的机器码。。。
能力值:
( LV7,RANK:100 )
38 楼
如果我来免杀你的检测点,就这么干:
1、重定位
8BFF mov edi, edi
55 push ebp
8BEC mov ebp, esp
/*之间插一大堆指令,该干嘛干嘛*/
8B45 04 mov eax, dword ptr [ebp+4]
8AC8 mov cl, al
66:8BC8 mov cx, ax
66:33C0 xor ax, ax
66:83E9 05 sub cx, xxxxxx /*忘记计算size了*/
5D pop ebp
C3 retn
出门之后再将eax和cx或起来就OK。
2 跨节区跳转
这个没有啥子很好的方法,条件允许就多次ret
3、如果你只对 push esp 后堆栈才进行检查的话,那
mov eax,esp
push eax
检查不呢?
4、EPO这个的选择看个人爱好!
=====================
原来LZ是做BD的!
能力值:
( LV12,RANK:390 )
39 楼
额,除了EPO还能怎么调病毒代码?求解。。。。
能力值:
( LV3,RANK:20 )
40 楼
菜鸟中,继续学习!
能力值:
( LV12,RANK:530 )
41 楼
文章很长,说实话,没看完,不过几个结构图讲的很好,清楚明了~~支持一下!
能力值:
( LV2,RANK:10 )
42 楼
楼主好人,11楼好人。
能力值:
( LV2,RANK:10 )
43 楼
好文!感谢楼主分享
能力值:
( LV2,RANK:10 )
44 楼
NB,标记一下,有时间读。