以前写的远线程保护都是基于罗云斌的代码的 可他的代码有个问题
invoke GetModuleHandle, CTXT('kernel32.dll')
mov ebx, eax
invoke GetProcAddress, ebx, CTXT('GetModuleHandleA')
mov g_lpGetModuleHandleA, eax ;要让代码段可写!
invoke GetProcAddress, ebx, CTXT('GetProcAddress')
mov g_lpGetProcAddress, eax
这种方法在注入的进程中获得API的地址 可在其他进程中就不一定了~~
所以远线程只是 勉强 能运行
现在偶改好了 和以前的相比 有以下改进
1.获取API地址的方法更合理 理论上支持vista
2.增加了错误处理
3.判断了操作系统版本
4.使用进程ID而不是进程名判断被保护进程
呵呵 大概就这么多改进 有不对的还请各位高手指出
光帖一下远线程的代码罢
程序代码:
.code
Remote_code_start equ this BYTE
g_lpGetModuleHandleA dd 0
g_lpGetProcAddress dd 0
g_szKernel32 db 'Kernel32.dll',0
g_hKernel32 dd 0
g_szCreateProcessA db 'CreateProcessA',0
g_lpCreateProcessA dd 0
g_szCreateToolhelp32Snapshot db 'CreateToolhelp32Snapshot',0
g_lpCreateToolhelp32Snapshot dd 0
g_szProcess32First db 'Process32First',0
g_lpProcess32First dd 0
g_szProcess32Next db 'Process32Next',0
g_lpProcess32Next dd 0
g_szCloseHandle db 'CloseHandle',0
g_lpCloseHandle dd 0
g_szSleep db 'Sleep',0
g_lpSleep dd 0
g_szPath db 'Cmd.EXE',0
g_szDesktop db 'WinSta0\Default',0
g_stProcess PROCESSENTRY32 <0>
g_hSnapshot dd 0
g_dwProcessID dd 0
g_stStartupInfo STARTUPINFO <0>
aaaa db 10 dup('a')
g_ProcInfo PROCESS_INFORMATION <0>
_RemoteThreadBegin:
call delta
delta:
pop ebx ;得到当前地址 这里没有再减 学习cih的重定位方法 貌似这样省字节
pushad
add esp,20h ;执行了 pushad
mov edi,[esp] ;获取 Kernel32.dll 的基地址
sub esp,20h
and edi, 0ffff0000h ;初始页
.while TRUE
.if WORD ptr [edi] == IMAGE_DOS_SIGNATURE ;MZ?
mov esi, edi
add esi, [esi + IMAGE_DOS_HEADER.e_lfanew]
.if WORD ptr [esi] == IMAGE_NT_SIGNATURE ;PE?
mov [ebx+(g_hKernel32-delta)], edi
.break
.endif
.endif
sub edi, 010000h ;即每次减少64k:
.break .if edi < 070000000h ; 基地址一般不可能小于70000000h
jmp @return
.endw
lea esi,[ebx+(g_szCreateProcessA-delta)]
call _GetFunctionAddress
.if eax==0
jmp @return
.endif
mov [ebx+(g_lpCreateProcessA-delta)],eax
lea esi,[ebx+(g_szCreateToolhelp32Snapshot-delta)]
call _GetFunctionAddress
.if eax==0
jmp @return
.endif
mov [ebx+(g_lpCreateToolhelp32Snapshot-delta)],eax
lea esi,[ebx+(g_szProcess32First-delta)]
call _GetFunctionAddress
.if eax==0
jmp @return
.endif
mov [ebx+(g_lpProcess32First-delta)],eax
lea esi,[ebx+(g_szProcess32Next-delta)]
call _GetFunctionAddress
.if eax==0
jmp @return
.endif
mov [ebx+(g_lpProcess32Next-delta)],eax
lea esi,[ebx+(g_szCloseHandle-delta)]
call _GetFunctionAddress
.if eax==0
jmp @return
.endif
mov [ebx+(g_lpCloseHandle-delta)],eax
lea esi,[ebx+(g_szSleep-delta)]
call _GetFunctionAddress
.if eax==0
jmp @return
.endif
mov [ebx+(g_lpSleep-delta)],eax
;第一次运行创建进程 并得到进程ID
@CreateProtectedProc:
lea eax, [ebx+(g_szDesktop-delta)]
lea ecx, [ebx+(g_stStartupInfo-delta)]
mov DWORD ptr [ecx], sizeof g_stStartupInfo
mov DWORD ptr [ecx+8], eax
lea eax, [ebx+(g_szPath-delta)]
lea edx, [ebx+(g_ProcInfo-delta)]
_invoke [ebx+(g_lpCreateProcessA-delta)], 0, eax, 0, 0, 0, 0, 0, 0, ecx, edx
lea esi,[ebx+(g_ProcInfo-delta)]
assume esi:ptr PROCESS_INFORMATION
mov eax,[esi].hProcess
_invoke [ebx+(g_lpCloseHandle-delta)],eax
assume esi:nothing
;int 3h
@Toolhelp32Loop:
lea esi,[ebx+(g_stProcess-delta)]
assume esi:ptr PROCESSENTRY32
mov [esi].dwSize,sizeof g_stProcess
assume esi:nothing
_invoke [ebx+(g_lpCreateToolhelp32Snapshot-delta)], TH32CS_SNAPPROCESS, 0
mov edi,eax ;edi = hSnapshot
lea ecx,[ebx+(g_stProcess-delta)]
_invoke [ebx+(g_lpProcess32First-delta)], edi,ecx
.while eax
;得到的进程ID与我们建的比较 找不到就在建
;这样最大限度的避免了重复的情况 进程ID重复概率很小~
lea esi,[ebx+(g_stProcess-delta)]
assume esi:ptr PROCESSENTRY32
mov edx,[esi].th32ProcessID
lea esi,[ebx+(g_ProcInfo-delta)]
assume esi:ptr PROCESS_INFORMATION
mov ecx,[esi].dwProcessId
assume esi:nothing
.if edx==ecx
mov esi,TRUE ;设置找到的标志
.break
.endif
lea ecx,[ebx+(g_stProcess-delta)]
_invoke [ebx+(g_lpProcess32Next-delta)], edi, ecx
.endw
_invoke [ebx+(g_lpCloseHandle-delta)], edi
.if esi!=TRUE ;没有就运行
jmp @CreateProtectedProc
.endif
_invoke [ebx+(g_lpSleep-delta)],300d ;刚杀掉又有了 呵呵 这里可以改的合适一点 间隔太小也不好
jmp @Toolhelp32Loop
@return:
popad
ret
_GetFunctionAddress proc uses ebx
mov eax, [ebx+(g_hKernel32-delta)] ;EAX = Kernel32 Address
mov ebx, [eax+3Ch] ;IMAGE_DOS_HEADER.e_lfanew
add ebx, eax
add ebx, 120
mov ebx, [ebx]
add ebx, eax ;EBX = Export Address
xor edx, edx
mov ecx, [ebx+32]
add ecx, eax
push esi
push edx
@CompareNext:
pop edx
pop esi
inc edx
mov edi, [ecx]
add edi, eax
add ecx, 4
push esi
push edx
@CompareName:
mov dl, [edi]
mov dh, [esi]
cmp dl, dh
jne @CompareNext
inc edi
inc esi
cmp BYTE ptr [esi], 0
je @GetAddress
jmp @CompareName
@GetAddress:
pop edx
pop esi
dec edx
shl edx, 1
mov ecx, [ebx+36]
add ecx, eax
add ecx, edx
xor edx, edx
mov dx, [ecx]
shl edx, 2
mov ecx, [ebx+28]
add ecx, eax
add ecx, edx
add eax, [ecx]
ret
_GetFunctionAddress endp
Remote_code_end equ this BYTE
Remote_code_length equ offset Remote_code_end - offset Remote_code_start
;注入代码的长度