C++实现远程注入完美游戏CALL

合集下载

内核 远程call 写法

内核 远程call 写法

内核远程call 写法内核远程调用 (Remote Procedure Call, RPC) 的实现通常涉及网络通信和数据序列化/反序列化。

以下是一个简化的示例,说明如何实现一个简单的内核 RPC 机制。

请注意,实际的 RPC 实现会更复杂,并且需要处理错误、重试、异步调用等更复杂的情况。

首先,定义一个简单的服务接口:```c//ifndef SERVER_Hdefine SERVER_Htypedef void (RemoteProcedure)(int);void register_remote_procedure(RemoteProcedure);endif // SERVER_H```然后,在服务器端实现这个接口:```c//include ""include <>void handle_remote_procedure(int value) {printf("Received value: %d\n", value);}void register_remote_procedure(RemoteProcedure procedure) {// 这里只是一个简化的示例,实际情况下你可能需要将 procedure 存储在某个数据结构中,并在需要时调用它。

procedure(123); // 假设我们收到一个值为 123 的调用。

}```客户端代码可能看起来像这样:```c//include "" // 注意: 假设我们已经有了这个头文件。

include <>include <rpc/> // 需要包含 rpc/ 和其他必要的头文件来使用 RPC。

int main() {RemoteProcedure procedure;int value = 123; // 要传递给远程过程的数据。

int result; // 用于接收远程过程的结果。

发段完美国际注入跑路call 全部原代码

发段完美国际注入跑路call 全部原代码

该死的DELPHI 变量申明和内存读取贴段代码://-------------------------注入代码的函数----------------------------{参数说明:InHWND:被注入的窗口句柄Func:注入的函数的指针Param:参数的指针ParamSize:参数的大小}procedure InjectFunc(InHWND: HWND; Func: Pointer; Param: Pointer; ParamSize: DWORD);varhProcess_N: THandle;ThreadAdd, ParamAdd: Pointer;hThread: THandle;ThreadID: DWORD;lpNumberOfBytes:DWORD;beginGetWindowThreadProcessId(InHWND, @ThreadID); //获得窗口IDhProcess_N := OpenProcess(PROCESS_ALL_ACCESS, False, ThreadID);//打开被注入的进程ThreadAdd := VirtualAllocEx(hProcess_N, nil, 4096, MEM_COMMIT,PAGE_READWRITE); //申请写入代码空间WriteProcessMemory(hProcess_N, ThreadAdd, Func, 4096, lpNumberOfBytes); //写入函数地址ParamAdd := VirtualAllocEx(hProcess_N, nil, ParamSize, MEM_COMMIT,PAGE_READWRITE); //申请写入代码参数空间WriteProcessMemory(hProcess_N, ParamAdd, Param, ParamSize, lpNumberOfBytes); //写入参数地址hThread := CreateRemoteThread(hProcess_N, nil, 0, ThreadAdd, ParamAdd, 0, lpNumberOfBytes); //创建远程线程ResumeThread(hThread); //直接运行线程CloseHandle(hThread); //关闭线程// 根据小金鱼修改后的代码修改来的VirtualFreeEx(hProcess_N, ThreadAdd, 4096, MEM_RELEASE);VirtualFreeEx(hProcess_N, ParamAdd, ParamSize, MEM_RELEASE); //释放申请的地址CloseHandle(hProcess_N); //关闭打开的句柄end;//-----------------------------定义一个参数类型-----------------------typeTPickCallParam = packed recordax, ay: single;end;PPickCallParam = ^TPickCallParam; //指向结构的指针(C中叫这种方式的数据应该叫结构体吧)procedure runCall(p:PPickCallParam);stdcall; // 走路callvaraddres,addres1,addres2:pointer;x,y:single;beginaddres:=pointer($0045ec00);addres1:=pointer($00462620);addres2:=pointer($0045f000);x:=p^.ax; //目的地X坐标y:=p^.ay; //目的地Y坐标asmpushadmov eax, dword ptr [$8f207c] mov eax, dword ptr [eax+$1C] mov esi, dword ptr [eax+$20] mov ecx, dword ptr [esi+$ba0] push 1call addresmov edi, eaxlea eax, dword ptr [esp+$18] push eaxpush 0mov ecx, edicall addres1push 0push 1push edimov ecx, dword ptr [esi+$ba0] push 1call addres2mov eax, dword ptr [$8f207c] mov eax, dword ptr [eax+$1C] mov eax, dword ptr [eax+$20] mov eax, dword ptr [eax+$ba0] mov eax, dword ptr [eax+$30] mov ecx, dword ptr [eax+4] mov eax, xmov [ecx+$20], eaxmov eax, ymov [ecx+$28], eaxpopadend;END;procedure TForm1.Button1Click(Sender: TObject);//在控件中做个按钮测试varCallParam:TPickCallParam;begin;getmem(pname,33);myhwnd := FindWindow(nil,'Element Client');{查找窗口句柄} GetWindowThreadProcessId(myhwnd, aproc); {得到窗口ID}phnd := OpenProcess(PROCESS_VM_READ , False, aproc);{以完全访问权限打开进程句柄}if (phnd<>0 ) thenbeginCallParam.ax:= 1860.0; //给注入代码函数赋值CallParam.ay:=120.0; //给注入代码函数赋值InjectFunc(myhWnd,@runCall,@CallParam,SizeOf(CallParam)); //运行注入代码函数sleep(100);CloseHandle(PHND) //关闭进程end;end;。

c#做外挂 step by step(更新至step3注入)

c#做外挂 step by step(更新至step3注入)

c#做外挂stepbystep(更新至step3:注入)做外挂我也是现学的。

可以说写的这个教程是现学现卖,希望对用C#的外挂爱好者能有点帮助。

本教程中有一些以“废话”字样标注的内容,赶时间的可以直接越过。

第一课:C#使用WINDOWAPI和对内存的操作。

这一课是些简单的东西,了解的可以直接越过。

考虑到大多数使用c#的人都是做网站的,可能没有机会接触这些,所以我在这里做一下粗略的介绍。

step1:认识WINAPIwindows系统里提供了很多的函数,我们如果做外挂的话,就需要用到其中的函数(以下简称API)。

(废话:这些API被封装在系统路径下的DLL文件里。

事实上,我们不用关心它在哪,我们只要知道怎么用就可以了,)用起来很简单,格式如下:{);...{...}...}代码段1用---)(废话:以看step2:下面我来说一下,如何使用上一步引用的那个API读取游戏的数据。

先来看看参数:publicstaticexternintReadProcessMemory(inthProcess,//进程,如果你是做外挂的话,它代表你要挂的那个游戏。

intlpBaseAddress,//你要读取的内存地址int[]lpBuffer,//从上面那个参数地址里读出来的东西(调用这个函数的就是为了它)不管这个参数是什么类型,它应该是一个数组,否则读不出东西来intnSize,//长度,上一个参数,类型是int,那个长度应该用4intlpNumberOfBytesWritten//用0就行了,想知道它是干嘛的,自己去MSND吧关于第一个参数hProcess如何获取,我过会再说。

假设它已经搞定了,那么这个函数,我们需要关心的只有lpBaseAddress和lpBuffer,既读的地址,和读出来的值。

(废话:对了,这个函数貌似还有个返回值,我们这里用不到它。

如果你有兴趣了解,MSDN)读出来的值outintlpBuffer我们在引用API的时候声明为int型了,但是,我们要从内存里读的值不一定总是int。

C++实现远程注入完美游戏CALL

C++实现远程注入完美游戏CALL

声明:该教程写给有一定外挂编程基础且热爱编程技术的朋友共同学习。

说明:1.教程本身只是作为技术交流探讨,没有其他目的2.以完美国际187版游戏为例,不具有任何针对意味3.在广海里学了很多东西,希望在广海里留下一些什么见解:1.虽然注入技术已经不再是什么“时尚”的技术,但是在编程应用领域,却依然得到很广泛的应用。

虽然本文是以外挂编程为例来说明的,但是希望热爱编程的朋友能够以此作为引申,达到抛砖引玉的作用。

2.注入是一种技术,也是一种思想;注入的手段并不是一般说的三种方法,凡是能将"可执行代码"或者“指令”写到目标进程空间里执行,都可以称之为注入技术。

3.本文仅做远程注入和全局DLL注入技术的介绍协议:如需转载,请说明出处。

1.一点引申计算机发展历程从单道技术道多道技术,到后来的分时技术,为了解决资源的高效分配和CPU利用率的提高,引入进程的概念可以说是一个操作系统的一个里程碑。

这里不多引申,主要是想说明,系统里各个进程的运行是相互独立的,每个进程独享自己的进程空间。

在单CPU上,微观上各个进程串行运作,但是宏观上表现为各个进程是并行处理。

进程只是一个“容器”,它复杂向系统申请资源,真正的执行操作的是线程。

这里仅仅是简单的说说...在进程加载的时候,代码被映射到进程的地址空间中,然后利用各种分页分段技术,在运行期将代码映射到具体的物理内存上,方可执行。

Windows下进程的地址空间在逻辑上是相互独立的,而在物理上却是相互重叠的,所谓的重叠是指在一块内存区域可能被多个进程同时使用(共享内存便是这个原理)。

2.注入的原理上面说了进程的地址空间是相互独立的,那么怎么使本进程的代码(比如一个CALL 函数)在目标进程里运行呢,那就需要注入了。

将代码利用一定的技术手段加载进目标进程空间,然后触发使之执行,这便是代码注入的雏形。

当然,后来的技术做了很多“变种”,以至于这种技术被病毒技术得到了很好的利用。

C++远程代码注入

C++远程代码注入

C++远程代码注⼊超级=_=,直接附上注⼊程序以及dll的代码。

dll 代码很简单只是弹窗,可以根据需要扩充。

注⼊程序由于是练⼿,只是随便写了打开计算器的远程注⼊。

从注⼊到卸载都包含,在程序执⾏完毕后扫尾巴1// InjectExample.cpp : 定义控制台应⽤程序的⼊⼝点。

234 #include "stdafx.h"56int EnableDebugPriv(const wchar_t *name)7 {8 HANDLE hToken;9 TOKEN_PRIVILEGES tp;10 LUID luid;1112//打开进程令牌环13if(NULL == OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))14return1;1516//获得进程本地唯⼀ID17if(!LookupPrivilegeValue(NULL,name,&luid))18return1;1920 tp.PrivilegeCount = 1;21 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;22 tp.Privileges[0].Luid = luid;2324//调整权限25if(!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))26return1;27return0;28 }2930 BOOL InjectDll(const wchar_t* DllFullPath,const DWORD dwRemoteProcessId)31 {32 HANDLE hRemoteProcess;33 EnableDebugPriv(SE_DEBUG_NAME);34//打开远程线程35 hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwRemoteProcessId);36if(!hRemoteProcess)37 {38 printf("OpenProcess Fail,GetLastError: %d",GetLastError());39return FALSE;40 }4142void *pszLibFileRemote;43//使⽤VirtualAllocEx 函数在远程进程的内存地址空间分配DLL⽂件名空间44 pszLibFileRemote = VirtualAllocEx(hRemoteProcess,NULL,(wcslen(DllFullPath)+1)*sizeof(wchar_t),MEM_COMMIT,PAGE_READWRITE); 45if(!pszLibFileRemote)46 {47 printf("VirtualAllocEx Fail,GetLastError: %d",GetLastError());48return FALSE;49 }5051//使⽤WriteProcessMemory 函数将DLL的路径写⼊到远程进程的内存空间52 DWORD dwReceiveSize;53if(0 == WriteProcessMemory(hRemoteProcess,pszLibFileRemote,(void*)DllFullPath,wcslen(DllFullPath)*sizeof(wchar_t),NULL))54 {55 printf("WriteProcessMemory Fail,GetLastError: %d",GetLastError());56return FALSE;57 }58 printf("WriteProcessMem Success!\r\n");5960//计算LoadLibrary 的⼊⼝地址61 PTHREAD_START_ROUTINE pfnStartAddr = NULL;6263//#ifdef _UNICODE64 pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(::GetModuleHandle(TEXT("Kernel32")),"LoadLibraryW");65//#else66//pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(::GetModuleHandle(TEXT("Kernel32")),"LoadLibraryA");67//#endif686970if(NULL == pfnStartAddr)71 {72 printf("GetProcAddress Fail,GetLastError: %d",GetLastError());73return FALSE;74 }7576//启动远程线程 LoadLibrary,通过远程线程调⽤创建新的线程77 DWORD dwThreadId=0;78 HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL); 79if(hRemoteThread == NULL)80 {81 printf("注⼊线程失败,ErrorCode: %d\r\n",GetLastError());82return FALSE;83 }8485 printf("Inject Success ,ProcessId : %d\r\n",dwRemoteProcessId);8687 WaitForSingleObject(hRemoteThread,INFINITE);88 GetExitCodeThread(hRemoteThread,&dwThreadId);8990//卸载注⼊dll91 pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")),"FreeLibrary");92 hRemoteThread = CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,(LPVOID)dwThreadId,0,NULL);9394//释放远程进程控件95 VirtualFreeEx(hRemoteProcess,pszLibFileRemote,wcslen(DllFullPath)*sizeof(wchar_t)+1,MEM_DECOMMIT);96//释放句柄97 CloseHandle(hRemoteThread);98 CloseHandle(hRemoteProcess);99return TRUE;100 }101102 DWORD GetProcessId()103 {104 DWORD Pid = -1;105 HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); // 创建系统快照106107//创建系统快照108 PROCESSENTRY32 lPrs; //保存进程信息的结构109 ZeroMemory(&lPrs,sizeof(PROCESSENTRY32));110111 lPrs.dwSize = sizeof(lPrs);112 wchar_t *targetFile = L"calc.exe";113 Process32First(hSnap,&lPrs); //取得系统快照中第⼀个进程信息114if(wcsstr(targetFile,lPrs.szExeFile)) // 判断进程信息是否为explore.exe115 {116 Pid = lPrs.th32ProcessID;117return Pid;118 }119while(1)120 {121 ZeroMemory(&lPrs,sizeof(lPrs));122 lPrs.dwSize = sizeof(lPrs);123if(!Process32Next(hSnap,&lPrs))124 {125 Pid=-1;126break;127 }128if(wcsstr(targetFile,lPrs.szExeFile))129 {130 Pid = lPrs.th32ProcessID;131break;132 }133 }134 CloseHandle(hSnap);135return Pid;136137 }138139int _tmain(int argc, _TCHAR* argv[])140 {141 wchar_t myFILE[MAX_PATH];142 GetCurrentDirectory(MAX_PATH,myFILE); //获取当前路径143 wcscat_s(myFILE,L"\\InjectDllExample.dll");144 InjectDll(myFILE,GetProcessId());145146return0;147 }DLL 代码:1// dllmain.cpp : 定义 DLL 应⽤程序的⼊⼝点。

VC++6.0远程调用CALL

VC++6.0远程调用CALL
if (strncmp(szProcessName, i, MAX_PATH) == 0)
{
dwPID = pe.th32ProcessID;
break;
}
fFound = Process32Next(hSnapshot, &pe);
}
CloseHandle(hSnapshot);
{
ParamData * lp;
lp=(ParamData *)lParam;
long lp1=(long)lp->Param1;
long lp2=(long)lp->Param2;
DWORD dwAddr = 0x45992C;
_asm
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
{
i = (pmc.WorkingSetSize / 1024) / 2;
CloseHandle(hProcess);
}
return i;
}
DWORD GetProcessIDByNam(const char* szProcessName)
}
//↓写
int WriteInt(HANDLE hProces,int Address,int Data)
{
DWORD dwWrite;
WriteProcessMemory(hProces, (LPVOID)Address, &Data, 4, &dwWrite);
return dwWrite;
}
byte ReadByte(HANDLE hProces,int Address)

c语言中call函数

c语言中call函数

c语言中call函数
在C语言中,"call"函数通常指的是函数调用的过程。

在C语
言中,要调用一个函数,我们使用函数名和一对括号来表示。

例如,如果我们有一个名为"add"的函数,它需要两个整数作为参数,并返
回它们的和,我们可以这样调用它,add(3, 4)。

在这个例子中,"add"是函数名,括号内的3和4是实际参数。

当程序执行到这一行时,它将跳转到"add"函数的定义处,执行函数体中的代码,然后返
回结果。

另外,"call"函数也可能指的是在汇编语言中用于调用函数的
指令。

在x86架构的汇编语言中,"call"指令用于调用函数,它会
将当前的指令指针压入堆栈,然后跳转到函数的入口地址开始执行
函数体。

在函数执行完毕后,使用"ret"指令返回到调用函数的地方,同时从堆栈中弹出之前保存的指令指针。

总的来说,在C语言中,"call"函数是指函数调用的过程,而
在汇编语言中,"call"函数是指用于调用函数的指令。

希望这些信
息能够帮助你理解"call"函数在C语言中的用法。

call 远调用实例

call 远调用实例

call 远调用实例
远程调用(Remote Procedure Call,RPC)是一种计算机通信协议,允许程序调用另一个地址空间(通常是另一台机器上)的过程或函数,就像本地调用一样。

以下是一个远程调用的简单示例:
假设我们有两台计算机,一台是客户端,另一台是服务器。

客户端想要调用服务器上的一个远程函数来获取一些数据。

首先,客户端会发送一个请求到服务器,请求执行特定的函数。

服务器接收到请求后,执行相应的函数,并将结果返回给客户端。

在这个过程中,远程调用涉及到网络通信、序列化和反序列化参数、远程函数的执行等步骤。

远程调用的实现可以使用不同的技术,比如基于HTTP的RESTful API、基于TCP的自定义协议、基于消息队列的异步调用等。

在实际的应用中,远程调用可以用于不同的场景,比如微服务架构中的服务间通信、分布式系统中的节点间通信等。

它可以帮助实现系统模块化、提高系统的可扩展性和灵活性。

总的来说,远程调用是一种重要的通信机制,它使得分布式系
统中的不同部分能够相互协作,完成复杂的任务。

在实际应用中,需要考虑到网络延迟、数据一致性、安全性等方面的问题,以确保远程调用的可靠性和性能。

vc++ 向其他进程注入代码的三种方法

vc++ 向其他进程注入代码的三种方法

vc++ 向其他进程注入代码的三种方法导言:我们在Code project()上可以找到许多密码间谍程序(译者注:那些可以看到别的程序中密码框内容的软件),他们都依赖于Windows钩子技术。

要实现这个还有其他的方法吗?有!但是,首先,让我们简单回顾一下我们要实现的目标,以便你能弄清楚我在说什么。

要读取一个控件的内容,不管它是否属于你自己的程序,一般来说需要发送 WM_GETTEXT 消息到那个控件。

这对edit控件也有效,但是有一种情况例外。

如果这个edit控件属于其他进程并且具有 ES_PASSWORD 风格的话,这种方法就不会成功。

只有“拥有(OWNS)”这个密码控件的进程才可以用 WM_GETTEXT 取得它的内容。

所以,我们的问题就是:如何让下面这句代码在其他进程的地址空间中运行起来:::SendMessage( hPwdEdit, WM_GETTEXT, nMaxChars, psBuffer );一般来说,这个问题有三种可能的解决方案:1. 把你的代码放到一个DLL中;然后用 windows 钩子把它映射到远程进程。

2. 把你的代码放到一个DLL中;然后用 CreateRemoteThread 和 LoadLibrary 把它映射到远程进程。

3. 不用DLL,直接复制你的代码到远程进程(使用WriteProcessMemory)并且用CreateRemoteThread执行之。

在这里有详细的说明:Ⅰ. Windows 钩子示例程序:HookSpy 和 HookInjExWindows钩子的主要作用就是监视某个线程的消息流动。

一般可分为:1.局部钩子,只监视你自己进程中某个线程的消息流动。

2.远程钩子,又可以分为:a.特定线程的,监视别的进程中某个线程的消息;b.系统级的,监视整个系统中正在运行的所有线程的消息。

如果被挂钩(监视)的线程属于别的进程(情况2a和2b),你的钩子过程(hook procedure)必须放在一个动态连接库(DLL)中。

远程注入代码

远程注入代码

远程注⼊代码1.复制代码的编写原则:1. 不能有全局变量2. 不能使⽤常量字符串3. 不能使⽤系统调⽤4. 不能嵌套调⽤其他函数1// 远程代码注⼊.cpp : 定义控制台应⽤程序的⼊⼝点。

2//34 #include "stdafx.h"5 #include <windows.h>6//⾃⼰定义个结构体,⽅⾯后⾯参数使⽤7/************************************************************************/8/* 远程线程实现CreateFile */9/************************************************************************/10 typedef struct11 {1213 DWORD dwCreateAPIAddr; //Createfile函数的地址14 LPCTSTR lpFileName; //下⾯都是CreateFile所需要⽤到的参数15 DWORD dwDesiredAccess;16 DWORD dwShareMode;17 LPSECURITY_ATTRIBUTES lpSecurityAttributes;18 DWORD dwCreationDisposition;19 DWORD dwFlagsAndAttributes;20 HANDLE hTemplateFile;21 }CREATEFILE_PARAM;2223//定义⼀个函数指针2425 typedef HANDLE(WINAPI* PFN_CreateFile)26 (LPCTSTR lpFileName,27 DWORD dwDesiredAccess,28 DWORD dwShareMode,29 LPSECURITY_ATTRIBUTES lpSecurityAttributes,30 DWORD dwCreationDisposition,31 DWORD dwFlagsAndAttributes,32 HANDLE hTemplateFile);3334353637//编写要复制到⽬标进程的函数 238 DWORD _stdcall CreateFileThreadProc(LPVOID lparam)39 {40 CREATEFILE_PARAM* Gcreate = (CREATEFILE_PARAM*)lparam;41 PFN_CreateFile pfnCreateFile;42 pfnCreateFile =(PFN_CreateFile) Gcreate->dwCreateAPIAddr;43//creatFile结构体全部参数 144 pfnCreateFile(Gcreate->lpFileName, Gcreate->dwDesiredAccess, Gcreate->dwShareMode,45 Gcreate->lpSecurityAttributes, Gcreate->dwCreationDisposition, Gcreate->dwFlagsAndAttributes,46 Gcreate->hTemplateFile);4748return0;4950 }5152//远程创建⽂件53 BOOL RemotCreateFile(DWORD dwProcessID, char* szFilePathName)54 {55 BOOL bRet;56 DWORD dwThread;57 HANDLE hProcess;58 HANDLE hThread;59 DWORD dwThreadFunSize;60 CREATEFILE_PARAM GCreateFile;61 LPVOID lpFilePathName;62 LPVOID lpRemotThreadAddr;63 LPVOID lpFileParamAddr;64 DWORD dwFunAddr;65 HMODULE hModule;666768 bRet = 0;69 hProcess = 0;70 dwThreadFunSize = 0x400;71//1.获取进程的句柄72 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);73if (hProcess == NULL)74 {75 OutputDebugString("OpenProcessError!\n");76return FALSE;77 }78//2.分配3段内存:存储参数,线程函数,⽂件名7980//2.1 ⽤来存储⽂件名,//+1是要计算到结尾处81 lpFilePathName = VirtualAllocEx(hProcess, NULL, strlen(szFilePathName)+1, MEM_COMMIT, PAGE_READWRITE);//在指定的进程中分配内存8283//2.2 ⽤来存储线程函数84 lpRemotThreadAddr = VirtualAllocEx(hProcess, NULL, dwThreadFunSize, MEM_COMMIT, PAGE_READWRITE);//在指定的进程中分配内存8586//2.3 ⽤来存储⽂件参数87 lpFileParamAddr = VirtualAllocEx(hProcess, NULL, sizeof(CREATEFILE_PARAM), MEM_COMMIT, PAGE_READWRITE);//在指定的进程中分配内存888990//3. 初始化CreateFile参数91 GCreateFile.dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;92 GCreateFile.dwShareMode = 0;93 GCreateFile.lpSecurityAttributes = NULL;94 GCreateFile.dwCreationDisposition = OPEN_ALWAYS;95 GCreateFile.dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;96 GCreateFile.hTemplateFile = NULL;9798//4.获取CreateFile的地址99/*因为每个进程中的LoadLibrary函数都在Kernel32,dll中,⽽且此dll的物理页是共享的,所以100我们进程中获得的LoadLibrary地址和别的进程都是⼀样的*/101 hModule = GetModuleHandle("kernel32.dll");102 GCreateFile.dwCreateAPIAddr = (DWORD)GetProcAddress(hModule, "CreateFileA");103 FreeLibrary(hModule);104105//5.初始化CreatFile⽂件名106 GCreateFile.lpFileName = (LPCTSTR)lpFilePathName;107108//6.修改线程函数起始地址109 dwFunAddr = (DWORD)CreateFileThreadProc;110111//间接跳112if (*((BYTE*)dwFunAddr) == 0xE9)113 {114 dwFunAddr = dwFunAddr + 5 + *(DWORD*)(dwFunAddr + 1);115 }116117//7.开始复制118//7.1 拷贝⽂件名119 WriteProcessMemory(hProcess, lpFilePathName, szFilePathName, strlen(szFilePathName) + 1, 0);120121//7.2 拷贝线程函数122 WriteProcessMemory(hProcess, lpRemotThreadAddr, (LPVOID)dwFunAddr, dwThreadFunSize, 0);123124//7.3拷贝参数125 WriteProcessMemory(hProcess, lpFileParamAddr, &GCreateFile, sizeof(CREATEFILE_PARAM), 0);126127128//8.创建远程线程129130 hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemotThreadAddr, lpFileParamAddr, 0, &dwThread);//lpAllocAddr传给线程函数的参数.因为dll名字分配在内存中131if (hThread == NULL)132 {133 OutputDebugString("CreateRemoteThread Error!\n");134 CloseHandle(hProcess);135 CloseHandle(hModule);136return FALSE;137 }138//9.关闭资源139 CloseHandle(hProcess);140 CloseHandle(hThread);141 CloseHandle(hModule);142return TRUE;143144 }145146147int main()148 {149 RemotCreateFile(PID, "⽂件名");150return0;151 }请勿转载,仅供学习使⽤。

createremotethread注入代码

createremotethread注入代码

createremotethread注入代码创建一个远程线程注入代码的方式有很多,以下是一个例子:```cpp#include <iostream>#include <windows.h>// 要注入的代码DWORD WINAPI InjectedCode(LPVOID lpParameter) {// 在这里编写你要注入的代码逻辑MessageBox(NULL, "注入成功!", "提示", MB_OK);return 0;}int main() {// 获取目标进程的句柄HWND hwnd = FindWindow(NULL, "目标进程窗口标题"); DWORD pid;GetWindowThreadProcessId(hwnd, &pid);HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);if (hProcess == NULL) {std::cout << "无法打开进程" << std::endl;return 1;}// 在目标进程中申请一块内存空间LPVOID pRemoteCode = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);// 在目标进程中写入要注入的代码if (!WriteProcessMemory(hProcess, pRemoteCode, (LPVOID)InjectedCode, (SIZE_T)InjectedCode.Length(), NULL)) {std::cout << "写入注入代码失败" << std::endl;return 1;}// 创建远程线程,将目标进程中的指定地址作为线程入口地址HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteCode, NULL, 0, NULL);if (hRemoteThread == NULL) {std::cout << "创建远程线程失败" << std::endl;return 1;}// 等待远程线程结束WaitForSingleObject(hRemoteThread, INFINITE);// 清理资源VirtualFreeEx(hProcess, pRemoteCode, 0, MEM_RELEASE); CloseHandle(hRemoteThread);CloseHandle(hProcess);return 0;}以上代码演示了如何在指定的目标进程中创建一个远程线程,并在其中注入一段代码逻辑。

在远程进程中注入DLL

在远程进程中注入DLL
10
实例
• This sample demonstrates how to get the command line another process was started with. To this end, it performs the following steps: 1、opens the target process 2、allocates two chunks of memory in the target process' address space; one is executable, the other one for data 3、copies a function from the local address space to the first piece of memory in the target 4、initializes the allocated data area in the target 5、calls CreateRemoteThread() to get the copied code going 6、waits on the thread handle until the newly created thread is done 7、copies the (now filled-in) data area back into the local address space
11
opens the target process
1、try to enable current process SeDebugPrivilege 2、calls OpenProcess()
12
Hale Waihona Puke try to enable current process SeDebugPrivileg

找call图文教程1

找call图文教程1

找call图文教程
打开"游戏找CALL练习实例one.exe",打开OD,附加"游戏找CALL练习实例one"进程。

以下几步是边学边用的:
F9运行。

输入bp send,回车,这样发包函数被设成中断。

点“吃血”,OD在发包处中断。

游戏中一个具体的功能都会设成一个具体的过程或函数,在游戏主程序运行时,相应功能的实现都会有一个Call,找Call就是为了找功能入口。

OD中按Ctrl+F9,是返回(retn)。

返回到哪里?看下图中画圈处。

找游戏Call就要在游戏模块中。

