fPort 工具可以查看端口号
学习c语言循环相关的知识点
使用pLog时可以使用LOGE_IF这样的话可以,使用DLL注入方式将其更改打印方式
实验证明:只需要用LOGE_IF(condition)即可,然后通过WriteProcessMemory将condition的地址改为0即可。
target ... : prerequisites ...
recipe
...
...
一个处方是make执行的一个动作。一个处方可能会有超过1个命令,或者在同一行,或者在各自行。
请注意:你需要在每个处方行的开始处放置一个tab字符。这可以默默地捕捉你的粗心。
如果你喜欢用一个区别于tab的字符作为处方的前缀,你可以设置.RECIPEPREFIX变量,将其改为其他字符。
通常一个处方伴随着一些prerequisite,并且当prerequisite有任何更改时,服务于创建一个目标文件。
然而,指定目标的处方的规则不需要有先决条件。例如,包含与目标clean相关的delete命令的规则
不需要有先决条件。
一个规则,解释了如何以及何时重新编译特定文件,这些特定文件是特定规则的目标。
make在先决条件的基础上执行这个处方,用于生成或者更新目标。
一个规则也可以解释如何以及何时执行一个动作。
一个makefile除了规则之外可能包含其他的文本,但是一个简单的makefile仅仅需要特定的规则。
规则可能会看起来比展示在这个模板里面的稍微更加复杂一些,但是所有的makefile都或多或少适合这个模式。
这里是一个直接了当的makefile,这个makefile描述了一个叫做edit的可执行文件
如何依赖于8个目标文件,而这8个目标文件反过来又依赖于8个C源文件和3个头文件。
在这个例子中,所有的C文件包含defs.h,但是只有那些定义了编辑命令的文件包含了command.h,
并且,仅仅改变编辑器缓存的低级别文件包含了buffer.h。
edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o
\t cc -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
main.o : main.c defs.h
\t cc -c main.c
kbd.o : kbd.c defs.h command.h
\t cc -c kbd.c
command.o : command.c defs.h command.h
\t cc -c command.c
display.o : display.c defs.h buffer.h
\t cc -c display.c
insert.o : insert.c defs.h buffer.h
\t cc -c insert.c
search.o : search.c defs.h buffer.h
\t cc -c search.c
files.o : files.c defs.h buffer.h command.h
\t cc -c files.c
utils.o : utils.c defs.h
\t cc -c utils.c
clean :
\t rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
我们使用/将每一个长行分割为2行;这如同使用一个长行,但是易读性好。
要使用这个makefile产生一个叫做edit的可执行文件,输入:make
要使用这个makefile从目录中删除可执行文件以及所有的目标文件,键入:make clean
在这个示例makefile中,目标包含可执行文件edit,以及目标文件main.o和kbd.o。
先决条件是文件比如main.c和defs.h。事实上,每个.o文件既是一个目标也是一个先决条件。
处方包含cc -c main.c以及cc -c kbd.c。
当一个目标是一个文件,它需要被重新编译或者重新连接,如果它的任何先决条件有更改。
另外,任何自动生成的先决条件应该被先更新。在这个例子中,edit依赖于8个目标文件。
目标文件main.o依赖于源文件main.c和头文件defs.h。
一个处方可能跟随着上面一行,上面这行包含一个目标和一个先决条件。
这些处方表示如何更新目标文件。一个tab字符必须在每一个处方的行首,用于区分处方,而不是
makefile中的其他行。(记住make不知道处方如何工作的任何事。取决于你提供处方去合适地
更新目标文件。make所有所做的事情就是当目标文件需要被更新的时候执行你指定的处方。)
目标clean不是一个文件,但是仅仅是一个动作的名字。
既然在这个规则里面平常不想要执行这个动作,clean不是任何其他规则的先决条件。
因此,make关于clean不做任何事,除非你特地指出来。
注意这个规则不仅不是一个先决条件,它也没有任何先决条件,所以这个规则的唯一目的
就是运行特定处方。
没有涉及到其他文件,仅仅是一个动作的目标叫做伪目标。
默认地,make从第一个目标开始执行(不是以.开头的目标)。
这叫做默认目标。(goals是make力求最终更新的targets,你可以用命令行重写这个行为,
或者使用.DEFAULT_GOAL特定变量来实现)。
在这个上节的简单的例子中,默认目标是去更新可执行程序edit;
因此,我们将那条规则放在最前面。
这样,当你执行如下命令时:
make
make读取当前目录中的makefile并且开始从第一个规则读取。
在这个例子中,这个规则是为了重新链接edit;但是在make可以完整地运行这条规则之前,
它必须执行这条规则中edit所依赖的文件,在这种情况下,他们是目标文件。
每一个文件根据它自己的规则被处理。
这些规则要通过编译它的源文件更新每个.o文件。重新编译必须被执行,如果源文件
或者任何作为先决条件的头文件比目标文件更新,或者目标文件不存在。
其他规则被处理因为他们的目标作为goal的先决条件。
如果一些其他的规则没有被goal所依赖(或者被goal所依赖的文件所依赖),那个规则可以不用执行,
除非你告诉make执行这个动作(比如make clean命令)。
在重新编译一个目标文件之前,make考虑更新它的先决条件。
对于源文件和头文件,这个makefile不会为他们指定任何事情去做,因为.c和.h文件不是任何
规则的目标。所以make不会为这些文件做任何事情。
但是make会自动更新产生的C程序,比如Bison或者Yacc此时按照自己的规则产生的C文件。
在重新编译任何一个它需要的目标文件,make决定是否重新链接edit。
如果edit不存在,或者任何一个目标文件比它新,那么这个动作必须执行。
如果一个目标文件刚刚被重新编译,它比edit新,那么edit被重新编译。
因此,如果改变文件insert.c,并且运行make,make将会编译那个文件去更新insert.o,
然后链接edit。
如果我们改变了文件command.h,并且运行make,mek将会重新编译目标文件kbd.o,command.o
以及files.o,然后连接edit文件。
在我们的例子中,我们必须在edit的规则中列出所有的目标文件两次(如下)
edit : main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
这种重复是易错的。如果新的目标文件增加到系统中,我们可能将其增加到一个列表中,
但是忘记了其他的列表。
我们可以使用一个变量来排除这种风险并且简化makefile。
变量允许一个文本字符串被定义一次,但是后来可以在多个地方被替代多次。
每个makefile拥有一个叫做objects,OBJECTS,objs,OBJS,obj,或者OBJ,来表示
所有目标文件名称列表,这已经成为了一个标准实践。
我们会在makefile中在一行中定义这样一个目标文件。
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o
这样,每一个我们想放置目标文件名称列表的地方,我们都可以用$(objects)来代替。
这里是当你为目标文件使用变量的情况下如何完成简单的makefile的外貌。
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
...
没有必要去拼读出要编译单独的C源文件的处方,因为make可以理解他们。
有一个隐含的规则去更新一个.o文件,从一个相关的.c文件,当你使用cc -c的命令的时候。
例如,可以使用处方cc -c main.c -o main.o去编译main.c变成main.o。
我们可以因此忽略目标文件的处方。
当一个.c文件自动使用这个规则的时候,它也被自动增加到先决条件列表中。
我们可以因此从先决条件中忽略.c文件,如果我们忽略了处方。
这里是整个例子,综合了以上两个策略。
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
edit :
这个是我们在实际编程当中会编写的makefile。(clean引起的并发症在别处介绍)。
因为隐式规则是十分方便的,他们是重要的。所以你将会看到它们被频繁地使用。
当一个makefile的目标仅仅被隐式规则所创建,另一个可选的makefile风格可能出现。
在这种makefile风格中,你可以按照他们的先决条件而不是他们的目标将条目进行组合。
如下所示:
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
edit :
这里,defs.h作为所有目标文件的先决条件而给出。command.h和buffer.h是特定目标文件的先决条件。
这种方式是优是劣是一个口味问题。它是紧凑的,但是一些人不喜欢他们因为他们发现将
所有关于每个目标的所有信息放到一个地方很清晰。
MyPluginDemo.cpp
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
DWORD GetProcessId(LPCSTR lpszProcessName)
{
// 创建进程快照句柄
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
DWORD dwPid = NULL;
PROCESSENTRY32 ProcessEntry;
// 查找第一个进程
ProcessEntry.dwSize = sizeof(PROCESSENTRY32);
Process32First(hProcessSnap, &ProcessEntry);
// 遍历进程获取 PID
do
{
if(!stricmp(ProcessEntry.szExeFile, lpszProcessName))
{
dwPid = ProcessEntry.th32ProcessID;
break;
}
}
while(Process32Next(hProcessSnap, &ProcessEntry));
// 清理现场
if(!dwPid)
{
return false;
}
CloseHandle(hProcessSnap);
return dwPid;
}
int main(int argc, char ** argv)
{
// 线程栈大小
const DWORD dwThreadSize = 1024;
// 获取指定映像的 PID
DWORD dwProcessId = false;
dwProcessId = GetProcessId("VisionMaster.exe");
if (!dwProcessId){
return 0;
}
// 定义远程进程句柄并打开该进程
HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (!hRemoteProcess)
{
return 0;
}
LPVOID pFunc = LoadLibrary;
LPVOID pRemoteParam = VirtualAllocEx(hRemoteProcess, NULL, strlen("MyPlugin.dll") + 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pRemoteParam)
{
return 0;
}
BOOL bWrite = WriteProcessMemory(hRemoteProcess, (LPVOID)pRemoteParam, "MyPlugin.dll", strlen("MyPlugin.dll") + 1, 0);
if (!bWrite)
{
return 0;
}
HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, (LPTHREAD_START_ROUTINE)(pFunc), pRemoteParam, 0, NULL);
if (!hRemoteThread)
{
return 0;
}
getchar();
return 0;
}
MyPlugin.cpp
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <Windows.h>
HMODULE g_hModule = NULL;
void *(* zmq_ctx_new) (void) = NULL;
void (__stdcall * IMVS_SetMaxSeverity)(const unsigned int nMaxSeverity) = NULL;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
OutputDebugString("成功加载MyPlugin.dll");
g_hModule = LoadLibraryEx("./PublicFile/x86/iMVS-6000SDK4Server.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (NULL == g_hModule)
{
return FALSE;
}
IMVS_SetMaxSeverity = (void (__stdcall *)(const unsigned int))GetProcAddress(g_hModule,"IMVS_SetMaxSeverity");
if (NULL == IMVS_SetMaxSeverity)
{
return FALSE;
}
OutputDebugString("成功加载iMVS-6000SDK4Server.dll");
IMVS_SetMaxSeverity(0);
OutputDebugString("成功设置日志打印级别");
}
break;
case DLL_THREAD_ATTACH:
{
}
break;
case DLL_THREAD_DETACH:
{
}
break;
case DLL_PROCESS_DETACH:
{
}
break;
}
return TRUE;
}