Can someone please tell me the problems with this piece of code?
I'm bulding a windows app, not a console. Am I using the functions
correctly. What types should I used? Okay I fixed semicolon err and
else err? Still not working properly.
#include <windows.h>
int WINAPI WinMain(HINSTANCE thisin,HINSTANCE previn,LPSTR lpstr,INT int_)
{
LPTSTR buffer;
DWORD size;
SetConsoleTitle("Console Title");
if(!GetConsoleTitle(buffer,size))
cout << "error" << endl;
else cout << *buffer << endl;
system("Pause");
return 0;
}
It have 2 problems, first a ';' at end of if that is a C++ mistyping error and every body say it, but second is: for every API that get a buffer to return something, you should provide a valid buffer. Assume GetConsoleTitle implemented as:
BOOL GetConsoleTitle(LPTSTR p, DWORD dwSize)
{
LPTSTR actualTitle = /* Get actual title from somewhere */;
while (dwSize--)
{
*p++ = *actualTitle++;
if (!*p++) return TRUE;
}
// Not enough buffer
return FALSE;
}
Now look at your program, you pass an uninitialized LPTSTR to the function and as soon as API call *p++ = *actualTitle++, it will cause a segmentation fault or Access violation.
so in order to solve it, you must pass a valid buffer as first argument and since LPTSTR is a typedef of TCHAR* you should have:
const DWORD dwSize = 128;
TCHAR buffer[dwSize];
if (GetConsoleTitle(buffer, dwSize)) std::cout << "OK!" << std::endl;
First thing is first. Your statement prints whether there is an error or not. Use an else there:
if(!GetConsoleTitle(buffer,size))
cout << "error" << endl;
else
cout << *buffer << endl;
and the ; after your if was a typo, I corrected it above.
You are using API's for Console App. Create a console app, copy this code to console project c or cpp source file and replace
int WINAPI WinMain(HINSTANCE thisin,HINSTANCE previn,LPSTR lpstr,INT int_)
with
int _tmain(int argc, char *argv[])
also remove ';' (semicolon) from 'if' statement.
Related
I am trying to get the various attributes of a file as seen in its "Details" tab with the WinAPI function VerQueryValue. I have successfully used this function to get the non-string version info with VS_FIXEDFILEINFO, but have not been able to get the example shown at the bottom of the functions documentation working.
The example isn't actually complete as it leaves out the use of the other related functions and the constructions of some buffers needed to use the function, so I've filled in the blanks the best I can and changed some of the in-between steps to use C++ SL since that's ultimately the language I need to use this in:
#include <iostream>
#include <iomanip>
#include "sstream"
#include "Windows.h"
#pragma comment(lib, "Version.lib")
int ReadOutFileDescriptions(std::wstring filename)
{
LPBYTE lpBuffer = NULL;
DWORD verHandle, verSize = GetFileVersionInfoSize(filename.c_str(), &verHandle);
if (verSize != NULL)
{
LPSTR verData = new char[verSize];
if (GetFileVersionInfo(filename.c_str(), verHandle, verSize, verData))
{
UINT cbTranslate;
// Structure used to store enumerated languages and code pages.
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// Read the list of languages and code pages.
VerQueryValue(verData, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate);
// Read the file description for each language and code page.
for (ULONGLONG i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
{
std::wostringstream ss; ss << std::setfill(L'0') << std::hex;
ss << std::setw(4) << lpTranslate[i].wLanguage;
std::wstring langS = ss.str();
ss.str(std::wstring());
ss << std::setw(4) << lpTranslate[i].wCodePage;
std::wstring codeS = ss.str();
std::wstring subBlock = L"\\StringFileInfo\\" + langS + codeS + L"\\FileDescription";
// Retrieve file description for language and code page "i".
WCHAR descBuffer[50];
LPVOID lpBuffer = &descBuffer;
UINT bufferSize;
VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize);
std::cout << bufferSize << '\n' << descBuffer;
}
}
delete[] verData;
}
return 0;
}
int main(int argc, char* argv[])
{
ReadOutFileDescriptions(L"MyFile.exe");
return 0;
}
I only have a little experience with WinAPI and its typedefs and my C is a bit rusty so I'm sure I'm just setting-up/using a buffer incorrectly or the like.
The printed buffer size is correct (the length of MyFile.exe's description + 1 for the null character) so I know the function is getting the right value, but the actually value that gets printed is just a series of hexadecimal character, most likely an address.
What am I doing wrong?
EDIT (Answer):
Thanks to #dxiv I was made aware that I did not fully understand how the "result" argument (lplpBuffer) of VerQueryValue was to be used, both internally and after the function returns.
Changing the end of the loop to the following achieves my desired result:
//WCHAR descBuffer[50] Not required, the function doesn't utilize a user made buffer
LPVOID lpBuffer;
UINT bufferSize;
VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize); // lpBuffer is reassigned here
std::wstring fileDescription((const TCHAR*)lpBuffer); // Create std::string from C style string (char*) that lpBuffer now points to
std::wcout << bufferSize << '\n' << fileDescription;
VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize);
std::cout << bufferSize << '\n' << descBuffer;
Once VerQueryValue returns, lpBuffer no longer points to descBuffer, but to a different buffer assigned inside the call. The returned string is at (const TCHAR *)lpBuffer at that point.
I have been experimenting with various aspects of the Windows API and thought I would give process memory manipulation a try. Previously I had been trying to do this in native C++ using this method: C++ - Get value of a particular memory address
However, this method does not work and I found a response somewhere on the Cplusplus forum that told me to use ReadProcessMemory. I found that WriteProcessMemory works just fine when attempting to edit values, but ReadProcessMemory either fails (returning error code 299) or crashes the application.
Here is my code:
#include <iostream>
#include <cstdint>
#include <Windows.h>
#include <cstdio>
using namespace std;
int main()
{
LPVOID bytes;
DWORD pid;
SIZE_T *num_bytes_read;
int temp;
SIZE_T size = sizeof(temp);
LPCVOID address = reinterpret_cast<int*>(0x404004);
HWND hwnd = FindWindow(NULL, "C:\\Users\\Delkarix\\Desktop\\memory_edit_test.exe");
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
BOOL worked = ReadProcessMemory(hProcess, address, bytes, size, num_bytes_read);
cout << "ERROR: " << GetLastError() << endl;
cout << "PROCESS: " << hProcess << endl;
cout << "BYTES: " << bytes << endl;
cout << "BASE ADDRESS: " << address << endl;
cout << "FUNCTION SUCCESS: " << worked << endl;
cout << "BYTES READ: " << *num_bytes_read << endl;
CloseHandle(hProcess);
}
I have noticed that the application crashes when the num_bytes_read variable is a pointer (the 5th parameter of ReadProcessMemory is the num_bytes_read variable) and it throws error 299 when it is not a pointer (the 5th parameter of ReadProcessMemory is the pointer to the num_bytes_read variable).
Here is the code for the memory_edit_test.cpp:
#include <iostream>
using namespace std;
int test = 6;
int main() {
string input;
cout << &test << endl; // Where I got the address 0x404004
getline(cin, input);
cout << test << endl; // Used to check the value against the one I got from ReadProcessMemory
getline(cin, input);
}
How can I get ReadProcessMemory to succeed? Answers to similar questions on StackOverflow either do nothing or they just make the problem worse.
The problem is very simple, third parameter to ReadProcessMemory is meant to point to a buffer, where the memory read will be written to. You just give it an unintialised pointer. Similar problem with the fifth parameter as well.
Your code should look something like this
int temp;
SIZE_T num_bytes_read;
BOOL worked = ReadProcessMemory(hProcess, address, &temp, sizeof temp, &num_bytes_read);
Note third and fifth parameters are pointers to already existing memory. Declare a variable and use & to get its address.
I am stuck in a tight spot and I need some help with some C++ code. This is my first attempt at doing C++ and it born mostly from necessity at this point.
I am trying (unsuccessfully it feels) to build a native NAN module for Node.JS that will be used by an Electron app on Windows.
I need it to return the WinHttpDetectAutoProxyConfigUrl when the users Proxy configuration is set to Auto Detect.
I have built this exact thing in C# for another application and it works seamlessly in our distributed user BYOD environment. However in this case I do not wish to be dependent on the dot.net framework unnecessarily.
Right know I am at the extent of my knowledge when it comes to C++ as most of my knowledge over the years has thus far been theoretical. I am hoping that someone that actually works in C++ daily can look at my code and help correct the error that is happening.
I have been trying to debug using the “std::cout” in VSCode.
As you can see from the output at the bottom of the image, that some of it appears to be working and the code is dropping into the “Get Auto URL” IF block as expected. However the output is very iritic (“�����”) and nothing like the wpad.dat URL I was expecting to see returned from the wpad protocol implemented by the winhttp.dll.
My Problem:
It is as though the result is blank and then the “char buffer[2083];” is being sent to the stdOut and the characters are all encoded wrong.
Any help on this would be very helpful so thanks in advance.
Please see the code below.
main.cpp
#include <nan.h>
#include <Windows.h>
#include <Winhttp.h>
#include <iostream>
#pragma comment(lib, "winhttp.lib")
using namespace std;
// NAN_METHOD is a Nan macro enabling convenient way of creating native node functions.
// It takes a method's name as a param. By C++ convention, I used the Capital cased name.
NAN_METHOD(AutoProxyConfigUrl) {
cout << "AutoProxyConfigUrl" << "\n";
v8::Isolate* isolate = info.GetIsolate(); // args.GetIsolate();
LPWSTR strConfigUrl = NULL;
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG MyProxyConfig;
if(!WinHttpGetIEProxyConfigForCurrentUser(&MyProxyConfig))
{
//check the error DWORD Err = GetLastError();
DWORD Err = GetLastError();
cout << "WinHttpGetIEProxyConfigForCurrentUser failed with the following error number: " << Err << "\n";
switch (Err)
{
case ERROR_FILE_NOT_FOUND:
cout << "The error is ERROR_FILE_NOT_FOUND" << "\n";
break;
case ERROR_WINHTTP_INTERNAL_ERROR:
cout << "ERROR_WINHTTP_INTERNAL_ERROR" << "\n";
break;
case ERROR_NOT_ENOUGH_MEMORY:
cout << "ERROR_NOT_ENOUGH_MEMORY" << "\n";
break;
default:
cout << "Look up error in header file." << "\n";
break;
}//end switch
//TODO this might not be a good idea but it is worth trying
strConfigUrl = L"http://wpad/wpad.dat"; //Default to Fallback wpad
}//end if
else
{
//no error so check the proxy settings and free any strings
cout << "Auto Detect is: " << MyProxyConfig.fAutoDetect << "\n";
if(MyProxyConfig.fAutoDetect){
cout << "Get Auto URL" << "\n";
if (!WinHttpDetectAutoProxyConfigUrl(WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A, &strConfigUrl))
{
cout << "Error getting URL" << "\n";
//This error message is not necessarily a problem and can be ignored if you are using direct connection. you get this error if you are having direct connection.
//check the error DWORD Err = GetLastError();
DWORD Err = GetLastError();
if (ERROR_WINHTTP_AUTODETECTION_FAILED == Err)
{
strConfigUrl = L"http://wpad/wpad.dat"; //Default to Fallback wpad
}
//TODO work out what to do with the other errors
}
}
if(NULL != MyProxyConfig.lpszAutoConfigUrl)
{
wcout << "AutoConfigURL (MyProxyConfig.lpszAutoConfigUrl) is: " << MyProxyConfig.lpszAutoConfigUrl << "\n";
GlobalFree(MyProxyConfig.lpszAutoConfigUrl);
}
if(NULL != MyProxyConfig.lpszProxy)
{
wcout << "AutoConfigURL (MyProxyConfig.lpszProxy) is: " << MyProxyConfig.lpszProxy << "\n";
GlobalFree(MyProxyConfig.lpszProxy);
}
if(NULL != MyProxyConfig.lpszProxyBypass)
{
wcout << "AutoConfigURL is: " << MyProxyConfig.lpszProxyBypass << "\n";
GlobalFree(MyProxyConfig.lpszProxyBypass);
}
}//end else
//cout << "strConfigUrl" << strConfigUrl << "\n";
char buffer[2083];
wcstombs( buffer, strConfigUrl, wcslen(strConfigUrl) ); // Need wcslen to compute the length of the string
// convert it to string
std::string returnUrl(buffer);
// Create an instance of V8's String type
auto message = Nan::New(returnUrl).ToLocalChecked();
// 'info' is a macro's "implicit" parameter - it's a bridge object between C++ and JavaScript runtimes
// You would use info to both extract the parameters passed to a function as well as set the return value.
info.GetReturnValue().Set(message);
if(strConfigUrl)
GlobalFree(strConfigUrl);
}
// Module initialization logic
NAN_MODULE_INIT(Initialize) {
// Export the `Hello` function (equivalent to `export function Hello (...)` in JS)
NAN_EXPORT(target, AutoProxyConfigUrl);
}
// Create the module called "addon" and initialize it with `Initialize` function (created with NAN_MODULE_INIT macro)
NODE_MODULE(proxyautodetect, Initialize);
main.js
// note that the compiled addon is placed under following path
//const {AutoProxyConfigUrl} = require('./build/Release/proxyautodetect.node');
const {AutoProxyConfigUrl} = require('./build/Debug/proxyautodetect.node');
// `Hello` function returns a string, so we have to console.log it!
console.log(AutoProxyConfigUrl());
Build and Run output:
C:\Code\Work\wpad-auto-detect>if not defined npm_config_node_gyp (node "C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild --debug ) else (node "C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" rebuild --debug )
Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
main.cpp
win_delay_load_hook.cc
Creating library C:\Code\Work\wpad-auto-detect\build\Debug\proxyautodetect.lib and object C:\Code\Work\wpad-auto-detect\build\Debug\proxyautodet
ect.exp
proxyautodetect.vcxproj -> C:\Code\Work\wpad-auto-detect\build\Debug\\proxyautodetect.node
PS C:\Code\Work\wpad-auto-detect> npm start
> proxyautodetect#1.0.0 start C:\Code\Work\wpad-auto-detect
> node main.js
AutoProxyConfigUrl
Auto Detect is: 1
Get Auto URL
"
"��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1��J╗
PS C:\Code\Work\wpad-auto-detect>
Image of code output
I did a sort of Trim
int urlLen = wcslen(strConfigUrl) ;
#if DEBUG
cout << "strConfigUrl wcslen : " << urlLen << "\n";
#endif
char buffer[2083]; //This is the max length a URL can be in IE
wcstombs( buffer, strConfigUrl, wcslen(strConfigUrl) ); // Need wcslen to compute the length of the string
// convert it to string
std::string returnUrl(buffer);
// Create an instance of V8's String type and Return only the Length needed so kind of Trim the extra char
auto message = Nan::New(returnUrl.substr(0, urlLen)).ToLocalChecked();
It changes the value while it's ran inside of Visual studio, but if I build the program and run the executable it does not actually change the value. Here is the code:
using namespace std;
DWORD pid;
DWORD players = 0x00883D70;
int playerCount = 0;
int readValue = 0;
int firstTime = 0;
int main()
{
HWND hWnd = FindWindowA(0, ("Diablo II"));
GetWindowThreadProcessId(hWnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
if (firstTime == 0)
{
cout << "This is a tool to set the player count in Diablo II: Lord of Destruction v1.14D" << endl;
cout << "This tool was made by xElite_V." << endl;
cout << "You can set a number between 0 and 255 for player difficulty:" << endl;
}
else {
cout << "You can set a number between 0 and 255 for player difficulty:" << endl;
}
firstTime = 1;
cin >> playerCount;
WriteProcessMemory(pHandle, (LPVOID)players, &playerCount, sizeof(playerCount), 0);
main();
}
So I don't understand why it wouldn't do the same thing as it would while it's in visual studio.
You almost certainly have a permissions problem, but since your code doesn't check for errors properly, nobody can actually tell you for sure.
There's actually a bunch of stuff you need to do to get this to work, and there's some code that does that here:
https://stackoverflow.com/a/51346951/5743288
Note that this is calling ReadProcessMemory but the idea is the same.
I'm currently learning c++ and i decided that i want to give it a shot and try to write a simple program that can read the values of other programs that are stored in memory (and later on be able to modify these values).
To test it i wrote a program that does a simple addition, i then run my other program and I'm trying to read in real time the value of the first program using its address in the memory.
The code will help you to understand better what i mean.
The "target" program that i want to read the value from:
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
int main()
{
int userValue=0;
int total=0;
int* t;
SetWindowText(NULL, "Memory");
while(1)
{
cin >> userValue;
total += userValue;
t = &total;
cout << *t << endl;
cout <<"Pointer: " << &t <<" Total: " << &total;
}
getch();
return 0;
}
And the program that reads the value from the first one:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD address = 0x28FEF0;
int value = 0;
DWORD pid;
HWND hwnd;
hwnd = FindWindow(NULL,"Memory");
if(!hwnd)
{
cout <<"Window not found!\n";
cin.get();
}
else
{
GetWindowThreadProcessId(hwnd,&pid);
HANDLE phandle = OpenProcess(PROCESS_VM_READ,0,pid);
if(!phandle)
{
cout <<"Could not get handle!\n";
cin.get();
}
else
{
while(1)
{
ReadProcessMemory(phandle,(void*)address,&value,sizeof(value),0);
cout << value << "\n";
Sleep(1000);
}
return 0;
}
}
}
The code from the second one was taken from a forum (after googling) and it works fine if i use it with any other program, but it doesn't want to work at all with my program.
I tried changing the address to both the pointer t and the actual integer total, but nothing worked.
I feel like I've done something wrong in the first program rather than the second one.
I'm using Code:Blocks with GCC compiler.
Thanks in advance for any help!
Oh, and Merry Christmas!
&t = the address of the pointer that points to total
&total = the address of the actual "total value"
In your first program you should output "&total"
In your second program you should use ReadProcessMemory to read the address which is output from the first program.
If it doesn't work, you must run the second program as administrator to get permissions. If you still have trouble, call GetLastError() after each Windows API call, check the return value of ReadProcessMemory() and utilize the last argument of ReadProcessMemory() for error checking.