📄 hook.pas
字号:
unit Hook;
{---------无影开发小组敬告:-------------------}
{ 外挂研究无罪,开放源码有理! }
{ 希望以此献给各位想研究外挂的朋友一窥外挂之容 }
{ 本代码只供研究之用,不得用于非法用途 }
interface
uses Windows, Messages, Dialogs, Sysutils, PopWin,
WorkThread,WinSock2,MadCodeHook,GameCode,NetData,FilterForm;
var
hNextHookProc: HHook;
procSaveExit: Pointer;
function sethook: bool; export;
function hookproc(iCode: Integer; wParam: WPARAM; lParam: LPARAM):LRESULT; stdcall;
function endhook: bool; export;
procedure HotKeyHookExit; far;
implementation
procedure IncPN(var N:Char);
begin
if N>='9' then
N:='1'
else
Inc(N);
end;
//----------------------------------------------------------
var WSASendOrigin:function(s:TSocket;lpBuffers:LPWSABUF;
dwBufferCount:dword;lpNumberOfBytesSent:LPDWORD;
dwFlags:DWORD;lpOverlapped:LPWSAOVERLAPPED;
lpCompletionROUTINE:LPWSAOVERLAPPED_COMPLETION_ROUTINE):integer;stdcall;
function WSASendHook(s:TSocket;lpBuffers:LPWSABUF;
dwBufferCount:dword;lpNumberOfBytesSent:LPDWORD;
dwFlags:DWORD;lpOverlapped:LPWSAOVERLAPPED;
lpCompletionROUTINE:LPWSAOVERLAPPED_COMPLETION_ROUTINE):integer;stdcall;
const
PackageType='Send';//定义封包的类型为Send
var
ChipherLen :integer;//密文包的长度
PackageLen :integer;//明文包的长度
Chipherbuf :array[0..5000] of char;//密文包的buffer
Packagebuf :array[0..5000] of char;//明文包的buffer
begin
ChipherLen:=lpBuffers.len;
CopyChar(@Chipherbuf[0],lpbuffers.buf,ChipherLen);
Chipherbuf[ChipherLen]:=#0;
PackageLen:=DecodeA(@Chipherbuf[2],@Packagebuf[0],ChipherLen-3);
Packagebuf[Packagelen]:=#0;
FrmNetData.AddSendData(@Packagebuf[0],PackageLen);
//OutputDebugString(@Chipherbuf[0]);
//-------------------------------------------------------
//修改封包序号
if MyPN='0' then
MyPN:=Chipherbuf[1]
else
begin
lpBuffers.buf[1]:=MyPN;
IncPN(MyPN);
end;
//-------------------------------------------------------
FrmNetData.AddPN(byte(MyPN));
//OutputDebugString(lpBuffers.buf);
WSASendHook:=WSASendOrigin(s,lpBuffers,dwBufferCount,
lpNumberOfBytesSent,dwFlags,lpOverlapped,lpCompletionROUTINE);
//初始化GameSocket
if GameSocket=0 then
GameSocket:=s;
end;
//------------------------------------------------------
function MyOneRecv(Buf:PChar;Len:Integer):Integer;
var
Text:array[0..10000] of char;
TextLen:integer;
begin
MyOneRecv:=1;
if Len>=10000 then
begin
ShowMessage('MyOneRecv:too long packet!');
exit;
end;
if (((Buf[0]='#') or (Buf[0]='*')) and (Buf[1]<>'+')) then
begin
TextLen:=DecodeA(@Buf[1],@Text[0],Len-1);
end
else if buf[1]='+' then
begin
CopyChar(@Text[0],@Buf[1],Len);
TextLen:=Len-1;
end
else
begin
TextLen:=DecodeA(@buf[0],@Text[0],Len);
end;
Text[len]:=#0;
if Text[0]='+' then
FrmNetData.AddRecvData(@Text[0],TextLen,'+')
else
FrmNetDAta.AddRecvData(@Text[0],TextLen,Buf[0]);
end;
function MyRecv(Buf:PChar;Len:Integer):Integer;
var
OneLen:Integer;
i :Integer;
pHeader:PChar;
begin
i:=0;
pHeader:=Buf;
Onelen:=0;
MyRecv:=1;
while i<len do
begin
if ((Buf[i]='*') or (Buf[i]='#')) then
begin
OneLen:=0;
pHeader:=@Buf[i];
end;
if Buf[i]='!' then
begin
MyOneRecv(pHeader,OneLen);
OneLen:=0;
pHeader:=@Buf[i];
end;
inc(OneLen);
inc(i);
end;
end;
//------------------------------------------------------
var WSARecvOrigin:function(s:TSocket;lpBuffers:LPWSABUF;
dwBufferCount:dword;lpNumberOfBytesRecvd:LPDWORD;
dwFlags:DWORD;lpOverlapped:LPWSAOVERLAPPED;
lpCompletionROUTINE:LPWSAOVERLAPPED_COMPLETION_ROUTINE):integer;stdcall;
function WSARecvHook(s:TSocket;lpBuffers:LPWSABUF;
dwBufferCount:dword;lpNumberOfBytesRecvd:LPDWORD;
dwFlags:DWORD;lpOverlapped:LPWSAOVERLAPPED;
lpCompletionROUTINE:LPWSAOVERLAPPED_COMPLETION_ROUTINE):integer;stdcall;
begin
WSARecvHook:=WSARecvOrigin(s,lpBuffers,dwBufferCount,
lpNumberOfBytesRecvd,dwFlags,lpOverlapped,lpCompletionROUTINE);
MyRecv(lpBuffers.buf,lpNumberOfBytesRecvd^);
if GameSocket=0 then
GameSocket:=s;
end;
//----------------------------------------------------------
function HookProc(iCode: integer; wParam: wParam; lParam: lParam):
LResult; stdcall;
var
hwnd: dword;
AppRect: TRect;
title: pchar;
begin
result := 0;
title := '';
if iCode < 0 then
begin
CallNextHookEx(hnexthookproc, iCode, wParam, lParam);
result := 0;
Exit;
end;
//if ((lParam and $80000000) = 0) and (wParam = 112) then FrmPopWin.show; //F1显示隐藏窗口 {测试用}
if ((lParam and $80000000) = 0) and (wParam = $6A) then
begin
hwnd := getforegroundwindow;
try
GetMem(title, 255);
getwindowtext(hwnd, title, 255);
//ShowMessage(title);
if FrmNetData <> nil then FrmNetData.show else //如果FrmPopWin已创建则显示隐藏窗口
begin
if title = '《神迹》公测版' then
begin
try
//Messagebeep(0);
FrmNetData := TFrmNetData.CreateParented(hwnd);
GetWindowRect(hwnd, AppRect);
FrmNetData.Caption := title + '外挂框架';
FrmFilter1:=TFrmFilter1.CreateParented(hwnd);
FrmNetData.Show;
//WorkThread.WThread.Resume;
HookAPI('ws2_32.dll','WSASend',@WSASendHook,@WSASendOrigin);
HookAPI('ws2_32.dll','WSARecv',@WSARecvHook,@WSARecvOrigin);
finally
//FrmPopWin.Free;
end;
end;
end;
finally
FreeMem(title);
end;
result := 1;
end;
end;
function sethook: bool; export;
begin
result := false;
if hnexthookproc <> 0 then
exit;
hNextHookProc := SetWindowsHookEx(WH_KEYBOARD, hookproc, HInstance, 0);
Result := hNextHookProc <> 0;
end;
procedure hotkeyhookexit;
begin
if hNextHookProc <> 0 then
endHook;
ExitProc := procSaveExit;
end;
function endhook: bool; export;
begin
if hNextHookProc <> 0 then
begin
UnhookWindowshookEx(hNextHookProc); // 解除 Keyboard Hook
hNextHookProc := 0;
end;
Result := hNextHookProc = 0;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -