首页
社区
课程
招聘
[原创]挖掘操作系统内部未导出函数,将注入进行到底
2006-6-29 15:43 11321

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

2006-6-29 15:43
11321
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


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (8)
雪    币: 236
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
误入楼台 1 2006-6-29 16:05
2
0
OOOO  学习
雪    币: 156
活跃值: (23)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
sbright 2 2006-6-29 18:04
3
0
能不能把程序例子也付上?我搜啦一下没有找到
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-6-29 23:17
4
0


雪    币: 32406
活跃值: (18810)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2006-6-30 09:45
5
0
RE:北极星2003
这些日志仅论坛管理人员能看到。
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
foxabu 13 2006-6-30 15:40
6
0
我有一点不明白,为什么注入主程序都要用Shellcode技术获取输入表呢?
比如VirtualAlloc 这个函数 直接用GetProcAddress不好吗?
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yujinjianx 2006-6-30 21:17
7
0
学习
雪    币: 1272
活跃值: (736)
能力值: ( LV13,RANK:810 )
在线值:
发帖
回帖
粉丝
Anskya 20 2006-7-1 00:10
8
0
最初由 foxabu 发布
我有一点不明白,为什么注入主程序都要用Shellcode技术获取输入表呢?
比如VirtualAlloc 这个函数 直接用GetProcAddress不好吗?


我感觉这么些很Cool~没别的原因...
其实这个代码就是ShellCode的代码
以前写Win9x下远程注入代码的ShellCode...
为了偷懒这里就直接粘贴过来了...呵呵
修改一下就OK了~不感觉我那种获取函数方式比较方便吗~
就是这个原因...懒人有懒招...

不过WIn9x也快过时了...这里写出来就是为了描述一下思路...
许多游戏外挂就是利用这种"系统"内部的函数做到的
如何去发掘这才是需要学习的。。。
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 4 2006-7-1 08:44
9
0
强,路过,看过,学习过
游客
登录 | 注册 方可回帖
返回