不在就Ctrl+F9...
按Ctrl+F9,按会找到一个retn,往上看看会有个Call。

看教程说按到第五层。

找到的是加血的。

照做。

看下图。

怎么知道是不是加血call?
这里设上断点,然后光标移到别处。

按运行...按吃血,吃蓝。

挨下试,看那个能中断到这里,(先把原来的中断去掉,如下图,红色总分点右键删除。

)只有加血能到这里,这个CALL 就是加血的。

要进一步确认,就可以注入代码测试。

下图红框中的代码,注入发现不成功,这里反复了好几次。

我把右边的寄存器的值也写上了一些再试....注入远程代码。

OK成功了!!
成功了的心情,无法言表。

压抑越久,喜悦越大,但这还是因为自己的水平太** 如果你也像我一样,反复做不成,但愿这篇文章给你启发,那怕就一点。

远程读写游戏内存VC带源码

远程读写游戏内存VC带源码

远程读写游戏内存VC带源码学习各种高级外挂制作技术,马上去百度搜索"魔鬼作坊",点击第一个站进入,快速成为做挂达人。

对于那些弹出游侠界面或暂停后就死掉的游戏,用类似的方法就可以修改了吧?!如果数值地址不是象ra2这样有多个,可在游戏中记下几个数值,然后写入一文件中,搜索时从文件中读取数值即可。

