0xAA55 发表于 2015-7-31 00:51:54

【C】Minecraft 1.8.7原版中文输入器(注入式)

这个东西的原理是在运行的时候,注入一段Shellcode到Minecraft游戏使用的LWJGL窗口(java.exe)拦截输入法打字的消息(WM_IME_CHAR)并将字符传递到剪贴板,然后发送Ctrl+V的模拟按键消息来让Minecraft游戏本身接收中文输入。用于按T键或/键聊天时输入中文。
Minecraft游戏在Win7上使用的Java库LWJGL对中文的输入存在问题:它会将WM_CHAR发送的大于0x7F的字符过滤掉导致游戏不接收中文输入。但是Minecraft聊天窗口接收Ctrl+C和Ctrl+V的复制粘贴操作。因此我写了这个玩意儿用于让Minecraft可以直接输入中文聊天。
不过这个东西我只完成了x86版。x64的Shellcode对CallWindowProcA的调用貌似会让Minecraft游戏退出(并且存一下档。这个存档的行为太可疑了!)但是如果是注入到自己进程创建的窗口的话似乎并没有什么问题。

这个程序目前只支持32位的Java的注入,不支持64位Java。



下载:

以下是32位注入的Shellcode的源码。用nasm编译为win32格式。%define WM_IME_CHAR 0x0286
%define WM_KEYDOWN 0x0100
%define WM_KEYUP 0x0101
%define WM_CHAR 0x0102
%define WM_TIMER 0x0113

%define GWLP_WNDPROC (-4)
%define CF_TEXT 1
%define LPTR 0x0040
%define VK_CONTROL 0x11
%define VK_V 0x56
%define KEYEVENTF_KEYUP 0x0002
%define USER_TIMER_MINIMUM 0x0000000A

;==============================================================================
;宏名:ProcBegin
;描述:用于每个过程的开头,建立栈帧,并使ebx指向指令起始地址
;------------------------------------------------------------------------------
%macro ProcBegin 0-1
push ebp;建立栈帧
mov ebp,esp
%if %0
sub esp,(%1)*4;局部变量内存
%endif
push ebx;保存ebx
call %%GetCurPos;取得指令原点
%%GetCurPos:
pop ebx
sub ebx,%%GetCurPos-_InjectCode
%endmacro

;==============================================================================
;宏名:ProcEnd
;描述:用于每个过程的结尾,恢复寄存器并返回,选择性清理栈内存
;------------------------------------------------------------------------------
%macro ProcEnd 0-1
pop ebx;恢复ebx
mov esp,ebp
pop ebp
%if %0;返回
ret %1
%else
ret
%endif
%endmacro

;==============================================================================
;宏名:Arg
;描述:用于过程中读取函数参数
;------------------------------------------------------------------------------
%define Arg(x)        (ebp+8+(x)*4)

;==============================================================================
;宏名:Var
;描述:用于过程中读取变量
;------------------------------------------------------------------------------
%define Var(x)        (ebp-4-(x)*4)

;==============================================================================
;宏名:Local
;描述:读取局部变量
;------------------------------------------------------------------------------
%define Local(x)       

global _InjectCode
global _InjWndProc@16
global _InjTimerProc@16
global _SizeOfInjCode

segment .data
;==============================================================================
;void InjectCode(HWND);
;------------------------------------------------------------------------------
_InjectCode:
ProcBegin

lea eax,Local(KrnlDll)
push eax
call Local(_LoadLib)
mov Local(.hKernel32),eax

lea eax,Local(UserDll)
push eax
call Local(_LoadLib)
mov Local(.hUser32),eax

%macro LoadFunc 2
lea eax,Local(%2_n)
push eax
push dword %1
call Local(_GetProcAddr)
mov Local(%2),eax
%endmacro

LoadFunc Local(.hUser32),        _GetWndLong
LoadFunc Local(.hUser32),        _SetWndLong
LoadFunc Local(.hUser32),        _Call_WndProc
LoadFunc Local(.hUser32),        _OpenClp
LoadFunc Local(.hUser32),        _EmptyClp
LoadFunc Local(.hKernel32),        _LocAlloc
LoadFunc Local(.hKernel32),        _LocFree
LoadFunc Local(.hKernel32),        _LocLock
LoadFunc Local(.hKernel32),        _LocUnlock
LoadFunc Local(.hUser32),        _SetClpData
LoadFunc Local(.hUser32),        _CloseClp
LoadFunc Local(.hUser32),        _SendMsg
LoadFunc Local(.hUser32),        _SetTmr
LoadFunc Local(.hUser32),        _KillTmr

%unmacro LoadFunc 2

;取得原始的WndProc
push dword GWLP_WNDPROC
push dword
call Local(_GetWndLong)
mov Local(_OrgWndProc),eax

;Hook掉
lea eax,Local(_InjWndProc@16)
push eax
push dword GWLP_WNDPROC
push dword
call Local(_SetWndLong)

ProcEnd

.hUser32 dd 0
.hKernel32 dd 0

;==============================================================================
;LRESULT CALLBACK InjWndProc(HWND,UINT,WPARAM,LPARAM);
;------------------------------------------------------------------------------
_InjWndProc@16:
ProcBegin

;处理WM_IME_CHAR消息
cmp dword,WM_IME_CHAR
jnz .WndProcEnd

;将字符添加到缓冲区
cmp dword Local(cbString),StringBufLen-2
ja .WndProcEnd;保证不要超过缓冲区的大小

;在末尾追加字符
lea eax,Local(StringBuf)
add eax,Local(cbString)
mov dx,
xchg dl,dh
or dl,dl
jz .OneByte
mov ,dl
inc dword Local(cbString)
inc eax
.OneByte:
mov ,dh
inc dword Local(cbString)
mov byte,0

;添加一个定时器,用于复制字符到游戏中
lea eax,Local(_InjTimerProc@16)
push eax
push USER_TIMER_MINIMUM
push TimerID
push dword
call Local(_SetTmr)

.WndProcEnd:
;通过调用CallWindowProc来调用旧的消息处理函数
push dword
push dword
push dword
push dword
push dword Local(_OrgWndProc)
call Local(_Call_WndProc)

ProcEnd 16

;==============================================================================
;VOID CALLBACK InjTimerProc(HWND,UINT Msg,UINT_PTR idEvent,DWORD dwTime);
;------------------------------------------------------------------------------
_InjTimerProc@16:
ProcBegin 1

cmp byte Local(CtrlVDown),0
jz .CVNotDown
dec byte Local(CtrlVDown)
jnz .CVNotDown

push 0xC02F0001;松开按键,扫描码0x2F,一次
push VK_V
push WM_KEYUP
push dword
push dword Local(_OrgWndProc)
call Local(_Call_WndProc)

push 0xC01D0001;松下按键,扫描码0x1D,一次
push VK_CONTROL
push WM_KEYUP
push dword
push dword Local(_OrgWndProc)
call Local(_Call_WndProc)

push TimerID
push dword
call Local(_KillTmr)

.CVNotDown:
;判断是否输入了字符串
cmp dword Local(cbString),0
jz .TimerProcEnd

;打开剪贴板
.OpenClp:
push dword
call Local(_OpenClp)
or eax,eax
jz .OpenClp
call Local(_EmptyClp);清空剪贴板

;给剪贴板分配内存
mov eax,Local(cbString)
inc eax
push eax
push LPTR
call Local(_LocAlloc)
mov ,eax

;锁定内存
push eax
call Local(_LocLock)

;写入字符数据
push esi
push edi
lea esi,Local(StringBuf)
mov edi,eax
mov ecx,Local(cbString)
rep movsb
pop edi
pop esi
mov dword Local(cbString),0

;解锁内存
push dword
call Local(_LocUnlock)

;设置剪贴板数据
push dword
push dword CF_TEXT
call Local(_SetClpData)

;关闭剪贴板
call Local(_CloseClp)

push 0x001D0001;按下按键,扫描码0x1D,一次
push VK_CONTROL
push WM_KEYDOWN
push dword
push dword Local(_OrgWndProc)
call Local(_Call_WndProc)

push 0x002F0001;按下按键,扫描码0x2F,一次
push VK_V
push WM_KEYDOWN
push dword
push dword Local(_OrgWndProc)
call Local(_Call_WndProc)

;两个定时器周期后,松开按键
mov byte Local(CtrlVDown),2

.TimerProcEnd:
ProcEnd 16

;==============================================================================
;全局变量区
;------------------------------------------------------------------------------
_OrgWndProc dd 0                ;原先的WndProc

;定义Dll函数:制造一个变量,以及相应的字符串用于读取
%macro DefDllFunc 2
global %1
%1 dd 0
%1_n db %2,0
%endmacro

KrnlDll db "kernel32.dll",0
UserDll db "user32.dll",0

DefDllFunc _LoadLib,                "LoadLibraryA"
DefDllFunc _GetProcAddr,        "GetProcAddress"
DefDllFunc _GetWndLong,                "GetWindowLongA"
DefDllFunc _SetWndLong,                "SetWindowLongA"
DefDllFunc _Call_WndProc,        "CallWindowProcA"
DefDllFunc _OpenClp,                "OpenClipboard"
DefDllFunc _EmptyClp,                "EmptyClipboard"
DefDllFunc _LocAlloc,                "LocalAlloc"
DefDllFunc _LocFree,                "LocalFree"
DefDllFunc _LocLock,                "LocalLock"
DefDllFunc _LocUnlock,                "LocalUnlock"
DefDllFunc _SetClpData,                "SetClipboardData"
DefDllFunc _CloseClp,                "CloseClipboard"
DefDllFunc _SendMsg,                "SendMessageA"
DefDllFunc _SetTmr,                        "SetTimer"
DefDllFunc _KillTmr,                "KillTimer"

cbString dd 0                        ;字符串长度
StringBufLen equ 1024
StringBuf:                                ;字符串缓冲
times StringBufLen db 0
CtrlVDown db 0                        ;是否按下了Ctrl+V

TimerID equ 0xAA55

;统计注入的字节数
InjCodeLen equ $-_InjectCode
_SizeOfInjCode dd InjCodeLen以下为注入器的源码(C语言)的源码(注意是控制台程序。)
你只需要把其中的重点代码抽出来用就行了。可以写成Dll。#include<Windows.h>
#include<stdio.h>
#include<conio.h>
#include<process.h>

HWND g_hWnd=NULL;

extern DWORD InjectCode(LPVOID);
extern DWORD SizeOfInjCode;
extern void*LoadLib;
extern void*GetProcAddr;

//=============================================================================
//函数:PrintLE
//描述:打印GetLastError的字符串信息。
//-----------------------------------------------------------------------------
void PrintLE()
{
        LPVOID lpMsgBuf;
        DWORD dwLastErr;
        FormatMessageA
        (
                FORMAT_MESSAGE_ALLOCATE_BUFFER | //返回一个已分配的内存
                FORMAT_MESSAGE_FROM_SYSTEM |//系统消息
                FORMAT_MESSAGE_IGNORE_INSERTS, //无视插入信息
                NULL,
                dwLastErr=GetLastError(),
                0, //默认语言
                (LPSTR)&lpMsgBuf,
                0,
                NULL
        );
        fprintf(stderr,"GetLastError()==%d,%s\n",dwLastErr,lpMsgBuf);
        LocalFree(lpMsgBuf);
}

//=============================================================================
//函数:SetPrivilege
//描述:提权,使自己拥有注射指令到别的进程的权限。
//-----------------------------------------------------------------------------
BOOL SetPrivilege()
{
        HANDLE hToken=INVALID_HANDLE_VALUE;
        TOKEN_PRIVILEGES tkp;
        LUID SEDebugNameValue;

        if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
        {
                PrintLE();
                return FALSE;
        }

        if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&SEDebugNameValue))
        {
                PrintLE();
                CloseHandle(hToken);
                return FALSE;
        }

        tkp.PrivilegeCount = 1;
        tkp.Privileges.Luid=SEDebugNameValue;
        tkp.Privileges.Attributes=SE_PRIVILEGE_ENABLED;

        if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
        {
                PrintLE();
                CloseHandle(hToken);
                return FALSE;
        }

        CloseHandle(hToken);
        return TRUE;
}

