• LyScript 实现绕过反调试保护


    LyScript插件中内置的方法可实现各类反调试以及屏蔽特定API函数的功能,这类功能在应对病毒等恶意程序时非常有效,例如当程序调用特定API函数时我们可以将其拦截,从而实现保护系统在调试时不被破坏的目的。

    LyScript项目地址: https://github.com/lyshark/LyScript

    绕过反调试机制: 最常用的反调试机制就是用IsDebuggerPresent该标志检查PEB+2位置处的内容,如果为1则表示正在被调试,我们运行脚本直接将其设置为0即可绕过反调试机制。

    也就是进程环境块中+2的位置,此处是一个字节标志,反调试的机制是,程序调用IsDebuggerPresent检查此处的标志,如果为1则说明程序正在被调试,为0则说明没有被调试,只需要在运行之前将其设置为0即可绕过反调试。

    1. from LyScript32 import MyDebug
    2. if __name__ == "__main__":
    3. # 初始化
    4. dbg = MyDebug()
    5. dbg.connect()
    6. # 通过PEB找到调试标志位
    7. peb = dbg.get_peb_address(dbg.get_process_id())
    8. print("调试标志地址: 0x{:x}".format(peb+2))
    9. flag = dbg.read_memory_byte(peb+2)
    10. print("调试标志位: {}".format(flag))
    11. # 将调试标志设置为0即可过掉反调试
    12. nop_debug = dbg.write_memory_byte(peb+2,0)
    13. print("反调试绕过状态: {}".format(nop_debug))
    14. dbg.close()

    将程序载入调试器,并运行如上脚本,然后运行程序,你会发现反调试被绕过了。

    其次我们还可以动态的在函数开头位置写入sub eax,eax,ret指令,这样当程序要调用特定函数时,会直接返回退出,从而达到屏蔽函数执行等目的。

    1. from LyScript32 import MyDebug
    2. # 得到所需要的机器码
    3. def set_assemble_opcde(dbg,address):
    4. # 得到第一条长度
    5. opcode_size = dbg.assemble_code_size("sub eax,eax")
    6. # 写出汇编指令
    7. dbg.assemble_at(address, "sub eax,eax")
    8. dbg.assemble_at(address + opcode_size , "ret")
    9. if __name__ == "__main__":
    10. # 初始化
    11. dbg = MyDebug()
    12. dbg.connect()
    13. # 得到函数所在内存地址
    14. process32first = dbg.get_module_from_function("kernel32","Process32FirstW")
    15. process32next = dbg.get_module_from_function("kernel32","Process32NextW")
    16. messagebox = dbg.get_module_from_function("user32.dll","MessageBoxA")
    17. messageboxw = dbg.get_module_from_function("user32.dll", "MessageBoxW")
    18. print(hex(messagebox)," ",hex(messageboxw))
    19. # 替换函数位置为sub eax,eax ret
    20. set_assemble_opcde(dbg, messagebox)
    21. set_assemble_opcde(dbg,messageboxw)
    22. dbg.close()

    如上,我们在弹窗位置写出返回指令,然后运行程序,你会发现,弹窗不会出现了,这也就把这个函数给屏蔽了。

    同理,绕过进程枚举,依然可以使用此方式实现。

    绕过进程枚举: 病毒会枚举所有运行的进程以确认是否有调试器在运行,我们可以在特定的函数开头处写入SUB EAX,EAX RET指令让其无法调用枚举函数从而失效。

    1. from LyScript32 import MyDebug
    2. # 得到所需要的机器码
    3. def set_assemble_opcde(dbg,address):
    4. # 得到第一条长度
    5. opcode_size = dbg.assemble_code_size("sub eax,eax")
    6. # 写出汇编指令
    7. dbg.assemble_at(address, "sub eax,eax")
    8. dbg.assemble_at(address + opcode_size , "ret")
    9. if __name__ == "__main__":
    10. # 初始化
    11. dbg = MyDebug()
    12. dbg.connect()
    13. # 得到函数所在内存地址
    14. process32first = dbg.get_module_from_function("kernel32","Process32FirstW")
    15. process32next = dbg.get_module_from_function("kernel32","Process32NextW")
    16. print("process32first = 0x{:x} | process32next = 0x{:x}".format(process32first,process32next))
    17. # 替换函数位置为sub eax,eax ret
    18. set_assemble_opcde(dbg, process32first)
    19. set_assemble_opcde(dbg, process32next)
    20. dbg.close()
  • 相关阅读:
    【前端Vue】社交信息头条项目完整笔记第1篇:一、项目初始化【附代码文档】
    总结影响系统健壮性的一些因素
    C++核心编程:P15->STL----常用容器(上)
    自注意力中的不同的掩码介绍以及他们是如何工作的?
    【Go 基础篇】Go语言标识符解析:命名的艺术与最佳实践
    Firefox国际版
    从零玩转系列之微信支付实战PC端支付微信取消接口搭建 | 技术创作特训营第一期
    【Linux】分布式版本控制工具git
    专题18:Django之Form,ModelForm
    centos7安装LAMP
  • 原文地址:https://blog.csdn.net/lyshark_csdn/article/details/126299942