SymGetSymFromAddr64 works but SymGetLineFromAddr64 fails with error code 487 - c++

I'm learning StackWalk API provided by "DbgHelp" in Windows 7. I wrote an exception filter that uses StackWalk64. The intention is to back trace at most 50 lines with function name and line number. "StackWalk64" iterates through each stack frame. The address(AddrPC) retrieved from Stack Frame is used in "SymGetSymFromAddr64" and "SymGetLineFromAddr64" to retrieve Symbol name and Line number respectively. But, though "SymGetSymFromAddr64" works successfully, "SymGetLineFromAddr64" fails. The Last Error returned is 487. How can the address work successfully for the former but not for the latter?
Am I missing something? Any Help?
LONG WINAPI TestStackWalker (EXCEPTION_POINTERS* lpFilter)
{
STACKFRAME64 st;
CONTEXT cc;
HANDLE hProcess = ::GetCurrentProcess();
HANDLE hThread = ::GetCurrentThread();
vector<IMAGEHLP_SYMBOL64> vectSymbs(50);
vector<IMAGEHLP_LINE64> vectLines(50);
if (!SymInitialize(hProcess, NULL, TRUE))
{
cout << "Issue with SymInitialize ! " << ::GetLastError() << endl;
return 1;
}
cc = *(lpFilter->ContextRecord);
printContext(cc);
::ZeroMemory(&st, sizeof(st));
st.AddrStack.Mode = AddrModeFlat;
st.AddrStack.Offset = cc.Esp;
st.AddrFrame.Mode = AddrModeFlat;
st.AddrFrame.Offset = cc.Ebp;
st.AddrPC.Mode = AddrModeFlat;
st.AddrPC.Offset = cc.Eip;
for (int i = 0; i < 50; i++)
{
if (!::StackWalk64(IMAGE_FILE_MACHINE_I386,
hProcess,
hThread,
&st,
&cc,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL))
{
cout << "Issue with StackWalkFailed: " << ::GetLastError () <<endl;
return 1;
}
if (st.AddrReturn.Offset == st.AddrPC.Offset)
{
cout << "i think it's done!" << endl;
break;
}
if (st.AddrPC.Offset != 0)
{
vectSymbs[i].SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
vectSymbs[i].MaxNameLength = 1024;
if (!SymGetSymFromAddr64 (hProcess, st.AddrPC.Offset, 0, &vectSymbs[i]))
{
cout << "Issue with Getting Symbol From Address " << ::GetLastError() << endl;
break;
}
SymSetOptions(SYMOPT_LOAD_LINES);
vectLines[i].SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (!SymGetLineFromAddr64 (hProcess, st.AddrPC.Offset, 0, &vectLines[i]))
{
cout << "Issue with Getting Line from Address " << ::GetLastError() << endl;
break;
}
cout << vectSymbs[i].Name << " at " << vectLines[i].LineNumber <<endl;
}
if (st.AddrReturn.Offset == 0)
{
cout << "seems finished " << endl;
break;
}
}
return 1;
}

The pdwDisplacement parameter is not optional:
DWORD dis;
if (!SymGetLineFromAddr64 (hProcess, st.AddrPC.Offset, &dis, &vectLines[i]))
{
cout << "Issue with Getting Line from Address " << ::GetLastError() << endl;
break;
}

I had the same problem. My symbols were on a symbol server. The solution was to put symsrv.dll (from the Windows SDK) next to dbghelp.dll, so it can be loaded. Everything worked after that. In practice, the solution was to distribute both dbghelp.dll and symsrv.dll with my application (together with dbgcore.dll and srcsrv.dll). See the Modules list in Visual Studio, to verify that both symsrv.dll and dbghelp.dll are being loaded from where you expect.
More info here:
https://learn.microsoft.com/en-us/windows/desktop/Debug/using-symsrv
(See "Installation" section)
https://learn.microsoft.com/en-us/windows/desktop/Debug/dbghelp-versions (regarding obtaining and distributing those dlls)

Related

Memory cheating with C++ WinApi