//=============================================================================
//函数:InjectToProcess
//描述:注射到指定窗口句柄所在的进程。
//-----------------------------------------------------------------------------
BOOL InjectToProcess(HWND hWnd)
{
        HANDLE hProc=INVALID_HANDLE_VALUE,hRemoteProc=INVALID_HANDLE_VALUE;
        HMODULE hKernel32=NULL;
        SIZE_T cbWrite;
        void*pMemAddr=NULL;
#        ifdef _DEBUG
        DWORD dwProcID=GetCurrentProcessId();
        DWORD dwOldProtect;
#        else
        DWORD dwProcID;
#        endif

        hKernel32=LoadLibrary(TEXT("kernel32.dll"));
        if(!hKernel32)
        {
                fputs("Could not load library.\n",stderr);
                PrintLE();
                return FALSE;
        }
       
        //写入API地址到要注射的代码中
        LoadLib=                GetProcAddress(hKernel32,        "LoadLibraryA");
        GetProcAddr=        GetProcAddress(hKernel32,        "GetProcAddress");

        FreeLibrary(hKernel32);hKernel32=NULL;

        //Debug编译的代码并没有注入的行为,主要用于调试。
#        ifdef _DEBUG
        VirtualProtectEx(GetCurrentProcess(),InjectCode,SizeOfInjCode,PAGE_EXECUTE_READWRITE,&dwOldProtect);
        InjectCode(hWnd);
        return TRUE;
#        endif

        //取得进程ID
        GetWindowThreadProcessId(hWnd,&dwProcID);
        if(!dwProcID)
        {
                fputs("Could not get process Id.\n",stderr);
                PrintLE();
                return FALSE;
        }
        fprintf(stderr,"Process Id = %u\n",dwProcID);
       
        //打开进程
        hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcID);
        if(!hProc||hProc==INVALID_HANDLE_VALUE)
        {
                fputs("Open process failed.\n",stderr);
                PrintLE();
                return FALSE;
        }

        //远程分配内存
        pMemAddr=VirtualAllocEx(hProc,NULL,SizeOfInjCode,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        if(!pMemAddr)
        {
                fputs("Could not allocate remote memory.\n",stderr);
                PrintLE();
                goto FailRet;
        }

        //注入代码
        if(!WriteProcessMemory(hProc,pMemAddr,InjectCode,SizeOfInjCode,&cbWrite))
        {
                fputs("Could not write data to remote memory.\n",stderr);
                PrintLE();
                goto FailRet;
        }
       
        //创建远程线程
        hRemoteProc=CreateRemoteThread(hProc,NULL,0,(LPTHREAD_START_ROUTINE)pMemAddr,hWnd,0,NULL);
        if(!hRemoteProc||hRemoteProc==INVALID_HANDLE_VALUE)
        {
                fputs("Could not create remote thread.\n",stderr);
                PrintLE();
                goto FailRet;
        }

        CloseHandle(hRemoteProc);
        CloseHandle(hProc);
        return TRUE;
FailRet:
        if(hKernel32)
                FreeLibrary(hKernel32);
        if(hProc&&hProc!=INVALID_HANDLE_VALUE)
                CloseHandle(hProc);
        if(hRemoteProc&&hRemoteProc!=INVALID_HANDLE_VALUE)
                CloseHandle(hRemoteProc);
        return FALSE;
}

//=============================================================================
//函数:MatchWindow
//描述:判断窗口是不是指定的窗口类
//-----------------------------------------------------------------------------
BOOL MatchWindow(HWND hWnd,LPCTSTR szClassName)
{
        TCHAR*szClass;
        int nClass,nNewClass;
        int cbClass;

        nClass=lstrlen(szClassName);
        nNewClass=nClass+2;
        cbClass=nNewClass*sizeof(TCHAR);
        szClass=(TCHAR*)malloc(cbClass);
        if(!szClass)return FALSE;
        memset(szClass,0,cbClass);

        if(GetClassName(hWnd,szClass,nNewClass)==nClass)
        {
                if(!lstrcmp(szClass,szClassName))
                {
                        free(szClass);
                        return TRUE;
                }
        }

        free(szClass);
        return FALSE;
}

//=============================================================================
//函数:EnumWindowsProc
//描述:枚举窗口的回调函数。
//-----------------------------------------------------------------------------
BOOL CALLBACK EnumWindowsProc(HWND hWnd,LPARAM lParam)
{
        TCHAR szClass={0};

        if(MatchWindow(hWnd,TEXT("LWJGL")))
        {
                printf("0x%08X\n",hWnd);
                InjectToProcess(hWnd);
        }
       
        return TRUE;
}

