有些模块经常用,很简单,但是反反复复写,最终下决定维护一个通用的模块库。
基于 minhook 和 EasyHook 实现的远程注入,少许代码可以实现钩子程序。
MinHook.x64.dll & MinHook.x86.dll
E:\kSource\pythonx\note\bin>kinjector.exe --help
-i, -I, --pid=PID Target process Id
-n, -N, --pname=PNAME Target process Name
-k, -K, --hook=DLL Hook DLL
-p, -P, --pause Exit pause
-h, -H, --help Shows the command help
typedef int (__stdcall *LPFN_ToyEntryPoint)(void*);
assert(GetModuleHandleW(libPath) == hDLL);
std::string fname = "ToyEntryPoint";
LPFN_ToyEntryPoint fptr = (LPFN_ToyEntryPoint)GetProcAddress(hDLL, fname.c_str());
if (!fptr) {
fname = "_ToyEntryPoint@4";
fptr = (LPFN_ToyEntryPoint)GetProcAddress(hDLL, fname.c_str());
}
#define DLL_API extern "C" __declspec(dllexport)
DLL_API int __stdcall ToyEntryPoint(void* inRemoteInfo);
int __stdcall ToyEntryPoint(void*) {
mainfunc();
return 7;
}
Windows 共享内存,跨进程内存读写,同步机制。
TestFileLock.zip 共享内存,同步机制 http://www.cnblogs.com/dongsheng/p/4460944.html http://blog.chinaunix.net/uid-26833883-id-3230564.html https://blog.csdn.net/shuilan0066/article/details/87979315
Windows 下进程的地址空间在逻辑上是相互隔离的,但在物理上却是重叠的。所谓的重叠是指同一块内存区域可能被多个进程同时使用。 共享内存,各个进程可以共享同一块物理内存,进程可以直接读写内存,不需要数据拷贝。 由于多个进程共享一块内存,所以也需要同步机制。
完整代码:github.com/hawkhai/ShareMemory.git 共享内存,写入只要不释放,就可以实现跨进程读取,避免文件内容落地。 写入的函数负责共享内存块的创建。 这样,同一块内存块被映射到了不同的进程空间,从而达到多个进程共享同一个内存块的目的。
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <assert.h>
#include "../ShareMemoryDll/ShareMemoryDll.h"
using namespace ShareMemoryDll;
#define SHARE_MEMORY_NAME L"SHARE_MEMORY_TEST"
#define SHARE_MEMORY_SIZE (1024*1024) // 1MB
void testread() {
ShareMemoryRead sharememory(SHARE_MEMORY_NAME);
if (!sharememory.check()) {
return;
}
CShareMemoryCallback callback;
ShareMemoryData* data = nullptr;
int datasize = 0;
if ((datasize = sharememory.read(data, &callback)) >= 1) {
TestData* testData = (TestData*)&data[0];
}
if (data) {
callback.free(data);
}
}
void testwrite() {
ShareMemoryWrite sharememory(SHARE_MEMORY_NAME, SHARE_MEMORY_SIZE);
if (!sharememory.check()) {
return;
}
TestData testData(true);
sharememory.write((ShareMemoryData*)&testData, sizeof(testData));
}
如果要实现动态长度,用两个 sharememory 实现即可。
这个区分服务端和客户端。
m_svrMgr = new KPipeSvrMgr(); m_pPipeSvr = m_svrMgr->CreatePipeSvr(); m_svrMgr->ReleasePipeSvr(m_pPipeSvr);
m_pPipeSvr->SetMsgProcessor(this); m_pPipeSvr->Start(GetChildSvrPipeName(GetCurrentProcessId()).GetString());
E:\kpdf\pdfreader_master\image\pipe\fastimagePipe.h
验证 收工 remotecall 实现 klauncher。 全部采用 md 源码模式。
崩溃收集。 升级实现。
kpipe 的进一步封装,包含握手过程,从而实现相互调用,简单到 爆 。
客户端:
#include <iostream>
#include <assert.h>
#include "../remotelib/myremote.h"
#include "../../vld/include/vld.h"
class ClientCallback : public IRmtCallPipeCallback {
// 线程回调。
virtual bool OnProcess(int func, const nlohmann::json& argv, nlohmann::json& retv) override {
printf("ClientCallback");
return true;
}
};
int main()
{
ClientCallback callback;
MyPipeRemoteServ myServ(callback);
// 启动子进程。
std::string gexe = GenerateExeName("remotetarget");
myServ.StartClient(true, gexe.c_str());
system("pause");
nlohmann::json data, result;
// 调用子进程函数。
CHECK_RETV_ASSERT(myServ.CallClientFunction(1, data, result));
return 0;
}
服务端:
#include <iostream>
#include <assert.h>
#include <string>
#include "../remotelib/myremote.h"
#include "../../vld/include/vld.h"
class ServCallback : public IRmtCallPipeCallback {
virtual bool OnProcess(int func, const nlohmann::json& argv, nlohmann::json& retv) override {
printf("ServCallback");
return true;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL, "chs");
ServCallback callback;
MyPipeRemoteClient myClient(argc, argv, callback);
nlohmann::json data, result;
// 调用父进程函数。
CHECK_RETV_ASSERT(myClient.CallServFunction(1, data, result));
system("pause");
return 0;
}
#pragma once
#include <assert.h>
#include <windows.h>
#include <string>
#ifdef KDLL_EXPORTS
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
#define KDLL_ERSION 1
__interface IDllInterface {
virtual int Version() = 0;
virtual int Release() = 0;
virtual int GetDocumentPageCount() = 0;
};
#ifdef __cplusplus
extern "C" {
#endif
DLLEXPORT IDllInterface* CreateEntry();
#ifdef __cplusplus
}
#endif
class KDllWrap : public IDllInterface {
static std::wstring getCurrentDir() {
wchar_t tpath[MAX_PATH] = { 0 };
DWORD dwRet = GetModuleFileNameW(NULL, tpath, MAX_PATH);
if (dwRet == 0) {
return L".\\";
}
std::wstring strexe = tpath;
int index = strexe.rfind(L'\\');
if (index <= 0) {
return L".\\";
}
return strexe.substr(0, index + 1);
}
static HINSTANCE loadLibrary(const wchar_t* libPath) {
std::wstring curdir = getCurrentDir();
if (curdir.empty()) {
return NULL;
}
std::wstring current = curdir;
current.append(libPath);
wchar_t lpBuffer[MAX_PATH];
GetCurrentDirectory(MAX_PATH, lpBuffer);
SetCurrentDirectory(curdir.c_str());
HINSTANCE hDLL = LoadLibrary(current.c_str());
SetCurrentDirectory(lpBuffer);
if (hDLL == NULL) {
int err = GetLastError();
assert(false);
return NULL;
}
return hDLL;
}
public:
virtual int Version() override {
if (!m_interface) {
return -1;
}
return m_interface->Version();
}
virtual int Release() override {
if (!m_interface) {
return -1;
}
auto retv = m_interface->Release();
m_interface = nullptr;
return retv;
}
virtual int GetDocumentPageCount() override {
if (!m_interface) {
return -1;
}
return m_interface->GetDocumentPageCount();
}
KDllWrap() {
const wchar_t* libPath = L"kdll.dll";
m_hDLL = loadLibrary(libPath);
if (m_hDLL == nullptr) {
int err = GetLastError();
assert(false);
return;
}
typedef IDllInterface* (*CreateEntryFunc)();
CreateEntryFunc fptr = (CreateEntryFunc)GetProcAddress(m_hDLL, "CreateEntry");
if (fptr == nullptr) {
int err = GetLastError();
assert(false);
return;
}
m_interface = fptr();
if (m_interface->Version() < KDLL_ERSION) {
m_interface->Release();
m_interface = nullptr;
assert(false);
}
}
virtual ~KDllWrap() {
if (!m_interface) {
return;
}
m_interface->Release();
m_interface = nullptr;
// m_hDLL 不释放了。
}
private:
IDllInterface* m_interface = nullptr;
HINSTANCE m_hDLL = nullptr;
};
#include "pch.h"
#include "kdll.h"
class KDllInstance : public IDllInterface {
public:
virtual int Version() override {
return KDLL_ERSION;
}
virtual int Release() override {
delete this;
return 0;
}
virtual int GetDocumentPageCount() override {
return 7;
}
};
IDllInterface* CreateEntry() {
return new KDllInstance();
}
pyinstaller 打包绿色软件,每次解压启动慢,如果 进程意外退出,还会残留。
实现一个启动器:kinstaller.exe 把散文件压进去,启动后自动解压运行。 解决 慢 和 残留 的痛点。
协议:
{
"files": {
"vcruntime140.dll": {
"fmtime": "2021-08-15 00:10:39",
"fsize": 89752,
"fzsize": 49318,
"keyname": "VCRUNTIME140_DLL",
"md5": "0e675d4a7a5b7ccd69013386793f68eb",
"md5z": "2c7b372ef359df97c913c3541d688b8a",
"petype": "x64",
"runfile": "pyenv\\vcxmake_win10x64\\{version}\\vcruntime140.dll",
"zipfile": "tempdir\\vcxmake\\vcruntime140_dll\\0e675d4a7a5b7ccd.zip"
},
"vcxmake.exe": {
"fmtime": "2021-08-15 00:06:35",
"fsize": 4185505,
"fzsize": 4037468,
"keyname": "VCXMAKE_EXE",
"md5": "0dcbac1ed863c113469ccca3796eb963",
"md5z": "fdd8d22c6c570a0060176dd89864b5ab",
"petype": "x64",
"runfile": "pyenv\\vcxmake_win10x64\\{version}\\vcxmake.exe",
"zipfile": "tempdir\\vcxmake\\vcxmake_exe\\0dcbac1ed863c113.zip"
},
"vcxmake.exe.manifest": {
"fmtime": "2022-01-13 09:30:41",
"fsize": 1032,
"fzsize": 672,
"keyname": "VCXMAKE_EXE_MANIFEST",
"md5": "c796b662fb2bbc734698609b6cb7f3f5",
"md5z": "8ae49632d1c27323c992ca36032967de",
"petype": "",
"runfile": "pyenv\\vcxmake_win10x64\\{version}\\vcxmake.exe.manifest",
"zipfile": "tempdir\\vcxmake\\vcxmake_exe_manifest\\c796b662fb2bbc73.zip"
},
"win32api.pyd": {
"fmtime": "2021-08-15 00:09:18",
"fsize": 132608,
"fzsize": 51325,
"keyname": "WIN32API_PYD",
"md5": "511367f74dd035502f2dc895b6a752e7",
"md5z": "26acb327f3fcd627bf06efef99025762",
"petype": "x64",
"runfile": "pyenv\\vcxmake_win10x64\\{version}\\win32api.pyd",
"zipfile": "tempdir\\vcxmake\\win32api_pyd\\511367f74dd03550.zip"
}
},
"genrestime": 1682256363,
"petype": "x64",
"version": "v2",
"zloader": "pyenv\\vcxmake_win10x64\\{version}\\vcxmake.exe"
}
upcode idxcode
上传当前 pythonx 代码。downcode
下载当前 pythonx 代码。upload image_ksample.json symlink
上传图片。download image_ksample.json
下载图片。dlindex image_ksample.json
下载索引。upindex image_ksample.json
上传索引。