Dll injection with GetFullPathNameA not working? - c++

If I explicitly write the address the dll injection works
char s[1000]="E:\\worldisnotenough.dll"; //Works
If I use GetFullPathNameA DLL injections do not work, and they do not give any runtime or compile time errors. I checked this:
char s[1000];
int ax =GetFullPathNameA("worldisnotenough.dll",
1000,
s, //Output to save the full DLL path
NULL);
std::cout<<s; //prints the correct path. Working.
The line cout << s prints the correct path, but DLL injection doesn't happen. No errors occur. I checked VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread, and all of them are working properly.
Edit: complete code
#include <QCoreApplication>
#include<windows.h>
#include<tchar.h>
#include<iostream>
#include "E:/Users/Gen/qt project freiza/FreizaLibrary/freizalibrary.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// FreizaLibrary lib;
// QTextStream s(stdin);
// QString value = s.readLine();
// lib.injection(value.toInt());
int procID = 13044;
HANDLE hHandle = OpenProcess( PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ,
FALSE,
procID );
QString dllName = "worldisnotenough.dll";
QFile myDllFile(dllName);
QFileInfo dllInfo(dllName);
QString str =dllInfo.absoluteFilePath();
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll";
std::cout<<strlen(s)<<"\n";
int ax =GetFullPathNameA("worldisnotenough.dll",
86, //I set it to 1000 before posting this question.
s, //Output to save the full DLL path
NULL);
//qDebug()<< QString::fromUtf8(s) <<" "<< ax;
std::cout<<s<<"size "<<ax;
LPVOID dllPathAddr = VirtualAllocEx(hHandle,
0,
strlen(s),
MEM_RESERVE|MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
std::cout<<" test \n";
std::cout<<(int*)dllPathAddr<<endl;
if(dllPathAddr==NULL)
{
qDebug()<<"virtual failed";
}
size_t x;
int n= WriteProcessMemory(hHandle,
dllPathAddr,
s,
strlen(s),
&x);
if(n==0)
{
qDebug()<<"write failed";
}
std::cout<<endl<<n<<"\t"<<x;
LPVOID addr = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
if(addr==NULL)
{
qDebug()<<"get proc failed";
}
HANDLE rThread = CreateRemoteThread(hHandle, NULL, 0, (LPTHREAD_START_ROUTINE)addr,dllPathAddr, 0, NULL);
if(rThread==NULL)
{
qDebug()<<"create remote failed";
}
WaitForSingleObject(rThread, INFINITE);
VirtualFreeEx(hHandle, dllPathAddr, 0, MEM_RELEASE);
CloseHandle(hHandle);
qDebug()<< "done";
return a.exec();
}
And why negative votes?
When I post full code. People say only post the segment of code which is not working.
And I explained the situation to its fullest. Because of these negative votes now I won't be able to ask questions on stackoverflow. Thank you.