//Debug编译时创建窗口的一系列操作
#ifdef DEBUG
//=============================================================================
//函数:WndProc
//描述:自己的窗口的消息处理函数
//-----------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd,UINT Msg,WPARAM wp,LPARAM lp)
{
        switch(Msg)
        {
        default:
                return DefWindowProc(hWnd,Msg,wp,lp);
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        }
        return 0;
}

//=============================================================================
//函数:CreateWnd
//描述:创建并显示自己的窗口
//-----------------------------------------------------------------------------
HWND CreateWnd()
{
        HINSTANCE hInst=GetModuleHandle(NULL);
        WNDCLASSEX WCEx={sizeof(WNDCLASSEX),0,WndProc,0,0,hInst,NULL,LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW)),(HBRUSH)COLOR_BTNFACE,NULL,TEXT("mcime"),NULL};//窗口类
        HWND hWnd=CreateWindowEx(0,MAKEINTATOM(RegisterClassEx(&WCEx)),TEXT("mcime"),WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInst,NULL);//窗口句柄
        ShowWindow(hWnd,SW_SHOW);
        UpdateWindow(hWnd);
        return hWnd;
}

//=============================================================================
//函数:RunWnd
//描述:线程函数,用于处理所有的窗口消息。
//-----------------------------------------------------------------------------
void RunWnd(void*p)
{
        MSG msg;

        g_hWnd=CreateWnd();
        if(!g_hWnd)
                return;

        while(GetMessage(&msg,NULL,0,0))//消息循环
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
}
#endif

int main(int argc,char**argv)
{
        //先提权
        if(!SetPrivilege())
        {
                fputs("Take privilege failed.(%u)\n",stderr);
                return 1;
        }
#        ifdef _DEBUG
        //创建线程用于显示窗口
        _beginthread(RunWnd,0,NULL);

        //等窗口创建好
        while(!g_hWnd)
                Sleep(1);

        //注入到窗口
        InjectToProcess(g_hWnd);
#        else
        EnumWindows(EnumWindowsProc,0);
#        endif

        //暂停一下以便于看到错误信息。
        _getch();
        return 0;
}另外附上x64的Shellcode。这个会让Minecraft退出,原因不明。%define WM_IME_CHAR 0x0286
%define WM_KEYDOWN 0x0100
%define WM_KEYUP 0x0101
%define WM_CHAR 0x0102
%define WM_TIMER 0x0113

%define STD_ERROR_HANDLE 0xFFFFFFF4

%define GWLP_WNDPROC (-4)
%define GCL_WNDPROC (-24)
%define CF_TEXT 1
%define LPTR 0x0040
%define VK_CONTROL 0x11
%define VK_V 0x56
%define KEYEVENTF_KEYUP 0x0002
%define USER_TIMER_MINIMUM 0x0000000A

;==============================================================================
;宏名:ProcBegin
;描述:用于每个过程的开头,建立栈帧,并使ebx指向指令起始地址
;------------------------------------------------------------------------------
%macro ProcBegin 0-1
push rbp;建立栈帧
mov rbp,rsp

;如果有参数
;参数的作用:指定当前过程中调用的所有子过程中最大参数个数
%if %0
%if (%1)!=0
        %define LocalVarsMem
        %assign LocalVarsMem (((((%1)+1)/2)*16)+8);参数个数16字节对齐,外加8字节
        sub rsp,LocalVarsMem;分配局部变量内存
%endif
%endif

push rbx;保存rbx
call %%GetCurPos;取得指令原点
%%GetCurPos:
pop rbx
sub rbx,%%GetCurPos-InjectCode
%endmacro

;==============================================================================
;宏名:ProcEnd
;描述:用于每个过程的结尾,恢复寄存器并返回,选择性清理栈内存
;------------------------------------------------------------------------------
%macro ProcEnd 0-1
.EndOfProc:
%ifdef LocalVarsMem
        %if LocalVarsMem;释放局部变量内存
                add rsp,LocalVarsMem
        %endif
        %undef LocalVarsMem
%endif
pop rbx;恢复ebx
mov rsp,rbp
pop rbp
ret
%endmacro

;==============================================================================
;宏名:Arg
;描述:用于过程中读取函数参数
;------------------------------------------------------------------------------
%define Arg(x)                (rbp+16+(x)*8)

;==============================================================================
;宏名:Var
;描述:用于过程中读取变量
;------------------------------------------------------------------------------
%define Var(x)                (rbp-8-(x)*8)

;==============================================================================
;宏名:Param
;描述:用于设置函数的参数
;------------------------------------------------------------------------------
%define Param(x)        (rsp+(x)*8)

;==============================================================================
;宏名:Local
;描述:读取局部变量
;------------------------------------------------------------------------------
%define Local(x)       

global InjectCode
global InjWndProc
global InjTimerProc
global SizeOfInjCode

segment .data
;==============================================================================
;void InjectCode(HWND);
;------------------------------------------------------------------------------
InjectCode:
ProcBegin 4;过程中调用的函数参数个数最大4个

mov ,rcx

lea rcx,Local(KrnlDll)
call Local(LoadLib)
mov Local(.hKernel32),rax

lea rcx,Local(UserDll)
call Local(LoadLib)
mov Local(.hUser32),rax

%macro LoadFunc 2
lea rdx,Local(%2_n)
mov rcx,%1
call Local(GetProcAddr)
mov Local(%2),rax
%endmacro

LoadFunc Local(.hUser32),        GetWndLong
LoadFunc Local(.hUser32),        SetWndLong
LoadFunc Local(.hUser32),        Call_WndProc
LoadFunc Local(.hUser32),        DefWndProc
LoadFunc Local(.hUser32),        OpenClp
LoadFunc Local(.hUser32),        EmptyClp
LoadFunc Local(.hKernel32),        LocAlloc
LoadFunc Local(.hKernel32),        LocFree
LoadFunc Local(.hKernel32),        LocLock
LoadFunc Local(.hKernel32),        LocUnlock
LoadFunc Local(.hUser32),        SetClpData
LoadFunc Local(.hUser32),        CloseClp
LoadFunc Local(.hUser32),        SendMsg
LoadFunc Local(.hUser32),        SetTmr
LoadFunc Local(.hUser32),        KillTmr

%unmacro LoadFunc 2

;取得原始的WndProc
mov rdx,GWLP_WNDPROC
mov rcx,
call Local(GetWndLong)
mov Local(OrgWndProc),rax

;Hook掉
lea r8,Local(InjWndProc)
mov rdx,GWLP_WNDPROC
mov rcx,
call Local(SetWndLong)

ProcEnd

.hUser32 dq 0
.hKernel32 dq 0

;==============================================================================
;LRESULT CALLBACK InjWndProc(HWND,UINT,WPARAM,LPARAM);
;------------------------------------------------------------------------------
InjWndProc:
ProcBegin 5;过程中调用的函数参数个数最大5个

mov,rcx
mov,rdx
mov,r8
mov,r9

;处理WM_IME_CHAR消息
cmp edx,WM_IME_CHAR
jnz .WndProcEnd

;将字符添加到缓冲区
cmp qword Local(cbString),StringBufLen-1
ja .WndProcEnd;保证不要超过缓冲区的大小

;在末尾追加字符
lea rax,Local(StringBuf)
add rax,Local(cbString)
mov dx,r8w
xchg dl,dh
or dl,dl
jz .OneByte
mov ,dl
inc qword Local(cbString)
inc rax
.OneByte:
mov ,dh
inc qword Local(cbString)

;添加一个定时器,用于复制字符到游戏中
lea r9,Local(InjTimerProc)
mov r8,USER_TIMER_MINIMUM
mov rdx,TimerID
mov rcx,
call Local(SetTmr)
jmp .DefProc

.WndProcEnd:
;通过调用CallWindowProc来调用旧的消息处理函数

mov rax,
mov ,rax;第五个参数入栈
mov r9,
mov r8,
mov rdx,
mov rcx,Local(OrgWndProc)
call Local(Call_WndProc)

jmp .EndOfProc

.DefProc:
call Local(DefWndProc)
ProcEnd

;==============================================================================
;VOID CALLBACK InjTimerProc(HWND,UINT Msg,UINT_PTR idEvent,DWORD dwTime);
;------------------------------------------------------------------------------
InjTimerProc:
ProcBegin 5;过程中调用的函数参数个数最大5个

