该源码演示拦截MessageBox函数,可用于多种用途,比如程序辅助制作等。
模块名 = 到小写 (模块名) ' 初始化
Moudle = 取模块基址 (进程句柄)
Name = 取空白文本 (取文本长度 (模块名))
.如果真 (是否为空 (进程句柄))
进程句柄 = -1
.如果真结束
' RtlMoveMemory即是我对ReadProcessMemory的引用,这样方便两个函数切换
' 这里不递归取值主要是提高代码可读性,写得粗糙别见怪啊(其实是PE结构太繁乱了)
RtlMoveMemory (进程句柄, Moudle + 60, pImageDosHearder, 4, 0) ' e_lfanew
pImageOptionalHeader = pImageDosHearder + Moudle + 24 ' ImageDosHearder
RtlMoveMemory (进程句柄, pImageOptionalHeader + 104, pImageImportDescriptor, 4, 0) ' DataDirectory[1]
pImageImportDescriptor = pImageImportDescriptor + Moudle ' pImageImportDescriptor
RtlMoveMemory (进程句柄, pImageImportDescriptor + 12, pMoudleName, 4, 0) ' MoudleName
.判断循环首 (pMoudleName ≠ 0)
取指针文本 (进程句柄, Moudle + pMoudleName, Name, 取文本长度 (模块名), 0) ' 溢出漏洞1
.如果真 (到小写 (Name) = 模块名)
RtlMoveMemory (进程句柄, pImageImportDescriptor + 16, pImageThunkData, 4, 0) ' FirstThunk(union),载入后会变为函数地址
RtlMoveMemory (进程句柄, pImageImportDescriptor, pOriginalFirstThunk, 4, 0)
.如果 (pImageThunkData ≠ 0 且 pOriginalFirstThunk ≠ 0)
pOriginalFirstThunk = Moudle + pOriginalFirstThunk
pImageThunkData = Moudle + pImageThunkData
' OriginalFirstThunk为NULL会取不到函数名,这样取地址考虑主要是因为不额外载入模块的原则;
' 如果hook的模块为系统dll, 就把下面的mark行改为自进程同一函数的地址(可能地址会不一样)
' 如果hook的模块为内核或未被删除,可以从PE读入IAT,手动计算重定位最后得到偏移(比较通用)
.循环判断首 ()
RtlMoveMemory (进程句柄, pOriginalFirstThunk, pImageImportByName, 4, 0) ' 指针
取指针文本 (进程句柄, Moudle + pImageImportByName + 2, Name, 取文本长度 (函数名) + 1, 0) ' \0; 溢出漏洞2
.如果真 (Name = 函数名) ' mark
NtProtectVirtualMemory (进程句柄, pImageThunkData + ret, 4, 4, OldProtect) ' 谁能解释下为甚麽这函数会改变传入的实参值(如果pImageThunkData + ret改为变量),msdn上也没说明
ret = NtWriteVirtualMemory (进程句柄, pImageThunkData + ret, 新地址, 4, 0)
NtProtectVirtualMemory (进程句柄, pImageThunkData, 4, OldProtect, 0)
返回 (ret)
.如果真结束
pOriginalFirstThunk = pOriginalFirstThunk + 4
ret = ret + 4
.循环判断尾 (pImageImportByName ≠ 0)
.否则
返回 (-1073741811)
.如果结束
.如果真结束
pImageImportDescriptor = pImageImportDescriptor + 20
RtlMoveMemory (进程句柄, pImageImportDescriptor + 12, pMoudleName, 4, 0)
.判断循环尾 ()
上一篇 WEB服务器搭建模块
下一篇 软件序列号使用授权模块