What's wrong? It crashes when I want to get value of AUVersion. This key exists in registry but I can't get it.
int main(int argc, char *argv[])
{
HKEY key;
if (RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\JavaSoft\\Auto Update\\"), &key) != ERROR_SUCCESS)
{
cout << "Unable to open registry key\n\n";
}
char path[1024];
DWORD value_length = 1024;
//here is the crash
RegQueryValueEx(key, "AUVersion", NULL, (LPDWORD)REG_SZ, (LPBYTE)&path, &value_length);
cout << "the value read from the registry is: " << path << endl;
system("pause");
return 0;
}
That fourth parameter is an LPDWORD -- a pointer to a DWORD. You took a regular integer and cast it to a pointer, which (when dereferenced) will crash.
That parameter receives the type of the registry value. Set it to NULL if you are not interested in knowing the type.
There are two errors with the call to RegQueryValueEx():
the type parameter is written to so must be a valid address, and this is not:
(LPDWORD)REG_SZ
and this is the probable cause of the crash.
&path should be path
Change to:
DWORD type;
RegQueryValueEx(key, "AUVersion", NULL, &type, (LPBYTE) path, &value_length);
You must check the result of RegQueryValueEx() to ensure path has been populated and subsequent code is not processing an unitialized variable:
const DWORD result = RegQueryValueEx(key,
"AUVersion",
NULL,
&type,
(LPBYTE) path,
&value_length);
// Check status of the query and ensure it was a string
// that was read.
if (ERROR_SUCCESS == result && REG_SZ == type)
{
// Success.
}
Related
in uPyCraft IDE or Putty, just sending km.press('a') then it works fine,
but in my C++, i tried to writefile with km.press('a'), it doesn't work.
i can't find what is wrong
uPyCraft Successfull
`bool CSerialPort::OpenPort(CString portname)
{
m_hComm = CreateFile(L"//./" + portname,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
if (m_hComm == INVALID_HANDLE_VALUE)
{
std::cout << "INVALID HANDLE" << std::endl;
return false;
}
else
return true;
}
bool CSerialPort::WriteByte(const char * bybyte)
{
byte iBytesWritten = 0;
if (WriteFile(m_hComm, &bybyte, 1, &m_iBytesWritten, NULL) == 0)
return false;
else
return true;
}
int main()
{
CSerialPort _serial;
_serial.OpenPort(L"COM4");
_serial.WriteByte("km.press('a')");
}`
i tried this,
but it doesn't work, i also check _serial Isn't INVALID HANDLE.
someone help me for sending "km.press('a')" to serial
and sending km.move(0,1) with using Putty and uPyCraft,
it works fine but
string test = "km.move(0,1)";
DWORD dwBytesWritten;
WriteFile(m_hComm,&test,sizeof(test),dwBytesWritten,NULL);
it doesn't work. just changing km.move(0,1) to km.move(0,10), then i don't know why but it works fine.
what is different with uPyCraft(Putty) and C++?
By the looks of it, I'm assuming your class definition looks something like this:
class CSerialPort {
public:
bool OpenPort(CString portname);
bool WriteByte(const char* bybyte);
private:
HANDLE m_hComm;
byte m_iBytesWritten;
};
byte is not the proper type. DWORD is.
CString may be used, but you are using wide string literals anyway so you could just use CreateFileW, std::wstrings and std::wstring_views.
WriteByte implies that you only want to write one byte - and indeed, your implementation does only write one byte - but it's the wrong byte. It writes one byte out of the memory of the bybyte variable, not the memory it points at.
A minor redefinition of the class:
#include <string_view> // added header
class CSerialPort {
public:
// take a `std::wstring` instead
bool OpenPort(const std::wstring& portname);
// WriteBytes instead of WriteByte:
bool WriteBytes(const void* bytesPtr, DWORD bytesToWrite);
// write both wide and non-wide string_views
bool WriteString(std::string_view str);
bool WriteString(std::wstring_view str);
private:
HANDLE m_hComm;
DWORD m_iBytesWritten; // the proper type
};
The implementation in the .cpp file then becomes:
bool CSerialPort::OpenPort(const std::wstring& portname) {
// Use CreateFileW since you've hardcoded wide string literals anyway:
m_hComm = CreateFileW((L"//./" + portname).c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
return m_hComm != INVALID_HANDLE_VALUE;
}
bool CSerialPort::WriteBytes(const void* bytesPtr, DWORD bytesToWrite)
{
return
WriteFile(m_hComm, bytesPtr, bytesToWrite, &m_iBytesWritten, nullptr) != 0;
}
// the WriteString overloads taking string_views pass on the pointer
// and length to `WriteBytes`:
bool CSerialPort::WriteString(std::string_view str) {
return WriteBytes(str.data(), str.size());
}
bool CSerialPort::WriteString(std::wstring_view str) {
return WriteBytes(str.data(), str.size() * // wchar_t's are more than 1 byte:
sizeof(std::wstring_view::value_type));
}
And your main would then use the WriteString overload taking a std::string_view (by passing a const char* to WriteString):
int main()
{
CSerialPort _serial;
if(_serial.OpenPort(L"COM4")) {
_serial.WriteString("km.press('a')");
} else {
std::cerr << "failed opening COM4\n";
}
}
Note: The section you added at the end has several errors:
string test = "km.move(0,1)";
DWORD dwBytesWritten;
WriteFile(m_hComm,&test,sizeof(test),dwBytesWritten,NULL);
&test takes the address of the std::string object. You should use test.c_str() to get a const char* to the first character in the string.
sizeof(test) gets the size of the std::string object, not the length of the actual string. You should use test.size() instead.
dwBytesWritten is passed by value but the function expects a pointer to a DWORD that it can write to. You should use &dwBytesWritten instead.
WriteFile(m_hComm, test.c_str(), test.size(), &dwBytesWritten, NULL);
I'm new to reverse engineering, and quite new to C++. I'm trying to collect a player's character name in a game using ReadProcessMemory() from the Win32 API, but it throws an exception whenever I try to read it:
if (procId != NULL) {
hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);
ModuleBase = getModuleBaseAddr(procId, "ac_client.exe");
localPlayerptr = ModuleBase + 0x10f4f4;
healthaddr = findDMAaddy(hprocess, localPlayerptr, { 0xf8 });
//load to entitylist Array
ReadProcessMemory(hprocess, (BYTE*)localPlayerptr, &Entitylist[0], sizeof(Entitylist[0]), 0);
for (int i = 1; i < 10; ++i) {
ReadProcessMemory(hprocess, (BYTE*)ModuleBase + 0x10f4f8, &Entitylist[i], sizeof(Entitylist[i]), 0);
ReadProcessMemory(hprocess,(BYTE*) Entitylist[i]+(i*4), &Entitylist[i], sizeof(Entitylist[i]), 0);
std::cout << std::hex << Entitylist[i] << std::endl;
uintptr_t nameaddres;
std::string name;
nameaddres = Entitylist[i] + 0x225;
//ReadProcessMemory(hprocess, (BYTE*)nameaddres, &name, sizeof(name), 0);
/*--> ** This is where I have a problem. ***/
std::cout << name << std::endl;
}
First, you need to determine whether the string you want to read is a wide-byte (wchar) or multi-byte (char) version, then you could use std::string/char* or std::wstring/wchar_t*.
Second, do not use sizeof(std::string), you need to determine the length of the string you want to read.
For wide-byte:
&(std::string)name is not a writable address, as comments pointed out, you could use a wchat_t array instead:
wchat_t name[100];
BOOL ret = ReadProcessMemory(hprocess, (BYTE*)nameaddres, name, sizeof(name), 0);
Or you could use &name[0](From #Remy):
std::wstring name;
name.reserve(100);
BOOL ret = ReadProcessMemory(hprocess, (BYTE*)nameaddres, &name[0], 100*sizeof(wchar_t), 0);
std::wcout << name << std::endl;
Then, std::cout is not available for the wchar_t*, it only prints the address value. It is a local variable in the for loop, so it will reallocate the address every time comes in. Due to certain rules, the system may prefer to choose the same address, so you've got the same address value.
Use the std::wcout << name to out put the wchar_t string, and If the output is always only one character, then you may consider using the multi-byte version to read memory.
When replacing from "wcslen" to "strnlen_s", is it the correct way to typecast with const char*?
In the below function I am replacing
if (szPath[wcslen(szPath) - 1] != L'\\')
with
if (szPath[strnlen_s((const char*)szPath, sizeof(szPath)) - 1] != L'\\')
Below is the code snippet:
bool Activation::Execute()
{
HRESULT hr = S_OK;
typedef ULONG(APIENTRY *ActivateNowProc)(int);
wchar_t szPath[MAX_PATH];
std::fill_n(szPath, MAX_PATH, L'\0');
//Gets the CSIDL Program files path
hr = SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, NULL, szPath);
if (SUCCEEDED(hr))
{
_tcscat_s(szPath, sizeof(szPath) / sizeof(TCHAR), MSC_PATH);
}
if (IsDirectoryExist(szPath))
{
std::wstringstream strActivationLibPath;
strActivationLibPath << szPath;
//if (szPath[wcslen(szPath) - 1] != L'\\')
if (szPath[strnlen_s((const char*)szPath, sizeof(szPath)) - 1] != L'\\')
strActivationLibPath << L"\\";
strActivationLibPath << OOBE_FOLDER_NAME << L"\\" << ACTIVATION_LIB_NAME;
DWORD dwErr = McValidateModule(strActivationLibPath.str().c_str());
if (dwErr != ERROR_SUCCESS)
{
return false;
}
HMODULE hModule = LoadLibrary(strActivationLibPath.str().c_str());
if (hModule == 0)
{
return false;
}
ActivateNowProc ActivateNow = (ActivateNowProc)GetProcAddress(hModule, ACTIVATION_PROC_NAME);
if (ActivateNow)
{
long retVal = ActivateNow(1);
if (retVal == E_FAIL)
{
FreeLibrary(hModule);
return false;
}
else
{
::Sleep(2000);
CheckProcessRunningAndWait(SYNCPROCESSNAME);
}
}
else
{
FreeLibrary(hModule);
return false;
}
FreeLibrary(hModule);
return true;
}
return false;
}
Short answer: No, it is definitely not the correct way!
Reason: Simply casting a wchar_t string pointer to a char pointer won't change the content of the string; as the 16-bit components of the wide string may possibly have elements whose 'upper byte' happens to be zero, then that would signal a premature end to the string. Also, even if this isn't the case, the value strnlen_s returns will be twice the value you want, as it will count each 16-bit wchar_t as two 8-bit char values.
Solution: As Mathieu has said, use wcsnlen_s instead! Always use the wcs... functions with wchar_t strings, and always use the str... functions for char strings.
EDIT: Also, I noticed in your code that you use _tcscat_s. Be careful when using the _tcs… functions on strings that aren't defined as TCHAR - because TCHAR evaluates to either char or wchar_t, depending on what your compile/build settings are. So, add: … and always use _tcs… functions for TCHAR strings!
I'm querying data from the registry and it's being outputted as LPBYTE, and this is where i'm stuck. I need to convert the LPBYTE into a type of data that I can manipulate such as a String.
This is my code so far
HKEY hk;
string poolID;
DWORD dwSize = 0;
DWORD dwDataType = 0;
DWORD dwValue;
LPBYTE lpValue = NULL;
CA2W registryLocation("Software\\Example");
// Check registry if exists, otherwise create.
LONG openReg = RegOpenKeyEx(HKEY_CURRENT_USER, registryLocation, 0, KEY_QUERY_VALUE, &hk);
if (openReg==ERROR_SUCCESS) { } else { cout << "Error (Could not open/create Registry Location)\n"; }
// Get buffer size
LONG getRegBuf = RegQueryValueExA(hk, "", 0, &dwDataType, lpValue, &dwSize);
if (getRegBuf==ERROR_SUCCESS) { cout << "Got reg key buf size\n"; } else { cout << "Error (registry key does not exist)/n"; intro(); }
lpValue = (LPBYTE)malloc(dwSize);
// Open reg value
LONG getReg = RegQueryValueExA(hk, "", 0, &dwDataType, (LPBYTE)&dwValue, &dwSize);
if (getReg==ERROR_SUCCESS) { cout << "Successful\n"; } else { cout << "Error\n"; }
cout << dwValue;
Any help or code examples will be much appreciated.
You need to declare lpValue to be char*.
char* lpValue;
Then allocate it with a call to new.
lpValue = new char[dwSize+1];
Allocate an extra element in case the registry data is mal-formed and is missing a null-terminator. That is something that can happen. Then set the last element to \0:
lpValue[dwSize] = '\0';
Then get the value:
LONG getReg = RegQueryValueExA(..., (LPBYTE)&dwValue, ...);
Deallocate using delete[]:
delete[] lpValue;
I am having problems with reading the registry.
This function finds the number of entries in a registry path. It works perfectly, I have tested it:
void findNumberEntries(registryTest &INSTALLKEY) {
char buffer[50];
char size = sizeof(buffer);
int index = 0;
if(RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)(INSTALLKEY.regpath.c_str()),0,KEY_ALL_ACCESS,&INSTALLKEY.hKey) == ERROR_SUCCESS) {
DWORD readEntry;
do {
readEntry = RegEnumValue(INSTALLKEY.hKey,index,(LPTSTR)buffer,(LPDWORD)&size,NULL,NULL,NULL,NULL);
index++;
}
while(readEntry != ERROR_NO_MORE_ITEMS);
}
INSTALLKEY.number = index;
RegCloseKey(INSTALLKEY.hKey);
}
now, the main function:
std::string regpath32 = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\";
struct registryTest {
HKEY hKey;
std::string regpath;
int number;
};
registryTest INSTALLKEY = {HKEY_LOCAL_MACHINE, regpath32};
findNumberEntries(INSTALLKEY);
printf("%d\n",INSTALLKEY.number);
system("PAUSE");
//until here everything works as it should
HKEY hKey = INSTALLKEY.hKey;
std::string regpath = INSTALLKEY.regpath;
char buffer[50];
char size = sizeof(buffer);
std::string bufferString;
DWORD regOpen = RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
if(regOpen == ERROR_SUCCESS) //this is the part that fails.
{
printf("Registry Key was successfully opened\n");
}
else
{
printf("Unable to open registry key\n");
LPVOID message;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL,(LPTSTR) &message, 0, NULL );
MessageBox(NULL,(LPCTSTR)message,"ERROR",MB_OK|MB_ICONINFORMATION);
}
...rest of the code
I always get "Unable to open registry" and the error message I get is "There are no more files". What is the problem??
your problem is that when you first open the registry key ,you assign it to hkey-member of your struct. So the second time this hkey doesn't contain the original basekey anymore.
change :
DWORD regOpen =
RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
into
DWORD regOpen = RegOpenKeyEx(
HKEY_LOCAL_MACHINE
,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
or change this:
void findNumberEntries( registryTest &INSTALLKEY)
{
char buffer[50];
char size = sizeof(buffer);
int index = 0;
HKEY hkOpen = 0; // can't use INVALID_HANDLE_VALUE for HKEY's;
if (RegOpenKeyEx( INSTALLKEY.hKey ,(LPTSTR)(INSTALLKEY.regpath.c_str())
,0,&hkOpen ) == ERROR_SUCCESS)
{
// You should use RegQueryInfoKey for below code !
DWORD readEntry;
do {
readEntry = RegEnumValue( hkOpen ,index,(LPTSTR)buffer
,(LPDWORD size,NULL,NULL,NULL,NULL);
index++;
}
while(readEntry != ERROR_NO_MORE_ITEMS); }
INSTALLKEY.number = index;
RegCloseKey( hkOpen );
}
You may need to specify KEY_ALL_ACCESS in the second call as well, rather than just in the first. And on Win7 64-bit you may be running into the registry redirect craziness (http://msdn.microsoft.com/en-us/library/aa384232%28VS.85%29.aspx).
EDIT: ah, you might just be getting an ERROR_CANTWRITE back (error code number 5). You might be able to ignore that and see if it still works.
It's very likely that on Windows 7 64-bit that you are being redirected via Registry Virtualization. You can determine what keys are being redirected by calling RegQueryReflectionKey.
If you modify your code to output the actual integer value that is returned rather than a generic "Unable to open key", then it would be helpful. For example,
long n = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("\\SOFTWARE"),
0,KEY_QUERY_VALUE, &hk );
if ( n == ERROR_SUCCESS ) {
cout << "OK" << endl;
}
else {
cout << "Failed with value " << n << endl;
}