Хорошо, давайте вернемся немного назад, и я объясню, что происходит.
Я сейчас переношу все скрипты, которые мы используем для учетных записей и тому подобное, из UMRA (что идет по пути Dodo) в PowerShell. Мне нужно было найти способ фиксировать изменения паролей, чтобы их можно было синхронизировать с другими системами, и я был рад, когда узнал, что могу написать свою собственную DLL-библиотеку фильтра паролей, чтобы добиться этой цели.
Я поигрался с несколькими языками программирования, и я уверен, что C++ где-то там был, поэтому, хотя прошло лет с тех пор, как я работал с C++, я решил, что , с небольшой помощью Google я смогу написать что-то, что запускает сценарий PowerShell, который позаботится обо всем остальном.
Когда я искал лучший способ запуска PowerShell скрипт, я нашел команду system(). Выглядит достаточно просто. Я вижу, что требуется символьная строка, а DLL получает PUNICODE_STRING, но преобразовать одну строку в другую не должно быть проблемой... верно?
Поэтому я решил Начнем с очень простой DLL, которая просто передает все, что получает, простому сценарию PowerShell в качестве аргументов командной строки (что я протестировал с помощью CMD, чтобы убедиться, что это работает). Затем, как только это заработает, я планирую добавить реальную фильтрацию паролей и, возможно, шифрование пароля (на случай, если где-то записана команда system()) перед передачей его в PS.
Это было 2 недели назад, и я даже не могу понять, как перевести PUNICODE_STRING в тип char, который ожидает system(). А я столько всего перепробовал, что все и не упомню. Вчера я потратил некоторое время на повторную попытку некоторых из тех, что смог вспомнить, чтобы задокументировать их здесь.
Я работаю в Visual Studio 2022 на Windows Server 2016.
Я работаю в Visual Studio 2022 на Windows Server 2016.
p>
В первом примере кода я показал весь код, но в последующих примерах я закомментировал DllMain, InitializeChangeNotify и PasswordFilter, чтобы сэкономить место в этом посте.
Я также хотел бы отметить, что я еще ничего не пробовал компилировать, я пытаюсь довести код до момента, когда отладчик будет доволен первым. Поэтому я включил ошибки отладчика в виде комментариев к строке, которая их вызвала.
Хорошо, моей первой попыткой было упаковать весь текст и переменные в команду system()... но это не сработало, поэтому я начал пытаться создать переменную char, которую можно было бы передать в system().
Код: Выделить всё
#include "pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
BOOLEAN __stdcall InitializeChangeNotify(void)
{
return TRUE;
}
NTSTATUS __stdcall PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId, PUNICODE_STRING NewPassword)
{
char PSCommand[] = "start powershell.exe SD60PWS.ps1 -Section 'ChangeNotify' -UserName ";
strcat(PSCommand, UserName); //Error - argument of type "PUNICODE_STRING" is incompatible with parameter of type "const char *"
//strcat(PSCommand, " -RelativeId ");
//strcat(PSCommand, RelativeId);
//strcat(PSCommand, " -NewPassword ");
//strcat(PSCommand, NewPassword);
system(PSCommand);
return 0;
}
BOOLEAN __stdcall PasswordFilter(PUNICODE_STRING AccountName, PUNICODE_STRING FullName, PUNICODE_STRING Password, BOOLEAN SetOperation)
{
return 1;
}
Код: Выделить всё
#include "pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
//DllMain and InitializeChangeNotify
NTSTATUS __stdcall PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId, PUNICODE_STRING NewPassword)
{
ANSI_STRING ConvUserName;
RtlUnicodeStringToAnsiString(&ConvUserName, UserName, TRUE);
//Note: the example I found had an & in front of both variables, but the debugger didn't like that
// So I took them both away, and it didn't like that either. But the debugger was OK with this.
char PSCommand[] = "start powershell.exe SD60PWS.ps1 -Section 'ChangeNotify' -UserName ";
strcat(PSCommand, ConvUserName); //Error - no suitable conversion function from "ANSI_STRING" to "const char *"
//strcat(PSCommand, " -RelativeId ");
//strcat(PSCommand, RelativeId);
//strcat(PSCommand, " -NewPassword ");
//strcat(PSCommand, NewPassword);
system(PSCommand);
return 0;
}
//PasswordFilter
Одна вещь, которую я нашел в нем, и которую я подумал, что мне стоит попробовать, — это макросы преобразования ATL.
Код: Выделить всё
#include "pch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//DllMain and InitializeChangeNotify
NTSTATUS __stdcall PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId, PUNICODE_STRING NewPassword)
{
USES_CONVERSION;
using std::string;
string ConvUserName;
ConvUserName = W2CA(UserName); //Error - a value of type "PUNICODE_STRING" cannot be assigned to an entity of type "LPCWSTR"
char PSCommand[] = "start powershell.exe SD60PWS.ps1 -Section 'ChangeNotify' -UserName ";
strcat(PSCommand, ConvUserName); //Error - no suitable conversion function from "std::string" to "const char *" exists
//strcat(PSCommand, " -RelativeId ");
//strcat(PSCommand, RelativeId);
//strcat(PSCommand, " -NewPassword ");
//strcat(PSCommand, NewPassword);
system(PSCommand);
return 0;
}
//PasswordFilter
Код: Выделить всё
#include "pch.h"
#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace System; //Error - name must be a namespace name
//DllMain and InitializeChangeNotify
NTSTATUS __stdcall PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId, PUNICODE_STRING NewPassword)
{
size_t origsize = wcslen(UserName) + 1; //Error - argument of type "PUNICODE_STRING" is incompatible with parameter of type "const wchar_t *"
size_t convertedChars = 0;
char strConcat[] = " (char *)";
size_t strConcatsize = (strlen(strConcat) + 1) * 2;
const size_t newsize = origsize * 2;
char* ConvUserName = new char[newsize + strConcatsize];
wcstombs_s(&convertedChars, ConvUserName, newsize, UserName, _TRUNCATE); //Error - no instance of overloaded function "wcstombs_s" matches the argument list
_mbscat_s((unsigned char*)ConvUserName, newsize + strConcatsize, (unsigned char*)strConcat);
char PSCommand[] = "start powershell.exe SD60PWS.ps1 -Section 'ChangeNotify' -UserName ";
strcat(PSCommand, ConvUserName);
//strcat(PSCommand, " -RelativeId ");
//strcat(PSCommand, RelativeId);
//strcat(PSCommand, " -NewPassword ");
//strcat(PSCommand, NewPassword);
system(PSCommand);
return 0;
}
//PasswordFilter
Код: Выделить всё
#include "pch.h"
#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//DllMain and InitializeChangeNotify
NTSTATUS __stdcall PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId, PUNICODE_STRING NewPassword)
{
WriteToPowerShell("ChangeNotify", UserName, NewPassword); //Error - argument of type "PUNICODE_STRING" is incompatible with parameter of type "const char *"
return 0;
}
//PasswordFilter
void WriteToPowerShell(const char* PSSection, const char* PSUserName, const char* PSPassWord)
{
char PSCommand[] = "start powershell.exe SD60PWS.ps1 -Section ";
strcat(PSCommand, PSSection);
strcat(PSCommand, " -UserName ");
strcat(PSCommand, PSUserName);
strcat(PSCommand, " -NewPassword ");
strcat(PSCommand, PSPassWord);
system(PSCommand);
}
Надеюсь, кто-нибудь сможет помочь. . И я надеюсь, что все эти неудачи произошли не только потому, что я не знал, что мне нужно #include или использовать пространство имен that.Кроме того, если есть другой способ запустить сценарий PowerShell, принимающий PUNICODE_STRING, это тоже будет полезно.
Спасибо.
Подробнее здесь: https://stackoverflow.com/questions/783 ... ng-to-char
Мобильная версия