I am trying to use node-ffi to interface with the win32 api FormatMessageA however I cannot seem to get the out lpBuffer parameter, here is a snippet of code to show what I have tried
'use strict';
const ref = require('ref');
const ffi = require('ffi');
const Kernel32 = ffi.Library('Kernel32.dll', {
FormatMessageA: ['ulong', [
'ulong', //flags
'void *',
'ulong', //status number
'ulong', //language
'uchar *',
'ulong',
'void *'
]]
});
const FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
const FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100;
const FORMAT_MESSAGE_IGNORE_INSERTS = 0x200;
const lpBuffer = ref.alloc('uchar *');
const result = Kernel32.FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
null,
0x80090300, //error code
0,
lpBuffer,
0,
null
);
console.log(result); //prints 57 bytes
I know function is successful as it returns 57 however I cannot get lpBuffer value which contains the error string I require.
As I stated in my 1st comment, according to [MSDN] FormatMessage function:
FORMAT_MESSAGE_ALLOCATE_BUFFER description:
The lpBuffer parameter is a pointer to an LPTSTR; you must cast the pointer to an LPTSTR (for example, (LPTSTR)&lpBuffer).
The (2nd) example at the bottom of the page:
// Some code (not relevant for this problem)
LPWSTR pBuffer = NULL;
// Some more code (still not relevant)
FormatMessage(FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
pMessage,
0,
0,
(LPWSTR)&pBuffer,
// The rest of the code (not relevant)
when the dwFlags argument is composed of FORMAT_MESSAGE_ALLOCATE_BUFFER, the function expects that the lpBuffer argument which is a LPTSTR (pointer to TCHAR), to actually be a pointer to LPTSTR (double pointer to TCHAR) cast ed to LPTSTR.
That, translated in JS (that I have no experience with), would mean:
const lpBuffer = ref.alloc('uchar **');
Note: according to the same page, the buffer should be freed using LocalFree when it's no longer needed (makes sense, since FormatMessage allocates memory for it - that's why it requires to be a double pointer). Again, don't know how this would translate in JS (what I do know is that LocalFree should be called on an uchar *(dereferenced) buffer, not directly on lpBuffer).
Related
I am trying to use the RegGetValueA() from the Windows API , but so far I've been unable to get any results from it. At best, I get a "file not found" error, and at worst it crashes hard without any error messages at all.
Below is the current code I have; I'm not sure what is and isn't relevant, and what might be causing the problem or not. I've only got a smidge of C knowledge, so please try to keep it simple.
ffi.cdef([[
typedef void * HKEY;
typedef HKEY * PHKEY;
typedef unsigned long DWORD;
int RegGetValueA(HKEY handle, const char* path, const char* value, int filter_flags, void* unused, char *result, DWORD* size);
]])
local size = ffi.new('DWORD[1]')
size = 1024
local data = ffi.new('char['..size..']')
local dptr = ffi.cast('char*', data)
local lenptr = ffi.cast('DWORD*', size)
test = reg.RegGetValueA(ffi.cast("HKEY", ffi.cast("uintptr_t",0x80000002)), "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\CereVoice Heather 5.0.1", "CLSID", 0x0000ffff, nil, dptr, lenptr)
When you use ffi.new, what you get is a pointer variable, and you assign the pointer to 1024, and then use ffi.cast to convert to DWORD *, which causes an access address conflict when calling RegGetValueA, so the program crashes.
You only need to modify the code as follows:
local ffi = require("ffi")
ffi.cdef([[
typedef void * HKEY;
typedef HKEY * PHKEY;
typedef unsigned long DWORD;
int RegGetValueA(HKEY handle, const char* path, const char* value, int
filter_flags, void* unused, char *result, DWORD* size);
]])
local size = 1024
local data = ffi.new('char['..size..']')
local dptr = ffi.cast('char*', data)
local lenptr = ffi.new('DWORD[1]', size)
local test = ffi.C.RegGetValueA(ffi.cast("HKEY", ffi.cast("uintptr_t",0x80000002)), "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\CereVoice Heather 5.0.1", "CLSID", 0x0000ffff, nil, dptr, lenptr)
print(test)
print(ffi.string(dptr))
I get a "file not found" error
This means "registry key not found".
There are two different registries in 64-bit Windows, you should try reading from both of them:
local ffi = require'ffi'
ffi.cdef"int RegGetValueA(uintptr_t, const char*, const char*, uint32_t, void*, char*, uint32_t*);"
local size = 1024
local pcbData = ffi.new'uint32_t[1]'
local pvData = ffi.new('char[?]', size)
local RRF_SUBKEY_WOW6464KEY = 0x00010000
local RRF_SUBKEY_WOW6432KEY = 0x00020000
for _, WOW64_flag in ipairs{RRF_SUBKEY_WOW6464KEY, RRF_SUBKEY_WOW6432KEY} do
pcbData[0] = size
local errcode = ffi.C.RegGetValueA(
0x80000002, -- HKLM
"SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\MS-Anna-1033-20-DSK",
"CLSID",
0x0000ffff + WOW64_flag,
nil,
pvData,
pcbData
)
if errcode == 0 then
break
end
end
print(ffi.string(pvData))
I'm trying to replace a specific string in memory belongs to a dll. Here's the code.
I can read it, and it gives me correct result, but when writing VC++ shows 'Access violation writing location'.
HMODULE HMODULE1 = LoadLibrary(L"my.dll");
std::string x1(8, '\0');
std::string x2 = "CIFCDMEY";
auto startPos = (void*)((char*)(HMODULE1)+0x1158A0 + 9);
// Correct, I can read the memory
memcpy_s((void*)x1.data(), x1.size(), startPos, x1.size());
// Access violation writing location
memcpy_s(startPos, x2.size(), x2.data(), x2.size());
auto handle = GetCurrentProcess();
SIZE_T num;
auto ret = WriteProcessMemory(handle, startPos, x2.data(), x2.size(), &num);
auto lastError1 = GetLastError();
LPVOID lpMessageBuffer1 = NULL;
size_t size1 = ::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
lastError1,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMessageBuffer1,
0,
NULL);
std::wstring errorMessage1;
if (size1 > 0) {
// errorMessage1: Invalid access to memory location.
errorMessage1 = std::wstring((LPCTSTR)lpMessageBuffer1, size1);
}
In 'Watch' window, the value of variable startPos is my.dll!0x0f2a58a9 (load symbols for additional information).
I know people use 'WriteProcessMemory' to write memory of a process, how about a dll?
If the target memory page does not have write permissions you need to take them using VirtualProtect()
I use a simple wrapper function for all my patching, it uses the PAGE_EXECUTE_READWRITE memory protection constant because if you are modifying a code page this will avoid crashes when the instruction pointer lands in the same memory page and you only used PAGE_READWRITE
void Patch(char* dst, char* src, const intptr_t size)
{
DWORD oldprotect;
VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
memcpy(dst, src, size);
VirtualProtect(dst, size, oldprotect, &oldprotect);
}
The docs for ExpandEnvironmentStrings say:
If the function fails, the return value is zero. To get extended error information, call GetLastError.
However, I have not been able to produce a test case where the function would return zero.
DWORD WINAPI ExpandEnvironmentStrings(
_In_ LPCTSTR lpSrc,
_Out_opt_ LPTSTR lpDst,
_In_ DWORD nSize
);
If either of the pointers is NULL, it just crashes and the size parameter isn't able to produce any error (if it's to small, the function returns the required size).
So is there any known case under which this function would return zero and do a SetLastError?
I wrote a simple application on Qt4 that modifier network adapter parameters, for that I have a slot called setInterfaceParams, implemented as so:
DWORD WinNetInterface::setInterfaceParams(QString index, QString ip, QString netmask, QString gateway)
{
DWORD res = NULL;
HINSTANCE lib = (HINSTANCE) LoadLibrary((WCHAR *)"iphlpapi.dll");
_SetAdapterIpAddress SetAdapterIpAddress = (_SetAdapterIpAddress) GetProcAddress(lib, "SetAdapterIpAddress");
PWSTR pszGUID = NULL;
//char *szGUID = (char *)index.toStdString().c_str();
QByteArray a = index.toLocal8Bit();
char *szGUID = a.data();
WideCharToMultiByte(CP_ACP, 0, pszGUID, -1, szGUID, sizeof(szGUID), NULL, NULL);
// Method 01
res = SetAdapterIpAddress(szGUID,
0,
inet_addr(ip.toStdString().c_str()),
inet_addr(netmask.toStdString().c_str()),
inet_addr(gateway.toStdString().c_str()));
// End of method 01
// Method 02
/*res = SetAdapterIpAddress("{422C5689-A17B-402D-A6A2-22CE13E857B5}",
0,
inet_addr("192.168.1.10"),
inet_addr("255.255.255.0"),
inet_addr("192.168.1.1"));*/
// End of method 02
return res;
}
When I click on button that connected to slot setInterfaceParams, I get segmentation fault. If I comment method01, nothing happen, the some thing happen when I use method02.
I tried this function on a simple c++ application and it is work fine, test on Windows XP SP3.
#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <iostream>
typedef DWORD (WINAPI *_SetAdapterIpAddress )(char *szAdapterGUID,
DWORD dwDHCP,
DWORD dwIP,
DWORD dwMask,
DWORD dwGateway);
int main()
{
HINSTANCE lib = (HINSTANCE) LoadLibrary("iphlpapi.dll");
_SetAdapterIpAddress SetAdapterIpAddress = (_SetAdapterIpAddress) GetProcAddress(lib, "SetAdapterIpAddress");
PWSTR pszGUID = NULL;
char szGUID[] = "{422C5689-A17B-402D-A6A2-22CE13E857B5}";
DWORD dwSize = 0;
WideCharToMultiByte(CP_ACP, 0, pszGUID, -1, szGUID, sizeof(szGUID), NULL, NULL);
DWORD res = SetAdapterIpAddress(szGUID,
0,
inet_addr("192.168.1.10"),
inet_addr("255.255.255.0"),
inet_addr("192.168.1.1"));
std::cout << res;
return 0;
}
LoadLibrary((WCHAR *)"iphlpapi.dll");
That can't work, the literal string is in 8-bits, casting it without real conversion doesn't make it wide, so the dll loading probably failed.
You should use the TEXT or _T macro around most of the literal strings passed to WinAPI functions to make them regular or wide depending on the compilation options:
LoadLibrary(_T("iphlpapi.dll"));
which will translate to either LoadLibrary("iphlpapi.dll"); or LoadLibrary(L"iphlpapi.dll");.
Also you should always check the value returned by the LoadLibrary and GetProcAddress functions, which return NULL if the call is unsuccessful.
It's taken a few years, but I am finally taking the plunge into VC++. I need to be able to read x number of sectors of a physical device (namely a hard drive). I am using the CreateFile() and SetFilePointerEx() and ReadFile() APIs.
I have done a LOT of reading online in all the major forums about this topic. I have exhausted my research and now I feel it's time to ask the experts to weigh in on this dilemma. As this is my very first post ever on this topic, please go easy on my :)
I should also point out that this is a .DLL that I consume with a simple C# app. The plumbing all works fine. It's the SetFilePointer(Ex)() APIs that are causing me grief.
I can get the code to work up until about the size of a LONG (4,xxx,xxx) - I can't remember the exact value. It suffices to say that I can read everything up to and including sector # 4,000,000 but not 5,000,000 or above. The problem lies in the "size" of the parameters for the SetFilePointer() and SetFilePointerEx() APIs. I've tried both and so far, SetFilePointerEx() seems to be what I should use to work on 64-bit systems.
The 2nd and 3rd parameters of the SetFilePointer are defined as follows:
BOOL WINAPI SetFilePointerEx(
__in HANDLE hFile,
__in LARGE_INTEGER liDistanceToMove,
__out_opt PLARGE_INTEGER lpNewFilePointer,
__in DWORD dwMoveMethod
);
Please note that I have tried passing the LowPart and the HighPart as the 2nd and 3 parameters without any success as I get a CANNOT CONVERT LARGE_INTEGER TO PLARGE_INTEGER (for parameter 3).
HERE IS MY CODE. I USE A CODE-BREAK TO VIEW buff[0], etc. I would like to read past the 4,xxx,xxx limitation. Obviously I am doing something wrong. Each read past this limit resets my file pointer to sector 0.
#include "stdafx.h"
#include <windows.h>
#include <conio.h>
extern "C"
__declspec(dllexport) int ReadSectors(long startSector, long numSectors)
{
HANDLE hFile;
const int SECTOR_SIZE = 512;
const int BUFFER_SIZE = 512;
LARGE_INTEGER liDistanceToMove;
PLARGE_INTEGER newFilePtr = NULL; // not used in this context.
// just reading from START to END
liDistanceToMove.QuadPart = startSector * SECTOR_SIZE;
DWORD dwBytesRead, dwPos;
LPCWSTR fname = L"\\\\.\\PHYSICALDRIVE0";
char buff[BUFFER_SIZE];
// Open the PHYSICALDEVICE as a file.
hFile = CreateFile(fname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// Here's the API definition
/*BOOL WINAPI SetFilePointerEx(
__in HANDLE hFile,
__in LARGE_INTEGER liDistanceToMove,
__out_opt PLARGE_INTEGER lpNewFilePointer,
__in DWORD dwMoveMethod
);*/
dwPos = SetFilePointerEx(hFile, liDistanceToMove, NULL, FILE_BEGIN);
if(ReadFile(hFile, buff, BUFFER_SIZE, &dwBytesRead, NULL))
{
if(dwBytesRead > 5)
{
BYTE x1 = buff[0];
BYTE x2 = buff[1];
BYTE x3 = buff[2];
BYTE x4 = buff[3];
BYTE x5 = buff[4];
}
}
// Close both files.
CloseHandle(hFile);
return 0;
}
startSector * SECTOR_SIZE;
startSector is a long (32bits), SECTOR_SIZE is a int (also 32bits), multiply these two guys and the intermediate result is going to be a long, which will overflow and you then stuff it into the __int64 of the LARGE_INTEGER, which is too late. You want to operate on __int64s, something like
liDistanceToMove.QuadPart = startSector;
liDistanceToMove.QuadPart *= SECTOR_SIZE;
for example.