Your problem is you are trying to use a statically defined character array as a buffer for GetFullPathNameA!
See here:
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll";
std::cout<<strlen(s)<<"\n";
int ax =GetFullPathNameA("worldisnotenough.dll",
86, //1000 is no good, MAX_PATH is 260
s, //Using 's' as a buffer? Don't do that please!
NULL);
Furthermore when using the ANSI version which you are as denoted by the 'A' a maximum path length of 260 characters is the maximum. MAX_PATH==260
"In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" "
Fixed code: (However I don't use QT so that is missing from here, shouldn't matter though as it wasn't used for anything needed for the injecting to work)
#include <windows.h>
#include <iostream>
#include <tlhelp32.h>
HANDLE GetProcessHandle(wchar_t *ProcessName,ULONG *ReturnedProcessId);
int main(int argc, char *argv[])
{
ULONG procID;
HANDLE hHandle=GetProcessHandle(L"ExeToInjectInto.exe",&procID);
/*HANDLE hHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,procID);*/
std::cout<<"handle: "<<hHandle<<" process ID: "<<procID<<"\n";
char s[]="C:\\Users\\DBVM_OS\\CodeBlocksProjects\\HelpFreizaProject\\bin\\Debug\\mytestdll.dll";
std::cout<<s<<"\n"<<strlen(s)<<"\n";
//First Problem:
/*In the ANSI version of this function, the name is limited to MAX_PATH characters.
To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\"
*/
//Second Problem:
/* Don't use a defined static char[] as a buffer! allocate some memory or use the stack */
//char s2[MAX_PATH];
//int ax=GetFullPathNameA("mytestdll.dll",MAX_PATH,s2,0);
char *s2=new char[MAX_PATH];
if(s2==0) return 0;
int ax=GetFullPathNameA("mytestdll.dll",MAX_PATH,s2,0);
std::cout<<s2<<"\nsize returned: "<<ax<<" strlen: "<<strlen(s2)<<"\n";
LPVOID dllPathAddr=VirtualAllocEx(hHandle,0,(strlen(s2)+1),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
std::cout<<"Remotely Allocated String Address: \n";
std::cout<<(int*)dllPathAddr<<"\n";
if(dllPathAddr==0)
{
OutputDebugStringA("VirtualAllocEx failed...");
return 0;
}
SIZE_T x;
BOOL n=WriteProcessMemory(hHandle,dllPathAddr,s2,(strlen(s2)+1),&x);
if(n==FALSE)
{
OutputDebugStringA("write failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
std::cout<<"WriteProcessMemory Success: "<<n<<", Bytes Written: "<<x<<"\n";
LPVOID addr=(LPVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryA");
if(addr==0)
{
OutputDebugStringA("get proc failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
std::cout<<"LoadLibraryA: "<<addr<<"\n";
HANDLE rThread=CreateRemoteThread(hHandle,0,0,(LPTHREAD_START_ROUTINE)addr,dllPathAddr,0,0);
if(rThread==0)
{
OutputDebugStringA("create remote failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
WaitForSingleObject(rThread,INFINITE);
std::cout<<"DLL Should have been injected successfully at this point...\nFreeing remote string";
BOOL freed=VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
if(freed==0) OutputDebugStringA("Freeing Remote String Failed...");
delete[] s2; //if you dynamically allocated s2 like I've done...
CloseHandle(hHandle);
return 0;
}
HANDLE GetProcessHandle(wchar_t *ProcessName,ULONG *ReturnedProcessId)
{
PROCESSENTRY32W pe;
HANDLE Snap;
ZeroMemory(&pe, sizeof(PROCESSENTRY32W));
pe.dwSize=sizeof(PROCESSENTRY32W);
Snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(Snap==INVALID_HANDLE_VALUE) return 0;
BOOL bProcess=Process32FirstW(Snap,&pe);
while(bProcess)
{
if(_wcsicmp(pe.szExeFile,ProcessName)==0)
{
HANDLE ProcessHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,pe.th32ProcessID);
if(ReturnedProcessId!=0)
*ReturnedProcessId=pe.th32ProcessID;
CloseHandle(Snap);
return ProcessHandle;
}
bProcess=Process32NextW(Snap, &pe);
}
if(ReturnedProcessId!=0) *ReturnedProcessId=0;
CloseHandle(Snap);
return 0;
}

you need to use
strlen(s)+1
cause it returnes the lenght of the string without including the terminating null character itself! So VirtualAllocEx and WriteProcessMemory will not write the '\0' char and the filename will terminate at a "random" position in memory.
Also
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll"; //- Length: 93+1
int ax =GetFullPathNameA("worldisnotenough.dll",
sizeof(s), //<-- old: 86 but s[] is 93 + 1 if this has to hold the total path may it was to small?
s, //Output to save the full DLL path
NULL);
looks wong?!

Related

How to get information about a file for programming on windows

In Linux, we can use the function stat() to get a file info, and use the type st.mode to judge the rights of the file before we can do some operation on it. In windows, I make a lot of attempts, but little help.
At first, I want to use the function GetSecurityInfo, but I can't get the handle argument. I did find some solutions, but they all need use fopen function which is exactly what I want to avoid. Becasue I want to not do anything substantial with the file until I can determine what permissions it has.
Then I try the GetFileSecurityA function, but useless. The following is my code, and I get an error code 998 from getlasterror
void GetFilesInfo(std::string& path)
{
char *path1 = new char[1024];
strcpy(path1, path.c_str());
SECURITY_INFORMATION FLAGS = ATTRIBUTE_SECURITY_INFORMATION;
PSECURITY_DESCRIPTOR file_security_descriptor = new char[1024];
LPDWORD minNeedWords = 0;
if(GetFileSecurityA(path1, FLAGS, file_security_descriptor, 1024, minNeedWords) == 0)
error_die("GetFileInfo");
else
std::cout << file_security_descriptor << std::endl;
}
The answer is as previous comments said. I answered the question for completion.
#include <Windows.h>
void main()
{
TCHAR FileName[] = {L"C:\\Users\\Path\\To\\FileName.extension" };
DWORD LengthNeeded = 0;
SECURITY_DESCRIPTOR* sp = (SECURITY_DESCRIPTOR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,100);
BOOL rs = GetFileSecurity(FileName, ATTRIBUTE_SECURITY_INFORMATION, sp,100,&LengthNeeded);
if (!rs)
{
DWORD e = GetLastError();
//return;
}
HeapFree(GetProcessHeap(), 0,sp);
}

How inject shellcode loaded from file?

I have a big problem that stuck me and today makes tree days trying solve. How i can load a shellcode from a binary file and inject correctly in a target process? When tested only with shellcode on own source code of program example this works fine.
Why this not works when the shellcode comes from a file? Someone already had this problem someday?
Here is the code tested (adapted from this to show a MessageBox) >
#include <windows.h>
#include <iostream>
#include <fstream>
#include <future>
using namespace std;
int main(int argc, char** argv) {
int process_id = atoi(argv[1]);
//MessageBox
//char xcode[] = "\x31\xc9\x64\x8b\x41\x30\x8b\x40\xc\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x1\xda\x8b\x52\x78\x1\xda\x8b\x72\x20\x1\xde\x31\xc9\x41\xad\x1\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x4\x72\x6f\x63\x41\x75\xeb\x81\x78\x8\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x1\xde\x66\x8b\xc\x4e\x49\x8b\x72\x1c\x1\xde\x8b\x14\x8e\x1\xda\x31\xc9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd2\x83\xc4\xc\x59\x50\x51\x66\xb9\x6c\x6c\x51\x68\x33\x32\x2e\x64\x68\x75\x73\x65\x72\x54\xff\xd0\x83\xc4\x10\x8b\x54\x24\x4\xb9\x6f\x78\x41\x0\x51\x68\x61\x67\x65\x42\x68\x4d\x65\x73\x73\x54\x50\xff\xd2\x83\xc4\x10\x68\x61\x62\x63\x64\x83\x6c\x24\x3\x64\x89\xe6\x31\xc9\x51\x56\x56\x51\xff\xd0";
vector<char> xcode;
ifstream infile;
infile.open("shellcode.bin", std::ios::in | std::ios::binary);
infile.seekg(0, std::ios::end);
size_t file_size_in_byte = infile.tellg();
xcode.resize(file_size_in_byte);
infile.seekg(0, std::ios::beg);
infile.read(&xcode[0], file_size_in_byte);
infile.close();
HANDLE process_handle;
DWORD pointer_after_allocated;
process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
if (process_handle == NULL)
{
puts("[-]Error while open the process\n");
}
else {
puts("[+] Process Opened sucessfully\n");
}
pointer_after_allocated = (DWORD)VirtualAllocEx(process_handle, NULL, sizeof(xcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pointer_after_allocated == NULL) {
puts("[-]Error while get the base address to write\n");
}
else {
printf("[+]Got the address to write 0x%x\n", pointer_after_allocated);
}
if (WriteProcessMemory(process_handle, (LPVOID)pointer_after_allocated, &xcode[0] /*(LPCVOID) shellcode*/, sizeof(xcode), 0)) {
puts("[+]Injected\n");
puts("[+]Running the shellcode as new thread !\n");
CreateRemoteThread(process_handle, NULL, 100, (LPTHREAD_START_ROUTINE)pointer_after_allocated, NULL, NULL, NULL);
}
else {
puts("Not Injected\n");
}
return 0;
}
It is because you are using sizeof(xcode). In first case it is a string constant with size known at compile time. In your case, the second one, the sizeof (xcode) returns 4 (or 8 depending on architecture). You should use file_size_in_byte instead. See this piece of code:
pointer_after_allocated = (DWORD)VirtualAllocEx(process_handle, NULL, sizeof(xcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
....
if (WriteProcessMemory(process_handle, (LPVOID)pointer_after_allocated, &xcode[0] /*(LPCVOID) shellcode*/, sizeof(xcode), 0))
The sizeof is meaningless in both, VirtualAllocEx and WriteProcessMemory. Consider replacing with the size of the file:
pointer_after_allocated = (DWORD)VirtualAllocEx(process_handle, NULL, file_size_in_byte, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
....
if (WriteProcessMemory(process_handle, (LPVOID)pointer_after_allocated, &xcode[0], file_size_in_byte, 0))
As commented by Botje:
update 1: You can pass xcode.data() and xcode.size() instead
update 2: The C++ escape symbols \x31, four symbols (bytes), is a C++ textual hex representation of a binary byte. Is something meant to be read/edited by human. The real .bin file should not be a textual file with C++ escape symbols and can be edited with a hex editor.

What's the actual size of PSAPI_WORKING_SET_INFORMATION buffer used in QueryWorkingSet function of PSAPI.h

I'd like to use the function QueryWorkingSet available in PSAPI, but I'm having trouble to actually define the size of the buffer pv. Here is the code :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi, wsi2;
GetSystemInfo(&si);
QueryWorkingSet(thisProcess, &wsi, sizeof(wsi));
DWORD wsi2_buffer_size = (wsi.NumberOfEntries) * sizeof(PSAPI_WORKING_SET_BLOCK);
if (!QueryWorkingSet(thisProcess, &wsi2, wsi2_buffer_size))
{
std::cout << "ERROR CODE : " << GetLastError() << std::endl;
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
I keep ending up with abort() being called and either an error code 24 or 998 during the first call to testQueryWorkingSet(). that I interpret respectively as : wsi2_buffer_size is too low and wsi2_buffer_size is too big.
Now I have no idea of the value this variable should take, I tried :
counting everything including the NumberOfEntries field, that is DWORD wsi2_buffer_size = sizeof(wsi.NumberOfEntries) + wsi.NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK); => error 998;
counting only the number of entries, that is the code given above => error 998;
the size of the variable wsi2, that is DWORD wsi2_buffer_size = sizeof(wsi2); => error 24;
There has to be something I do not understand in the way we're supposed to use this function but I can't find what. I tried to adapt the code given there, that is :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi_1, * wsi;
DWORD wsi_size;
GetSystemInfo(&si);
wsi_1.NumberOfEntries = 0;
QueryWorkingSet(thisProcess, (LPVOID)&wsi_1, sizeof(wsi));
#if !defined(_WIN64)
wsi_1.NumberOfEntries--;
#endif
wsi_size = sizeof(PSAPI_WORKING_SET_INFORMATION)
+ sizeof(PSAPI_WORKING_SET_BLOCK) * wsi_1.NumberOfEntries;
wsi = (PSAPI_WORKING_SET_INFORMATION*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, wsi_size);
if (!QueryWorkingSet(thisProcess, (LPVOID)wsi, wsi_size)) {
printf("# Second QueryWorkingSet failed: %lu\n"
, GetLastError());
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
This code is working for only 1 call to testQueryWorkingSet(), the second one is aborting with error code 24. Here are the questions in brief :
How would you use QueryWorkingSet in a function that you could call multiple times successively?
What is representing the value of the parameter cb of the documentation given a PSAPI_WORKING_SET_INFORMATION?
Both examples are completely ignoring the return value and error code of the 1st call of QueryWorkingSet(). You are doing error handling only on the 2nd call.
Your 1st example fails because you are not taking into account the entire size of the PSAPI_WORKING_SET_INFORMATION when calculating wsi2_buffer_size for the 2nd call of QueryWorkingSet(). Even if the 1st call were successful, you are not allocating any additional memory for the 2nd call to fill in, if the NumberOfEntries returned is > 1.
Your 2nd example is passing in the wrong buffer size value to the cb parameter of the 1st call of QueryWorkingSet(). You are passing in just the size of a single pointer, not the size of the entire PSAPI_WORKING_SET_INFORMATION. Error 24 is ERROR_BAD_LENGTH. You need to use sizeof(wsi_1) instead of sizeof(wsi).
I would suggest calling QueryWorkingSet() in a loop, in case the working set actually changes in between the call to query its size and the call to get its data.
Also, be sure you free the memory you allocate when you are done using it.
With that said, try something more life this:
void testQueryWorkingSet()
{
HANDLE thisProcess = GetCurrentProcess();
PSAPI_WORKING_SET_INFORMATION *wsi, *wsi_new;
DWORD wsi_size;
ULONG_PTR count = 1; // or whatever initial size you want...
do
{
wsi_size = offsetof(PSAPI_WORKING_SET_INFORMATION, WorkingSetInfo[count]);
wsi = (PSAPI_WORKING_SET_INFORMATION*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wsi_size);
if (!wsi)
{
printf("HeapAlloc failed: %lu\n", GetLastError());
abort();
}
if (QueryWorkingSet(thisProcess, wsi, wsi_size))
break;
if (GetLastError() != ERROR_BAD_LENGTH)
{
printf("QueryWorkingSet failed: %lu\n", GetLastError());
HeapFree(GetProcessHeap(), 0, wsi);
abort();
}
count = wsi->NumberOfEntries;
HeapFree(GetProcessHeap(), 0, wsi);
}
while (true);
// use wsi as needed...
HeapFree(GetProcessHeap(), 0, wsi);
}

Get file size using GetFileSize reports a segv on a valid file

I have an application that scans file and collects meta data about a file. One function is to get the file size of a file. To do so, I am using the winapi function GetFileSizeEx(Handle, PLARGE_INTEGER). The parameters require a file HANDLE and a reference to a PLARGE_INTEGER aka (*LARGE_INTEGER).
To get a file HANDLE in Qt, it is suggested here to get the file handle using QFile::handle() and pass the result into _get_osfhandle(int) and cast it as a HANDLE.
HANDLE handle = (HANDLE) _get_osfhandle(file.handle()).
Using this handle, pass it with a PLARGE_INTEGER variable into the [GetFileSizeEx(Handle, PLARGE_INTEGER)] which returns 0 if the operation failed or != 0 if the operation succeeded.
GetFileSize(HANDLE, PLARGE_INTEGER) returns with:
0 (or failure), one can use GetLastError in accordance with this list of error codes (as a start, there are many more) to help.
any non-zero value indicating success
Problem:
Using this approach, I attempt the same on a valid file, however I get a SEGV when calling GetFileSizeEx(Handle, PLARGE_INTEGER). I attempted this before and after calling QFile::open(QIODevice::ReadOnly) as a test, however it fails non the less.
int localHandle = file.handle(); // handle returns -1 as expected
bool localOpen = file.open(QIODevice::ReadOnly);
if (localOpen) {
int localFileHandle = file.handle(); // returns a valid >0 handle value
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle); // returns a valid > 0 handle value
PLARGE_INTEGER l = PLARGE_INTEGER(); // representation value of 0
BOOL b = GetFileSizeEx(handle, l); // segv
if (!b) {
qDebug() << getLastErrorMsg();
return QFileInfo(filepath).size();
}
return l->QuadPart;
}
Did I do something wrong?
See attached screenshot
MVCE
#include <QCoreApplication>
#include "windows.h"
#include <comdef.h>
#include <QFile>
#include <QDebug>
#include <QString>
#include <QFileInfo>
#include <windows.h>
#include <fileapi.h>
#include <io.h>
static QString toString(HRESULT hr)
{
_com_error err{hr};
const TCHAR* lastError = err.ErrorMessage();
return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0'))
.arg(lastError);
}
static QString getLastErrorMsg()
{
DWORD lastError = GetLastError();
QString s = toString(HRESULT_FROM_WIN32(lastError));
return s;
}
static qint64 getWinAPIFileSize(QString filepath)
{
QFile file(filepath);
if (!file.exists()) {
return 0;
}
int localHandle = file.handle(); // handle returns -1 as expected
bool localOpen = file.open(QIODevice::ReadOnly);
if (localOpen) {
int localFileHandle = file.handle(); // returns a valid >0 handle value
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle); // returns a valid > 0 handle value
PLARGE_INTEGER l = PLARGE_INTEGER(); // representation value of 0
BOOL b = GetFileSizeEx(handle, l); // segv
if (!b) {
qDebug() << getLastErrorMsg();
return QFileInfo(filepath).size();
}
return l->QuadPart;
}
return QFileInfo(filepath).size();
}
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
QString src = QString("C:/Users/CybeX/.bash_history"); // change path to a valid file on your PC
qint64 size = getWinAPIFileSize(src);
qDebug() << size;
return a.exec();
}
The type PLARGE_INTEGER is an alias for "pointer to LARGE_INTEGER". And PLARGE_INTEGER() is a default value initialization for the type "pointer to LARGE_INTEGER". And for all pointers such an initialization is a null pointer.
That means the definition
PLARGE_INTEGER l = PLARGE_INTEGER();
is equivalent to
LARGE_INTEGER* l = nullptr;
Which means you pass a null-pointer to GetFileSizeEx.
You need to create an actual LARGE_INTEGER object, and pass a pointer to that object using the address-of operator &:
LARGE_INTEGER l;
GetFileSizeEx(handle, &l); // Pass pointer to the variable l
The problem is that you are mishandling the PLARGE_INTEGER. You are creating a PLARGE_INTEGER (aka LARGE_INTEGER*) pointer that doesn't actually point anywhere, which is why GetFileSizeEx() crashes when it tries to write out the file size.
You need to allocate a LARGE_INTEGER (not a PLARGE_INTEGER) and then pass its memory address to GetFileSizeEx(), eg:
static qint64 getWinAPIFileSize(QString filepath)
{
QFile file(filepath);
if (file.open(QIODevice::ReadOnly)) {
int localFileHandle = file.handle();
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle);
LARGE_INTEGER l;
if (GetFileSizeEx(handle, &l)) {
return l.QuadPart;
}
qDebug() << getLastErrorMsg();
}
return QFileInfo(file).size();
}
That being said, there is really no point in using GetFileSizeEx() manually at all in this situation. Depending on its implementation (which I can't check), QFileInfo.size() will either open the file for you, or it will simply query the file's size directly from the filesystem's metadata and not actually open the file at all:
static qint64 getWinAPIFileSize(QString filepath)
{
return QFileInfo(filepath).size();
}

Stackbased buffer overrun

When running my code I get the following error:
Unhandled exception at 0x00BA16A0 in GameLauncher.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
I have no idea what could be causing this. It is caused with the following code:
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
int main()
{
std::cout << "Which process would you like to close? (Include .exe)" << std::endl;
wchar_t userProcessToFind;
std::wcin.getline(&userProcessToFind, 20);
HANDLE processSnapshot;
DWORD processID = 0;
PROCESSENTRY32 processEntery;
processEntery.dwSize = sizeof(PROCESSENTRY32);
processSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, processID);
if(Process32First(processSnapshot, &processEntery) == TRUE)
{
while (Process32Next(processSnapshot, &processEntery) == TRUE)
{
if (_wcsicmp(processEntery.szExeFile, &userProcessToFind) == 0)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, processEntery.th32ProcessID);
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}
CloseHandle(processSnapshot);
}
return 0;
}
In
wchar_t userProcessToFind;
std::wcin.getline(&userProcessToFind, 20);
You have allocated space for a single wchar_t but you are trying to read in up to 20 characters and place it in the memory at the address of userProcessToFind. This will cause stack corruption as you are going to try to write into memory that does not belong to &userProcessToFind. What you need to do is create an array like
wchar_t userProcessToFind[20];
std::wcin.getline(userProcessToFind, 20);
Or you could use a std::wstring and your code would become
std::wstring userProcessToFind;
std::getline(std::wcin, userProcessToFind);
This gives the benefit of not having to use an arbitrary size for the process name as std::wstring will scale to fit the input. If you need to pass the underlying wchar_t* to a function you can use std::wstring::c_str() to get it.