ToB企服应用市场:ToB评测及商务社交产业平台

标题: LyScript 内存扫描与查壳实现 [打印本页]

作者: 西河刘卡车医    时间: 2022-9-17 08:38
标题: LyScript 内存扫描与查壳实现
LyScript 中提供了多种内存特征扫描函数,每一种扫描函数用法各不相同,在使用扫描函数时应首先搞清楚他们之间的差异,如下将分别详细介绍每一种内存扫描函数是如何灵活运用的,最后将实现一个简易版内存查壳脚本,可快速定位目标程序加了什么壳。
先来了解第一个函数scan_memory_all()的特点,该函数用来扫描当前进程内EIP所指向位置处整个内存段中符合条件的特征,如果找到了则返回一个列表,如果没有找到则返回False,该函数与scan_memory_one()函数原理是一致的,唯一的不同是all以列表形式返回所有匹配到的行,one则只返回匹配到的第一条记录,这两个函数都支持??模糊匹配。
如果载入一个程序,默认停留在系统领空,则调用该函数你所能得到的特征记录只能是系统领空特定dll内的特征集。

例如扫描ntdll.dll模块内的所有特征字段是55 8b ec 83 e4的记录,代码是这样的。
  1. from LyScript32 import MyDebug
  2. if __name__ == "__main__":
  3.     dbg = MyDebug()
  4.     conn = dbg.connect()
  5.     ref_one = dbg.scan_memory_one("55 8b ec 83 e4")
  6.     print("扫描一行: {}".format(hex(ref_one)))
  7.     ref_all = dbg.scan_memory_all("55 8b ec 83 e4")
  8.     for index in range(0, len(ref_all)):
  9.         print("记录: {} 地址: {}".format(index,hex(ref_all[index])))
  10.     dbg.close()
复制代码
运行效果如下:

有时我们需要指定扫描某个模块,例如扫描进程内的msvcr120.dll模块,里面的特征值。

此时需要想得到该模块的入口地址,然后将EIP切换过去,此时在调用scan_memory_all()来完成搜索,当然最好先备份原始EIP位置,这样扫描完以后可以直接切回去。
  1. from LyScript32 import MyDebug
  2. if __name__ == "__main__":
  3.     dbg = MyDebug()
  4.     conn = dbg.connect()
  5.     # 得到所有模块
  6.     local_module_base = dbg.get_all_module()
  7.     for index in local_module_base:
  8.         # 找到需要的模块
  9.         if index.get("name") == "msvcr120.dll":
  10.             entry = index.get("entry")
  11.             print("扫描入口: {}".format(hex(entry)))
  12.             # 切过去
  13.             dbg.set_register("eip",entry)
  14.             # 开始搜索特征
  15.             scan_ref = dbg.scan_memory_all("5d c2 0c 00 55 8b ec")
  16.             for x in scan_ref:
  17.                 print("扫描到: {}".format(hex(x)))
  18.     dbg.close()
复制代码
输出结果如下:

当然为了使扫描效率更高一些,新版插件中新增了scan_memory_any()函数,该函数无需切换到模块入口处即可实现扫描特定模块内的特征,不过该函数只能返回找到的第一条记录,且需要传入扫描起始位置以及扫描长度,不过得到这些参数并不难。
  1. from LyScript32 import MyDebug
  2. if __name__ == "__main__":
  3.     dbg = MyDebug()
  4.     conn = dbg.connect()
  5.     # 得到进程模块
  6.     local_module = dbg.get_all_module()[0]
  7.     # 得到模块参数
  8.     module_base = local_module.get("base")
  9.     module_size = local_module.get("size")
  10.     print("基地址: {} 长度: {} 结束地址: {}".format(hex(module_base),hex(module_size),hex(module_base+module_size)))
  11.     # 扫描内存
  12.     ref = dbg.scan_memory_any(module_base,module_size,"51 5c a8 f8 4c 34 33")
  13.     if ref != False:
  14.         print("找到内存: {}".format(hex(ref)))
  15.     dbg.close()
复制代码
扫描结果如下:

如上内存扫描方法如果可以搞明白,那么查壳这个功能就变得很简单了,市面上的查壳软件PEID等基本都是采用特征码定位的方式,所以我们想要实现查壳以及检测编译器特征可以采用特征码扫描法,如下代码即可实现查壳功能。
  1. from LyScript32 import MyDebug
  2. # 查壳功能
  3. def scan(dbg, string):
  4.     # 得到进程模块
  5.     local_module = dbg.get_all_module()[0]
  6.     # 得到模块参数
  7.     module_base = local_module.get("base")
  8.     module_size = local_module.get("size")
  9.     # print("基地址: {} 长度: {} 结束地址: {}".format(hex(module_base),hex(module_size),hex(module_base+module_size)))
  10.     # 扫描内存
  11.     ref = dbg.scan_memory_any(module_base,module_size,string)
  12.     if ref != False:
  13.         return True
  14.     return False
  15. if __name__ == "__main__":
  16.     dbg = MyDebug()
  17.     conn = dbg.connect()
  18.     # 存储特征码
  19.     signs = [
  20.         {"key": "Microsoft Visual C++ 2013", "value": "e8 ?? ?? ?? ?? e9 ?? ?? ?? ?? 55 8b ec"},
  21.         {"key": "UPX 3.96w", "value": "60 be ?? ?? ?? ?? 8d be 00 90 ff ff 57"}
  22.     ]
  23.     for index in signs:
  24.         check = scan(dbg, index.get("value"))
  25.         if check == True:
  26.             print("编译特征: {}".format(index.get("key")))
  27.     dbg.close()
复制代码
分别检测后输出结果如下:
upx加壳软件输出为

vs2013编译器特征输出


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4