LyScript 插件中内置的办法可实现各类反调试以及屏蔽特定 API 函数的性能,这类性能在应答病毒等恶意程序时十分无效,例如当程序调用特定 API 函数时咱们能够将其拦挡,从而实现爱护零碎在调试时不被毁坏的目标。
- 插件地址:https://github.com/lyshark/Ly…
绕过反调试机制: 最罕用的反调试机制就是用 IsDebuggerPresent
该标记查看 PEB+2
地位处的内容,如果为 1 则示意正在被调试,咱们运行脚本间接将其设置为 0 即可绕过反调试机制。
也就是过程环境块中 + 2 的地位,此处是一个字节标记,反调试的机制是,程序调用 IsDebuggerPresent
查看此处的标记,如果为 1 则阐明程序正在被调试,为 0 则阐明没有被调试,只须要在运行之前将其设置为 0 即可绕过反调试。
from LyScript32 import MyDebug
if __name__ == "__main__":
# 初始化
dbg = MyDebug()
dbg.connect()
# 通过 PEB 找到调试标记位
peb = dbg.get_peb_address(dbg.get_process_id())
print("调试标记地址: 0x{:x}".format(peb+2))
flag = dbg.read_memory_byte(peb+2)
print("调试标记位: {}".format(flag))
# 将调试标记设置为 0 即可过掉反调试
nop_debug = dbg.write_memory_byte(peb+2,0)
print("反调试绕过状态: {}".format(nop_debug))
dbg.close()
将程序载入调试器,并运行如上脚本,而后运行程序,你会发现反调试被绕过了。
其次咱们还能够动静的在函数结尾地位写入 sub eax,eax,ret
指令,这样当程序要调用特定函数时,会间接返回退出,从而达到屏蔽函数执行等目标。
from LyScript32 import MyDebug
# 失去所须要的机器码
def set_assemble_opcde(dbg,address):
# 失去第一条长度
opcode_size = dbg.assemble_code_size("sub eax,eax")
# 写出汇编指令
dbg.assemble_at(address, "sub eax,eax")
dbg.assemble_at(address + opcode_size , "ret")
if __name__ == "__main__":
# 初始化
dbg = MyDebug()
dbg.connect()
# 失去函数所在内存地址
process32first = dbg.get_module_from_function("kernel32","Process32FirstW")
process32next = dbg.get_module_from_function("kernel32","Process32NextW")
messagebox = dbg.get_module_from_function("user32.dll","MessageBoxA")
messageboxw = dbg.get_module_from_function("user32.dll", "MessageBoxW")
print(hex(messagebox)," ",hex(messageboxw))
# 替换函数地位为 sub eax,eax ret
set_assemble_opcde(dbg, messagebox)
set_assemble_opcde(dbg,messageboxw)
dbg.close()
如上,咱们在弹窗地位写出返回指令,而后运行程序,你会发现,弹窗不会呈现了,这也就把这个函数给屏蔽了。
同理,绕过过程枚举,仍然能够应用此形式实现。
绕过过程枚举: 病毒会枚举所有运行的过程以确认是否有调试器在运行,咱们能够在特定的函数结尾处写入 SUB EAX,EAX RET 指令让其无奈调用枚举函数从而生效。
from LyScript32 import MyDebug
# 失去所须要的机器码
def set_assemble_opcde(dbg,address):
# 失去第一条长度
opcode_size = dbg.assemble_code_size("sub eax,eax")
# 写出汇编指令
dbg.assemble_at(address, "sub eax,eax")
dbg.assemble_at(address + opcode_size , "ret")
if __name__ == "__main__":
# 初始化
dbg = MyDebug()
dbg.connect()
# 失去函数所在内存地址
process32first = dbg.get_module_from_function("kernel32","Process32FirstW")
process32next = dbg.get_module_from_function("kernel32","Process32NextW")
print("process32first = 0x{:x} | process32next = 0x{:x}".format(process32first,process32next))
# 替换函数地位为 sub eax,eax ret
set_assemble_opcde(dbg, process32first)
set_assemble_opcde(dbg, process32next)
dbg.close()