I got two processes. In process A, application Alpha is prepared for using shared memory. In process B, my windows console application with a main method accesses this shared memory. It works, I can connect to the memory. Unfortunately if I store the memory content in a variable (here pBuf) and inspect the variable via MsVisualStudioDebugger, there is only one letter in the buffer - what went wrong? How am I able to look in the memory/file to get a clue, what objects are stored in the memory? Thanks in advance.
Here is the code of my console app:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
using namespace std;
#define BUF_SIZE 256
TCHAR szName[] = TEXT("SIMITSHM"); // Name des SHMs;
int main(void){
std::cout << "*** start SharedMemory ***\n";
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
if (hMapFile == NULL){
MessageBox(NULL, TEXT("Could not open file mapping object"), TEXT("FEHLER"), MB_OK);
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
if (pBuf == NULL){
MessageBox(NULL, TEXT("Could not map view of file"), TEXT("FEHLER"), MB_OK);
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("SIMIT-SHM"), MB_OK); // content of memory
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
std::cout << "*** close app by typing a number. ***\n";
int a = 0;
cin >> a;
return 0;
}
UPDATE: after doing more research on this issue, I guess the problem is the casting of the return value of MapViewOfFile()-function.
UPDATE-2: Thanks Hans! I was able to look the pBuf content as a hexdump, see:
UPDATE-3: Thanks Hans! Due to your advice I was able to use fwrite() to put the shared-memory-content in a file on my local machine. Moreover I am able to see some familiar names, i.e. names like EingangMotor1 which I configured in application-Alpha and it seems this content was stored in shared memory. Now I hope to play around with application-Alpha, recognize the related changes in shared-memory and afterwards hopefully I will be able to change the values of the shared memory variable values, so application-Alpha will change its behaviour on the fly.
UPDATE-4: current code - thanks in advance for feedback, which lines needs to be improved.
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <strsafe.h>
#include <fstream>
#include <sstream>
#include <vector>
#pragma comment(lib, "user32.lib")
using namespace std;
#define BUF_SIZE 256
TCHAR szName[] = TEXT("SIMITSHM"); // Name des SHMs;
int main(void){
std::cout << "*** Start SharedMemory ***\n";
HANDLE hMapFile;
FILE * pBuf;
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
if (hMapFile == NULL){
MessageBox(NULL, TEXT("Could not open file mapping object"), TEXT("ERROR"), MB_OK);
return 1;
}
// MapViewOfFile return a pointer to void, so you need to cast it to a suitable structure
pBuf = (FILE*) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
if (pBuf == NULL){
MessageBox(NULL, TEXT("Could not map view of file"), TEXT("ERROR"), MB_OK);
CloseHandle(hMapFile);
return 1;
}
// write file
FILE * pFile;
pFile = fopen ("shm-main-simit-content-fwrite.txt","w");
fwrite(pBuf, 50, 20, pFile);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
std::cout << "*** close app by typing a number. ***\n";
int a = 0;
cin >> a;
return 0;
}
Yes, you certainly have a type mismatch. That file is very unlikely to contain a properly zero-terminated C string. Using the TCHAR macros adds to the randomness, there is no point in using them anymore. The last non-Unicode version of Windows died 10 years ago.
Answering the question: use Debug + Windows + Memory + Memory 1 and put "pBuf" in the Address box. You'll see a raw hex dump of the shared memory content.
Related
(Using C++, Windows 10, Microsoft Visual Studio 2017)
Hello, I am new to serial ports but trying to learn how to open, close, read, and write with them
Right now, I am trying to use the CreateFile() and WriteFile() functions to write to a txt file.
I created a .txt file called "write.txt" and saved it in my Documents folder. Then I added it to my project's source files via "Add" --> "Existing Item". The file is empty.
I wrote the program below, hoping I could write to the file, but after running then checking on the file, the file is still empty. The program compiles but I am guessing I have an error somewhere. Am I going about writing to a file correctly?
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main() {
HANDLE write;
write = CreateFile(TEXT("\\write.txt"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (write == INVALID_HANDLE_VALUE) {
DWORD errorWrite = GetLastError();
printf("Error in opening file\n");
printf("Error = 0x%x\n", errorWrite);
}
else {
printf("Opening file successful\n");
}
WriteFile(write, "hello", 5, 0, 0);
CloseHandle(write);
return 0;
}
The output says the file was opened successfully, but the write.txt file remains empty. Any advice?
Thank you in advance :D
You are not accessing the text file that is located in your Documents folder. You are accessing a text file that is located at the root of the drive where the calling process's current working directory is currently pointing at.
You need to explicitly query the OS for the path to the Documents folder (ie, via SHGetFolderPath() or SHGetKnownFolderPath()), and then append your filename to that path.
Also, you are calling WriteFile() incorrectly. In particular, the lpNumberOfBytesWritten parameter is wrong:
lpNumberOfBytesWritten
A pointer to the variable that receives the number of bytes written when using a synchronous hFile parameter. WriteFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
And, you are not doing any error handling on WriteFile(), either:
If the function succeeds, the return value is nonzero (TRUE).
If the function fails, or is completing asynchronously, the return value is zero (FALSE). To get extended error information, call the GetLastError function.
Try something more like this instead:
#include <iostream>
#include <string>
#include <Windows.h>
#include <Shlobj.h>
#include <shlwapi.h>
using namespace std;
int main() {
TCHAR path[MAX_PATH] = {};
HRESULT hRes = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path);
if (FAILED(hRes)) {
printf("Can't get Documents folder path\nError = 0x%08x\n", hRes);
}
else {
PathAppend(path, TEXT("write.txt"));
HANDLE write = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (write == INVALID_HANDLE_VALUE) {
DWORD errorWrite = GetLastError();
printf("Can't open file\nError = %u\n", errorWrite);
}
else {
printf("File opened successful\n");
DWORD written;
if (!WriteFile(write, "hello", 5, &written, NULL)) {
DWORD errorWrite = GetLastError();
printf("Can't write to file\nError = %u\n", errorWrite);
} else {
printf("File written successful\n");
}
CloseHandle(write);
}
}
return 0;
}
I recently coded an injector where as long as the dll is in the same directory as the exe injector it will inject but even when the dLL is in the same path it still returns with the error file not found.
Very new to c++ so not exactly sure how to fix it, only this I know that the problem must lie in the dll_name
The c++ code is listed here
#include <Windows.h>
#include <string>
#include <thread>
#include <libloaderapi.h>
using namespace std;
void get_proc_id(const char* window_title, DWORD &process_id)
{
GetWindowThreadProcessId(FindWindow(NULL, window_title), &process_id); // Find Process ID by using title of window
}
void error(const char* error_title, const char* error_message)
{
MessageBox(NULL, error_message, error_title, NULL);
exit(-1);
//if error occurs output false
}
bool file_exists(string file_name) // Makes sure file exists
{
struct stat buffer;
return (stat(file_name.c_str(), &buffer) == 0);
//Information goes through buffer if = 0 , it worked
//Creates random buffer of stat sturc doesnt matter what goes in - making sure function is successful, gets info about file and checks if it workeed
}
int main()
{
DWORD proc_id = NULL;
char dll_path[MAX_PATH];
const char* dll_name = "TestDll2.dll"; //Name of Dll
const char* window_title = "Untitled - Paint"; //Must Match Title Name
if (!file_exists(dll_name));
{
error("file_exists", "File does not exist");
}
if (!GetFullPathName(dll_name, MAX_PATH, dll_path, nullptr))
{
error("GetFullPathName", "Failed to get full file path");
}
get_proc_id(window_title, proc_id);
if (proc_id == NULL)
{
error("get_proc_id", "Failed to get process ID");
}
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, NULL, proc_id);
if (!h_process)
{
error("OpenProcess", "Failed to open handle to process");
}
void* allocated_memory = VirtualAllocEx(h_process, nullptr, MAX_PATH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); //Calling Virutal Allocation, passing handle to process - reserving memory by going thru reserve and need to commit to it so we can write
if (!allocated_memory)
{
error("VirtualAllocEx", "Failed to allocate memory");
}
if (!WriteProcessMemory(h_process, allocated_memory, dll_path, MAX_PATH, nullptr)) // Write DLL path into the target program
{
error("WriteProcessMemory", "Failed to write process memory");
}
//If above works we call loadlibarya which is where the dll is stored
HANDLE h_thread = CreateRemoteThread(h_process, nullptr, NULL, LPTHREAD_START_ROUTINE(LoadLibraryA), allocated_memory, NULL, nullptr);
if (!h_thread)
{
error("CreateRemoteThread", "Failed to create remote thread");
}
CloseHandle(h_process);
VirtualFreeEx(h_process, allocated_memory, NULL, MEM_RELEASE);
MessageBox(0, "Successfully Injected!", "Sucess", 0);
} ```
Try to use C++ STL function or Windows native API:
#include <string>
#include <filesystem>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
bool IsExists(const std::string &FilePathName)
{
return std::filesystem::exists(FilePathName);
}
bool IsExists(const std::string &FilePathName)
{
return PathFileExistsA(FilePathName.c_str());
}
The file is being searched in the current directory, not in the directory of the exe file. These might not be the same. You have to find the path to the exe file in order to search for files in its directory. On Windows you could do something like this:
#include <psapi.h>
// ....
HANDLE Handle = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, GetCurrentProcessId() );
if ( Handle ) {
TCHAR buffer[MAX_PATH];
if ( GetModuleFileNameEx( Handle, 0, buffer, MAX_PATH ) ) {
std::filesystem::path exePath( buffer ); // TODO this might need encoding conversion
auto exeDir = exePath.parent_path();
auto dllPath = exeDir / "TestDll2.dll";
if ( std::filesystem::exists( dllPath ) ) {
// ...
}
}
}
You can also try GetProcessImageFileName if GetModuleFileNameEx does not work. Apparently it does not work in 32-bit applications on a 64-bit system (see comments in this answer).
I have this code which prints the computer name.
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain(void)
{
TCHAR buffer[256] = TEXT("");
TCHAR szDescription[8][32] = { TEXT("NetBIOS"),
TEXT("DNS hostname"),
TEXT("DNS domain"),
TEXT("DNS fully-qualified"),
TEXT("Physical NetBIOS"),
TEXT("Physical DNS hostname"),
TEXT("Physical DNS domain"),
TEXT("Physical DNS fully-qualified") };
int cnf = 0;
DWORD dwSize = sizeof(buffer);
if (!GetComputerNameEx((COMPUTER_NAME_FORMAT)0, buffer, &dwSize))
{
_tprintf(TEXT("GetComputerNameEx failed (%d)\n"), GetLastError());
return;
}
else _tprintf(TEXT("%s: %s\n"), szDescription[0], buffer);
if (buffer == TEXT("DESKTOP-SURPO18")) _tprintf(TEXT("CORRECT"));
dwSize = _countof(buffer);
ZeroMemory(buffer, dwSize);
}
I just want to create or construct a simple if statement like if(buffer == text("MyComputerName")) tprint(TEXT("CORRECT")); but it's not working. Or can you suggest other simplest way of code like I posted above that work with if statement easily using a computer name? Thank you.
I am trying to make an executable which can read itself from memory using ReadProcessMemory api of windows.
Then, I will use this to calculate the checksum of executable.
This is my code :
#define PSAPI_VERSION 1
#include <string>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
#pragma comment(lib, "psapi.lib")
int main(void)
{
HWND hMyProcess = (HWND)(GetCurrentProcess());
HMODULE hModule = (HMODULE)GetModuleHandle(NULL);
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
MODULEINFO moduleInfo;
if(hModule != NULL && hMyProcess != NULL){
// if (GetModuleInformation())
GetModuleBaseName(hMyProcess, hModule, szProcessName, MAX_PATH);
printf("%s\n", szProcessName);
if (GetModuleInformation(hMyProcess, hModule, &moduleInfo, sizeof(moduleInfo))){
printf("lpBaseOfDLL : %x\n", moduleInfo.lpBaseOfDll);
printf("Entry Point : %x\n", moduleInfo.EntryPoint);
printf("SizeOfImage : %x\n", moduleInfo.SizeOfImage);
}
}
// Till here working fine, problem lies below
// read process memory
TCHAR *hexEXE;
SIZE_T *lpNumberOfBytesRead;
if(ReadProcessMemory(hMyProcess, moduleInfo.lpBaseOfDll,
hexEXE, moduleInfo.SizeOfImage, 0)){
//printf("%s\n", hexEXE);
printf("Read memory\n");
printf("%d \n",strlen(hexEXE));
}
// will be implemented later, taken from --> https://msdn.microsoft.com/en-us/library/aa382380(VS.85).aspx
DWORD dwStatus = 0;
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
/*if (!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)){
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
//CloseHandle(hFile);
return dwStatus;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)){
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
//CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return dwStatus;
}*/
return 0;
}
Problem :
I am not able to read the my own process's memory, it's the first time I'm using WinAPI, so perhaps I am using the function in some wrong way.
The program just hangs and it shows "Windows has encountered some problem..."
Possible Reasons of Error :
I think the handle to the process ( hMyProcess ) I'm getting earlier isn't with the required privileges ( PROCESS_VM_READ ), how do I verify it and if it isn't then how do I get the correct privileges.
TCHAR *hexEXE;
SIZE_T *lpNumberOfBytesRead;
hexEXE = malloc (moduleInfo.SizeOfImage);
if(ReadProcessMemory(hMyProcess, moduleInfo.lpBaseOfDll,
hexEXE, moduleInfo.SizeOfImage, 0)){
//printf("%s\n", hexEXE);
printf("Read memory\n");
//hexEXE is not a string. Don't use it in strlen.
//printf("%d \n",strlen(hexEXE));
print("%d \n", moduleInfo.SizeOfImage);
}
The ReadProcessMemory need a memory to store the image. So, the "hexEXE" need be assign to a memory buffer.
Sorry for the extended discussion, but I got it running by changing the code to instead of using ReadProcessMemory directly iterating over the memory through a for loop like this :
long *baseAddress = (long *)moduleInfo.lpBaseOfDll;
printf("%d %x\n",baseAddress, baseAddress);
for (int i = 0; i < moduleInfo.SizeOfImage; ++i){
long *addressToRead = baseAddress+i;
printf("%x : %x\n", addressToRead, *addressToRead);
}
Here's the output :
Further thoughts
However, I don't understand why am I not able to get it using ReadProcessMemory.
I want to make a share memory pool for all the other process to share the data, but after I read about the CreateFileMapping API document, I was confused about that it will need to specify the size of the share memory. I actually want it to be dynamic allocate and free which looks more like a service. Is there some way to do the share memory dynamic using createFileMapping or not?
Creating Named Shared Memory.
First Process
The first process creates the file mapping object by calling the CreateFileMapping function with INVALID_HANDLE_VALUE and a name for the object. By using the PAGE_READWRITE flag, the process has read/write permission to the memory through any file views that are created.
Then the process uses the file mapping object handle that CreateFileMapping returns in a call to MapViewOfFile to create a view of the file in the process address space. The MapViewOfFile function returns a pointer to the file view, pBuf. The process then uses the CopyMemory function to write a string to the view that can be accessed by other processes.
Process 1 code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
_getch();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Second Process
A second process can access the string written to the shared memory by the first process by calling the OpenFileMapping function specifying the same name for the mapping object as the first process. Then it can use the MapViewOfFile function to obtain a pointer to the file view, pBuf. The process can display this string as it would any other string. In this example, the message box displayed contains the message "Message from first process" that was written by the first process.
Process 2 code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx