早些年用纯汇编写的一个自用的《征途》外挂(四)

本文介绍了一个简单的内存拷贝函数实现,并详细解析了事件队列的管理和操作流程,包括如何判断队列是否为空、如何从队列中获取事件等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 内存拷贝
;        参数:        target        (类型PVOID)目标地址
;        参数:        source        (类型PVOID)源地址
;        参数:        dwSize        (类型PVOID)需拷贝的字节数
;        返回:        EAX        (=dwSzie)SUCCESS
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CopyMemory        proc        uses edi esi target:DWORD, source:DWORD, dwSize:DWORD
                mov        esi, source
                mov        edi, target
                mov        ecx, dwSize
                jecxz        _copy_memory_failed
                
                cld
        ;_copy_memory_loop:
                rep        movsb
                ;loop        _copy_memory_loop
                mov        eax, dwSize
                jmp        _copy_memory_exit
        _copy_memory_failed:
                xor        eaxeax
        _copy_memory_exit:
                ret
CopyMemory        endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 初始化事件队列
;        参数:        evtQueue        (类型PVOID)队列
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
InitEventQueue        proc        uses esi edi edx lpEvtQueue:DWORD
                cmp        lpEvtQueue, NULL
                jne        _exit_init_event_queue
                invoke        EnterCriticalSection, addr g_stCS
                mov        esi, lpEvtQueue
                assume        esi:ptr EVENTQUEUE
                ;mov        [esi + EVENTQUEUE.front], 0
                ;mov        [esi + EVENTQUEUE.rear], 0
                mov        [esi].front, 0
                mov        [esi].rear, 0
                assume        esi:nothing
                invoke        LeaveCriticalSection, addr g_stCS
        _exit_init_event_queue:
                xor        eaxeax
                ret
                
InitEventQueue        endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 事件入队列
;        参数:        evtQueue        (类型PVOID)队列
;        参数:        ke        (类型PVOID)按键事件
;        返回:        EAX        (TRUE, SUCCESS;FALSE, FAILED)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
EnterEventQueue        proc        uses edx esi edi lpEvtQueue:DWORD, lpEvt:DWORD
                        
                invoke        EnterCriticalSection, addr g_stCS
                xor        eaxeax
                cmp        lpEvtQueue, NULL
                je        _en_ke_queue_exit
                mov        edi, lpEvtQueue
                assume        edi:ptr EVENTQUEUE
        _en_ke_queue:
                movzx        eax, [edi].rear
                add        eax, 1
                mov        ecx, MAX_KEY_EVENT
                xor        edxedx
                div        ecx
                cmp        dl, [edi].front
                je        _en_ke_queue_full
                mov        [edi].rear, dl
                mov        ecx, sizeof EVENTDATA
                mov        eaxedx
                mul        ecx
                lea        esiDWORD ptr [edi + eax]
                invoke        CopyMemory, esi, lpEvt, ecx
                mov        eaxeax
                jmp        _en_ke_queue_exit
        _en_ke_queue_full:
                invoke        InitEventQueue, lpEvtQueue
                jmp        _en_ke_queue
        _en_ke_queue_exit:
                push        eax
                invoke        LeaveCriticalSection, addr g_stCS
                assume        edi:nothing
                pop        eax
                ret
EnterEventQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 事件出队列
;        参数:        evtQueue(类型PVOID)队列
;        参数:        ke        (类型PVOID)出队的按键事件
;        返回:        EAX        (TRUE, SUCCESS;FALSE, FAILED)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetEventQueue        proc        uses edi esi edx lpEvtQueue:DWORD, lpEvt:DWORD
                invoke        EnterCriticalSection, addr g_stCS
                xor        eaxeax
                cmp        lpEvtQueue, NULL
                je        _get_ke_queue_exit
                mov        edi, lpEvtQueue
                assume        edi:ptr EVENTQUEUE
                movzx        eax, [edi].front
                cmp        al, [edi].rear
                je        _get_ke_queue_empty
                add        eax, 1
                mov        ecx, MAX_KEY_EVENT
                xor        edxedx
                div        ecx
                mov        [edi].front, dl
                mov        ecx, sizeof EVENTDATA
                mov        eaxedx
                mul        ecx
                lea        esiDWORD ptr [edi + eax]
                invoke        CopyMemory, lpEvt, esiecx
                mov        ebx, [esi + EVENTDATA.dwCurWnd]
                cmp        ebx, g_ZTCurWnd
                jne        _front_dec
                invoke        MemSet, esi, 0, sizeof EVENTDATA
                mov        eaxTRUE
                jmp        _get_ke_queue_exit
        _front_dec:
                sub        [edi].front, 1
        _get_ke_queue_empty:
                xor        eaxeax
        _get_ke_queue_exit:
                push        eax
                invoke        LeaveCriticalSection, addr g_stCS
                assume        edi:nothing
                pop        eax
                ret
GetEventQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 判断队列是否为满
;        参数:        evtQueue        (类型PVOID)队列
;        返回:        EAX                (TRUE, FULL;FALSE, NotFull)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IsFullEventQueue        proc        uses esi lpEvtQueue:DWORD
                invoke        EnterCriticalSection, addr g_stCS
                xor        eaxeax
                cmp        lpEvtQueue, NULL
                je        _exit_is_full
                mov        esi, lpEvtQueue
                assume        esi:ptr EVENTQUEUE
                movzx        eax, [esi].rear
                add        eax, 1
                mov        ecx, MAX_KEY_EVENT
                xor        edxedx
                div        ecx
                cmp        dl, [esi].front
                jne        _not_full
                mov        eaxTRUE
                jmp        _result_full_adjust
        _not_full:
                xor        eaxeax
        _result_full_adjust:
                assume        esi:nothing
        _exit_is_full:
                push        eax
                invoke        LeaveCriticalSection, addr g_stCS
                pop        eax
                ret
IsFullEventQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 判断队列是否为空
;        参数:        evtQueue        (类型PVOID)队列
;        返回:        EAX        (TRUE, Empty;FALSE, NotEmpty)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IsEmptyEventQueue        proc        uses esi lpEvtQueue:DWORD
                invoke        EnterCriticalSection, addr g_stCS
                xor        eaxeax
                cmp        lpEvtQueue, NULL
                je        _exit_is_empty
                mov        esi, lpEvtQueue
                assume        esi:ptr EVENTQUEUE
                movzx        eax, [esi].front
                cmp        al, [esi].rear
                jne        _not_empty
                mov        eaxTRUE
                jmp        _result_empty_adjust
        _not_empty:
                xor        eaxeax
        _result_empty_adjust:
                assume        esi:nothing
        _exit_is_empty:
                push        eax
                invoke        LeaveCriticalSection, addr g_stCS
                pop        eax
                ret
IsEmptyEventQueue        endp        

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 向事件队列添加按键事件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
AddKeyEventToQueue        proc        uses edx edi esi skillKeyIndex:DWORD, \
                                skillLevel:DWORD, time:DWORD, skillState:DWORD
                local        _evt:EVENTDATA
                local        _vKey:DWORD
                
                mov        eax, skillKeyIndex
                .if        eax <= 9
                        add        eax, 30H
                .else
                        add        eax, 66H        
                .endif
                mov        _vKey, eax
                invoke        RtlZeroMemory, addr _evt, sizeof EVENTDATA
                push        skillLevel
                pop        _evt.dwLevel
                mov        _evt.EvtInput.dwType, INPUT_KEYBOARD
                PUSH        _vKey
                POP        _evt.EvtInput.ki.wVk
                invoke        MapVirtualKey, _vKey, 0
                mov        _evt.EvtInput.ki.wScan, eax
                push        time
                pop        _evt.dwDelay
                push        skillState
                pop        _evt.dwEvtMask
                mov        _evt.EvtInput.ki.dwFlags, KEYEVENTF_UNICODE
                push        g_ZTCurWnd
                pop        _evt.dwCurWnd
                
