QQ 连连看外挂 Python 版本.

2017-01-22 17:37:54 +08:00
 sleshep

初中时候写过一个 MFC 的,最近翻代码找到了,倍感怀念,于是写了个 Python 版的,大牛别喷

使用方法:打开 QQ 游戏连连看,找到个房间,比如高手区 然后打开脚本就可挂机了

代码:

#!/usr/bin/env python
# coding:utf-8
"""
作者:sleshep
邮箱:x@icexz.com
日期:16-9-19
时间:上午 11:50
"""
import struct
import time
from ctypes import *
from logging import basicConfig, getLogger, DEBUG

basicConfig()
log = getLogger(__name__)
log.setLevel(DEBUG)
user32 = WinDLL('user32.dll')
kernel32 = WinDLL('kernel32.dll')

WM_LBUTTONDOWN = 0x201
WM_LBUTTONUP = 0x202


def read_chess_memory():
    hwnd = get_llk_hwnd()
    chess = create_string_buffer(11 * 19)

    if hwnd:
        pid = c_int()
        user32.GetWindowThreadProcessId(hwnd, byref(pid))
        h_process = kernel32.OpenProcess(0xf0000 | 0x100000 | 0xfff, 0, pid)
        kernel32.ReadProcessMemory(h_process, 0x129fb4, byref(chess), 11 * 19, byref(pid))
        kernel32.CloseHandle(h_process)
    return chess


def get_llk_hwnd():
    hwnd = user32.FindWindowA('#32770'.encode('ascii'), 'QQ 游戏 - 连连看角色版'.encode('gb2312'))
    if not hwnd:
        log.info('找不到游戏了.')
    return hwnd


def make_long(x, y):
    return c_long((x << 16) + y)


def click_both(x, y, xx, yy):
    # print('a({},{}) b({},{})'.format(x, y, xx, yy))
    hwnd = get_llk_hwnd()
    if hwnd:
        first_x = 28
        first_y = 199
        user32.SendMessageA(hwnd, WM_LBUTTONDOWN, 0, make_long(first_y + y * 35, first_x + x * 31))
        user32.SendMessageA(hwnd, WM_LBUTTONUP, 0, make_long(first_y + y * 35, first_x + x * 31))
        user32.SendMessageA(hwnd, WM_LBUTTONDOWN, 0, make_long(first_y + yy * 35, first_x + xx * 31))
        user32.SendMessageA(hwnd, WM_LBUTTONUP, 0, make_long(first_y + yy * 35, first_x + xx * 31))


def clear_all():
    chess = read_chess_memory()
    for x in range(19):
        for y in range(11):
            for xx in range(19):
                for yy in range(11):
                    if chess.raw[19 * y + x] != 0 and chess.raw[19 * yy + xx] != 0 and (xx != x or yy != y) and \
                                    chess.raw[19 * y + x] == chess.raw[19 * yy + xx]:
                        click_both(x, y, xx, yy)


def get_chess_count():
    return len(list(filter(int, read_chess_memory().raw)))


def send_redeploy():
    hwnd = get_llk_hwnd()
    if hwnd:
        log.info('检测到无解,重列!')
        y = 197
        x = 652
        user32.SendMessageA(hwnd, WM_LBUTTONDOWN, 0, make_long(y, x))
        user32.SendMessageA(hwnd, WM_LBUTTONUP, 0, make_long(y, x))
        time.sleep(2)


def fully_clear():
    while get_chess_count():
        last_count = get_chess_count()
        clear_all()
        if last_count == get_chess_count() and last_count != 0:
            send_redeploy()


def start_game():
    hwnd = get_llk_hwnd()
    if hwnd:
        y = 570
        x = 668
        user32.SendMessageA(hwnd, WM_LBUTTONDOWN, 0, make_long(y, x))
        user32.SendMessageA(hwnd, WM_LBUTTONUP, 0, make_long(y, x))


def quick_start():
    """
    大厅快速开始没法 SendMessage ,所以只能移动鼠标然后再点
    """
    hwnd = user32.FindWindowA(0, '连连看'.encode('gb2312'))
    if hwnd:
        rect = create_string_buffer(16)
        user32.GetWindowRect(hwnd, byref(rect))
        left_x, left_y, *_ = struct.unpack('<IIII', rect.raw)
        x = 275 + left_x
        y = 150 + left_y
        user32.SetCursorPos(x, y)
        time.sleep(.5)
        user32.mouse_event(0x0002, x, y, 0, 0)
        time.sleep(.5)
        user32.mouse_event(0x0004, x, y, 0, 0)
        time.sleep(3)


def main():
    while 1:
        if not get_llk_hwnd():
            log.info('没找到游戏,估计被踢出来了,现在重新进..')
            quick_start()
        start_game()
        time.sleep(1)
        fully_clear()


if __name__ == '__main__':
    main()
4517 次点击
所在节点    Python
15 条回复
sleshep
2017-01-22 17:39:00 +08:00
windows xp + python3.4 成功,只能运行于 python3+
windows7 以上有 ASLR 基地址可能会有问题,没试验
lucifer4he
2017-01-22 17:43:01 +08:00
现在写的不是应该 win10 + python3 么
sleshep
2017-01-22 17:46:15 +08:00
@lucifer4he
虚拟机里只装了 xp
母鸡 ubuntu
zhuce1234578888
2017-01-22 18:42:22 +08:00
能不能写个文章,分析下这个脚本,大神
YingJie
2017-01-23 00:00:37 +08:00
一些 win api 的调用, py 不适合干这个
jy02201949
2017-01-23 00:55:33 +08:00
连连看,当初开外挂撩妹子装高手
master13
2017-01-23 09:02:40 +08:00
py3 对中文支持正好
#coding:utf8
'#32770'.encode('ascii'), 'QQ 游戏 - 连连看角色版'.encode('gb2312')
mcds
2017-01-23 09:33:14 +08:00
import * 这个习惯不太好~
0x5010
2017-01-23 10:29:20 +08:00
@mcds ctypes 一般还真都这么用
sleshep
2017-01-23 11:47:56 +08:00
@mcds
一看你就是没咋写过
whx20202
2017-01-23 13:11:44 +08:00
@mcds 说说为什么不好
ech0x
2017-01-23 15:46:12 +08:00
@whx20202 命名空间被导入了,有可能出现冲突。
ech0x
2017-01-23 15:47:03 +08:00
@ech0x 不过有些库无所谓。。。
mcds
2017-01-23 18:18:23 +08:00
@sleshep 哈, ctypes 还真用的少..
Mavious
2017-01-23 21:00:51 +08:00
咦,我一个非程序猿都看懂了不少行,和按键精灵的代码很像。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/336263

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX