实验室有强大的防火墙,而且管理很严格。封了很多端口,比如浩方,QQ游戏,电驴。
一直都想着在寝室的时候如何去远程控制实验室的机器。一般的远程控制软件都是要在被控制的机器上装一个server,监听外部的连接请求。然后我从 另外一个机器上运行client,连接到这个server,进行远程控制。但是因为防火墙的存在,从外面主动去连接实验室的机器,是不可能连接上的。
其实我一般也就想远程控制实验室的机器下点电影什么的。不需要实现真正的远程控制。我可以把要下载的文件链接或者bt种子放在一个公共的ftp上面,然后实验室的机器上跑一个程序,每隔几分钟就去ftp上查一下,自动把bt种子下载下来,然后自动开始bt下载。
这样做起来很简单,但是功能太弱,不好做复杂的下载任务。另外还有一个问题。我想使用DriveHQ 提供的免费文件服务做ftp中转,这种网站会不会限制你每天的连接次数?如果我频繁的去连接,有可能被封帐号。
于是为了更强大的控制,我要尝试另外的方式–QQ的远程控制。实验室机器上运行一个qq,然后主动的向别人发起远程控制的请求,可以穿透防火墙,实现远程控制。我要解决的问题即使如何让实验室的机器主动发起请求。
以前用过PAMIE 来做自动填表。它就是自动在网页上找控件,然后做填表或者点击的动作。当时还看到过自动处理windows窗口事件的demo。是不是也可以类似的自动操作QQ聊天窗口呢?
搜到一个例子 ,思路就是找窗口和控件的句柄,然后向句柄发送消息。我也要这么办,而且用可爱的Python来实现。不过我需要先安装pywin32 ,它提供了win32api的python支持。另外,有一个很有用的辅助工具Spy++。用FindWindow和FindWindowEx查找句柄时,它可以辅助编程。另外它可以监听窗口的消息以确定人手动进行正常操作时产生了哪些事件。
如果你在和一个昵称为”owen”的人聊天,那么聊天窗口的标题就是”owen”,下面的代码可以找到这个聊天窗口,然后最小化窗口。
import win32gui,win32con
dlg=win32gui.FindWindow(None,"owen")
win32gui.ShowWindow(dlg,win32con.SW_MINIMIZE)
当然,我要做的事情可不是简单的最小化窗口,我需要找到窗口中的控件,然后做点击操作。可以用FindWindowEx来查找窗口内部的控件。很遗 憾,经过我多次尝试,我用FindWindowEx只能找到一个子句柄,而这个子句柄没有自己的子句柄。这和我设想的不太一样。我原先认为我可以找到远程 控制的button,然后发送鼠标点击的事件。但是我现在找不到button的句柄,就没法做下去了。我水平太低,QQ应该是故意设计成这样来增加设计外 挂的难度的,不然我都能轻松的写一个外挂出来,QQ的安全性何在?
此路不通!怎么办?
我不是真的要设计外挂,所有可以用笨一点,不通用但是实用的办法:模拟鼠标点击。
思路:把聊天对话框移动到屏幕的左上角,然后在固定的位置模拟鼠标依次点击:”应用”,”远程协助”。然后等待对方确认连接之后再点击”确认”和”申请控制”。代码如下:
#在屏幕的(x,y)位置点击鼠标左键
def click_at_pos(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)
def startRemoteControl():
# 找到聊天对话框
dlg = win32gui.FindWindow(None,'owen')
# 还原对话框(之前可能是最小化的状态)
win32gui.ShowWindow(dlg,win32con.SW_RESTORE)
# 对话框移动到屏幕的左上角
win32gui.MoveWindow(dlg,0,0,0,0,1)
# 激活对话框,提升到所有窗口的前面
win32gui.SetForegroundWindow(dlg)
# 点击 应用,下面的两个坐标都是试出来的。
# 因为窗口移动到左上角后,这些按钮的位置就固定了。
click_at_pos(320,60)
# 点击 远程协助
click_at_pos(320,100)
# 等待对方同意远程协助
time.sleep(15)
# 点击 确认
click_at_pos(400,450)
# 等待连接建立
time.sleep(15)
# 点击 申请控制
click_at_pos(400,450)
经过测试,上述代码可以成功的建立远程控制。
现在的问题就是什么适合发起远程协助的请求?
监听QQ的聊天内容?有点难度。聊天?恩,我曾经用Python写过MSN机器人呐,给MSN机器人发消息,然后机器人去调用上面的代码,发起远程协助。爽!
只需要简单的改动机器人代码中,收到消息后的回调函数。另外,我根据不同的消息内容来做不同的操作。原来的startRemoteControl 中,发起远程协助的请求之后要等待对方确认,默认等待15秒。如果对方在收到请求后15秒内没有响应,上面的代码还是会继续执行,就达不到建立远程连接的 效果了。如果把默认等待的事件调长,又可能会让接受请求方等待的时间变长。所以,把startRemoteControl分为3步,根据msn机器人收到 的消息内容决定做哪一步操作,就可以解决这个问题。
def handle(m,email,msg):
if email=='[email protected]' :
if msg=='1':
# 点击 远程协助
dlg = win32gui.FindWindow(None,'owen')
win32gui.ShowWindow(dlg,win32con.SW_RESTORE)
win32gui.MoveWindow(dlg,0,0,0,0,1)
win32gui.SetForegroundWindow(dlg)
click_at_pos(320,60)
click_at_pos(320,100)
elif msg=='2':
# 点击 确认
click_at_pos(400,450)
elif msg=='3':
# 点击 申请控制
click_at_pos(400,450)