尘。 发表于 2017-9-20 20:18:36

通过APIHook实现反远程注入及钩子检测

写在最前:
这只是一份demo.朋友软件被通过注入的方式做了PJ,我就帮忙写了这份源码
实际上这只是一种治标不治本的方法,但是也有一定的可行性
就这种方法而言,我的这份demo并非完善,甚至还有很多很显而易见的漏洞
比如我没hook LoadLibraryEx,也没有hook 使用宽字符的函数,不过原理基本没啥变化,有心人可以自行完善和补充.

工作原理:
1.通过hook LoadLibrary拦截所加载的模块.
b.在LoadLibrary中插入自己的暗桩代码.同时自己再调用LoadLibrary,根据暗桩是否触发判断hook是否被恢复
c.通过模块路径,模块版权信息,数字签名判断模块是否为非法模块

代码说明:
如下是对LoadLibraryA Hook的代码
把LoadLibrary返回的hModule保存起来,并且插入了我们自己的暗桩代码,如果是调用我们自己的验证模块,则调用模块内的check函数
同时还用一个定时器调用LoadLibrary.以确保check函数被一直调用
.版本 2
.支持库 const
.支持库 spec

.子程序 hookLoadlibraryA, 整数型
.局部变量 loadlibraryAddr, 整数型
.局部变量 oldFlag, 整数型
.局部变量 byte, 字节集
.局部变量 lenth, 整数型
.局部变量 myJmp, 整数型

loadlibraryAddr = _取API地址 (“kernel32.dll”, “LoadLibraryA”)
.如果真 (loadlibraryAddr = -1)
    返回 (-1)
.如果真结束
myJmp = _取子程序真实地址 (&_LoadlibraryA) + 4
VirtualProtect (myJmp, 4, #PAGE_EXECUTE_READWRITE, oldFlag)
写到内存 (到整数 (loadlibraryAddr + 5), myJmp, )
VirtualProtect (myJmp, 4, oldFlag, oldFlag)

lenth = 到整数 (&myLoadlibraryA) - loadlibraryAddr - 5
byte = { 233 } + 到字节集 (lenth)
VirtualProtect (loadlibraryAddr, 5, #PAGE_EXECUTE_READWRITE, oldFlag)
写到内存 (byte, loadlibraryAddr, )
VirtualProtect (loadlibraryAddr, 5, oldFlag, oldFlag)
返回 (loadlibraryAddr)

.子程序 _LoadlibraryA, 整数型
.参数 lpLibFileName, 整数型

' _asm:mov eax,0x400000
' _asm:jmp eax
返回 (0)

.子程序 myLoadlibraryA, 整数型
.参数 lpLibFileName, 整数型
.局部变量 hModule, 整数型
.局部变量 fileName, 文本型

hModule = _LoadlibraryA (lpLibFileName)
.如果真 (hModule > 0)
    fileName = 到文本 (_读字节集 (lpLibFileName, 200))
    .判断开始 (-1 ≠ 寻找文本 (fileName, keyDll, , 真))
      调用子程序 (GetProcAddress (hModule, “check”), , , )
    .判断 (-1 = 寻找文本 (fileName, “fne”, , 真))
      loaded.add (fileName)
    .默认

    .判断结束

.如果真结束
返回 (hModule)


check函数:
check函数取得MessageBoxW函数的地址,并且修改头4字节的内存为timeGettime()
因为易语言用的都是ascii,所以MessageBoxW一般很少用到
当然后期的修改也可以对timegettime的值做加密再写入或者用pipedName等其他办法代替,还可以甚至加上你的心跳包
.版本 2

.子程序 check, , 公开
.局部变量 hModule, 整数型
.局部变量 address, 整数型
.局部变量 oldFlag, 整数型

hModule = LoadLibrary (“user32.dll”)
address = GetProcAddress (hModule, “MessageBoxW”)
VirtualProtect (address, 4, #PAGE_EXECUTE_READWRITE, oldFlag)
写到内存 (timeGetTime (), address, )
VirtualProtect (address, 4, oldFlag, oldFlag)


钩子检查:
取出我们写入的时间值,和timeGetTime做比对,看看是否超过一定的范围,是的话则说明钩子被处理
.版本 2
.支持库 const

.子程序 _按钮2_被单击
.局部变量 hModule, 整数型
.局部变量 address, 整数型
.局部变量 oldFlag, 整数型
.局部变量 integer, 整数型

hModule = LoadLibrary (“user32.dll”)
address = GetProcAddress (hModule, “MessageBoxW”)
VirtualProtect (address, 4, #PAGE_EXECUTE_READWRITE, oldFlag)
integer = _读整数型 (address)
VirtualProtect (address, 4, oldFlag, oldFlag)
.判断开始 (取绝对值 (timeGetTime () - integer) > 1000)
    编辑框1.加入文本 (“程序异常” + #换行符)
.默认
    编辑框1.加入文本 (“检测通过” + #换行符)


模块检查
a.首先我们判断是否有非白名单内的模块在根目录下加载,是的话判定为非法模块.这种办法可以预防一些挟持注入.当然可能这样写有点不合理
b.判断文件的版权信息,如果是白名单版权的则认定为有效文件
c.判定数字签名是否有效.
.版本 2
.支持库 eAPI

.子程序 模块检查
.局部变量 i, 整数型
.局部变量 hModule, 整数型
.局部变量 fileFullName, 文本型
.局部变量 filePath, 文本型
.局部变量 info, 文件版本信息

.计次循环首 (loaded.size (), i)
    hModule = GetModuleHandle (loaded.get (i))
    .判断开始 (hModule = 0)
      编辑框1.加入文本 (loaded.get (i) + “.hModule=NULL” + #换行符)
    .默认
      fileFullName = getModulePath (hModule)
      .判断开始 (fileFullName = “”)
            编辑框1.加入文本 (loaded.get (i) + “.hModule=” + 到文本 (hModule) + “ getPath=NULL” + #换行符)
      .默认
            filePath = _全路径取路径 (fileFullName)
            .判断开始 (-1 ≠ 寻找文本 (取运行目录 (), filePath, , 真))
                .判断开始 (whiteList.index (loaded.get (i)) = 0)
                  编辑框1.加入文本 (loaded.get (i) + “.hModule=” + 到文本 (hModule) + “ hackerModule” + #换行符)
                .默认
                  编辑框1.加入文本 (loaded.get (i) + “.hModule=” + 到文本 (hModule) + “ whiteListModule” + #换行符)
                .判断结束

            .默认
                取文件版本信息 (fileFullName, info)
                .判断开始 (-1 ≠ 寻找文本 (info.合法版权, “Microsoft Corporation. All rights reserved”, , 真))
                  编辑框1.加入文本 (loaded.get (i) + “.hModule=” + 到文本 (hModule) + “ Microsoft Corporation Library” + #换行符)
                .判断 (VerifyEmbeddedSignature (A2W (fileFullName)))
                  编辑框1.加入文本 (loaded.get (i) + “.hModule=” + 到文本 (hModule) + “ userModule” + #换行符)
                .默认
                  编辑框1.加入文本 (loaded.get (i) + “.hModule=” + 到文本 (hModule) + “ hackerModule” + #换行符)
                .判断结束

            .判断结束

      .判断结束

    .判断结束

.计次循环尾 ()


写在最后:
本人搞了几年游戏了,也多少了解到一些PJ与反PJ,个人观点还是认为没必要太崇拜壳子
基本把关键代码VM一下也差不多了,壳子更多的是调试和一些相关的检测,这些其实网上很多资料了.
起码我这一两年来,我的验证系统都只用vmp1.22做了vm,没有任何其他的壳子的保护.
主要的还是自己的系统是否严谨,是否能有效的增加PJ的难度.
如果一个市面上销售的软件,个人更倾向于一个全局钩子,对一些敏感的api做处理,自身把用到的一些敏感的api自己做一个hook做处理,加上CRC可能效果未必比壳差
当然了,以上都是本人的愚见而已,希望大神们也不吝赐教.

xuanxuan 发表于 2018-2-21 04:24:00

谢谢分享            

尘。 发表于 2017-9-20 20:20:04

补充下附件:


yyjpcx 发表于 2017-9-23 02:52:07

论坛 附件下载的大小是39B

yyjpcx 发表于 2017-9-20 20:53:42

远程汇编   也可以的

冯古屋 发表于 2017-9-20 21:49:34

不明觉厉!!!

小码人 发表于 2017-12-22 09:33:11

666666,学习了!

Jtuzi小兔 发表于 2018-1-25 16:00:10

感谢分享,学习学习

Jtuzi小兔 发表于 2018-1-28 18:48:51

感谢分享!下来学习学习!

rjl6258537 发表于 2019-1-21 03:44:23

谢谢分享   
页: [1] 2
查看完整版本: 通过APIHook实现反远程注入及钩子检测