i'm trying to make a little program to my university that can change values in the memory of another process. With the exact address value that the Cheat Engine give me i can do this, but not ever the value is the same then my problem is with the memory pointers. In the following image i has the every offset that i found in the pointer scan map:
I already make a program but it not work and ever gives me 299 error code, i Run it as administrator. The code is the following:
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include <queue>
using namespace std;
int main() {
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(PROCESSENTRY32);
// Snapshot to list all process
HANDLE pHandlers = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if (pHandlers == NULL) {
cout << "Error 1";
return 1;
}
// Listing process
if (Process32First(pHandlers, &pEntry)) {
while (Process32Next(pHandlers, &pEntry)) {
// Convert value to string
wstring wstr(pEntry.szExeFile);
string str(wstr.begin(), wstr.end());
// Check if is the process that i wan't
if (str == "Playgroundd.exe") {
MODULEENTRY32 mEntry;
mEntry.dwSize = sizeof(MODULEENTRY32);
// Snapshot to list all modules inside process
HANDLE mHandlers = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pEntry.th32ProcessID);
if (mHandlers == NULL) {
cout << "Error 2";
return 1;
}
// Usually the first process is the main module
if (Module32First(mHandlers, &mEntry)) {
// Convert the name to string
wstring wstrr(mEntry.szExePath);
string strr(wstrr.begin(), wstrr.end());
if (strr.find("Playgroundd.exe")) {
// Get the base address of module
DWORD moduleBaseAddress = (DWORD)mEntry.modBaseAddr;
// Append initial value
moduleBaseAddress += (DWORD)0x000000E8;
// Offsets defined
DWORD offsets[] = {0x88,0x98,0x90,0x20,0x10,0x48,0x904};
// Open process with the right process id
cout << "process id: " << pEntry.th32ProcessID << endl << endl;
HANDLE processHandler = OpenProcess(PROCESS_ALL_ACCESS, 0, pEntry.th32ProcessID);
if (processHandler == NULL) {
cout << "Can't open the process";
return 1;
}
// Sum offsets
for (int i = 0; i < 7;i++) {
moduleBaseAddress += offsets[i];
}
int receive = 0;
size_t bytesRead = 0;
bool resultStatus = ReadProcessMemory(processHandler,
(LPCVOID)moduleBaseAddress, &receive, sizeof(receive), &bytesRead);
cout << "result status :" << resultStatus << endl;
cout << "Received : " << receive << endl;
cout << "Bytes read : " << bytesRead << endl;
cout << "Possible error code : " << GetLastError() << endl;
}
else {
cout << "Can't find module";
return 1;
}
}
}
}
}
};
This is the output of the above program, the error code can be ignored if the result status be non-zero
result status :0
Received : 0
Bytes read : 0
Possible error code : 299
What i am doing wrong?
As pointed by the comment above, your calculation of the target address is questionable.
Your use of GetLastError is unsafe - you should call it immediately after FAILED call to ReadProcessMemory. However, in this case, cout << ... doesn't change that code, so you are OK.
According to docs
ERROR_PARTIAL_COPY
299 (0x12B)
Only part of a ReadProcessMemory or WriteProcessMemory request was completed.
And this post states
ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.

'dll_file' could be '0': This does not adhere to the specification for the function 'GetProcAddress'

So I would like to use the DLL that I created, and I have this really weird warning I didn't see anyone has this one. I checked if LoadLibray returns "NULL", and this is not the case.
typedef DATA_BLOB(*encryption_decryption)(DATA_BLOB, bool*);
HINSTANCE dll_file = LoadLibrary(L"dllForEncryptionNDecryptionn.dll");
if (dll_file != NULL) {
cout << "Library loaded!" << endl;
}
else {
failed();
}
encryption_decryption encryption = (encryption_decryption)GetProcAddress(dll_file,"encryption");
if(encryption != NULL)
{
cout << "Workded!" << endl;
}
else
{
failed();
}
void failed() {
cout << GetLastError() << endl;
cout << "Faild!" << endl;
}
Warning at the 8th line: "'dll_file' could be '0': this does not adhere to the specification for the function 'GetProcAddress'."
Everything works, it doesn't write any errors when I run it.
If anything goes wrong in LoadLibrary you call failed() that prints the error code and returns.
HINSTANCE dll_file = LoadLibrary(L"dllForEncryptionNDecryptionn.dll");
if (dll_file != NULL) {
cout << "Library loaded!" << endl;
}
else {
failed(); // returns even when dll_file is NULL
}
// so, here you don't know if it's NULL or a valid handle which is why you get the warning
encryption_decryption encryption = (encryption_decryption)GetProcAddress(dll_file,"encryption");
If LoadLibrary fails, you shold not use that dll_file to call GetProcAddress.
encryption_decryption encryption = nullptr;
HINSTANCE dll_file = LoadLibrary(L"dllForEncryptionNDecryptionn.dll");
if(dll_file) {
encryption_decryption encryption =
(encryption_decryption)GetProcAddress(dll_file,"encryption");
} else {
// do NOT call GetProcAddress
}
if(encryption) {
// function successfully loaded
}