也可用键盘钩子记录按键,进行无界面动态输入。

*-------------------------------------------------------------------------------;------------------------------------------------------------------------;取得游戏进程的句柄。

游戏中按下“*”号键便来到这里;有两种常用的方法:进程快照查找法和当前活动窗口法;------------------------------------------------------------------------_GetProcessHandle proccomment*在调试时用这段代码取得游戏进程的句柄为好LOCAL info:PROCESSENTRY32LOCAL handle:HANDLEinvoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0;进程快照mov handle,eaxmov info.dwSize,sizeof PROCESSENTRY32invoke Process32First,handle,addr info.repeatmov eax,@Finvoke lstrcmpi,addr info.szExeFile,eax;比较是否为我们要找的进程名,不区分大小写.if!eaxinvoke CloseHandle,handle;invoke MessageBox,NULL,addr info.szExeFile,NULL,MB_OKinvoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,info.th32ProcessIDjmp EXIT.endifinvoke Process32Next,handle,addr info.until!eaxinvoke CloseHandle,handlexor eax,eaxEXIT:ret@@:db"Game.exe",0*通常情况下也可以用下面的方法取得游戏进程的句柄,但要注意……LOCAL ProcessIdinvoke GetForegroundWindow;你必须确保当前窗口为游戏界面窗口,这样才能正确取得游戏进程IDlea edx,ProcessIdinvoke GetWindowThreadProcessId,eax,edxinvoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,ProcessIdret_GetProcessHandle endp;------------------------------------------------------------------------;第一遍搜索。