;                invoke        IsFullEventQueue, g_EvtQueueOfMapAddr
;                test        eax, eax
;                jz        _add_key_evt_to_queue
;                invoke        InitEventQueue, g_EvtQueueOfMapAddr
        _add_key_evt_to_queue:
                invoke        EnterEventQueue, offset g_EvtQueue, addr _evt
                xor        eaxeax
                ret
                
AddKeyEventToQueue        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 事件执行线程执行体
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
EventThreadProc        proc        uses edx edi esi lParam:DWORD
                local        _evt:EVENTDATA
                local        _activeWnd:DWORD
                local        _threadID:DWORD
                local        _buf[5]:BYTE
                
        _event_thread_loop:
                invoke        Sleep, 10
                invoke        RtlZeroMemory, addr _evt, sizeof EVENTDATA
                invoke        IsExistGameProcess
                .if        !eax
                        invoke        SendMessage, g_MainWnd, WM_CLOSE, TRUE, 0
                .endif
                
                cmp        g_HelpStop, TRUE
                je        _event_thread_exit
        
        ; 检查当前队列是否为空
        ;********************************************************************
                invoke        IsEmptyEventQueue, offset g_EvtQueue
                test        eaxeax
                jnz        _event_thread_loop
        ; 等待事件执行互斥体释放
        ;********************************************************************
                invoke        WaitForSingleObject, g_hMutex, INFINITE
        ; 从事件队列中获取事件
        ;********************************************************************
                invoke        GetEventQueue, offset g_EvtQueue, addr _evt
                test        eaxeax
                jz        _event_thread_release_mutex
        ; 事件类型判断
        ;********************************************************************        
                mov        eax, _evt.EvtInput.dwType
                cmp        eax, INPUT_KEYBOARD
                jne        _event_thread_release_mutex
        
        _event_thread_keyboard_evt:
        ; 是否处于打坐状态,是站起
        ;********************************************************************        
                invoke        GetSitState, 0
                .if        eax
                        invoke        PostMessage, g_ZTCurWnd, WM_KEYDOWN, 044H, 00440001H
                        invoke        PostMessage, g_ZTCurWnd, WM_KEYUP, 044H, 0C0440000H
                        invoke        Sleep, 200
                .endif
;                .if        _evt.EvtInput.ki.wVk >=0  && _evt.EvtInput.ki.wVk <= 39H
;                        mov        eax, _evt.EvtInput.ki.wScan
;                        shl        eax, 10H
;                        or        eax, 00000001H
;                        push        eax
;                        invoke        lpSetKeyData, TRUE, _evt.EvtInput.ki.wVk
;                        invoke        SendMessage, g_ZTCurWnd, WM_KEYDOWN, _evt.EvtInput.ki.wVk, _evt.EvtInput.ki.wScan
;;                        invoke        Sleep, 100
;;                        pop        eax
;;                        or        eax, 0C0000000H
;;                        invoke        PostMessage, g_ZTCurWnd, WM_KEYUP, _evt.EvtInput.ki.wVk, eax
;                        invoke        lpSetKeyData, FALSE, NULL
;                .else
        ; 保存当前前台窗体句柄
        ;********************************************************************
                mov        _activeWnd, NULL
                invoke        GetForegroundWindow
                mov        _activeWnd, eax
                invoke        SetForegroundWindow, g_ZTCurWnd
                invoke        Sleep, 500
                
                invoke        keybd_event, _evt.EvtInput.ki.wVk, _evt.EvtInput.ki.wScan, 0, 0
                invoke        Sleep, 100
                invoke        keybd_event, _evt.EvtInput.ki.wVk, _evt.EvtInput.ki.wScan, \
                        KEYEVENTF_KEYUP, 0
                invoke        Sleep, 500
                
        ; 置原窗体为前台窗体
        ;********************************************************************
                mov        eax, _activeWnd
                cmp        eax, g_ZTCurWnd
                je        _event_thread_delay_time
                
                cmp        eax, NULL
                je        _event_thread_delay_time
                invoke        SetForegroundWindow, _activeWnd
                
;                .endif
        
        ;********************************************************************
        _event_thread_delay_time:
                invoke        ReleaseMutex, g_hMutex
                invoke        Sleep, _evt.dwDelay
                mov        eax, _evt.dwEvtMask
                BTC        g_SkillAssoilState, eax
                jmp        _event_thread_loop
        ;********************************************************************
        _event_thread_release_mutex:
                invoke        ReleaseMutex, g_hMutex
;        _event_thread_other_evt:
                jmp        _event_thread_loop
        _event_thread_exit:
                xor        eaxeax
                ret
EventThreadProc        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 显示信息线程执行体
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ShowInfoThreadProc        proc        uses edx edi esi lParam:DWORD
                
        _show_thread_loop:
                invoke        Sleep, 10
                invoke        IsExistGameProcess
                .if        !eax
                        invoke        SendMessage, g_MainWnd, WM_CLOSE, TRUE, 0
                .endif
                
                cmp        g_HelpStop, TRUE
                je        _show_thread_exit
                ;call        GetMousePos
                invoke        ShowSelfInfo, 0
                .if        !g_IsLoadOption
                        call LoadOption
                        mov        g_IsLoadOption, TRUE
                .endif
                invoke        ShowObjectInfo, 0
                invoke        GetSitState, 0
                jmp        _show_thread_loop
                
        _show_thread_exit:
                xor        eaxeax
                ret
                
ShowInfoThreadProc        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 角色辅助线程执行体
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
HelpThreadProc        proc
                
        _help_thread_loop:
                invoke        Sleep, 10
                invoke        IsExistGameProcess
                .if        !eax
                        invoke        SendMessage, g_MainWnd, WM_CLOSE, TRUE, 0
                .endif
                mov        eax, g_IsLoadOption
                cmp        eaxTRUE
                jne        _help_thread_loop
                
                cmp        g_HelpStop, TRUE
                je        _help_thread_exit
                
                call        SafeSelf
                call        HelpeSelf
                call        AutoAssoilSkill
                call        XianSafeObject
                call        XianSitDown
                jmp        _help_thread_loop
        _help_thread_exit:
                xor        eaxeax
                ret
                
HelpThreadProc        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 类似C语言的memset函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
MemSet                proc        uses edx edi esi dest:DWORD, char:BYTE, _dwSize:DWORD
                
                mov        edi, dest
                mov        ecx, _dwSize
                mov        al, char
                cld
                rep        stosb
                ret
MemSet                endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 查找游戏PID
;        参数:        lpProcessName        游戏进程名
;                lpPidFilterList        要过滤掉的游戏进程PID
;        返回:无
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SearchGameProcess        proc        uses ebx edi esi lpProcessName:DWORD, lpPidFilterList:DWORD
                local        _stProcess:PROCESSENTRY32
                local        _hSnapShot
                
                invoke        RtlZeroMemory, addr _stProcess, sizeof PROCESSENTRY32
                mov        _stProcess.dwSize, sizeof PROCESSENTRY32
                invoke        CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, 0
                mov        _hSnapShot, eax
                invoke        Process32First, _hSnapShot, addr _stProcess
                test        eaxeax
                jz        _exit_search_game_process
                
        _search_game_process_start:
                invoke        lstrcmp, [lpProcessName], addr _stProcess.szExeFile
                test        eaxeax
                jnz        _search_game_process_next
        ;************************************************************
        ; 搜索存在的PID列表,是否存在当前PID值
                mov        esi, lpPidFilterList
                mov        ecx, MAX_GAME_PROCESS_INFO
                mov        eax, _stProcess.th32ProcessID
        _search_pid_loop:
                cmp        [esi], eax
                je        _search_game_process_next
                add        esi, 4
                loop        _search_pid_loop
        
        ;************************************************************
                push        _stProcess.th32ProcessID                        ; 如果列表以查找完并且没有存在,则保存当前PID值
                pop        g_ZTCurPID
                
                jmp        _exit_search_game_process
                
        _search_game_process_next:
                invoke        Process32Next, _hSnapShot, addr _stProcess
                test        eaxeax
                jz        _exit_search_game_process
                jnz        _search_game_process_start

        _exit_search_game_process:
                invoke        CloseHandle, _hSnapShot
                xor        eaxeax
                ret        
SearchGameProcess        endp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值