C++ Change the desktop with ChangeParametersInfo not working GetLastError returns 0

I'm trying to use the following code to change the wall paper on a Windows 7 machine. I'm compiling with Multi Byte Character Set.
if(SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, L"c:\\temp\\extracted.png", SPIF_SENDCHANGE) != 0)
{
std::cout << "Success !" << std::endl;
}
else
{
std::cout << "Failure :(" << std::endl;
std::cout << "Error: " << GetLastError() << std::endl;
system("title :(");
}
I have no idea of why this is not working since it doesn't return an error code (GetLastError gives 0). No need to say that the wall paper remains unchanged.
EDIT: tried to change to this and to put a bmp file instead.
int error(0);
if(SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, L"c:\\temp\\extracted.bmp", SPIF_SENDCHANGE) != 0)
{
std::cout << "Success !" << std::endl;
}
else
{
error = GetLastError();
std::cout << "Failure :(" << std::endl;
std::cout << "Error: " << error << std::endl;
system("title :(");
}
system("pause");
Output in console is Failure :( followed by Error: 0
From the advice on the comments I abandoned ChangeParametersInfo and implemented this quick function I found. Worked instantly.
void SetWallpaper(LPCWSTR file)
{
CoInitializeEx(0, COINIT_APARTMENTTHREADED);
IActiveDesktop* desktop;
HRESULT status = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&desktop);
WALLPAPEROPT wOption;
ZeroMemory(&wOption, sizeof(WALLPAPEROPT));
wOption.dwSize = sizeof(WALLPAPEROPT);
wOption.dwStyle = WPSTYLE_CENTER;
status = desktop->SetWallpaper(file, 0);
status = desktop->SetWallpaperOptions(&wOption, 0);
status = desktop->ApplyChanges(AD_APPLY_ALL);
desktop->Release();
CoUninitialize();
}
Usage
SetWallpaper(L"c:\\temp\\extracted.png");
This is so much easier than bothering with the old one. Still wondering why it wasn't giving an error. Hope this will help someone else.
Thanks for the advices everyone.

GetProcessDEPPolicy error 87