寻找网络游戏中CALL的教程

寻找网络游戏中CALL的教程

寻找网络游戏中CALL的教程寻找网络游戏中CALL的教程说一说一个简单的找call原理其实游戏中的call是有一定规律的,这个规律是什么?1、调用之前,必定有call名入栈,什么,不知道如何看堆栈有哪些内容。

很简单啊,按alt+k就看到了2、系统进程空间,一般都可以忽略,那么,哪些是系统进程呢,我自己也分不太清,但是NTDLL,USER32,WS_S32等一般都是系统进程空间,在od的状态栏上就可以分辨出来。

举个例子:ZX中找死亡回程call一、在弄死小号后,先下了BP SEND指令,od中断下来,按ALT+K,看到的堆栈情况是这样的:地址堆栈函数过程参数调用来自结构029FFEC800572860WS2_32.send elementc.0057285A029FFECC000006BC Socket=6BC029FFED006D1F2A8Data=06D1F2A8029FFED400000003DataSize=3029FFED800000000Flags=0029FFEE800578BE7包含elementc.00572860elementc.00578BE4029FFEF000578827elementc.00578BB0elementc.00578822029FFF38005785DE elementc.00578640elementc.005785D9029FFF4800577128包含elementc.005785DE elementc.00577125二、然后F9让游戏正常,再回到游戏中,按下“回城”三、od中断下来,再按alt+K,看到的堆栈是另外一个样子了:地址堆栈函数过程参数调用来自结构0012F3B400581775elementc.005898B0elementc.005817700012F3C400583F75elementc.00581740elementc.00583F700012F400005A8CF6elementc.00583ED0elementc.005A8CF10012F4100057E701elementc.005A8CD0elementc.0057E6FC0012F42000509E80elementc.0057E6C0elementc.00509E7B0012F424006C6527包含elementc.00509E80elementc.006C65240012F444006C647C elementc.006C64B0elementc.006C64770012F45C006C8F0E包含elementc.006C647C elementc.006C8F0B0012F4640054A432elementc.006C8F00elementc.0054A42D0012F47C006C236B包含elementc.0054A432elementc.006C23680012F494006C269B elementc.006C22C0elementc.006C26960012F4E0006C93AA elementc.006C2380elementc.006C93A50012F55C00549BBB elementc.006C8F50elementc.00549BB6四、如果用CTRL+F9跟踪,很容易发现,前三个都是在WS32系统进程空间,所以,第4个,做了个标记的那里,就是死亡回程call了希望大家多多实践,注意观察。

CALL的概念篇(已修改)

CALL的概念篇(已修改)

●CALL的概念篇:堆栈的平衡(一)作者:重楼日期:2009-09-05*堆栈平衡是一个很重要的东西,其实说白了也没有什么,只要自己反汇编看看执行过程中的变化便能了解的一清二楚.* 这章需要知道一些简单的汇编知识,比如说EIP的作用ESP的概念这些我就不详细多说了,想要学习的请看王爽老师的汇编语言非常经典的一本书此次例子以武易打坐CALL为例===========================开始分析================ [attachment=42598]这个就是打坐CALL的原型和代码当然了这个寄存器的值是动态的,因为是做堆栈平衡的所以我们没有找基址,可能跟你的值会不一样.[attachment=42599]这里是打坐CALL的内部我们来用加了堆栈平衡和没加堆栈平衡的CALL分别调用看看他们的堆栈和寄存器的变化[attachment=42600]这里是CALL内部中头部和尾部的变化, 我们发现并没有任何的不同,看来堆栈平衡跟CALL内部无关[attachment=42601]这里不一样了, 我们发现, 有堆栈平衡的代码里多了一行add es p,4而执行到RETN 时候栈顶也各不相同当CPU 执行完add esp,4 后就把栈顶的第一行挤出堆栈.而没有处理过堆栈平衡的则跳转到了9EC8950 这里我们来看看这个正确指向代码地址的值是从哪里来的[attachment=42602]图中9EC8818 是我们代码中PUSH进去的值80f000a 则是跳出这个CALL返回时候所跳转的代码地址当执行retn的时候EIP指向这里7C80B729 则是跳出去以后执行retn 时候所指向的代码地址.如果我们把第一个堆栈80f000a 换成7c80b729 会如何? [attachment=42603]呵呵调用成功也没有出错, 这是因为在最后执行retn的时候我们帮他指向了正确的地址,当然了也不是所有游戏都可以这样弄的,有些游戏压入的数值不是随意便可以CALL成功的.好了从上面的例子可以看出堆栈平衡其实就是帮助EIP 指向正确的地址, 如果你压入一个0 而不做堆栈平衡处理那么执行完后EIP便会执行0 这个代码地址.说白了,堆栈平衡处理就是把压入的数值的空间去删去.因为ESP永远指向栈顶,RETN永远执行跳转到栈顶的地址.CALL的概念篇:CALL出错分析作者:重楼日期:2009-09-05在刚开始找CALL的时候,绝大部分的时间都是在重新打开游戏和出错中度过,这个可能绝大部分朋友都有这个感受~CALL为何会出错?今天我们就来分析下出错的原因目标:F8找CALL02目的:分析各种CALL的错误弄过F8找CALL模拟器的朋友都知道F8CALL02是一个喊话模拟的模拟器,而且只能注入才能正确调用远程调用的话就会出错,今天我们来分析下到底错在哪里.======分析开始=======================CALL 我就不找了,大家可以看配套视频,在断点社区精华区可以下载.[attachment=42604]这里就是F8 CALL 02的喊话功能CALL的地方[attachment=42605]这是运行到CALL时候堆栈中的值...这里很多朋友都不明白为何只要写一个CALL就可以实现喊话,我之前说过,我们只需要给CALL他想要的参数.这里的堆栈分别压入了基址喊话内容喊话模式喊话对象这个就是参数而且也没做什么处理,所以我们只要给他想要的参数按照顺序就可以了.这里正确的写法我就不说了,我们主要来调试下错误的信息. [attachment=42606]这里其实需要处理堆栈平衡,我们先不写,来分析下堆栈不平衡为何会出错,好了这里没有加上堆栈平衡,图中是出错的信息.我们在CALL 内部第一行下断[attachment=42607]运行代码注入器调用CALL后就会断下来,.*这里为何会断在这里而不断在CALL地址呢?因为,我们写一个CALL ***** 其实就是从*****这个地址开始运行的,却不是从游戏调用这个CALL的代码开始. 这里弄多了你就会明白,你写一个CALL其实在模拟游戏调用CALL的那部分.[attachment=42608]我们来按F8 一直执行......一直到图中的位置才出错.出错信息跟刚刚是一样的[attachment=42609]*45d000 一般是程序的代码段开始部分,而图中参数的存放是ebp-8 已经超过了代码段的范围了,所以我们这里就会出现无法读内存的错误.解决方法:这里我们把存放内容的地址弄后面一点便可以了[attachment=42610]好了我们继续往下单步运行(F8)[attachment=42611]好了运行到这里又出错了~~重新运行吧~[attachment=42612][attachment=42613]我们到了上面那个地址出错~而EAX的值就是我们出错的信息地址,从调试窗口看到EAX的值是???我们来看看用模拟器自身的喊话,这里是如何一个过程[attachment=42614]图中对比了使用自身喊话和代码注入器的调用情况 .如果这个时候我们把ECX改成8呢?[attachment=42615]好了,这里已经解决了第二个问题, 又出现第三个问题 .这个时候我们发现错误信息中有出错代码的地址.我们跳过去看看[attachment=42616]这里又有一处内存无法读出, 这里的值是指向270这个地址(前面部分处理按照上面的来)错误找到了我们重新再来一次这次停到错误代码地址前面(第二个错误依旧按照上面的处理来)[attachment=42617]我们来看看正常情况下的寄存器值[attachment=42618]这里我们用模拟器能成功的读取到地址.我们来跟踪一下这个值是如何产生的[attachment=42619]这里我们从头部开始找....[attachment=42620]头部的值还是跟上面一样所以我们返回一层看看.[attachment=42621]463cc4 就是EBX的基址.我们把代码注入器的代码改一下[attachment=42622][attachment=42623]好了运行到原来出错的地方发现现在已经能正常读取内存地址了,又解决一个错误(到第二步的地方仍然需要手动解决)我们继续运行,发现卡在了下面那个CALL那里按运行或点程序都没反应, 这个时候我们只要在调用一次CALL就可以了.我们继续运行到上面这里然后按F8 ,发现又一个错误... [attachment=42624]这里的代码段是从45d000 开始的而图中却是4030a7 这里我们也没办法跳过去调试了.好了今天我们的调试错误信息就到这里了,虽然最终没有解决这个问题,但也获得不少收获~CALL的概念篇:寄存器值的跟踪作者:重楼日期:2009-09-04================前言============================很多时候CALL里的一些数值,都是变化的,或者不同的电脑值也不一样,如何寻找这些值的基址呢?不同的值有不同的找法下面就列出几条常用的方法。

