2007 年 12 月
      1
2345678
9101112131415
16171819202122
23242526272829
3031   
上一年下一年   上一月下一月

站点统计
日志:516 篇
评论:331 篇
留言:31 篇
收藏夹:0 个书签
会员数:149 人

最新评论
上海地区广告伞太阳伞专业...
没附件了郁闷,还在的话麻...
已经发送到你的邮箱了,请...
写了一个进程间通讯的类....
行啊,二博客都一样
已经发送了附件到你的邮箱...
老马写的..可惜没的附件...
欢迎!
谢谢了。
第一次走进您的博客,^_...


终于实现了远程线程调用了!!!!!!!   [ 2006-07-13 | 作者:马大哈 | 来自:本站原创]

之前在网上看到一个代码,是向某进程插入一个DLL的VB代码.

试过,可以成功插入,代码如下:

'------------------------------------------------
'pszLibFile指定的文件注入进程ID为dwProcessId的进程
Public Function InjectLibA(ByVal InjectFile As String, ByVal pszLibFile As String)
Dim hProcess As Long, hThread As Long
Dim pszLibFileRemote As Long
Dim pfnThreadRtn As Long
Dim dwProcessId As Long

On Error GoTo errhandle

dwProcessId = EnumProc(InjectFile)
If dwProcessId = 0 Then Exit Function

hProcess = OpenProcess(PROCESS_CREATE_THREAD Or PROCESS_VM_OPERATION Or PROCESS_VM_WRITE, 0, dwProcessId)
'-------3个参数分别为:访问标志;继承标志;进程ID

If hProcess = 0 Then GoTo errhandle '失败,跳出
Dim cch As Long, cb As Long

cch = LenB(StrConv(pszLibFile, vbFromUnicode))
'-------pszLibFile的字节长度
cch = cch + 1
'------为什么加1---"\0".
' Print cch
pszLibFileRemote = VirtualAllocEx(hProcess, 0&, cch, MEM_COMMIT, PAGE_READWRITE)
'---------在hProcess内分配cch字节的空间
' Print "r" & pszLibFileRemote
If pszLibFileRemote = 0 Then GoTo errhandle '失败,跳出

If (WriteProcessMemory(hProcess, pszLibFileRemote, ByVal pszLibFile, cch, ByVal 0&) = 0) Then GoTo errhandle '***********在这里跳出了!
'--------将DLL的路径名复制到远程进程的内存空间。


pfnThreadRtn = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")
'---------取得LoadLibraryA函数在Kernel32.dll中的入口地址

If pfnThreadRtn = 0 Then GoTo errhandle '失败,跳出

hThread = CreateRemoteThread(hProcess, ByVal 0&, 0&, ByVal pfnThreadRtn, pszLibFileRemote, 0, ByVal 0&)
'---------在进程hProcess内创建LoadLibraryA的远程线程。
'---------参数说明:("进程句柄","线程安全描述字,指向SECURITY_ATTRIBUTES结构的指针","线程栈大小",
'---------"指向在远程进程中执行的函数地址","创建线程的其它标志","线程身份标志,如果为NULL,则不返回")
'---------hProcess--->被嵌入的远程进程;pfnThreadRt--->LoadLibraryA的入口地址

If (hThread = 0) Then GoTo errhandle '失败,跳出

WaitForSingleObject hThread, INFINITE
'---------等待线程返回

errhandle:
Debug.Print "fileR" & pszLibFileRemote, "hThread" & hThread, "hProc" & hProcess
If pszLibFileRemote <> 0 Then VirtualFreeEx hProcess, pszLibFileRemote, 0, MEM_RELEASE
'-------释放进程空间中的内存

'------关闭句柄
If hThread <> 0 Then CloseHandle hThread
If hProcess <> 0 Then CloseHandle hProcess
End Function
'*********************************************************************

点击下载完整文件:ModInjectLib.bas

调用很简单,如下:

Call InjectLibA("explorer.exe","testdll.dll")

如果成功,就把testdll.dll插入到了explorer.exe里了.

但是这里还有一个问题.

就是插入后的事.

插入后,当然是要调用那个DLL内的函数啊.

理所当然,还是只能使用CreateRemoteThread这个API,相关代码如下:

pfnThreadRtn = GetFunctionAddress(App.Path & "\testdll.dll", "CallMsgbox")
'---------取得函数dll中的入口地址,GetFunctionAddress是自己封装的函数,后面有介绍
'DLL也是自己的,用VC++6.0写成.VB6.0写的DLL没有试过,以后再试.

If pfnThreadRtn = 0 Then GoTo errhandle '失败,跳出

hThread = CreateRemoteThread(hProcess, ByVal 0&, 0&, ByVal pfnThreadRtn, 0&, 0, ByVal 0&)

它这里有几个问题,比如,目标函数在宿主进程内的入口地址,多参数函数的调用,等.

我就先是卡在了第一个问题上,花了两个晚上才搞定.

先是插入了记事本,没问题;

可是,调用时, 老是让记事本挂.

想不明白.

于是在没有调用前,就使用了WinHex查看了当时的内存,发现目标内存中什么也没有,才发觉地址可能有问题.

之前取得函数入口地址的代码是这样:

tmpDLL = LoadLibrary(pFileName) '载入目标DLL
pfnThreadRtn = GetProcAddress(tmpDLL, "CallMsgbox")
Call FreeLibrary(tmpDLL)

可是,取得的值老是不对,代码按这个值去宿主内存中找,什么也找不到,从而使宿主进程非法操作.

于是我干脆自己用WinHex在宿主内存里查CallMsgbox,终于手工找到了入口地址.

花了近半个小时,才明白它们间的关系:

GetProcAddress返回的那个地址,只有低四位才是正确的.(这里是1006,我用eXeScope看到是10001006)

再在"可选文件头"里找到了一个"ImageBase",值是10000000.

咦,好象.....?

再用eXeScope打开一个DLL,看到某个函数的地址是11001F55,而那个映象基地址是11000000.....

哈,应该是它了!!

于是在MSDN里搜索"ImageBase",经过痛苦的查找,还真让我找到了!!(我E文差得不是一点半点,金山词霸也辛苦了!!)

在里面找到了一篇Randy Kath写的文章:

The Portable Executable File Format from Top to Bottom

这个标题意思我不太明白,按金山词霸来看,可能是叫"PE文件格式大全"吧...... 乱翻的.......

反正里面我查到了那个结构: _IMAGE_OPTIONAL_HEADER

然后在那个DLL里找到了一个专门用于查找文件基地址的API:GetImageBase

嘿嘿,这下太好了!!!

得到了基地址,再把它的高四位与GetProcAddress返回值的低四位合并,得到了最终的函数入口地址:

Public Function GetFunctionAddress(ByVal pFileName As String, ByVal FuncName As String) As Long
'本函数返回指定文件中指定函数的入口地址
Dim tmpDLL As Long, tmpI As Long, tmpJ As Long

tmpDLL = LoadLibrary(pFileName) '载入目标DLL
tmpI = GetImageBase(tmpDLL) '取得DLL基地址
GetFunctionAddress = "&H" & Left(Hex(tmpI), 4) & Hex(Abs(tmpDLL - GetProcAddress(tmpDLL, "CallMsgbox")))
Call FreeLibrary(tmpDLL)
End Function

点击下载ModGetPEOpHeader.bas与PEFILE.dll

于是这个问题就搞定了!!!

现在可以使用CreateRemoteThread来正确调用远程函数了!!

现在已经十一点十一分了,睡觉!!!

明天开始搞多参数传入的问题!!!!


为什么受伤的总是我的右手中指? 又想到以前的一句话:挣钱才是王道

 马大哈 于 2007-06-23 11:22 PM 发表评论: 

引用内容
最初由 水木之 发表于 2007-06-21 01:47 PM: 马哥,我做的怎么老是不成功呢?注入时,卡吧提示有程序进行注入...
我试过EXE文件与DLL文件的注入,都是成功的 在注入后,你可以找来类似PEID里自带的进程查看器那种可查看进程模块的功能,来看看是否成功注入. 我在试验时,没有发现注入失败的情况(针对正常的DLL)

 水木之 于 2007-06-21 01:47 PM 发表评论: 

马哥,我做的怎么老是不成功呢?注入时,卡吧提示有程序进行注入动作,我已经允许它了,后来我干脆退掉了卡吧,还是不行啊。你能不能直接发一份完整的代码给我啊,真的很对这个感兴趣呀!我的邮箱是xiejienet@126.com,谢谢了。

 马大哈 于 2007-05-02 12:15 PM 发表评论: 

一直没时间去搞,抱歉 思路有: 先将参数放在一个结构中,然后将结构写入目标内存中 最后在CreateRemoteThread时传入此结构地址就行了

 pop 于 2007-05-02 12:51 AM 发表评论: 

牛人站长 怎么传入参数解决了吗 我想知道

 马大哈 于 2007-04-13 06:52 PM 发表评论: 

谢谢牛人支持~~~~~

 mydnet 于 2007-04-12 01:37 PM 发表评论: 

牛人支持你!

 风飞雪 于 2007-04-09 02:32 PM 发表评论: 

顶顶

 tyeken8 于 2007-03-20 07:08 PM 发表评论: 

强人

 马大哈 于 2006-07-13 11:15 PM 发表评论: 

嘿,先自己顶顶 这是在自己机器IIS6.0里写的,除了自己没人能顶.....