mov,rcx
mov,rdx

cmp byte Local(CtrlVDown),0
jz .CtrlVUp
dec byte Local(CtrlVDown)
jnz .CtrlVUp

mov dword,0xC02F0001
mov r9,VK_V
mov r8,WM_KEYUP
mov rdx,
mov rcx,Local(OrgWndProc)
call Local(Call_WndProc)

;发送Ctrl+V的松开
mov dword,0xC01D0001
mov r9,VK_CONTROL
mov r8,WM_KEYUP
mov rdx,
mov rcx,Local(OrgWndProc)
call Local(Call_WndProc)

mov rdx,TimerID
mov rcx,
call Local(KillTmr)

.CtrlVUp:
;判断是否输入了字符串
cmp qword Local(cbString),0
jz .TimerProcEnd

;打开剪贴板
.OpenClp:
mov rcx,
call Local(OpenClp)
or rax,rax
jz .OpenClp

call Local(EmptyClp);清空剪贴板

;给剪贴板分配内存
mov rdx,Local(cbString)
inc rdx
mov rcx,LPTR
call Local(LocAlloc)
mov,rax;用参数2的位置(没用)来存储内存句柄

;锁定内存
mov rcx,rax
call Local(LocLock)

;写入字符数据
push rsi
push rdi
lea rsi,Local(StringBuf)
mov rdi,rax
mov rcx,Local(cbString)
rep movsb
pop rdi
pop rsi
mov qword Local(cbString),0

;解锁内存
mov rcx,
call Local(LocUnlock)

;设置剪贴板数据
mov rdx,
mov rcx,CF_TEXT
call Local(SetClpData)

;关闭剪贴板
call Local(CloseClp)

;发送Ctrl+V的按键信息
mov dword,0x001D0001
mov r9,VK_CONTROL
mov r8,WM_KEYDOWN
mov rdx,
mov rcx,Local(OrgWndProc)
call Local(Call_WndProc)

mov dword,0x002F0001
mov r9,VK_V
mov r8,WM_KEYDOWN
mov rdx,
mov rcx,Local(OrgWndProc)
call Local(Call_WndProc)

;已按下这个键
mov byte Local(CtrlVDown),2;键盘反应时间

.TimerProcEnd:
ProcEnd 16

;==============================================================================
;全局变量区
;------------------------------------------------------------------------------
OrgWndProc                dq 0                ;原先的WndProc

;定义Dll函数:制造一个变量,以及相应的字符串用于读取
%macro DefDllFunc 2
global %1
%1 dq 0
%1_n db %2,0
%endmacro

KrnlDll db "kernel32.dll",0
UserDll db "user32.dll",0
hStdErr dq 0
StrLen dq 0

DefDllFunc LoadLib,                "LoadLibraryA"
DefDllFunc GetProcAddr,        "GetProcAddress"
DefDllFunc GetWndLong,        "GetWindowLongPtrA"
DefDllFunc SetWndLong,        "SetWindowLongPtrA"
DefDllFunc Call_WndProc,"CallWindowProcA"
DefDllFunc DefWndProc,        "DefWindowProcA"
DefDllFunc OpenClp,                "OpenClipboard"
DefDllFunc EmptyClp,        "EmptyClipboard"
DefDllFunc LocAlloc,        "LocalAlloc"
DefDllFunc LocFree,                "LocalFree"
DefDllFunc LocLock,                "LocalLock"
DefDllFunc LocUnlock,        "LocalUnlock"
DefDllFunc SetClpData,        "SetClipboardData"
DefDllFunc CloseClp,        "CloseClipboard"
DefDllFunc SendMsg,                "SendMessageA"
DefDllFunc SetTmr,                "SetTimer"
DefDllFunc KillTmr,                "KillTimer"

cbString                dq 0        ;字符串长度
StringBufLen equ 1024
StringBuf:                                ;字符串缓冲
times StringBufLen db 0
CtrlVDown db 0                        ;是否按下了Ctrl+V

TimerID equ 0xAA55

;统计注入的字节数
InjCodeLen equ $-InjectCode
SizeOfInjCode dq InjCodeLen全部源码:
页: [1]
查看完整版本: 【C】Minecraft 1.8.7原版中文输入器(注入式)