C++ MiniDumpWriteDump failed - c++

I am trying to create a simple C++ console app which dump the memory space of a given process (e.g. calc.exe) So I use MiniDumpWriteDump function
Here is the code :
DWORD procID = 1150;
char* procName = "calc.exe";
// opens the dump file
HANDLE hFile = CreateFile( "calc.dmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if(hFile)
{
// opens the process
HANDLE hProcToDump = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procID);
if(hProcToDump)
{
// dumps via the API
BOOL rv = MiniDumpWriteDump(hProcToDump, GetProcessId(hProcToDump), hFile, MiniDumpNormal, NULL, NULL, NULL);
HRESULT hr = GetLastError();
if( !rv )
printf("MiniDumpWriteDump failed.");
else
printf("Minidump OK!");
CloseHandle( hFile );
CloseHandle( hProcToDump );
}
}
But I get the error :
GetLastError() = hresult 0x8007012b Only part of a ReadProcessMemory or WriteProcessMemory request was completed
Why ?
Note : I am admin on Win 7 x64.
Thank you for your help.

Try this, which is similar to your example. Usage of MiniDumpWriteDump.

Related

DeviceIoControl fails with error 395 to set a reparse point

Recently I posted this question and now I am trying to set a reparse point after a file modification with WordPad app. Currently I checked that the reparse point is a Microsoft tag and I can save the reparse point data in a REPARSE_DATA_BUFFER pointer before the file lose the reparse point. But when I try to set the reparse point to the file, after a file modification, I always get the 395 error with the GetLastError function after call to DeviceIoControl function using the control code FSCTL_SET_REPARSE_POINT. The error 395 doesn't appear in this System Error Codes although I found this error here that has sense. I also removed the discretionary access control list (DACL) from the file, to grants full access to the file by everyone, before try to set the reparse point but I got the same error. Here I put two fragments of my code to get and set the reparse point. I will appreciate any help.
Code to get the reparse point
HANDLE hDevice = CreateFile(
filePath.c_str(), // File path in the computer
0,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
size_t maxReparse = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
rdb = (REPARSE_DATA_BUFFER*)malloc(maxReparse); // rdb was declared as: REPARSE_DATA_BUFFER* rdb;
DWORD outBufferSize = maxReparse;
DWORD bytesReturned = 0;
if (DeviceIoControl(hDevice, FSCTL_GET_REPARSE_POINT, NULL, 0, rdb, outBufferSize, &bytesReturned, NULL))
{
if (rdb != NULL)
{
if (IsReparseTagMicrosoft(rdb->ReparseTag))
{
wprintf(L"Is a Microsoft tag.\n");
}
Code to set the reparse point
LPTSTR pszObjName = const_cast<wchar_t*>(filePath.c_str()); // File path in the computer
PACL newDACL = NULL; // NULL discretionary access control list to grant full access to everyone
DWORD secInfo = SetNamedSecurityInfo(pszObjName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newDACL, NULL);
if (secInfo == ERROR_SUCCESS)
{
HANDLE hDevice = CreateFile(filePath.c_str(),
GENERIC_ALL, //GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
size_t maxReparse = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
DWORD inBufferSize = maxReparse;
if (rdb != NULL)
{
DWORD bytesReturned = 0;
if (!DeviceIoControl(hDevice, FSCTL_SET_REPARSE_POINT, rdb, inBufferSize, NULL, 0, &bytesReturned, NULL))
{
DWORD error = GetLastError(); // Error 395
unsigned long errorUL = error;
wprintf(L"Error %lu in DeviceIoControl method.\n", errorUL);
}

How can i make createprocess reindirect input success, I have successully get the reindirect out put result

I searched a lot on internet, but most of them are talking about reindirect output. No one gives any successful reindirect input example. For my codes below, it gave right output when I ran command "ipconfig" or "192.168.0.10" because child process ends after running these commands, no input needed. But when I ran command "ftp" instead of "ipconfig" child process which is console is waiting for the next input command. And I tried to write 11111 as input to console in this case as you can see. However console did not receive my input command and waiting for the input command forever. How can I successfully response to "ftp" command in this program and keep console running
#include <windows.h>
#include <fstream>
using namespace std;
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpComLine,
int nCmdShow)
{
SECURITY_ATTRIBUTES secAttr;
HANDLE hRead,hWrite;
char command[256];
char testBuf[256] = {0};
strcpy(command, "ipconfig");
// strcpy(command, "ping 192.168.0.10")
// strcpy(command, "ftp");
secAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
secAttr.lpSecurityDescriptor = NULL;
secAttr.bInheritHandle = TRUE;
HANDLE hTxtFile = CreateFile("tmp.txt", GENERIC_ALL, 0, &secAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hTxtFile == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "Error createfile", NULL, MB_OK);
return 0;
}
HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_WRITE, 0, &secAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hWriteFile == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "Error createWritefile", NULL, MB_OK);
return 0;
}
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
startupInfo.cb = sizeof(STARTUPINFO);
GetStartupInfo(&startupInfo);
startupInfo.hStdError = hTxtFile;
startupInfo.hStdOutput = hTxtFile;
startupInfo.hStdInput = hWriteFile;
startupInfo.wShowWindow = SW_SHOW;
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
char output[10240] = {0};
DWORD bytesRead;
if (!CreateProcess(NULL, command,NULL,NULL,TRUE,NULL,NULL,NULL,&startupInfo,&processInfo))
{
MessageBox(NULL, "Error createprocess", NULL, MB_OK);
CloseHandle(hWrite);
CloseHandle(hRead);
return FALSE;
}
DWORD processExitCode = 0;
strcpy(testBuf, "11111\r\n");
while (GetExitCodeProcess(processInfo.hProcess, &processExitCode))
{
WriteFile(hWriteFile, testBuf, 7, &bytesRead, NULL);
if (processExitCode != STILL_ACTIVE)
{
// MessageBox(NULL, "End process", NULL, MB_OK);
break;
}
Sleep(1000);
}
SetFilePointer(hTxtFile, NULL, NULL, FILE_BEGIN);
ReadFile(hTxtFile, output, 10240, &bytesRead, NULL);
CloseHandle(hTxtFile);
MessageBox(NULL, output, NULL, MB_OK);
return 0;
}
Redirecting (not "reindirecting") input works just the same as redirecting output. Of course, the flow of data is in the opposite direction. This means that the process reads from the file. This in turn means when you open a handle for writing, as you do in the example code:
HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_WRITE, ...);
the process will not be able to read from it. You must open the file for reading:
HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_READ, ...);
But then, this also means that you must prepare the input that you want to send down to the process in advance. It does not help to write to the file after you have created the process.
If you do not know the data that you have to send to the process in advance, you cannot use a file for standard input, but you must use something else, such as a (named or anonymous) pipe.
you must redirect the console output and then write the buffer into file
1)
/* Create a pipe for the child process's STDOUT */
if(!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
BAIL_OUT(-1);
2)
/* Duplicate the pipe HANDLE */
if (!DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
BAIL_OUT(-1);
3)
CHAR chBuf[BUFSIZE];
DWORD dwRead;
DWORD dwAvail = 0;
if (!PeekNamedPipe(hChildStdoutRdDup, NULL, 0, NULL, &dwAvail, NULL) || !dwAvail)
return;
if (!ReadFile(hChildStdoutRdDup, chBuf, min(BUFSIZE - 1, dwAvail), &dwRead, NULL) || !dwRead)
return;
chBuf[dwRead] = 0;
Please find more details here:
https://www.codeproject.com/Articles/5531/Redirecting-an-arbitrary-Console-s-Input-Output

