6
0
mirror of https://github.com/JKornev/hidden synced 2024-06-25 00:18:04 +00:00

/install and /uninstall commands

This commit is contained in:
JKornev 2016-12-23 03:05:09 +03:00
parent 93ea859610
commit 4f3e364d72
10 changed files with 394 additions and 33 deletions

@ -138,7 +138,7 @@ NTSTATUS CfgEnumConfigsTable(enum CfgMultiStringTables Table, CfgMultiStringCall
buffer = table->Buffer; buffer = table->Buffer;
length = table->Length; length = table->Length;
while (length > 0) while (length > 1)
{ {
UNICODE_STRING entry; UNICODE_STRING entry;
ULONG inx, delta = 0; ULONG inx, delta = 0;

@ -25,11 +25,88 @@ void LoadCommandsStack(vector<CommandPtr>& stack)
// ================= // =================
SingleCommand::SingleCommand(Arguments& args) void ICommand::InstallCommand(RegistryKey& configKey)
{
throw WException(-2, L"Error, install mode is not supported");
}
void ICommand::UninstallCommand(RegistryKey& configKey)
{
}
// =================
CommandMode::CommandMode(Arguments& args) : m_type(CommandModeType::Execute)
{
wstring mode, all;
if (!args.Probe(mode))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
if (mode == L"/install")
{
args.SwitchToNext();
m_type = CommandModeType::Install;
LoadConfigPath(args);
}
else if (mode == L"/uninstall")
{
args.SwitchToNext();
m_type = CommandModeType::Uninstall;
LoadConfigPath(args);
}
if (m_type == CommandModeType::Uninstall)
{
if (!args.Probe(all) || all != L"all")
throw WException(-2, L"Error, invalid '/unistall' format");
args.SwitchToNext();
}
}
void CommandMode::LoadConfigPath(Arguments& args)
{
wstring path;
if (!args.Probe(path) || path.compare(0, 1, L"/") == 0 || path == L"all")
{
m_regConfigPath = L"System\\CurrentControlSet\\Services\\Hidden";
return;
}
args.SwitchToNext();
m_regConfigPath = L"System\\CurrentControlSet\\Services\\";
m_regConfigPath += path;
}
CommandModeType CommandMode::GetModeType()
{
return m_type;
}
const wstring& CommandMode::GetConfigRegistryKeyPath()
{
return m_regConfigPath;
}
// =================
SingleCommand::SingleCommand(Arguments& args, CommandModeType mode)
{ {
wstring arg; wstring arg;
bool found = false; bool found = false;
if (mode == CommandModeType::Uninstall)
{
if (args.SwitchToNext())
throw WException(-2, L"Error, too many arguments");
LoadCommandsStack(m_commandsStack);
return;
}
if (!args.GetNext(arg)) if (!args.GetNext(arg))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'"); throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
@ -62,12 +139,26 @@ void SingleCommand::Perform(Connection& connection)
m_current->PerformCommand(connection); m_current->PerformCommand(connection);
} }
void SingleCommand::Install(RegistryKey& configKey)
{
m_current->InstallCommand(configKey);
}
void SingleCommand::Uninstall(RegistryKey& configKey)
{
for (auto it = m_commandsStack.begin(); it != m_commandsStack.end(); it++)
(*it)->UninstallCommand(configKey);
}
// ================= // =================
MultipleCommands::MultipleCommands(Arguments& args) MultipleCommands::MultipleCommands(Arguments& args, CommandModeType mode)
{ {
wstring arg; wstring arg;
if (mode == CommandModeType::Uninstall)
throw WException(-2, L"Error, /uninstall can't be combined with /multi");
if (!args.GetNext(arg)) if (!args.GetNext(arg))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'"); throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
@ -105,6 +196,17 @@ void MultipleCommands::Perform(Connection& connection)
(*it)->PerformCommand(connection); (*it)->PerformCommand(connection);
} }
void MultipleCommands::Install(RegistryKey& configKey)
{
for (auto it = m_currentStack.begin(); it != m_currentStack.end(); it++)
(*it)->InstallCommand(configKey);
}
void MultipleCommands::Uninstall(RegistryKey& configKey)
{
throw WException(-2, L"Error, uninstall mode is not supported");
}
// ================= // =================
class ArgsParser class ArgsParser
@ -157,22 +259,25 @@ public:
}; };
MultipleCommandsFromFile::MultipleCommandsFromFile(Arguments& args) MultipleCommandsFromFile::MultipleCommandsFromFile(Arguments& args, CommandModeType mode)
{ {
wstring configFile; wstring configFile;
if (mode == CommandModeType::Uninstall)
throw WException(-2, L"Error, /uninstall can't be combined with /config");
if (!args.GetNext(configFile)) if (!args.GetNext(configFile))
throw WException(-2, L"Error, no command, please use 'hiddencli /help'"); throw WException(-2, L"Error, no command, please use 'hiddencli /help'");
if (args.SwitchToNext()) if (args.SwitchToNext())
throw WException(-2, L"Error, too many arguments"); throw WException(-2, L"Error, too many arguments");
wifstream config(configFile); wifstream fconfig(configFile);
wstring line; wstring line;
LoadCommandsStack(m_commandsStack); LoadCommandsStack(m_commandsStack);
while (getline(config, line)) while (getline(fconfig, line))
{ {
ArgsParser parser(line); ArgsParser parser(line);
wstring arg; wstring arg;
@ -218,3 +323,13 @@ void MultipleCommandsFromFile::Perform(Connection& connection)
(*it)->PerformCommand(connection); (*it)->PerformCommand(connection);
} }
void MultipleCommandsFromFile::Install(RegistryKey& configKey)
{
for (auto it = m_currentStack.begin(); it != m_currentStack.end(); it++)
(*it)->InstallCommand(configKey);
}
void MultipleCommandsFromFile::Uninstall(RegistryKey& configKey)
{
throw WException(-2, L"Error, uninstall mode is not supported");
}

@ -14,56 +14,86 @@ public:
virtual bool CompareCommand(std::wstring& command) = 0; virtual bool CompareCommand(std::wstring& command) = 0;
virtual void LoadArgs(Arguments& args) = 0; virtual void LoadArgs(Arguments& args) = 0;
virtual void PerformCommand(Connection& connection) = 0; virtual void PerformCommand(Connection& connection) = 0;
virtual void InstallCommand(RegistryKey& configKey);
virtual void UninstallCommand(RegistryKey& configKey);
virtual CommandPtrInternal CreateInstance() = 0; virtual CommandPtrInternal CreateInstance() = 0;
}; };
typedef ICommand::CommandPtrInternal CommandPtr; typedef ICommand::CommandPtrInternal CommandPtr;
class ICommandMode enum CommandModeType {
{ Execute,
public: Install,
virtual ~ICommandMode() {} Uninstall
virtual void Perform(Connection& connection) = 0;
}; };
typedef std::shared_ptr<ICommandMode> CommandModePtr; class CommandMode
{
std::wstring m_regConfigPath;
CommandModeType m_type;
class SingleCommand : public ICommandMode void LoadConfigPath(Arguments& args);
public:
CommandMode(Arguments& args);
CommandModeType GetModeType();
const std::wstring& GetConfigRegistryKeyPath();
};
class ICommandTemplate
{
public:
virtual ~ICommandTemplate() {}
virtual void Perform(Connection& connection) = 0;
virtual void Install(RegistryKey& configKey) = 0;
virtual void Uninstall(RegistryKey& configKey) = 0;
};
typedef std::shared_ptr<ICommandTemplate> CommandTemplatePtr;
class SingleCommand : public ICommandTemplate
{ {
std::vector<CommandPtr> m_commandsStack; std::vector<CommandPtr> m_commandsStack;
CommandPtr m_current; CommandPtr m_current;
public: public:
SingleCommand(Arguments& args); SingleCommand(Arguments& args, CommandModeType mode);
virtual ~SingleCommand(); virtual ~SingleCommand();
virtual void Perform(Connection& connection); virtual void Perform(Connection& connection);
virtual void Install(RegistryKey& configKey);
virtual void Uninstall(RegistryKey& configKey);
}; };
class MultipleCommands : public ICommandMode class MultipleCommands : public ICommandTemplate
{ {
std::vector<CommandPtr> m_commandsStack; std::vector<CommandPtr> m_commandsStack;
std::vector<CommandPtr> m_currentStack; std::vector<CommandPtr> m_currentStack;
public: public:
MultipleCommands(Arguments& args); MultipleCommands(Arguments& args, CommandModeType mode);
virtual ~MultipleCommands(); virtual ~MultipleCommands();
virtual void Perform(Connection& connection); virtual void Perform(Connection& connection);
virtual void Install(RegistryKey& configKey);
virtual void Uninstall(RegistryKey& configKey);
}; };
class MultipleCommandsFromFile : public ICommandMode class MultipleCommandsFromFile : public ICommandTemplate
{ {
std::vector<CommandPtr> m_commandsStack; std::vector<CommandPtr> m_commandsStack;
std::vector<CommandPtr> m_currentStack; std::vector<CommandPtr> m_currentStack;
public: public:
MultipleCommandsFromFile(Arguments& args); MultipleCommandsFromFile(Arguments& args, CommandModeType mode);
virtual ~MultipleCommandsFromFile(); virtual ~MultipleCommandsFromFile();
virtual void Perform(Connection& connection); virtual void Perform(Connection& connection);
virtual void Install(RegistryKey& configKey);
virtual void Uninstall(RegistryKey& configKey);
}; };

@ -1,7 +1,10 @@
#include "helper.h" #include "helper.h"
#include <memory>
using namespace std; using namespace std;
// =================
WException::WException(unsigned int Code, wchar_t* Format, ...) : WException::WException(unsigned int Code, wchar_t* Format, ...) :
m_errorCode(Code) m_errorCode(Code)
{ {
@ -25,6 +28,8 @@ unsigned int WException::Code()
return m_errorCode; return m_errorCode;
} }
// =================
Arguments::Arguments(int argc, wchar_t* argv[], int start) : Arguments::Arguments(int argc, wchar_t* argv[], int start) :
m_argPointer(0) m_argPointer(0)
{ {
@ -64,6 +69,8 @@ bool Arguments::GetNext(wstring& arg)
return true; return true;
} }
// =================
Handle::Handle(HANDLE handle) : Handle::Handle(HANDLE handle) :
m_handle(handle), m_handle(handle),
m_error(::GetLastError()) m_error(::GetLastError())
@ -86,6 +93,146 @@ DWORD Handle::Error()
return m_error; return m_error;
} }
// =================
RegistryKey::RegistryKey(std::wstring regKey) : m_hkey(NULL)
{
LONG status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, regKey.c_str(), 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &m_hkey);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't open registry key");
}
RegistryKey::~RegistryKey()
{
RegCloseKey(m_hkey);
}
void RegistryKey::SetDwordValue(const wchar_t* name, DWORD value)
{
LONG status;
status = RegSetValueExW(m_hkey, name, NULL, REG_DWORD, (LPBYTE)&value, sizeof(value));
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't set registry value");
}
DWORD RegistryKey::GetDwordValue(const wchar_t* name, DWORD defValue)
{
DWORD value, size = sizeof(value), type = REG_DWORD;
LONG status;
status = RegQueryValueEx(m_hkey, name, NULL, &type, (LPBYTE)&value, &size);
if (status != ERROR_SUCCESS)
{
if (status != ERROR_FILE_NOT_FOUND)
throw WException(status, L"Error, can't query registry value");
return defValue;
}
return value;
}
void RegistryKey::SetMultiStrValue(const wchar_t* name, const std::vector<std::wstring>& strs)
{
DWORD size = 0, offset = 0;
shared_ptr<BYTE> buffer;
LONG status;
for (auto it = strs.begin(); it != strs.end(); it++)
{
if (it->size() > 0)
size += (it->size() + 1) * sizeof(wchar_t);
}
if (size == 0)
{
WCHAR value = 0;
status = RegSetValueExW(m_hkey, name, NULL, REG_MULTI_SZ, (LPBYTE)&value, 2);
if(status != ERROR_SUCCESS)
throw WException(status, L"Error, can't set registry value");
return;
}
buffer.reset(new BYTE[size]);
memset(buffer.get(), 0, size);
for (auto it = strs.begin(); it != strs.end(); it++)
{
if (it->size() == 0)
continue;
DWORD strSize = (it->size() + 1) * sizeof(wchar_t);
memcpy(buffer.get() + offset, it->c_str(), strSize);
offset += strSize;
}
status = RegSetValueExW(m_hkey, name, NULL, REG_MULTI_SZ, buffer.get(), size);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't set registry value");
}
void RegistryKey::GetMultiStrValue(const wchar_t* name, std::vector<std::wstring>& strs)
{
DWORD size = 0, type = REG_MULTI_SZ;
shared_ptr<BYTE> buffer;
LPWSTR bufferPtr;
LONG status;
strs.clear();
status = RegQueryValueEx(m_hkey, name, NULL, &type, NULL, &size);
if (status != ERROR_SUCCESS)
{
if (status != ERROR_FILE_NOT_FOUND)
throw WException(status, L"Error, can't query registry value");
return;
}
if (size == 0)
return;
buffer.reset(new BYTE[size + sizeof(WCHAR)]);
memset(buffer.get(), 0, size + sizeof(WCHAR));
status = RegQueryValueEx(m_hkey, name, NULL, &type, buffer.get(), &size);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't query registry value");
bufferPtr = (LPWSTR)buffer.get();
while (size > 1)
{
ULONG inx, delta = 0;
ULONG len = size / sizeof(WCHAR);
for (inx = 0; inx < len; inx++)
{
if (bufferPtr[inx] == L'\0')
{
delta = 1;
break;
}
}
if (inx > 0)
strs.push_back(bufferPtr);
size -= (inx + delta) * sizeof(WCHAR);
bufferPtr += (inx + delta);
}
}
void RegistryKey::RemoveValue(const wchar_t* name)
{
LONG status = RegDeleteKeyValue(m_hkey, NULL, name);
if (status != ERROR_SUCCESS)
throw WException(status, L"Error, can't delete registry value");
}
// =================
HidRegRootTypes GetRegType(wstring& path) HidRegRootTypes GetRegType(wstring& path)
{ {
static wchar_t regHKLM[] = L"HKLM\\"; static wchar_t regHKLM[] = L"HKLM\\";

@ -53,6 +53,26 @@ public:
}; };
class RegistryKey
{
private:
HKEY m_hkey;
public:
RegistryKey(std::wstring regKey);
~RegistryKey();
void SetDwordValue(const wchar_t* name, DWORD value);
DWORD GetDwordValue(const wchar_t* name, DWORD defValue);
void SetMultiStrValue(const wchar_t* name, const std::vector<std::wstring>& strs);
void GetMultiStrValue(const wchar_t* name, std::vector<std::wstring>& strs);
void RemoveValue(const wchar_t* name);
};
enum EObjTypes { enum EObjTypes {
TypeFile, TypeFile,
TypeDir, TypeDir,

@ -32,6 +32,10 @@ bool PrintUsage(Arguments& args)
L" parameter is used for set valid registry path if driver name is changed, by\n" L" parameter is used for set valid registry path if driver name is changed, by\n"
L" default \"hidden\"\n" L" default \"hidden\"\n"
L"\n" L"\n"
L" /uninstall [%driver%] all\n"
L" Uninstall all configs from registry. This flag is all-sufficient therefore\n"
L" if this flag is set no other parameters and commands should be set after\n"
L"\n"
L"connection:\n" L"connection:\n"
L"\n" L"\n"
L" /gate <%name%>\n" L" /gate <%name%>\n"
@ -45,7 +49,7 @@ bool PrintUsage(Arguments& args)
L" Enable multiple commands per execution, just type commands one by one\n" L" Enable multiple commands per execution, just type commands one by one\n"
L" without any separator\n" L" without any separator\n"
L"\n" L"\n"
L" /config\n" L" /config <%path%>\n"
L" Loads multiple commands from file, each command should be on separate line\n" L" Loads multiple commands from file, each command should be on separate line\n"
L"\n" L"\n"
L"commands:\n" L"commands:\n"
@ -107,25 +111,28 @@ bool PrintUsage(Arguments& args)
return true; return true;
} }
CommandModePtr LoadCommands(Arguments& args) CommandTemplatePtr LoadCommandsTemplate(Arguments& args, CommandMode& mode)
{ {
wstring command; wstring templateType;
if (!args.Probe(command)) if (mode.GetModeType() == CommandModeType::Uninstall)
throw WException(-2, L"Error, unknown mode, please use 'hiddencli /help'"); return CommandTemplatePtr(new SingleCommand(args, mode.GetModeType()));
if (command == L"/multi") if (!args.Probe(templateType))
throw WException(-2, L"Error, unknown perform mode, please use 'hiddencli /help'");
if (templateType == L"/multi")
{ {
args.SwitchToNext(); args.SwitchToNext();
return CommandModePtr(new MultipleCommands(args)); return CommandTemplatePtr(new MultipleCommands(args, mode.GetModeType()));
} }
else if (command == L"/config") else if (templateType == L"/config")
{ {
args.SwitchToNext(); args.SwitchToNext();
return CommandModePtr(new MultipleCommandsFromFile(args)); return CommandTemplatePtr(new MultipleCommandsFromFile(args, mode.GetModeType()));
} }
return CommandModePtr(new SingleCommand(args)); return CommandTemplatePtr(new SingleCommand(args, mode.GetModeType()));
} }
int wmain(int argc, wchar_t* argv[]) int wmain(int argc, wchar_t* argv[])
@ -146,9 +153,24 @@ int wmain(int argc, wchar_t* argv[])
return 0; return 0;
{ {
CommandModePtr commands = LoadCommands(arguments); CommandMode mode(arguments);
connection.Open(); CommandTemplatePtr commands = LoadCommandsTemplate(arguments, mode);
commands->Perform(connection);
if (mode.GetModeType() == CommandModeType::Execute)
{
connection.Open();
commands->Perform(connection);
}
else if (mode.GetModeType() == CommandModeType::Install)
{
RegistryKey key(mode.GetConfigRegistryKeyPath());
commands->Install(key);
}
else if (mode.GetModeType() == CommandModeType::Uninstall)
{
RegistryKey key(mode.GetConfigRegistryKeyPath());
commands->Uninstall(key);
}
} }
} }
catch (WException& exception) catch (WException& exception)

@ -43,6 +43,20 @@ void CommandState::PerformCommand(Connection& connection)
wcout << L"status:ok" << endl; wcout << L"status:ok" << endl;
} }
void CommandState::InstallCommand(RegistryKey& configKey)
{
configKey.SetDwordValue(L"Hid_State", (m_state ? 1 : 0));
wcerr << L"Install 'state' successful" << endl;
wcout << L"status:ok" << endl;
}
void CommandState::UninstallCommand(RegistryKey& configKey)
{
configKey.RemoveValue(L"Hid_State");
wcerr << L"Uninstall 'state' successful" << endl;
wcout << L"status:ok" << endl;
}
CommandPtr CommandState::CreateInstance() CommandPtr CommandState::CreateInstance()
{ {
return CommandPtr(new CommandState()); return CommandPtr(new CommandState());

@ -16,6 +16,8 @@ public:
virtual bool CompareCommand(std::wstring& command); virtual bool CompareCommand(std::wstring& command);
virtual void LoadArgs(Arguments& args); virtual void LoadArgs(Arguments& args);
virtual void PerformCommand(Connection& connection); virtual void PerformCommand(Connection& connection);
virtual void InstallCommand(RegistryKey& configKey);
virtual void UninstallCommand(RegistryKey& configKey);
virtual CommandPtr CreateInstance(); virtual CommandPtr CreateInstance();
}; };

@ -11,10 +11,14 @@ mode:
connection parameters shouldn't be set. Optional parameter is used for set valid registry path if connection parameters shouldn't be set. Optional parameter is used for set valid registry path if
driver name is changed, by default "hidden" driver name is changed, by default "hidden"
/uninstall [%driver%]
Uninstall all configs from registry. This flag is all-sufficient therefore if this flag is set
no other parameters and commands should be set after
connection: connection:
/gate <%name%> /gate <%name%>
Set specific connection gate name (driver device name) Set specific connection gate name (driver device name)
perform: perform:
@ -23,7 +27,7 @@ perform:
/multi /multi
Enable multiple commands per execution, just type commands one by one without any separator Enable multiple commands per execution, just type commands one by one without any separator
/config /config <%path%>
Loads multiple commands from file, each command should be on separate line Loads multiple commands from file, each command should be on separate line
commands: commands:

@ -5,6 +5,13 @@
; Enable driver if it's disabled ; Enable driver if it's disabled
/state on /state on
; Cleanup configs
/unhide file all
/unhide dir all
/unhide regval all
/unhide regkey all
; Following config used for hidding VMWare components ; Following config used for hidding VMWare components
/hide dir "c:\Program Files\VMware" /hide dir "c:\Program Files\VMware"