We are not able to set customized passwordFilter in windows 10 - c++

I created my own password filter.dll, but I am not able to set it into Windows system.
I appended it under LSA->Notificationpackage, and I copied into c:\Window\System32 as well.
In my password filter, at start I created the log file, but it is not creating it.
Please let me know is there are any more steps I need to perform to set my password filter in Windows 10.
Please find this snippet of my password filter:
#include <regex>
#include <fstream>
#include "Ntsecapi.h"
#define MAX_SIZE 4028
using namespace std;
using namespace std::tr1;
fstream writeLog;
BOOLEAN __stdcall InitializeChangeNotify(void)
{
wchar_t *pLogFile = L"c:\AmitPasswordFilter.log";
wchar_t aLogFileExp[64];
ExpandEnvironmentStrings(pLogFile, aLogFileExp, sizeof(aLogFileExp)/sizeof(wchar_t));
writeLog.open(aLogFileExp, ios::out|ios::app);
writeLog<<"InitializeChangeNotify"<<endl;
return TRUE;
}
BOOLEAN __stdcall PasswordFilter(PUNICODE_STRING AccountName, PUNICODE_STRING FullName, PUNICODE_STRING Password, BOOLEAN SetOperation)
{
writeLog<<"BabaPasswordFilter"<<endl;
writeLog<< "PasswordFilterAmit"<<endl;
wcmatch mr;
BOOL match = FALSE;
std::wstring seperator(L")(?=");
std::wstring regExp(L"(?=");
const int cathegories=4;
unsigned int aRegCondition[cathegories]={2,2,2,2};
for(int i=0;i<cathegories;i++)
{
for(int i=0;i<aRegCondition[0];i++)
regExp+=L".*\\d";
regExp+=seperator;
for(int i=0;i<aRegCondition[1];i++)
regExp+=L".*\\W";
regExp+=seperator;
for(int i=0;i<aRegCondition[2];i++)
regExp+=L".*[A-Z]";
regExp+=seperator;
for(int i=0;i<aRegCondition[3];i++)
regExp+=L".*[a-z]";
regExp+=L")(?![.\\n]).*$";// check for newline characters and end
wregex rx(regExp);
if (Password)
{
match = regex_search(Password->Buffer, mr, rx);
if (match)
{
match = TRUE;
writeLog<<"SumitPassword matches the complexity"<<endl;
}
else
{
match = FALSE;
writeLog<<"SumitPassword does not matche the complexity"<<endl;
}
}
else
{
writeLog<<"SumitPassword is NULL"<<endl;
}
return match;
}

Does your domain password policy, do you have "Passwords must meet complexity requirements" enabled? Per Microsoft's documentation on enabling a custom password filter, this policy needs to be enabled for the password filter to be applied (when we implemented our password filter five or so years ago, I confirmed the policy was required too).
If you've got the complexity policy enabled, run a remote debugging session against LSASS.EXE (in WinDBG, you need to close the debugging session with 'qd' {quit and detach} otherwise lsass.exe terminates unexpectedly and your computer is all sorts of messed up until it reboots).
I would recommend not putting anything under InitializeChangeNotify unless you have thorough exception handling. Exceptions occurring through this call can create wide-spread issues. My InitializeChangeNotify is simply a return true ... which is accurate since my filter has a separate service which applies the business logic to test password validity -- if my DLL is up enough to respond to InitializeChangeNotify, then it is up.
For reference, my PasswordFilter function:
extern "C" __declspec(dllexport) BOOLEAN __stdcall PasswordFilter(PUNICODE_STRING AccountName,
PUNICODE_STRING FullName,
PUNICODE_STRING Password,
BOOLEAN SetOperation) {
//build the account struct
PasswordFilterAccount *pfAccount = new PasswordFilterAccount();
pfAccount->AccountName = AccountName;
pfAccount->Password = Password;
//start an asynchronous thread to be able to kill the thread if it exceeds the timout
HANDLE pfHandle = (HANDLE)_beginthreadex(0, 0, CreateSocket, (LPVOID *)pfAccount, 0, 0);
// timeout is milliseconds. Is 30 seconds too long?
DWORD dWaitFor = WaitForSingleObject(pfHandle, 30000); //do not exceed the timeout.
if (dWaitFor == WAIT_TIMEOUT) {
//timeout exceeded
writeWindowsEventLog("Timeout exceeded", "OPF", "ERROR", 5);
}
else if (dWaitFor == WAIT_OBJECT_0) {
//here is where we want to be
}
else {
//WAIT_ABANDONED
//WAIT_FAILED
writeWindowsEventLog("WAIT abandoned or failed", "OPF", "ERROR", 5);
}
if (pfHandle != INVALID_HANDLE_VALUE && pfHandle != 0) {
if (CloseHandle(pfHandle)) {
pfHandle = INVALID_HANDLE_VALUE;
}
}
return bPasswordOk;
}

Related

Integrate Google Crashpad with Linux application

I'm trying to integrate Google's Crashpad into my application running on Ubuntu.
As per it's overview design
I create one handler process on ubuntu by following this link
Now for the client process, I should register it with the handler via a socket connection.
Linux/Android
On Linux, a registration is a connected socket pair between a client process and the Crashpad handler. This socket pair may be private or shared among many client processes.
How do I do that?
There is not much information available on internet related to crashpad. Can someone provide link to any working example
Unless you have a special use case that isn't listed here you shouldn't have to do anything with sockets manually. Just create a new instance of CrashpadClient at the entry point of your program and call StartHandler.
Here's a snippet from BugSplat's myUbuntuCrasher sample:
// Start crash handler
CrashpadClient *client = new CrashpadClient();
bool status = client->StartHandler(handler, reportsDir, metricsDir, url, annotations, arguments, true, false, attachments);
Here's the full example from main.cpp:
#include <stdio.h>
#include <unistd.h>
#include "client/crashpad_client.h"
#include "client/crash_report_database.h"
#include "client/settings.h"
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#if defined(OS_POSIX)
typedef std::string StringType;
#elif defined(OS_WIN)
typedef std::wstring StringType;
#endif
using namespace base;
using namespace crashpad;
using namespace std;
bool initializeCrashpad(void);
StringType getExecutableDir(void);
void crash(void);
int main(int argc, char **argv) {
initializeCrashpad();
crash();
}
void crash() {
*(volatile int *)0 = 0;
}
bool initializeCrashpad() {
// Get directory where the exe lives so we can pass a full path to handler, reportsDir and metricsDir
StringType exeDir = getExecutableDir();
// Ensure that handler is shipped with your application
FilePath handler(exeDir + "/../crashpad/bin/crashpad_handler");
// Directory where reports will be saved. Important! Must be writable or crashpad_handler will crash.
FilePath reportsDir(exeDir);
// Directory where metrics will be saved. Important! Must be writable or crashpad_handler will crash.
FilePath metricsDir(exeDir);
// Configure url with BugSplat’s public fred database. Replace 'fred' with the name of your BugSplat database.
StringType url = "http://fred.bugsplat.com/post/bp/crash/crashpad.php";
// Metadata that will be posted to the server with the crash report map
map<StringType, StringType> annotations;
annotations["format"] = "minidump"; // Required: Crashpad setting to save crash as a minidump
annotations["database"] = "fred"; // Required: BugSplat database
annotations["product"] = "myUbuntuCrasher"; // Required: BugSplat appName
annotations["version"] = "1.0.0"; // Required: BugSplat appVersion
annotations["key"] = "Sample key"; // Optional: BugSplat key field
annotations["user"] = "fred#bugsplat.com"; // Optional: BugSplat user email
annotations["list_annotations"] = "Sample comment"; // Optional: BugSplat crash description
// Disable crashpad rate limiting so that all crashes have dmp files
vector<StringType> arguments;
arguments.push_back("--no-rate-limit");
// File paths of attachments to be uploaded with the minidump file at crash time - default bundle limit is 2MB
vector<FilePath> attachments;
FilePath attachment(exeDir + "/attachment.txt");
attachments.push_back(attachment);
// Initialize Crashpad database
unique_ptr<CrashReportDatabase> database = CrashReportDatabase::Initialize(reportsDir);
if (database == NULL) return false;
// Enable automated crash uploads
Settings *settings = database->GetSettings();
if (settings == NULL) return false;
settings->SetUploadsEnabled(true);
// Start crash handler
CrashpadClient *client = new CrashpadClient();
bool status = client->StartHandler(handler, reportsDir, metricsDir, url, annotations, arguments, true, false, attachments);
return status;
}
StringType getExecutableDir() {
char pBuf[FILENAME_MAX];
int len = sizeof(pBuf);
int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if (bytes >= 0) {
pBuf[bytes] = '\0';
}
char* lastForwardSlash = strrchr(&pBuf[0], '/');
if (lastForwardSlash == NULL) return NULL;
*lastForwardSlash = '\0';
return pBuf;
}
More information about configuring Crashpad in Ubuntu can be found here.

Properly use WinInet in parallel thread

I am writing a user-interfaced program that parses Google results page for finding stuff from shopping sites, in particularly, from Amazon.
Because it has user interface, it, obviously should make all internet actions in parallel thread, or the program will be hanged.
I am not actually good in multithreading, and obviously do it not correctly, in example:
HINTERNET internet;
int GetRequest(wchar_t* url, char *buffer, int bufersize)
{
int read = 0;
if (internet)
{
DWORD dwBytesRead;
HINTERNET hu = InternetOpenUrl(internet, url, L"Content-Type: application/x-www-form-urlencoded\r\n", wcslen(L"Content-Type: application/x-www-form-urlencoded\r\n"), INTERNET_FLAG_KEEP_CONNECTION, 0);
if (hu)
{
int err = GetLastError();
for (;;)
{
char b[1024] = {};
BOOL bRead = InternetReadFile(hu, buffer + read, sizeof(b), &dwBytesRead);
read += dwBytesRead;
if (dwBytesRead == 0)
break;
}
}
else
read = -1;
InternetCloseHandle(hu);
}
else
read = -2;
return read;
}
Usage
int status;
void run();
int main()
{
internet = InternetOpen(L"My user agent", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
std::thread t(run);
t.detach();
while(status==0){}
if(status==1)
{
char *response = new char[1024*1024*2];
MessageBoxA(NULL, response,"Aga",MB_OK);
}
else
MessageBoxA(NULL, "Error","Aga",MB_OK);
delete[] response;
status = 0;
return 0;
}
void run()
{
char *buffer = new char[1024*1024*2]; // 2mb buffer
int read = GetRequest(L"https://www.google.com/search?q=lolkek", buffer, 1024*1024*2); // or www.search.yahoo.com
strcat_s(response,1024*1024*2,buffer);
delete[] buffer;
if(read>=0)
status = 1;
else
status = -1;
}
Actually it works perfectly. The program does what I want.
But I faced an issue: when the program is running, I open Chrome, and some buttons in Amazon’s site doesn’t work. In particularly, sell button in product page - by clicking on it, nothing is happens, closing my program and now that button opens login page. Also, seems it breaks data in some google sheets, even, when program works only with Yahoo.
Program does not access amazon.com or any shopping site directly. It has been connecting to google.com, but now even only to search.yahoo.com.
Has anyone faced something like that? Is the problem in not correct multithreading? Maybe I should change internet flags(not exactly to asynchronous, but, maybe add INTERNET_FLAG_NO_CACHE_WRITE or something like that?
I have one assumption: it could happened because three instance of program was run at one time. Also the tabs with Google Sheets that was corrupted was opened in Chrome, when the program was running.

How to get attribute of a directory like last access and last modify

I wanted to get timestamps of a directory and then show it to the user. I have written the following function, but it doesn't work when I give a full path of a directory to present its timestamp like access time. What should I do to fix this issue? I didn't know how should I open a directory and get information about its timestamps correctly for regular files my code works fine but when I wanted to extract information about directory it doesn't work.
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <strsafe.h>
BOOL GetLastWriteTimeDirectory(HANDLE arg_h_file, LPSTR arg_lpsz_string, DWORD arg_dw_size)
{
FILETIME ft_CreateTime, ft_AccessTime, ft_WriteTime;
SYSTEMTIME st_UTC, st_Local;
DWORD dw_Return;
// Retrieve the file times for the file.
if (!GetFileTime(arg_h_file, &ft_CreateTime, &ft_AccessTime, &ft_WriteTime))
{
return FALSE;
}
// Convert the last-write time to local time.
FileTimeToSystemTime(&ft_WriteTime, &st_UTC);
SystemTimeToTzSpecificLocalTime(NULL, &st_UTC, &st_Local);
// Build a string showing the date and time.
dw_Return = StringCchPrintfA(arg_lpsz_string, arg_dw_size, "%02d/%02d/%d %02d:%02d", st_Local.wMonth, st_Local.wDay, st_Local.wYear, st_Local.wHour, st_Local.wMinute);
if (S_OK == dw_Return)
{
return TRUE;
}
else
{
return FALSE;
}
}
bool AttributeLastAccessDirectory(const char* arg_path)
{
HANDLE handleFile;
char bufferLastAccessTime[MAX_PATH];
char pathDirectory[MAX_PATH];
strcpy(pathDirectory, arg_path);
handleFile = CreateFileA(pathDirectory, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (handleFile == INVALID_HANDLE_VALUE)
{
return false;
}
if (GetLastWriteTimeDirectory(handleFile, bufferLastAccessTime, MAX_PATH))
{
printf("\n\t\t");
printf("%s", "Last Accessed: \t");
printf("%s\n", bufferLastAccessTime);
CloseHandle(handleFile);
return true;
}
CloseHandle(handleFile);
return false;
}
int main(int argc, char* argv[])
{
AttributeLastAccessDirectory("C:\\Users\\mkahs\\Desktop\\Sample\\");
return 0;
}
According to the documentation for CreateFileA:
To open a directory using CreateFile, specify the FILE_FLAG_BACKUP_SEMANTICS flag as part of dwFlagsAndAttributes. Appropriate security checks still apply when this flag is used without SE_BACKUP_NAME and SE_RESTORE_NAME privileges.
Your CreateFileA function call currently sets the dwFlagsAndAttributes parameter (the sixth parameter) to 0. Setting it to FILE_FLAG_BACKUP_SEMANTICS should fix the problem.
Also, there is no need for the pathDirectory array and the call to strcpy that sets it. The arg_path parameter can be passed to CreateFileA directly.

Set file owner to non-existing user/SID in windows

I'm trying to write a backup and recovery tool. I'm running my code on a WinPE CD (http://en.wikipedia.org/wiki/Windows_Preinstallation_Environment). I'm trying to read the entire C: partition and write it to the network. Just like the tar command, but windows specific. I have everything working except for setting the file owner. Windows seems to be really intolerant to files being owned by unknown SIDs. Since I'm running in WinPE, most of the users defined on C: aren't in the local user database.
Here are some of the functions I've tried:
SetFileSecurity (returns 1307)
SetSecurityInfo (returns 1307)
SetNamedSecurityInfo (returns 1307)
BackupWrite (returns 1307)
NtSetSecurityObject (returns 0xC000005A)
I know this can be done. SetACL (http://helgeklein.com/setacl/) is able to do it.
So, the question. How do I set the owner of a file to a non-existing user/SID? Any help is greatly appreciated!
Here's a sample of the code I've tried:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <sddl.h>
#include <aclapi.h>
#include <tchar.h>
INT _tmain(){
PSECURITY_DESCRIPTOR psdOwner = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
if (InitializeSecurityDescriptor(psdOwner,SECURITY_DESCRIPTOR_REVISION)){
PSID psOwner = (PSID)0;
if (ConvertStringSidToSid(TEXT("S-1-5-21-3626571138-2175758104-1447827851-1013"),&psOwner)){
if (SetSecurityDescriptorOwner(psdOwner,psOwner,FALSE)){
DWORD dwError = SetNamedSecurityInfo(TEXT("test.txt"),SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,psdOwner,NULL,NULL,NULL);
if (dwError == ERROR_SUCCESS){
_tprintf(TEXT("Success!\n"));
}else{
_tprintf(TEXT("Failed to set owner: %u\n"),dwError);
}
}else{
_tprintf(TEXT("Failed to set owner into SD: %u\n"),GetLastError());
}
}else{
_tprintf(TEXT("Failed to covnert Sid string to Sid: %u\n"),GetLastError());
}
if (psOwner) LocalFree(psOwner);
}else{
_tprintf(TEXT("Failed to initialize SD: %u\n"),GetLastError());
}
if (psdOwner) LocalFree(psdOwner);
return 0;
}
Turns out you need SE_RESTORE_NAME token privilege. You can adjust your process token with the following:
BOOL TakeSecurityPriv(LPCTSTR szPriv){
BOOL bReturn = FALSE;
HANDLE hProcToken = (HANDLE)0;
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hProcToken)){
TOKEN_PRIVILEGES tpTokPriv;
if (LookupPrivilegeValue(NULL,szPriv,&tpTokPriv.Privileges[0].Luid)){
tpTokPriv.PrivilegeCount = 1;
tpTokPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(hProcToken,FALSE,&tpTokPriv,0,NULL,0)){
bReturn = TRUE;
}
}
}
return bReturn;
}
Then you can add the following to the beginning of main in my example:
if (TakeSecurityPriv(SE_RESTORE_NAME)){
That gets rid of the 1307 error. Unfortunately there is another bug in my example because the owner isn't set to the correct SID. However, when I switch back to BackupRead/BackupWrite I won't have to create a SID or SECURITY_DESCRIPTOR. I've pondered over what could be the issue for a while now with no luck. Perhaps someone else could answer that part.

Send command to service from C++

how can I send command to a Windows service from C++? Equivalent .NET code is:
ServiceController sc = new ServiceController("MyService");
sc.ExecuteCommand(255);
From native C++, you will need to:
Open a handle to the service control manager,
Use the service control manager to obtain a service handle for the service you want to control,
Send a control code or codes to the service, and
Close the handles opened in steps 1 and 2.
For example, this code restarts the time synchronization service. First, I create a wrapper class for the service handles, to close them automatically when leaving the block.
class CSC_HANDLE
{
public:
CSC_HANDLE(SC_HANDLE h) : m_h(h) { }
~CSC_HANDLE() { ::CloseServiceHandle(m_h); }
operator SC_HANDLE () { return m_h; }
private:
SC_HANDLE m_h;
};
Then, I open the service control manager (using OpenSCManager()) and the service I want to control. Note that the dwDesiredAccess parameter to OpenService() must include permissions for each control I want to send, or the relevant control functions will fail.
BOOL RestartTimeService()
{
CSC_HANDLE hSCM(::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, GENERIC_READ));
if (NULL == hSCM) return FALSE;
CSC_HANDLE hW32Time(::OpenService(hSCM, L"W32Time", SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS));
if (NULL == hW32Time) return FALSE;
To stop the service, I use ControlService() to send the SERVICE_CONTROL_STOP code, and then check the return value to make sure the command succeeded. If any error other than ERROR_SERVICE_NOT_ACTIVE is reported, I assume that starting the service is not going to succeed.
SERVICE_STATUS ss = { 0 };
::SetLastError(0);
BOOL success = ::ControlService(hW32Time, SERVICE_CONTROL_STOP, &ss);
if (!success)
{
DWORD le = ::GetLastError();
switch (le)
{
case ERROR_ACCESS_DENIED:
case ERROR_DEPENDENT_SERVICES_RUNNING:
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_SERVICE_CONTROL:
case ERROR_SERVICE_CANNOT_ACCEPT_CTRL:
case ERROR_SERVICE_REQUEST_TIMEOUT:
case ERROR_SHUTDOWN_IN_PROGRESS:
return FALSE;
case ERROR_SERVICE_NOT_ACTIVE:
default:
break;
}
}
After instructing the service to stop, I wait for the service manager to report that the service is in fact stopped. This code has two potential bugs, which you may wish to correct for production code:
Sleep(1000) will suspend the message loop on this thread, so you should use another method to delay execution if this function will run on a UI thread. You can construct a suitable sleep-with-message-loop using MsgWaitForMultipleObjectsEx().
The DWORD returned from GetTickCount() will wrap around to zero eventually; if it wraps around while this function is waiting, the wait may give up sooner than I intended.
DWORD waitstart(::GetTickCount());
while (true)
{
ZeroMemory(&ss, sizeof(ss));
::QueryServiceStatus(hW32Time, &ss);
if (SERVICE_STOPPED == ss.dwCurrentState) break;
::Sleep(1000);
DWORD tick(::GetTickCount());
if ((tick < waitstart) || (tick > (waitstart + 30000))) return FALSE;
}
Finally, knowing that the service is in a stopped state, I call StartService() run it again.
success = ::StartService(hW32Time, 0, NULL);
if (!success) return FALSE;
return TRUE;
}
You use ControlService, see Service Control Requests.
Here is a little program which will connect to a service called "MYSERVICE" then send a command 141 (which is defined by the service)
// ServiceCommunicator.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
SC_HANDLE managerHandle;
SC_HANDLE serviceHandle;
SERVICE_STATUS controlParms;
DWORD retStatus;
managerHandle = OpenSCManager(NULL, NULL, GENERIC_READ);
if (NULL != managerHandle)
{
serviceHandle = OpenService(managerHandle, L"MYSERVICE", SERVICE_USER_DEFINED_CONTROL | SERVICE_QUERY_STATUS);
if (NULL != serviceHandle)
{
cout << "connected to Service" << endl;
retStatus = ControlService(serviceHandle, 141, &controlParms);
if (retStatus)
{
//Get the return code from the service
cout << "For command 141, return code from service was " << controlParms.dwWin32ExitCode << endl;
}
else
cout << "Sending command 141 failed" << endl;
CloseServiceHandle(serviceHandle);
}
else
{
cout << "could not connect to Service" << endl;
}
CloseServiceHandle(managerHandle);
}
else
{
cout << "could not open service manager" << endl;
}
return 0;
}