When I try to check if some process is using data execution protection (DEP) I get error 87 (INVALID_PARAMETER). I checked my code and it seems to be okay but unfortunately I still have the same error.
Code:
BOOL var = true;
DWORD dwPolicy;
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, false, 3624);
if (hProc == NULL) {
cout << "Can't open Process because of the error " << GetLastError() << endl;
}
if (GetProcessDEPPolicy(hProc, &dwPolicy, 0) != FALSE) {
if (dwPolicy == PROCESS_DEP_ENABLE) {
cout << "For try.exe process data execution prevention is enabled" << endl;
}
else if (dwPolicy == NULL) {
cout << "For try.exe process data execution prevention is disabled" << endl;
}
else {
cout << "Data is thrunked and we can't change DEP value in future" << endl;
}
}
else {
cout << "There was an error with discovering DEP in try.exe process because of "<<GetLastError() << endl;
}
After compiling and execution I get:
There was an error with discovering DEP in try.exe process because of 87
Looking at the documentation, the function GetProcessDEPPolicy is defined:
BOOL WINAPI GetProcessDEPPolicy(
_In_ HANDLE hProcess,
_Out_ LPDWORD lpFlags,
_Out_ PBOOL lpPermanent
);
Notice that the last argument is an out parameter and it's not optional, but you're passing 0 aka NULL. The call should be:
BOOL permanent = FALSE;
if (GetProcessDEPPolicy(hProc, &dwPolicy, &permanent) != FALSE) {

DLL Injection fails with code 127

I am trying to do some dll injection. I think I tried everything I could but cound not solve the problem unfortunately. I always get ERROR CODE 127 which means ERROR_PROC_NOT_FOUND. I am using Windows 7 64 bit.
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
char FileToInject[] = "theDll.dll";
char ProcessName[] = "calc.exe";
typedef HINSTANCE (*fpLoadLibrary)(char*);
bool InjectDLL(DWORD processId);
int main() {
DWORD processId = NULL;
PROCESSENTRY32 pre32 = {sizeof(PROCESSENTRY32)};
HANDLE hProcSnap;
cout << "BEFORECreateToolhelo32Snapshot:" << GetLastError() <<endl;
while(!processId) {
system("CLS");
cout << "Searching..." << endl;
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
cout << "CreateToolhelo32Snapshot:" << GetLastError() <<endl;
if(Process32First(hProcSnap, &pre32)) {
do {
if(!(strcmp(pre32.szExeFile, ProcessName))) {
processId = pre32.th32ProcessID;
break;
}
}
while(Process32Next(hProcSnap, &pre32));
}
Sleep(1000);
}
cout << GetLastError() <<endl;
while(!InjectDLL(processId)) {
cout << "DLL Injection failed" << endl;
Sleep(1000);
}
cout << "DLL Injected successfully" << endl;
getchar();
CloseHandle(hProcSnap);
return 0;
}
bool InjectDLL(DWORD processId) {
HANDLE hProc;
LPVOID paramAddr;
cout << "START:" << GetLastError() <<endl;
HINSTANCE hDll = LoadLibrary("KERNEL32");
cout << "LoadLibrary:" << GetLastError() <<endl;
fpLoadLibrary LoadLibraryAddr = (fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
cout << "LoadLibraryArr:" << GetLastError() <<endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
cout << "OpenProcess:" << GetLastError() <<endl;
char DllPath[250] = "C:\\Hacks\test.dll";
paramAddr = VirtualAllocEx(hProc, 0, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
cout << "VirtualAlloxEx:" <<GetLastError() <<endl;
bool MemoryWritten = WriteProcessMemory(hProc, paramAddr, DllPath, strlen(DllPath) + 1, NULL);
cout << "WriteProcessMemory:" << GetLastError() <<endl;
CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryAddr, paramAddr, 0, 0);
cout << "CreateRemoteThread:" <<GetLastError() <<endl;
CloseHandle(hProc);
return MemoryWritten;
}
The output is the following:
Searching...
CreateToolhelp32Snapshot: 18 ERROR_NO_MORE_FILES
LoadLibrary:18 ERROR_NO_MORE_FILES
LoadLibraryArr:127 ERROR_PROC_NOT_FOUND
OpenProcess:127 ERROR_PROC_NOT_FOUND
VirtualAlloxEx:127 ERROR_PROC_NOT_FOUND
WriteProcessMemory:127 ERROR_PROC_NOT_FOUND
CreateRemoteThread:5 ACCESS DENIED
DLL Injected successfully
The program finds the calc.exe as a process with no problem, but after that something goes wrong. Could someone please help me with this?
Thank you,
Tamas
This is one problem:
char DllPath[250] = "C:\\Hacks\test.dll";
The last backslash is not escaped. Change to:
char DllPath[250] = "C:\\Hacks\\test.dll";
The function is called LoadLibraryA(), not LibraryLoadA():
fpLoadLibrary LoadLibraryAddr =
(fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
A few other suggestions:
Only check GetLastError() if the previous WINAPI function failed.
Only continue processing if the previous WINAPI code (or other code) succeeded.
In
fpLoadLibrary LoadLibraryAddr = (fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
you should rather resolve the string LoadLibraryA. The
OpenProcess:127 ERROR_PROC_NOT_FOUND
VirtualAlloxEx:127 ERROR_PROC_NOT_FOUND (<-- sic)
WriteProcessMemory:127 ERROR_PROC_NOT_FOUND
errors are caused because you're using GetLastError even though these functions maybe didn't even fail. So before calling GetLastError, make sure that these functions yield an error return value (NULL or the like).