InjectCode for Win9x..
文章作者:Anskya
原文出处:看雪论坛
转载请保留版权~谢谢

本节附件下载:msgboxex.rar

现在注入方式很多,不过无外复三种:
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

  • 标 题: 答复
  • 作 者:Anskya
  • 时 间:2006-07-01 00:10

引用: 最初由 foxabu 发布
我有一点不明白,为什么注入主程序都要用Shellcode技术获取输入表呢?
比如VirtualAlloc 这个函数 直接用GetProcAddress不好吗? 


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

不过WIn9x也快过时了...这里写出来就是为了描述一下思路...
许多游戏外挂就是利用这种"系统"内部的函数做到的
如何去发掘这才是需要学习的。。。