超级详细找CALL写CALL教程

超级详细找CALL写CALL教程
我们刚才说看CALL的参数,CALL的参数其实就是在调用CALL的时候所需要的运行环境,在什么条件下,CALL执行之后是吃血,什么情况下是吃蓝。
好的。我们现在利用到了寄存器。看寄存器中的提示,有两个红色,说明当我们调用CALL的时候,它使用了寄存器中的两个地址。那么这个就是CALL的
运行环境了,也就是说,只要在我们调用这个CALL的时候,寄存器EAX中有值00D51FE4和寄存器ECX中有值0042ABE4就可以运行。这里还有一个特殊
好,不管是不是这个CALL,我们先来测试一下
我是用delphi的,所以这里讲解delphi-----这里我还要多一嘴,其实语言只是工具,只要学会了道理,就不在乎语言的问题了,其实在我们这个阶段,语言的区分仅仅是命令不同而已
我会把如何写的理论告诉给大家。让大家知道------花儿为什么这样红!o(∩_∩)o...哈哈
呵呵谢谢lz这么好的文章,希望能解答下我的问题。。。
回答:这里的ECX不是环境之一,这个不一定就要一定不变才是因素,具体问题要具体分析,如果你想知道到底这个寄存器中的值在call后是否变化了,可以进入这个call看看这个call的具体运算方法。
Quote:
引用第10楼ffzzfcll于2008-04-18 15:06发表的:
WriteProcessMemory(Hid, ThreadAdd,FunName, 128, WriteCount);//将要注入的过程写到上面建立的内存空间中
TmpHandle := CreateRemoteThread(Hid, nil, 0, ThreadAdd, nil, CREATE_SUSPENDED, ThreadID);//获得注入后过程的句柄ID
首先,我们要调用一个程序的CALL,需要干什么。当然是指定这个程序啦!如何指定?如果这里您不知道,建议您去句柄那里好好修炼一下。

火山pc call写法

火山pc call写法

火山pc call写法火山PC调用方法详解[火山pc call写法] 这个主题下,让我们一步一步了解如何调用火山PC。

火山PC(Call)是一种用于实现远程过程调用(RPC)的工具,它提供了一个简单而高效的方式来实现分布式系统中的通信。

通过火山PC调用方法,我们可以将不同的计算机节点连接在一起,实现数据共享和协同工作。

在本文中,我们将详细介绍火山PC调用的步骤和方法。

第一步:准备工作要开始使用火山PC进行远程过程调用,我们首先需要准备好一些基本的工作。

首先,我们需要确保我们的计算机上安装了火山PC库。

您可以从官方网站下载并安装适用于您所使用的编程语言的火山PC库。

此外,您还需要确定所使用的RPC协议。

火山PC支持多种RPC协议,例如HTTP、TCP等。

在本文中,我们将以HTTP为例进行介绍。

第二步:定义服务在使用火山PC之前,我们需要定义我们的服务。

服务是一组网络可调用的函数,它们可以在不同的计算机节点上运行。

在定义服务时,需要指定函数名称、输入参数和返回值类型。

例如,我们定义一个名为"计算器"的服务,其中包含几个基本的数学运算函数,如加法、减法、乘法和除法。

我们可以使用以下代码片段来定义此服务:pythonclass Calculator:def add(self, x, y):return x + ydef subtract(self, x, y):return x - ydef multiply(self, x, y):return x * ydef divide(self, x, y):return x / y第三步:启动服务器在启用RPC调用之前,我们需要启动一个服务器来监听网络请求。

服务器将负责接收请求并调用相应的函数。

在火山PC中,我们可以使用以下代码启动一个简单的HTTP服务器:pythonfrom volcano import servercalculator = Calculator()server.run_http_server(calculator, "localhost", 8000)以上代码片段将启动一个HTTP服务器,监听本地主机的8000端口,并将所有传入的请求转发给Calculator对象。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

声明:该教程写给有一定外挂编程基础且热爱编程技术的朋友共同学习。

说明:1.教程本身只是作为技术交流探讨,没有其他目的2.以完美国际187版游戏为例,不具有任何针对意味3.在广海里学了很多东西,希望在广海里留下一些什么见解:1.虽然注入技术已经不再是什么“时尚”的技术,但是在编程应用领域,却依然得到很广泛的应用。

虽然本文是以外挂编程为例来说明的,但是希望热爱编程的朋友能够以此作为引申,达到抛砖引玉的作用。

2.注入是一种技术,也是一种思想;注入的手段并不是一般说的三种方法,凡是能将"可执行代码"或者“指令”写到目标进程空间里执行,都可以称之为注入技术。

3.本文仅做远程注入和全局DLL注入技术的介绍协议:如需转载,请说明出处。

1.一点引申计算机发展历程从单道技术道多道技术,到后来的分时技术,为了解决资源的高效分配和CPU利用率的提高,引入进程的概念可以说是一个操作系统的一个里程碑。

这里不多引申,主要是想说明,系统里各个进程的运行是相互独立的,每个进程独享自己的进程空间。

在单CPU上,微观上各个进程串行运作,但是宏观上表现为各个进程是并行处理。

进程只是一个“容器”,它复杂向系统申请资源,真正的执行操作的是线程。

这里仅仅是简单的说说...在进程加载的时候,代码被映射到进程的地址空间中,然后利用各种分页分段技术,在运行期将代码映射到具体的物理内存上,方可执行。

Windows下进程的地址空间在逻辑上是相互独立的,而在物理上却是相互重叠的,所谓的重叠是指在一块内存区域可能被多个进程同时使用(共享内存便是这个原理)。

2.注入的原理上面说了进程的地址空间是相互独立的,那么怎么使本进程的代码(比如一个CALL 函数)在目标进程里运行呢,那就需要注入了。

将代码利用一定的技术手段加载进目标进程空间,然后触发使之执行,这便是代码注入的雏形。

当然,后来的技术做了很多“变种”,以至于这种技术被病毒技术得到了很好的利用。

明白了上面的原理,就可以自己进行我们下面的这个实例了。

系列的操作,Windows提供了相应的API,我也把它封装了成函数,中间过程的一些重要的细节等会解剖。

3.远程注入这是一种比较普遍的做法,但是也有着明显的缺点,频繁的注入比较容易产生内碎片的大量累积。

当然,有改进的做法,比如固定申请的地址,一次申请,多次利用,这里不在多说。

这里仅作为技术探讨,列出主要的实现步骤。

分二层实现,稍作了封装我们以带参数的选怪CALL为例:void CallSelectMonster (long MonsterSn){DWORD dwAddr = 0x59B8B0;_asm{pushadmov edi , MonsterSnpush edimov eax , dword ptr [0x950954]mov eax , dword ptr [eax]mov ecx , dword ptr [eax + 0x20]add ecx , 0xeccall dwAddrpopad}}这里CALL存在问题,等会解决1>. 第一层调用:选怪函数,里面封装了调用注入函数的操作。

void CSkill::SelectMonster(DWORD ProcessId, long MonsterSn){long * m_pGuaiId = & MonsterSn ;//调用注入函数InjectRemoteFunc(ProcessId,CallSelectMonster,m_pGuaiId,sizeof(*m_pGuaiId));}2>.封装注入代码并调用执行的操作。

<注:这个函数是师傅的,封装的比较好,当然写法不一,但步骤都一样:开辟空间,写入,然后调用执行之>//封装远程注入的函数//参数1. 进程ID//参数2. 被注入函数指针<函数名>//参数3. 参数//参数4. 参数长度BOOL InjectRemoteFunc(DWORD dwProcId,LPVOID mFunc, LPVOID pRemotePara m, DWORD ParamSize){HANDLE hProcess;LPVOID ThreadAdd;LPVOID ParamAdd = NULL;HANDLE hThread = NULL;DWORD lpNumberOfBytes;BOOL BO;ThreadAdd = mFunc;hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcId);//打开被注入的进程ThreadAdd = VirtualAllocEx(hProcess,NULL,4096,MEM_COMMIT,PAGE_EXECUTE_R EADWRITE);BO = WriteProcessMemory(hProcess,ThreadAdd,mFunc,4096, &lpNumberOfBytes); //写入函数地址if(ParamSize!=0){ParamAdd = VirtualAllocEx(hProcess,NULL,ParamSize, MEM_COMMIT, PAGE_RE ADWRITE);BO = WriteProcessMemory(hProcess, ParamAdd, pRemoteParam, ParamSize, &lp NumberOfBytes); //写入参数地址}hThread = CreateRemoteThread(hProcess, NULL,0,(LPTHREAD_START_ROUTINE)T hreadAdd, ParamAdd, 0,&lpNumberOfBytes); //创建远程线程WaitForSingleObject(hThread, INFINITE);//等待线程结束VirtualFreeEx(hProcess, ThreadAdd, 4096, MEM_RELEASE);if(ParamSize!=0){VirtualFreeEx(hProcess, ParamAdd, ParamSize, MEM_RELEASE); //释放申请的地址}CloseHandle(hThread);CloseHandle(hProcess);return TRUE;}4.分析会C++的朋友可以马上要它运行起来,哪怕是控制台下,只要获得了窗口句柄,赋值一个比较合适的怪物ID,做个循环加,都可以实现选怪了。

其他附加的代码我不贴出来了,前面说了,这是写给有一定基础的外挂编程的朋友学习讨论的。

我在前面留了一个小的bug,这也是我主要写这篇教程的原因之一。

在处理这个问题的时候,我也郁闷了好一阵,但最后还是解决了。

如果现在能看出来bug的朋友,并知道为什么会有这样bug的朋友,可以不用看了,呵呵。

1>为了说明这个问题,我想引入msdn里的一些说明:首先,创建远程线程的函数原型:HANDLE CreateRemoteThread(HANDLE hProcess, // handle to process LPSECURITY_ATTRIBUTES lpThreadAttributes, // SDSIZE_T dwStackSize, // initial stack sizeLPTHREAD_START_ROUTINE lpStartAddress, // thread functionLPVOID lpParameter, // thread argumentDWORD dwCreationFlags, // creation optionLPDWORD lpThreadId // thread identifier);看第四个参数,也就是回调函数(由用户编写,但调用权限由操作系统主宰的函数) ,当调用了这个创建远程线程的函数,只要这个倒数第二个参数设置为0,也就是dwCreatio nFlags=0,那么回调函数将会立即执行。

现在看看回调函数的原型:DWORD WINAPI ThreadProc(LPVOID lpParameter // thread data);发现该函数只接收一个LPVOID类型的参数,那么如果这个参数不是指针行不行呢,当然并行了,呵呵,现在明白了吧,前面的带参数CALL相当于这个“回调函数”,只是样子变了一下而已,这个思想很重要那么现在改下CALL原型,变成这样就OK了void CallSelectMonster (long * MonsterSn){long sn = *MonsterSn;DWORD dwAddr = 0x59B8B0;_asm{pushadmov edi , snpush edimov eax , dword ptr [0x950954]mov eax , dword ptr [eax]mov ecx , dword ptr [eax + 0x20]add ecx , 0xeccall dwAddrpopad}}到这里,都明白了吧,前面CALL的原型就是错误的,也就是不匹配,当调用创建远程线程时,参数传递就出现问题了。

作为引申,我在说明一点,观察另外一个函数的原型:HMODULE LoadLibrary(LPCTSTR lpFileName // file name of module);比较一下DWORD WINAPI ThreadProc(LPVOID lpParameter // thread data);原型一样,那么可以用LoadLibrary来作这个“回调函数”,又一个变形的回调函数,那么就可以轻松的将一个DLL注入的目标进程了,并且在DLL初始化的时候做很多事情。

5.又一种注入DLL的方式,全局DLL注入这里我不再贴代码,很分散,我只是想说下实现的步骤和思想。

这种方式可以用hook + DLL来实现:1>.安装一个钩子,将钩子回调函数写在DLL里,在回调函数里new PerfectDialog() ,创建一个窗口,方便操作。

2>.安装这个钩子,消息触发回调函数,那么指定的进程就会加载这个DLL了,这个进程当然就是你所要操作的进程。

这个时候,DLL里代码操作的数据就和目标进程空间里的数据通用了。

貌似很爽,调用CALL就好像调用自己进程空间的CALL一样,不用在进程注入了。

但是,也会引发一些其他的问题,应该就是对于异常的考虑。

比如,用指针读相关数据,指针+偏移,在读相关数据,这些操作都是要进行异常判断。

这里不在用ReadProcess Memory WriteProcessMemory函数,那么,这些操作你就是考虑自己封装,理论上就像是模拟一个自己进程空间的读写函数。

相关文档
最新文档