作 者: Anskya
時 間: 2006-06-29,15:43
鍊 接: http://bbs.pediy.com/showthread.php?threadid=28211
InjectCode for Win9x..
文章作者:Anskya
原文出處:看雪論壇
轉載請保留版權~謝謝
現在注入方式很多,不過無外複三種:
1.使用映射代碼然後建立遠端線程
2.利用消息鈎子插入DLL兩種
3.使用調試API.GetThreadContext,SetThreadContext來改變線程的環境啟動代碼
4.不過基本上Win9x下差不多都是使用消息鈎子挂鈎模式
當然EliCZ叔叔釋出的~EliRT可以讓我們在Win9x下也可以使用
CreateRemoteThread注入函數...這裡偶簡單的說一下另外一種注入方式
利用系統内部函數進行建立遠端線程.
這裡我就不多說一大堆理論了~相關文獻請參見EliCZ叔叔的文章...
當然這裡使用的注入方式~他的文章中并沒有提及...
1.原理
[1]定位目标
既然是誇程序的建立程序,首先我們懷疑的就是調試API
他們是如何作到調試遠端程序的,比如DebugActiveProcess,
他是如何挂起目标程序的...是以對目标程序進行逆向分析..
(關于次問題請到...exetools裡面檢視相關文章吧...裡面有讨論過)
(一下代碼是反彙編DebugActiveProcess函數的...這裡貼的是關鍵部分分析)
其實就在DebugActiveProcess下面幾行的位置處...自己分析一下就知道了
代碼:--------------------------------------------------------------------------------
; IDA output:
;.text:BFF9490D push 8 ; const
;.text:BFF9490F push edi
;.text:BFF94910 push offset sub_BFF9494D ; thread
;.text:BFF94915 push 0FFFFF000h ; tells kernel to allocate stack
;.text:BFF9491A push edi ; pdb
;.text:BFF9491B call CreateRemoteThread9x; arbitrary name
;0xE8 = call; 0x85 = push edi; 0xFFFF = higher part of 0xFFFFF000
特征碼:0E857FFFFh(看不懂嗎?自己反一下這個函數就知道了...16進制碼...請問IDA這裡怎麼用???為顯示不出...)
--------------------------------------------------------------------------------
至少跟蹤發現這個函數不是WIndows導出的函數是以我們不能直接調用這個函數
(至少無法通過GetProcAddress函數搜尋出位址來...但是我們完全可以定位函數位址和傳入參數...分析代碼看下面的文章)
2.定位
知道原理了..開始逆向分析...這裡分析的目标是國外的一款非常恐怖的"Trojan"程式
Spirit(反向連接配接+遠端注入代碼,上傳DLL或者EXE并運作之...體積:1.55k,
還有系統資料庫添加,自删除等功能...支援Win9x下程序插入--一開始就對他很好奇^_^)
關鍵函數逆向分析部分:OD反出來的...
代碼:--------------------------------------------------------------------------------
00400158 68 40000000 push 40
0040015D 68 00300008 push 8003000
00400162 68 D5050000 push 5D5
00400167 57 push edi
00400168 FF15 42144000 call [401442] ; kernel32.VirtualAlloc
0040016E 68 08000000 push 8
00400173 57 push edi
00400174 50 push eax
00400175 57 push edi
00400176 68 D1040000 push 4D1
0040017B 8D15 0E114000 lea edx, [40110E] ;這個位址是需要插入的代碼記憶體位址
00400181 52 push edx
00400182 50 push eax
00400183 56 push esi
00400184 FF15 32144000 call [401432] ; kernel32.WriteProcessMemory
0040018A FF15 3E144000 call [40143E] ; kernel32.GetCurrentProcessId
00400190 64:3305 3000000>xor eax, fs:[30]
00400197 31C3 xor ebx, eax
00400199 8B35 3A144000 mov esi, [40143A] ;kernel32.DebugActiveProcess
0040019F 46 inc esi
004001A0 813E FFFF57E8 cmp dword ptr [esi], E857FFFF ;比較是否是CreateRemoteThread9x記憶體特征
004001A6 ^ 75 F7 jnz short 0040019F ;不等繼續跳轉
004001A8 AD lods dword ptr [esi] ;搜尋到以後開始擷取位址(掃描兩次)
004001A9 AD lods dword ptr [esi]
004001AA 01F0 add eax, esi
004001AC 68 00F0FFFF push -1000
004001B1 53 push ebx
004001B2 FFD0 call eax
004001B4 57 push edi
004001B5 50 push eax
004001B6 8B35 2A144000 mov esi, [40142A] ; kernel32.OpenProcess
004001BC 46 inc esi
004001BD 813E 50FF32E8 cmp dword ptr [esi], E832FF50
004001C3 ^ 75 F7 jnz short 004001BC
004001C5 AD lods dword ptr [esi]
004001C6 AD lods dword ptr [esi]
004001C7 01F0 add eax, esi
004001C9 53 push ebx
004001CA FFD0 call eax ;調用此函數
004001CC 61 popad
004001CD C3 retn
--------------------------------------------------------------------------------
3.實作
不用說了吧~上面的代碼逆向寫一下就OK了...
既然注入代碼我們就作全套...
[1]申請遠端程序空間(C代碼實作)
WinNT下我就不多說了~反正大家都知道的
關鍵說說Win9x
逆向分析一下中國黑客病毒
(CreateKernelThread建立線程...和
MoveDataToKnl函數(WHG自己寫的具體看ChineseHacker代碼))
不過他好像不能讓我們将代碼注入到别的程序内部...
好了Google搜了一下文章...發現Win9x核心下0x8000000以上空間都是透明的?
Why?你最好别問我,我也不知道..我很菜...
是以以上反彙編出來的代碼是
代碼:--------------------------------------------------------------------------------
00400158 68 40000000 push 40
0040015D 68 00300008 push 8003000
00400162 68 D5050000 push 5D5
00400167 57 push edi
00400168 FF15 42144000 call [401442] ; kernel32.VirtualAlloc
--------------------------------------------------------------------------------
啊~好了...寫一下具體代碼好了
代碼:--------------------------------------------------------------------------------
LPVOID My_VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD
flProtect)
{
if (GetVersion() > 0x80000000)
{
return VirtualAlloc(lpAddress, dwSize, 0x8000000 + MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}else
{
return VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
}
}
BOOL My_VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType)
{
if (GetVersion() > 0x80000000)
{
return VirtualFree(lpAddress, dwSize, MEM_RELEASE);
}else
{
return VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType);
}
}
--------------------------------------------------------------------------------
需要注意的是~在Win9x下申請空間和釋放空間以前需要~~OpenProcess
一下....在Win9x下申請空間還有一種方法:SharedMemoryAlloc函數
直接的Windows頭部裡面好像沒有...大家可以從ComCtl32.dll裡面導出...
這個函數使用非常簡單..就一個參數.申請空間長度...
建立遠端線程代碼在附件内....(把上面的OD反彙編代碼寫一遍就OK了~有必要嗎???)
具體示例代碼看:附件~注入代碼到記事本....支援Win9x下注入
參考文獻:
[1]EliCZ 的EliRT代碼,首頁.看雪上有友情連接配接
[2]y0da 的Invisibility代碼,首頁.看雪上有友情連接配接
文章作者:Anskya
原文出處:看雪論壇
轉載請保留版權~謝謝
終于可以上傳了~
代碼:--------------------------------------------------------------------------------
;======================================================
;遠端線程注入對話框示範 Ex By Anskya
;支援Win9x下代碼注入..
;Email:[email protected]
;======================================================
.586
.model flat
locals @@
include /D.N.ASM/include/useful.inc
include /D.N.ASM/include/MZ.INC
include /D.N.ASM/include/PE.INC
.data
notepad db 'Notepad',0
injected:
;int 3
pushad
call @@delta
@@delta:
pop ebp
sub ebp,offset @@delta
push 0
lea eax,[ebp+offset cap]
push eax
lea eax,[ebp+offset msg]
push eax
push 0
call [ebp+__MessageBoxA]
@@Exit:
push 0
call [ebp+__ExitThread]
;_invoke [ebp+__ExitThread],0
popad
ret
;------------------使用資料----------------------------------
msg db "
-
Hello World Coder! (C) Anskya.",0dh,0ah,0
cap db "MsgBox By Anskya",0
k32_api:
db 'kernel32',0
__ExitThread dd 0058F9201h
__WinExec dd 028452C4Fh
__OpenProcess dd 033D350C4h
__WriteProcessMemory dd 00E9BBAD5h
dd 0
u32_api:
db 'user32',0
__MessageBoxA dd 0D8556CF7h
__FindWindowA dd 085AB3323h
__GetWindowThreadProcessId dd 07B46AF5Eh
dd 0
injected_size equ $-injected
.code
public c entry
entry:
;-------擷取相關API函數
lea eax,k32_api
push eax
call get_apicrc
lea eax,u32_api
push eax
call get_apicrc
;-------擷取完畢-------執行主函數部分
;call injected
push 5
push offset notepad
call __WinExec
push 0
push offset notepad
call __FindWindowA ;擷取視窗句柄
push eax
push esp
push eax
call __GetWindowThreadProcessId
pop eax
mov ebx,eax
push eax
push 0
push 1f0fffh ;PROCESS_ALL_ACCESS
call __OpenProcess
mov ebp,eax
push 40h ;PAGE_EXECUTE_READWRITE
push 3000h ;MEM_COMMIT or MEM_RESERVE
push injected_size
push 0
push ebp ;pid
call RT32_VirtualAllocEx
mov edi,eax
push eax
push esp
push injected_size
lea eax,injected
push eax
push edi
push ebp
call __WriteProcessMemory
pop eax
push eax
push esp
push 0
push esi
push edi
push 0
push 0
push ebx
call RT32_CreateRemoteThread
pop ecx
ExitProc:
push 0
callw ExitProcess
ret
;-------使用函數位址
RT32_VirtualAllocEx:
pushad
mov ebx,[esp+8*4+4]
mov ebp,[esp+8*4+8]
mov edx,[esp+8*4+12]
mov esi,[esp+8*4+16]
mov edi,[esp+8*4+20]
call get_k32base
mov ecx,cs
xor cl,cl
jecxz @@os_nt
@@os_9x:
push edi
or esi,8000000h
push esi
push edx
push ebp
push 04402890Eh ;VirtualAlloc
push eax
call get_addr32crc
call eax
jmp @@finished
@@os_nt:
push 0DA89FC22h ;VirtualAllocEx
push eax
call get_addr32crc
push edi
push esi
push edx
push ebp
push ebx
call eax
@@finished:
mov [esp+pushad_eax],eax
popad
ret 4*5
RT32_CreateRemoteThread:
pushad
mov ebp,[esp+8*4+4]
call get_k32base
mov esi,eax
push ebp
push 0
push 1f0fffh ;PROCESS_ALL_ACCESS
push 033D350C4h ;OpenProcess
push esi
call get_addr32crc
call eax
mov ebx,eax
push 0CF4A7F65h ;CreateRemoteThread
push esi
call get_addr32crc
mov ecx,cs
xor cl,cl
jecxz @@os_nt
@@os_9x:
call get_obfs
xor ebp,eax
call search_crt9x
jnc @@error
mov esi,eax
mov edi,[esp+8*4+16]
mov eax,[esp+8*4+20]
push 8
push eax
push edi
push 0fffff000h
push ebp
call esi
push eax
call search_halloc9x
jnc @@error
mov edx,eax
pop eax
push 0
push eax
push ebp
call edx
jmp @@finished
@@os_nt:
; push dwo [esp+8*4+28+ 0]
; push dwo [esp+8*4+24+ 4]
; push dwo [esp+8*4+20+ 8]
; push dwo [esp+8*4+16+12]
; push dwo [esp+8*4+12+16]
; push dwo [esp+8*4+8 +20]
push 6
pop ecx
@@loop_push:
push dwo [esp+8*4+28]
loop @@loop_push
push ebx
call eax
@@finished:
mov [esp+pushad_eax],eax
popad
ret 4*7
@@error:
sub eax,eax
dec eax
mov [esp+pushad_eax],eax
popad
ret 4*7
get_obfs:
pushad
push 0EB1CE85Ch ;GetCurrentProcessId
call get_k32base
push eax
call get_addr32crc
call eax
mov ebx,eax
mov eax,fs:[30h]
xor eax,ebx
mov [esp+pushad_eax],eax
popad
retn
search_halloc9x:
pushad
call get_k32base
push 033D350C4h ;OpenProcess
push eax
call get_addr32crc
mov esi,eax
mov eax,0E832ff50h
jmp search_compare
search_crt9x:
pushad
call get_k32base
push 07FC598E3h ;DebugActiveProcess
push eax
call get_addr32crc
mov esi,eax
; IDA output:
;.text:BFF9490D push 8 ; const
;.text:BFF9490F push edi
;.text:BFF94910 push offset sub_BFF9494D ; thread
;.text:BFF94915 push 0FFFFF000h ; tells kernel to allocate stack
;.text:BFF9491A push edi ; pdb
;.text:BFF9491B call CreateRemoteThread9x; arbitrary name
;0xE8 = call; 0x85 = push edi; 0xFFFF = higher part of 0xFFFFF000
; mov eax,0fffff000h
mov eax,0E857FFFFh
; DEBUG: CloseHandle
; mov eax,0E8560002h
search_compare:
sub ecx,ecx
mov cl,255 ;approx. size of DebugActiveProcess, just in case
@@compare:
cmp eax,[esi]
jz @@save
inc esi
dec ecx
jecxz @@exit
jmp @@compare
@@save:
lodsd
lodsd ;eax = relative address of CreateRemoteThread9x()
add eax,esi ;absolute address
mov [esp+pushad_eax],eax
stc
@@exit:
popad
retn
;--------The End~~~[^_^]
get_apicrc:
pushad
mov esi,[esp+8*4+4]
call get_k32base
push 04134D1ADh ;LoadLibraryA
push eax
call get_addr32crc
push esi
call eax
mov ebx,eax
sub eax,eax
lodsb
test al,al
jnz $-3
mov edi,esi
@@loop:
lodsd
test eax,eax
jz @@end
push eax
push ebx
call get_addr32crc
stosd
jmp @@loop
@@end:
popad
retn 4
;void* get_addr32crc(DWORD base, DWORD crc32)
get_addr32crc:
pushad
mov ebx,[esp+8*4+4]
mov esi,[esp+8*4+8]
sub ebp,ebp ;counter
mov edx,ebx
add edx,[edx.mz_neptr]
mov edx,[edx.pe_exportrva]
add edx,ebx
mov eax,[edx.ex_numofnamepointers]
mov edi,[edx.ex_addresstablerva]
add edi,ebx
mov edi,[edx.ex_namepointersrva]
add edi,ebx
push edx
mov edx,edi
@@next:
mov edx,[edi]
add edx,ebx
inc ebp
pushad
mov esi,edx
sub ecx,ecx
lodsb
inc ecx
test al,al
jnz $-4
mov [esp+pushad_ecx],ecx
popad
@@cmpstr:
pushad
; mov edx,edx
sub eax,eax
call xcrc32
cmp eax,esi
popad
jz @@found
; push eax
; sub eax,eax
; scasb
; jnz $-1
; pop eax
add edi,4
dec eax
jz @@error
jmp @@next
@@found:
pop edx
dec ebp
mov ecx,[edx.ex_ordinaltablerva]
add ecx,ebx
movzx eax,wo [ecx+ebp*2]
mov ebp,[edx.ex_addresstablerva]
add ebp,ebx
mov eax,[ebp+eax*4]
add eax,ebx
@@error:
mov [esp+pushad_eax],eax
popad
ret 4*2
;void* get_k32base();
get_k32base:
pushad
sub eax,eax
mov eax,fs:[eax+30h]
test eax,eax
js @@os_9x
@@os_nt:
mov eax,[eax+0ch]
mov esi,[eax+1ch]
lodsd
mov eax,[eax+8]
jmp @@finished
@@os_9x:
mov eax,[eax+34h]
lea eax,[eax+7ch]
mov eax,[eax+3ch]
@@finished:
mov [esp+pushad_eax],eax
popad
retn
; zhengxi's crc32(): optimised by Vecna
; input: EDX=data, ECX=size, EAX=crc
; output: EAX=crc, EDX+=ECX, ECX=BL=0
xcrc32:
pushad
jecxz @@4
not eax
@@1:
xor al, [edx]
inc edx
mov bl, 8
@@2:
shr eax, 1
jnc @@3
xor eax, 0EDB88320h
@@3:
dec bl
jnz @@2
loop @@1
not eax
@@4:
mov [esp+pushad_eax],eax
popad
ret
end