CreateProcess application not found in cache c++ MFC

i am writing a simple program which calls CreateProcess thousands of times, so its taking a while to run. in my output windows i'm seeing this message each time
application "whatever.exe" not found in cache
i call CreateProcess like this
BOOL result = CreateProcess(NULL, g_minicapcmd,
NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInformation);
if (!result) {
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
CString strError = (LPTSTR) lpMsgBuf;
TRACE(_T("::executeCommandLine() failed at CreateProcess()\nCommand=%s\nMessage=%s\n\n"), g_minicapcmd, strError);
LocalFree(lpMsgBuf);
return false;
} else {
// Successfully created the process. Wait for it to finish.
WaitForSingleObject( processInformation.hProcess, INFINITE );
// Close the handles.
CloseHandle( processInformation.hProcess );
CloseHandle( processInformation.hThread );
}
is there a way to get it to cache or some way to make it faster? i already tried putting the .exe its loading on ramdisk and that helped a bit

C++ - CreateRemoteThread DLL Injection [Windows 7]

Wherever I look the method of injecting through CreateRemoteThread is the same, however the method of grabbing the process ID is not... My function will return the correct process ID, and I am not interested in any help on that, so I will void that portion out and only include the actual injection.
I am only just learning DLL injection and am attempting to on notepad.exe. If the injection works, the title of a notepad will change from "Untitled - Notepad" to "Hooked".
#define DLL_NAME "injectme.dll"
.....
BOOL InjectRemoteThread(DWORD ProcessID)
{
HANDLE RemoteProc;
char buf[50] = {0};
LPVOID MemAlloc;
LPVOID LoadLibAddress;
// Process ID does show correctly!
WCHAR id[100];
StringCbPrintf(id, 100, L"%d", ProcessID); // id contains the process ID... is confirmed in comparing ID shown in tasklist and the messagebox.
MessageBox(NULL, id, L"Process ID", MB_ICONINFORMATION);
// Process ID does show correctly!
if ( !ProcessID )
{
MessageBox(NULL, (LPCWSTR)GetLastError(), L"An error occured", NULL);
return 0;
}
RemoteProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
if ( !RemoteProc )
{
MessageBox(NULL, (LPCWSTR)GetLastError(), L"An error occured", NULL);
return 0;
}
LoadLibAddress = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
MemAlloc = (LPVOID)VirtualAllocEx(RemoteProc, NULL, strlen(DLL_NAME)+1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(RemoteProc, (LPVOID)MemAlloc, DLL_NAME, strlen(DLL_NAME)+1, NULL);
CreateRemoteThread(RemoteProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddress, (LPVOID)MemAlloc, NULL, NULL);
CloseHandle(RemoteProc);
VirtualFreeEx(RemoteProc, (LPVOID)MemAlloc, 0, MEM_RELEASE | MEM_DECOMMIT);
return 1;
}
The DLL works on using another person's injector, but I don't understand why...
It is indeed in the same directory as the injector.
I found the problem... I feel so stupid.
Anyone with a similar problem: Instead of a relative path, use an absolute path.
I changed
#define DLL_NAME "injectme.dll"
To
#define DLL_NAME "C:\\Users\\Raikazu\\Documents\\Visual Studio 2012\\Projects\\Hooking\\Release\\injectme.dll"

Creating a MiniDump of a running process

Im trying to make a tool for my end users that can create a MiniDump of my application if it hangs (i.e. external to the app). Im using the same code as the internal MiniDumper but with the handle and processid of the app but i keep getting error code 0xD0000024 when calling MiniDumpWriteDump. Any ideas?
void produceDump( const char* exe )
{
DWORD processId = 0;
HANDLE process = findProcess(exe, processId);
if (!process || processId == 0)
{
printf("Unable to find exe %s to produce dump.\n", exe);
return;
}
LONG retval = EXCEPTION_CONTINUE_SEARCH;
HWND hParent = NULL; // find a better value for your app
// firstly see if dbghelp.dll is around and has the function we need
// look next to the EXE first, as the one in System32 might be old
// (e.g. Windows 2000)
HMODULE hDll = NULL;
char szDbgHelpPath[_MAX_PATH];
if (GetModuleFileName( NULL, szDbgHelpPath, _MAX_PATH ))
{
char *pSlash = _tcsrchr( szDbgHelpPath, '\\' );
if (pSlash)
{
_tcscpy( pSlash+1, "DBGHELP.DLL" );
hDll = ::LoadLibrary( szDbgHelpPath );
}
}
if (hDll==NULL)
{
// load any version we can
hDll = ::LoadLibrary( "DBGHELP.DLL" );
}
LPCTSTR szResult = NULL;
int err = 0;
if (hDll)
{
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
if (pDump)
{
char szDumpPath[_MAX_PATH];
char szScratch [_MAX_PATH];
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
char comAppPath[MAX_PATH];
SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA , NULL, SHGFP_TYPE_CURRENT, comAppPath );
//COMMONAPP_PATH
_snprintf(szDumpPath, _MAX_PATH, "%s\\DN", comAppPath);
CreateDirectory(szDumpPath, NULL);
_snprintf(szDumpPath, _MAX_PATH, "%s\\DN\\D", comAppPath);
CreateDirectory(szDumpPath, NULL);
_snprintf(szDumpPath, _MAX_PATH, "%s\\DN\\D\\dumps", comAppPath);
CreateDirectory(szDumpPath, NULL);
char fileName[_MAX_PATH];
_snprintf(fileName, _MAX_PATH, "%s_Dump_%04d%02d%02d_%02d%02d%02d.dmp", exe, timeinfo->tm_year+1900, timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec );
_snprintf(szDumpPath, _MAX_PATH, "%s\\DN\\D\\dumps\\%s", comAppPath, fileName);
// create the file
HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile!=INVALID_HANDLE_VALUE)
{
MINIDUMP_CALLBACK_INFORMATION mci;
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
mci.CallbackParam = 0;
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
MiniDumpWithDataSegs |
MiniDumpWithHandleData |
//MiniDumpWithFullMemoryInfo |
//MiniDumpWithThreadInfo |
MiniDumpWithProcessThreadData |
MiniDumpWithUnloadedModules );
// write the dump
BOOL bOK = pDump( process, processId, hFile, mdt, NULL, NULL, &mci );
DWORD lastErr = GetLastError();
if (bOK)
{
printf("Crash dump saved to: %s\n", szDumpPath);
return;
}
else
{
_snprintf( szScratch, _MAX_PATH, "Failed to save dump file to '%s' (error %u)", szDumpPath, lastErr);
szResult = szScratch;
err = ERR_CANTSAVEFILE;
}
::CloseHandle(hFile);
}
else
{
_snprintf( szScratch, _MAX_PATH, "Failed to create dump file '%s' (error %u)", szDumpPath, GetLastError());
szResult = szScratch;
err = ERR_CANTMAKEFILE;
}
}
else
{
szResult = "DBGHELP.DLL too old";
err = ERR_DBGHELP_TOOLD;
}
}
else
{
szResult = "DBGHELP.DLL not found";
err = ERR_DBGHELP_NOTFOUND;
}
printf("Could not produce a crash dump of %s.\n\n[error: %u %s].\n", exe, err, szResult);
return;
}
this code works 100% when its internal to the process (i.e. with SetUnhandledExceptionFilter)
Are you opening the process with the necessary access rights? MiniDumpWriteDump() needs the process handle to be opened using PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights. When using GetCurrentProcess(), I think these are granted automatically, but when using OpenProcess() to open another process, you have to request these rights.
To do so, you might also have to enable SeDebugPrivilege, which would cause problems for users whose accounts don't have that privilege. But the documentation doesn't seem to be clear on whether SeDebugPrivilege is necessary for PROCESS_QUERY_INFORMATION and PROCESS_VM_READ rights specifically (as opposed to all process access rights), particularly when opening a process that is running as the same user account.
I see that you are explicitly casting MyMiniDumpCallback to be a PMINIDUMP_CALLBACK_INFORMATION type. That looks fishy, as if you had a compiler error that you were getting around because the types didn't match. That, and PMINIDUMP_CALLBACK_INFORMATION is a struct, not a function pointer.
The direct cast of function pointer to PMINIDUMP_CALLBACK_INFORMATION might be valid since the first parameter of that struct is the callback function. But again, it looks real fishy. Perhaps you misdeclared your callback function (like forgetting the CALLBACK/__stdcall modifier). Get your code to compile without casting those formal params first, then I'll be more inclined to help you.
Also, did you even check that your callback function is even getting called at all?