|
楼主 |
发表于 2007 年 4 月 12 日 16:08:55
|
显示全部楼层
在win9x下,coralqq.exe先创建QQ的进程,同时也就创建了QQ的暂停的主线程,接着往QQ.exe的内存
写数据,改写QQ.exe的oep从而达到改变程序流程的目的,让其先执行加入了的代码,加载Coralqq.dll,
加载完后再跳到原来的QQ.exe的oep继续执行.
其实在win2000/xp下面完全可以用远程线程的方法来实现加载dll文件,我后来自己编程实现了外挂
这一步.
也许有读者读完这编文章后会问:"加载了coralqq.dll又有什么用?它是怎样显IP的?"
其实,要显IP当然要修改QQ的内存中的代码,而修改内存代码这一步是在加载coralqq.dll的时候由
coralqq.dll完成的.也就是说,在执行LoadLibrary的过程中系统会执行corall.dll的 LibMain ,修改
的过程就在LibMain中完成了!而说到显IP的原理,抱歉,不在我们这编文章的讨论范围之内,我们只是讨论
外挂中"挂"这一步.
下面是我写的代码,可以做出一个顶替Coralqq.exe的程序,但原理上和Coralqq.exe有一点点不同
.586
.model flat, stdcall
option casemap :none ; case sensitive
include windows.inc
include kernel32.inc
includelib kernel32.lib
.data
qq db ".\QQ.exe",0
ikeyname db "qq",0
isecname db "main",0
szBuffer dw 50 dup(0)
dllname db ".\CoralQQ.dll",0
szkernel32 db "Kernel32.dll",0
dllin dd 0
szloadlibrary db "LoadLibraryA",0
oaddr dd 0
wriaddr dd 0
ininame db ".\CoralQQ.ini",0
.data?
align dword
con CONTEXT <>
align dword
con2 CONTEXT <>
stStartUp STARTUPINFO
stProcInfo PROCESS_INFORMATION
.code
start:
main proc
local wrisize:dword ;用来存放要写入的代码的大小
local num:dword
local oldpro:dword
local lastwri:dword
local wribase:dword ;用来存放写入代码的基址
invoke GetPrivateProfileString,offset isecname,offset ikeyname,\
offset szloadlibrary,offset szBuffer,\
sizeof szBuffer,offset ininame ;从Coralqq.ini中获取QQ程序的路径
invoke GetModuleHandle,offset szkernel32
invoke GetProcAddress,eax,offset szloadlibrary
mov dllin,eax
invoke GetStartupInfo,addr stStartUp
invoke CreateProcess,NULL,offset szBuffer,NULL,NULL,FALSE,\
CREATE_SUSPENDED,NULL,NULL,addr stStartUp,addr stProcInfo ;创建QQ进程
cmp eax,0
jz exit
invoke GetVersion
test eax,080000000h ;判断操作系统类型
jnz win9x
invoke VirtualAllocEx,stProcInfo.hProcess,NULL,01000h,MEM_COMMIT,\
PAGE_EXECUTE_READWRITE ;在QQ内存中分配空间
mov oaddr,eax
invoke WriteProcessMemory,stProcInfo.hProcess,oaddr,offset dllname,\
sizeof dllname,addr num ;写入数据
invoke CreateRemoteThread,stProcInfo.hProcess,NULL,0,dllin,oaddr,0,\
addr num ;创建远程线程
invoke CloseHandle,eax
invoke ResumeThread,stProcInfo.hThread ;让QQ继续运行
invoke ExitProcess,0
ret
win9x:
mov wribase,oepwrite
mov wrisize,codeend-oepwrite
invoke VirtualProtect,wribase,wrisize,\
PAGE_EXECUTE_READWRITE,addr oldpro ;改变这个程序的要写入代码的地方的属性,其实可以在编译时加上开关
mov wrisize,codeend-codewrite
mov wriaddr,080000000h
sub wriaddr,1000h
again:
add wriaddr,1000h
mov wribase,codewrite
invoke WriteProcessMemory,stProcInfo.hProcess,wriaddr,\
wribase,wrisize,addr num ;写入代码
mov eax,wrisize
cmp eax,num
jnz again
mov eax,wriaddr
mov ebx,chan0-4
mov [ebx],eax
invoke VirtualProtectEx,stProcInfo.hProcess,0464b58h,7,\
PAGE_EXECUTE_READWRITE,addr oldpro ;改变QQ.exe的oep处的属性
mov wribase,oepwrite
invoke WriteProcessMemory,stProcInfo.hProcess,0464b58h, wribase,7,\
addr num ;写入数据
mov eax,dllin
mov ebx,chan2-4
mov [ebx],eax
mov eax,codeend-codewrite
add eax,wriaddr
mov ebx,chan1-4
mov [ebx],eax
mov wribase,codewrite
mov wrisize,codeend-codewrite
invoke WriteProcessMemory,stProcInfo.hProcess,wriaddr,\
wribase,wrisize,addr num
mov eax,codeend-codewrite
add eax,wriaddr
mov lastwri,eax
invoke WriteProcessMemory,stProcInfo.hProcess,lastwri,offset dllname,\
sizeof dllname,addr num
invoke ResumeThread,stProcInfo.hThread ;让QQ继续执行
exit:
invoke ExitProcess,0
ret
main endp
;下面的都是要写入到QQ.exe的内存的附加代码,但有些数值在写入前要实时修正
oepwrite:
mov eax,0
chan0: jmp eax
codewrite:
mov eax,0464b58h
push 6aec8b55h
pop [eax]
mov eax,0464b5ch
push 101868ffh
pop [eax]
push 080000000
chan1:
push 464b58h
mov eax,0
chan2:
jmp eax
codeend:
end start |
|