小探xpaj
本帖最后由 L4Nce 于 2014-3-23 09:47 编辑样本MD5:03AF8CA26B6859C4ED56D513CB700D18
简单的分析下xpaj,主要是分析了xpaj的虚拟机部分。
感谢ximo师傅,提供学习机会。
本文如同学习笔记,不免出现各种错误,请谅解
拿到样本之后一看,发现没有奇怪的区段,还有各个区段的属性都很正常,头部也没有被hook掉。但是文件的(98记事本)大小不对。只能单步找了。
水平很弱,静态分析依旧心里感觉不踏实。
0040113A|.50 push eax
0040113B|.E8 730F0000 call NotePad_.004020B3
00401140|.50 push eax ; /ExitCode
进到这个call以后里面的代码非常奇怪,一直在循环,就感觉这里的代码有问题。于是进行分析。发现是一个所谓的虚拟机吧,虚拟的程度不高。
给出几个关键处
004020B3 $55 push ebp
004020CB .8B7D C4 mov edi,dword ptr ss: ;定位的常量
004020DD .897D CC mov dword ptr ss:,edi ;给初始的esi提供
004020E0 .8B4D F8 mov ecx,dword ptr ss:
004020E3 .8965 E4 mov dword ptr ss:,esp ;;保存esp
004020E6 .BE A42D2E01 mov esi,0x12E2DA4
004031CE .337D D4 xor edi,dword ptr ss:
004031D1 .096D D8 or dword ptr ss:,ebp
004031D4 .037D C4 add edi,dword ptr ss: ;固定地址
004031D7 .897D FC mov dword ptr ss:,edi ;handler地址
004031DA .0B4D C8 or ecx,dword ptr ss:
00403234 .8B0E mov ecx,dword ptr ds:
00403236 .334D D4 xor ecx,dword ptr ss: ;解密
00403239 .815D C8 1E11B>sbb dword ptr ss:,0xB2111E
00403240 .894D F4 mov dword ptr ss:,ecx
00403243 .8B7D F4 mov edi,dword ptr ss:
00403246 .0375 E0 add esi,dword ptr ss:
00403249 .8975 CC mov dword ptr ss:,esi ;下一条指令
0040324C .FF65 FC jmp dword ptr ss: ;004136EB;004032BF
经过分析会发现原来idata节被感染了,所有的vopcode都在那边
最后确定0040324C处为handler的派发处,用条件断点过滤出所有handler有7个
大体结构如下
;固定长度的opcode len=0ch
;esi为veip
;虚拟指令表添加在idata处
ebp-3c;固定地址来自call下一句
ebp-34;下一条指令的起始
ebp-2c;xor_key
ebp-20;固定值4可用来修正veip
ebp-1c;vesp的基址 0012FF0C
ebp-18;固定值返回到00402119
ebp-0c;handler用参数2
ebp-08;handler用参数1
ebp-04;handler入口
vopcode:
B A 9 8 7 6 5 4 3 2 1 0
------- ------- -------
加密的参数最后 加密的参数 加密的handler偏移
给了edi和ebp-c (ebp-08)
handler:
00403264
004032BF
004032D2
00403323
004032A0
004032EE
0040333D
-----------CALL---------------------------------------------------------------------------------------
00403264 .0955 C8 or dword ptr ss:,edx
00403267 .8945 BC mov dword ptr ss:,eax
0040326A .037D CC add edi,dword ptr ss:
0040326D .894D D4 mov dword ptr ss:,ecx
00403270 .8955 E0 mov dword ptr ss:,edx
00403273 .BE 8D852D01 mov esi,0x12D858D
00403278 .81E6 28B4DB01 and esi,0x1DBB428
0040327E .5F pop edi
0040327F .FFD7 call edi
00403281 .50 push eax
00403282 .8B45 BC mov eax,dword ptr ss:
00403285 .8B4D D4 mov ecx,dword ptr ss:
00403288 .895D F0 mov dword ptr ss:,ebx
0040328B .8B55 E0 mov edx,dword ptr ss:
0040328E .81CE 2FCC1100 or esi,0x11CC2F
00403294 .8BFD mov edi,ebp
00403296 .C745 D8 29830>mov dword ptr ss:,0x20B8329
0040329D .^ FF67 E8 jmp dword ptr ds: ;NotePad_.00402119
-------------PUSH DWORD----------------------------------------------------------------------------
004032BF .815D C8 BC262>sbb dword ptr ss:,0x22D26BC
004032C6 .FF75 F8 push dword ptr ss:
004032C9 .8B7D D4 mov edi,dword ptr ss: ;获取了xor解密key
004032CC .FF75 E8 push dword ptr ss:
004032CF .C3 retn ;402119
-------------PUSH VESP-------------------------------------------------------------------------------
004032D2 .19E1 sbb ecx,esp
004032D4 .8B75 E4 mov esi,dword ptr ss: ;保存的esp
004032D7 .0375 F8 add esi,dword ptr ss: ;参数1
004032DA .89C1 mov ecx,eax
004032DC .8B36 mov esi,dword ptr ds:
004032DE .0375 F4 add esi,dword ptr ss: ;参数2
004032E1 .FF36 push dword ptr ds: ;保存
004032E3 .FF75 E8 push dword ptr ss:
004032E6 .29CE sub esi,ecx
004032E8 .C3 retn ;00402119
--------------ADD-------------------------------------------------------------------------------
00403323 .214D C0 and dword ptr ss:,ecx
00403326 .5E pop esi
00403327 .B9 0571BE01 mov ecx,0x1BE7105
0040332C .5F pop edi
0040332D .8165 C0 C353A>and dword ptr ss:,0xA253C3
00403334 .01FE add esi,edi
00403336 .56 push esi
00403337 .2B75 F8 sub esi,dword ptr ss:
0040333A .FF65 E8 jmp dword ptr ss:
-------------GET FS:[]---------------------------------------------------------------------------------------
004032A0 .11C1 adc ecx,eax ;NotePad_.00400000
004032A2 .5E pop esi
004032A3 .89E1 mov ecx,esp ;junk_code
004032A5 .64:8B0E mov ecx,dword ptr fs: ;get fs[]
004032A8 .81C7 8198B400 add edi,0xB49881
004032AE .51 push ecx ;save
004032AF .81E1 0CD2EE01 and ecx,0x1EED20C
004032B5 .FF75 E8 push dword ptr ss:
004032B8 .1955 C0 sbb dword ptr ss:,edx
004032BB .C3 retn
------------POPVESP--------------------------------------------------------------------------------------------
004032EE .8B7D E4 mov edi,dword ptr ss: ;vesp基址
004032F1 .8175 C0 22393>xor dword ptr ss:,0x3C3922
004032F8 .037D F8 add edi,dword ptr ss: ;参数1
004032FB .8B3F mov edi,dword ptr ds:
004032FD .816D F0 8BFD0>sub dword ptr ss:,0xEFD8B
00403304 .037D F4 add edi,dword ptr ss: ;参数2
00403307 .8F07 pop dword ptr ds: ;00261E90
00403309 .81F6 AB709101 xor esi,0x19170AB
0040330F .1945 C8 sbb dword ptr ss:,eax
00403312 .BE E8FFFFFF mov esi,-0x18
00403317 .81D7 C3381A00 adc edi,0x1A38C3
0040331D .03F5 add esi,ebp
0040331F .19E1 sbb ecx,esp
00403321 .FF26 jmp dword ptr ds:
-------------EQ_JMP-------------------------------------------------------------------------------------------------
0040333D .59 pop ecx
0040333E .89CE mov esi,ecx
00403340 .5F pop edi
00403341 .8B75 C0 mov esi,dword ptr ss:
00403344 .3BF9 cmp edi,ecx ;比较
00403346 .8B7D E4 mov edi,dword ptr ss: ;junk_code
00403349 .^ 0F85 CAEDFFFF jnz NotePad_.00402119
0040334F .BF 5C05EA01 mov edi,0x1EA055C
00403354 .8B75 F8 mov esi,dword ptr ss: ;获取参数1
00403357 .B9 76235F02 mov ecx,0x25F2376
0040335C .0175 CC add dword ptr ss:,esi ;修正下一条指令
0040335F .8B75 D4 mov esi,dword ptr ss:
00403362 .8BFD mov edi,ebp
00403364 .FF67 E8 jmp dword ptr ds:
其中PUSH VESP更像是用来传输数据用的。可以改变目的地址用push来传输数据。
而EQ_JMP这个handler自带了判断和是否相等来确定是否跳转。相当于cmp;je这样的操作
分析完handler以后写了一个od脚本来记入handler执行过程并分析参数
VAR handler_entry
VAR vm_handler_call
VAR vm_handler_push_dword
VAR vm_handler_push4vesp
VAR vm_handler_add
VAR vm_handler_getfs
VAR vm_handler_pop2vesp
VAR vm_handler_jmp
VAR temp_1
VAR temp_2
//---INIT-----------------------
MOV handler_entry,0040324C
MOV vm_handler_call,00403267
MOV vm_handler_push_dword,004032BF
MOV vm_handler_push4vesp,004032D2
MOV vm_handler_add,00403323
MOV vm_handler_getfs,004032A0
MOV vm_handler_pop2vesp,004032EE
MOV vm_handler_jmp,0040333D
BP handler_entry
LOOP:
RUN
CMP eip,handler_entry
JNE END
CMP ,vm_handler_call,4
JNE NEXT_1
MOV temp_1,,0
LOG temp_1,"call "
JMP LOOP
NEXT_1:
CMP ,vm_handler_push_dword,4
JNE NEXT_2
MOV temp_1,,4
LOG temp_1,"push dword "
JMP LOOP
NEXT_2:
CMP ,vm_handler_push4vesp,4
JNE NEXT_3
MOV temp_1,,4
ADD temp_1,
MOV temp_2,,4
ADD temp_2,
MOV temp_1,,4
LOG temp_1,"push from vesp "
JMP LOOP
NEXT_3:
CMP ,vm_handler_add,4
JNE NEXT_4
MOV temp_1,,4
MOV temp_2,,4
LOG"ADD"
LOG temp_1
LOG temp_2
JMPLOOP
NEXT_4:
CMP ,vm_handler_getfs,4
JNE NEXT_5
MOV temp_1,,4
LOG temp_1,"get fs: "
JMP LOOP
NEXT_5:
CMP ,vm_handler_pop2vesp,4
JNE NEXT_6
MOV temp_1,,4
ADD temp_1,
MOV temp_2,,4
ADD temp_2,
MOV temp_1,temp_2
//MOV temp_1,,4
MOV temp_2,,4
LOG temp_2,"pop to vesp "
LOG temp_1,"vesp "
JMP LOOP
NEXT_6:
CMP ,vm_handler_jmp,4
JNENEW_HANDLER
MOV temp_1,,4
MOV temp_2,,4
CMP temp_1,temp_2
JNE NOT_EQU
MOV temp_1,,4
MOV temp_2,,4
ADD temp_1,temp_2
LOG temp_1,"jmp "
JMP LOOP
NOT_EQU:
LOG "JMP 0"
JMP LOOP
NEW_HANDLER:
MSG "新的handler出现"
RET
END:
MSG "FINISH"
RET
由于是动态脚本所以一些循环记了多次导致log数据很长。
我们根据特殊的handler get_fs来定位关键。
部分log数据
JMP 0
push dword 00000030
get fs: 00000030 ;获取fs:
pop to vesp 7FFD7000
vesp 0012FEDC
push from vesp 00251E90
pop to vesp 00251E90
vesp 0012FEDC
push from vesp 00251EC0
pop to vesp 00251EC0
vesp 0012FEDC
push from vesp 00251F18
pop to vesp 00251F18
vesp 0012FEDC
push from vesp 7C920000 ;定位到ntdll
pop to vesp 7C920000
vesp 0012FED8
push from vesp 7C920000
push dword 00000000
JMP 0
push from vesp 7C920000
push from vesp 000000E0 ;并不是用3c那边去找pe头而是用定值
ADD
temp_1: 000000E0
temp_2: 7C920000
pop to vesp 7C9200E0 ;定位到pe头
vesp 0012FED4
push from vesp 00003400 ;导出表rva
push from vesp 7C920000
temp_2: 00003400
pop to vesp 7C923400 ;保存到空间中
vesp 0012FED0
push from vesp 7C923400
push from vesp 7C920000
JMP 0
push from vesp 00006786
push from vesp 7C920000
ADD
temp_1: 7C920000
temp_2: 00006786
pop to vesp 7C926786 ;导出函数名字
vesp 0012FECC
push from vesp 6C64746E ;ntdl
push dword 6C64746E ;立即数
jmp 004128CF ;相等跳转
push from vesp 00005D40
push from vesp 7C920000
push dword 69567463
JMP 0 ;比较是不是相等
push from vesp 7C9248B4
push dword 00000004
ADD
temp_1: 00000004 ;下一个继续比较
temp_2: 7C9248B4
pop to vesp 7C9248B8
vesp 0012FEC8
push from vesp 7C925D40
push dword 00000002
ADD
temp_1: 00000002
temp_2: 7C925D40
pop to vesp 7C925D42
vesp 0012FECC
push dword 00000000
push dword 00000000
jmp 0041292F ;相同定位成功
push from vesp 000067A9
push from vesp 7C920000
然后开始一大堆循环
再根据特殊handler call定位到
pop to vesp 7C92D6D0 ;ZwProtectVirtualMemory
vesp 0012FEC4
push from vesp 0012FF0C
push dword FFFFFFD4
ADD
temp_1: FFFFFFD4
temp_2: 0012FF0C
push dword 00000040
push from vesp 0012FF0C
push dword FFFFFFAC
ADD
temp_1: FFFFFFAC
temp_2: 0012FF0C
push from vesp 0012FF0C
push dword FFFFFFB0
ADD
temp_1: FFFFFFB0
temp_2: 0012FF0C
push dword FFFFFFFF
push from vesp 7C92D6D0
call 7C92D6D0 ;调用
pop to vesp 00000000
push dword 0424448B
pop to vesp 0424448B
vesp 00412F23
push dword 1424548B
pop to vesp 1424548B
vesp 00412F27
push dword 10391087
pop to vesp 10391087
vesp 00412F2B
push dword 0025840F
pop to vesp 0025840F
vesp 00412F2F
push dword 548B0000
pop to vesp 548B0000
vesp 00412F33
push dword 4C8B0C24
pop to vesp 4C8B0C24
vesp 00412F37
push dword 02E90824
pop to vesp 02E90824
vesp 00412F3B
push dword 31000000
pop to vesp 31000000
vesp 00412F3F
push dword 24540310
pop to vesp 24540310
vesp 00412F43
push dword 81D2D310
pop to vesp 81D2D310
vesp 00412F47
push dword 362092F2
pop to vesp 362092F2
vesp 00412F4B
push dword 04C083DE
pop to vesp 04C083DE
vesp 00412F4F
push dword E8850F49
pop to vesp E8850F49
vesp 00412F53
push dword C2FFFFFF
pop to vesp C2FFFFFF
vesp 00412F57
push dword 90900014
pop to vesp 90900014
vesp 00412F5B
push from vesp 0000E860
push from vesp C0787D01
push from vesp 12AE9AB5
push from vesp 000001AE
push from vesp 00413037
push from vesp 00412F23
call 00412F23
这里就是压入ocpode然后去执行了,这些数据都是代码
00412F23 8B4424 04 mov eax,dword ptr ss: ; NotePad_.00413037
00412F27 8B5424 14 mov edx,dword ptr ss:
00412F2B 8710 xchg dword ptr ds:,edx
00412F2D 3910 cmp dword ptr ds:,edx
00412F2F 0F84 25000000 je NotePad_.00412F5A
00412F35 8B5424 0C mov edx,dword ptr ss:
00412F39 8B4C24 08 mov ecx,dword ptr ss:
00412F3D E9 02000000 jmp NotePad_.00412F44
00412F42 3110 xor dword ptr ds:,edx
00412F44 035424 10 add edx,dword ptr ss:
00412F48 D3D2 rcl edx,cl
00412F4A 81F2 922036DE xor edx,0xDE362092
00412F50 83C0 04 add eax,0x4
00412F53 49 dec ecx
00412F54^ 0F85 E8FFFFFF jnz NotePad_.00412F42
00412F5A C2 1400 retn 0x14
00412F5D 90 nop
00412F5E 90 nop
、
这个明显是个解码函数
push from vesp 90909090
push from vesp 90909090
jmp 00412E0F
push dword 5C04C483
pop to vesp 5C04C483
vesp 00412F23
push dword C9595E5F
pop to vesp C9595E5F
vesp 00412F27
push dword 000107E9
pop to vesp 000107E9
vesp 00412F2B
push dword 00258400
pop to vesp 00258400
vesp 00412F2F
push dword 90909090
pop to vesp 90909090
vesp 00412F33
push dword 90909090
pop to vesp 90909090
vesp 00412F37
push dword 90909090
pop to vesp 90909090
vesp 00412F3B
push dword 90909090
pop to vesp 90909090
vesp 00412F3F
push dword 90909090
pop to vesp 90909090
vesp 00412F43
push from vesp 0012FF0C
push from vesp 00412F23
call 00412F23
之后用相同的手法更新数据
jmp 00412E0F这里有个eq跳
00412F23 83C4 04 add esp,0x4
00412F26 5C pop esp
00412F27 5F pop edi
00412F28 5E pop esi
00412F29 59 pop ecx
00412F2A C9 leave
00412F2B E9 07010000 jmp NotePad_.00413037
00412F30 8425 00909090 test byte ptr ds:,ah
00413037 60 pushad
00413038 E8 00000000 call NotePad_.0041303D
0041303D 5F pop edi
0041303E 81EF 101C9700 sub edi,0x971C10
00413044 31C0 xor eax,eax
00413046 B8 01000000 mov eax,0x1
0041304B F0:8787 721C970>lock xchg dword ptr ds:,ea>
00413052 83F8 00 cmp eax,0x0
00413055 0F85 2C000000 jnz NotePad_.00413087
0041305B 01D2 add edx,edx
0041305D B8 37300100 mov eax,0x13037
00413062 8DB7 0A1C9700 lea esi,dword ptr ds:
00413068 29C6 sub esi,eax
0041306A 29C9 sub ecx,ecx
0041306C 56 push esi
0041306D 57 push edi
0041306E E8 34000000 call NotePad_.004130A7
00413073 09C0 or eax,eax
00413075 8987 6D1C9700 mov dword ptr ds:,eax
0041307B B8 01000000 mov eax,0x1
00413080 F0:8787 761C970>lock xchg dword ptr ds:,ea>
00413087 F3: prefix rep:
00413088 90 nop
00413089 8B87 761C9700 mov eax,dword ptr ds:
0041308F 83F8 01 cmp eax,0x1
00413092^ 0F85 EFFFFFFF jnz NotePad_.00413087
00413098 61 popad
00413099 68 BD7D9300 push 0x937DBD
0041309E C3 retn
申请了内存解密后射入937DBD开始干坏事
在937DBD中使用各种乱序技巧
比如
0093667F 68 DA97FFFF push 0xFFFF97DA ; 返回地址修正
00936684 E8 84A8FFFF call 00930F0D ; 跳转函数
00930F0D 9C pushfd
00930F0E 53 push ebx
00930F0F 50 push eax
00930F10 8B5C24 0C mov ebx,dword ptr ss:
00930F14 B8 8E7A0000 mov eax,0x7A8E
00930F19 0343 FC add eax,dword ptr ds:
00930F1C 034424 10 add eax,dword ptr ss:
00930F20 014424 0C add dword ptr ss:,eax
00930F24 58 pop eax
00930F25 5B pop ebx
00930F26 9D popfd
00930F27 C2 0400 retn 0x4
给分析带来然后,不敢f8。
还有一些假的jcc指令和无意义的循环消耗调试者的体力。
之后开始获取有用的函数00924F49 56 push esi
00924F4A E8 524E0000 call 00929DA1
然后用jmp eax这种方式调用
然后用调用
可以发现都是获取计算机信息的还有一个是 CreateThread
建立一个新线程
7C8106C7 >8BFF mov edi,edi
7C8106C9 55 push ebp
7C8106CA 8BEC mov ebp,esp
7C8106CC FF75 1C push dword ptr ss:
7C8106CF FF75 18 push dword ptr ss:
7C8106D2 FF75 14 push dword ptr ss:
7C8106D5 FF75 10 push dword ptr ss:
7C8106D8 FF75 0C push dword ptr ss:
7C8106DB FF75 08 push dword ptr ss:
7C8106DE 6A FF push -0x1
7C8106E0 E8 D7FDFFFF call kernel32.CreateRemoteThread
新线程地址00939747
下断后发现代码类似,开始载入dl
尝试连接l
附上log数据
简单的分析,不免有所纰漏,请各位指针。
分析虚拟机,现在越来越多的软件被虚拟机绑定了,脱壳难,离开相应的虚拟机,无法执行。
谢谢提供虚拟机类的分析报告 本帖最后由 yuansunxue 于 2014-3-23 18:03 编辑
有兴趣 可以分析下他是怎么生成虚拟机代码的 我在vb上发了篇分析:Inside W32.Xpaj.B's infection 虽然看不懂,但还是会支持楼主,感谢分享 赞一个。 L4Nce就爱玩这些高难度的。 厉害厉害 摸鸟,虽然完全看不懂 小的看不懂,日后再来. 完全看不懂,离虚拟机还很遥远