|
Well, it's a bit long winded, but something like this:
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPTSTR szExeName = GetCommandLine();
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( ! ::CreateProcess( L"Demo.exe", 0, 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi ) )
return NULL;
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS , FALSE, pi.dwProcessId );
CONTEXT context;
ZeroMemory( &context, sizeof( CONTEXT ) );
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
if ( ! GetThreadContext( pi.hThread, &context ) )
return 0;
LDT_ENTRY entry;
ZeroMemory( &entry, sizeof( LDT_ENTRY ) );
GetThreadSelectorEntry( pi.hThread, context.SegFs, &entry );
DWORD dwFSBase = ( entry.HighWord.Bits.BaseHi << 24 ) | ( entry.HighWord.Bits.BaseMid << 16 ) | ( entry.BaseLow );
DWORD read;
Local::TEB teb; ZeroMemory( &teb, sizeof( Local::TEB ) );
Local::PPEB pPeb = NULL;
if ( ReadProcessMemory( hProcess, (LPCVOID)(DWORD_PTR)dwFSBase, &teb, sizeof( Local::TEB ), &read ) )
pPeb = teb.Peb;
else
return NULL;
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeader;
DWORD dwBase = (DWORD)(DWORD_PTR)pPeb->ImageBaseAddress;
DWORD dwSize = 0;
ReadProcessMemory( hProcess, (LPCVOID)(DWORD_PTR)dwBase, &DosHeader, sizeof( IMAGE_DOS_HEADER ), &read );
if ( DosHeader.e_magic != IMAGE_DOS_SIGNATURE )
throw "Not a valid executable file.\n";
ReadProcessMemory( hProcess, (LPCVOID)(DWORD_PTR)(dwBase + DosHeader.e_lfanew), &NtHeader, sizeof( IMAGE_NT_HEADERS ), &read );
if ( NtHeader.Signature != IMAGE_NT_SIGNATURE )
throw "No PE header found.\n";
dwSize = NtHeader.OptionalHeader.SizeOfImage;
BOOL bSuccess = FALSE;
DWORD dwOldProtect;
bSuccess = VirtualProtectEx( hProcess, (PVOID)dwBase, m_dwImageSize, PAGE_EXECUTE_READWRITE, &dwOldProtect );
...
bSuccess = VirtualProtectEx( hProcess, (PVOID)dwBase, m_dwImageSize, PAGE_EXECUTE, &dwOldProtect );
CloseHandle( hProcess );
ResumeThread( pi.hThread );
return pi.hProcess;
I realize CreateProcess() should return with ALL_ACCESS_RIGHTS but I thought I would try the OpenProcess() also.
|
|
|
|
|
WalderMort wrote: if( ! ::CreateProcess( L"Demo.exe", 0, 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi ) )
I doubt the create suspended is making some problem. can you change it to NULL and try?
Also i found you are doing som much code to find the base address of the code. you can achive the same by the following code
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pi.dwProcessId );<br />
MODULEENTRY32 stEntry = {0};<br />
stEntry.dwSize = sizeof(MODULEENTRY32);<br />
Module32First( hSnap, &stEntry );
But I found that the above code is not working when the process is created in suspended mode.
Also one more information regarding what we discussed yesterday. When a process is created only kernel32.dll and ntdll.dll is loaded.
|
|
|
|
|
The trouble is I neeed to get my hands on those PEB and TEB structures, so while I have them I might aswell use my method.
You say only kernel32 and ntdll are loaded, but I have found this not to be the case. When it's created in a suspended state, no code has been executed, including the code which builds the IAT. That's why most code injection tricks also have to inject the addresses of the API's they require.
I don't suppose you tried out my code on your machine? I have found a few references to the same problem on the web. All relating to VistaX64, which happens to be all I have installed right now.
|
|
|
|
|
WalderMort wrote: You say only kernel32 and ntdll are loaded
I just used the process explorer and checked.
WalderMort wrote: I don't suppose you tried out my code on your machine
I tried. But with some modifications. i found with that PEB and TEB ur trying to get the image base address and that codes where making some many compilation error( since some structures are not defined ). So I too the base address through another method and tried. But as I mentioned eariler that method requires the process to be created in normal way. Not in suspended.
I am running in XP.
|
|
|
|
|
Ah yes, I had to use my own defiition of those structures, from www.ntinternals.net
|
|
|
|
|
WalderMort wrote: DWORD dwFSBase = ( entry.HighWord.Bits.BaseHi << 24 ) | ( entry.HighWord.Bits.BaseMid << 16 ) | ( entry.BaseLow );
One doubt. if your using a 64 bit mechine, are you sure the above shifting is correct?. I found the original code was written for 32 bit mechine. Also confirm the TEB have same size in both 64 bit and 32 OS. Expecially in VISTA.
|
|
|
|
|
It may be a 64bit machine, but the exe is 32bit. Also, if you look at the code, before accepting the entry point, I check the PE headers to validate that it points to the correct location.
As far as this project goes, I'm going to have to give up, at least until I install VmWare. For now I will stick with being able to run only console apps, which is the main reason I started this.
The strange thing is, every single article I have found on the topic is the same as my code. I have played around with the TOKEN and SECURITY_DESCRIPTOR structs. But, when the initial pages are allocated for the process, they are done so with the PAGE_EXECUTE_WRITECOPY protection, and I can find no way around this.
I really must test this code on other machines to test if it is a Vista x64 'feature'!
|
|
|
|
|
BTW. Taking your suggestion of inserting the whole thing into a spawned process, but it requires a lot of work in the PEB and TEB headers.
|
|
|
|
|
hmm.. May be complicated..
|
|
|
|
|
My application is a MFC Win32 Dialog developed in VS6.0.
The dialog is used mainly for user input to parameters for a lengthy process called from a function within the dialog. I am using the windows UpdateWindow() method and Invalidate() from within the function to update the dialog indicating the number of records that have been processed and saved to a file. This seems to work correctly when ran on a Windows 2000 PC. but when I run it on a Window-XP PC the dialog is blanked with only the frame remaining whenever the application's focus is lost, by clicking on a desktop icon or launching an other application. Is there a solution to this problem? Could some sample code be provided to do this task?
Thank you.
Sample of my code follows:
<br />
while(!feof(In_File) )
{<br />
if(fgets(Sbuf,3000,In_File) != NULL)<br />
{<br />
rin++;<br />
DRec Srec(Sbuf, ',' , ',');<br />
Pn = Srec.Extract(m_uFieldNorth);<br />
Pe = Srec.Extract(m_uFieldEast);<br />
classNumber = (int)Srec.Extract(m_uClassField);<br />
<br />
Rn = Tn-Pn; Re = Te-Pe;<br />
<br />
RnRe = (Rn*Rn)+(Re*Re);<br />
<br />
if( ( RnRe ) <= Trr )
{<br />
fprintf(Out_File,"%s", Sbuf);
classCount[classNumber] += 1;
}<br />
}<br />
<br />
if((rin % 5000) == 0)
{<br />
SetDlgItemInt(IDC_SDataRecords,rin);<br />
<br />
UpdateWindow();
}<br />
}<br />
<br />
}
<br />
Ralph_L
|
|
|
|
|
UpdateWindow() won't do anything if none of the window is marked for repainting.
Have you tried Invalidate[Rect]() before UpdateWindow() on the window or calling
UpdatwWindow on the control itself?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: ...if none of the window is marked for repainting.
Wouldn't SetDlgItemInt() invalidate the window?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
I would expect it to invalidate the control window (if it didn't draw
the text immediately), not the entire window.
I just tried to offer something to try.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
My previous post was a test, and only a test. Had it been an actual post, it would have contained something intelligible.
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
If a make a call to CreateProcess() from within my code, is there any way I can break and start debugging the newly created process? Having no sources is no problem, I have become quite good at stepping through assembly.
|
|
|
|
|
in the VS Debug menu, you can use 'Attach To Process' to start a debugging session on the process you just launched.
|
|
|
|
|
I'm guessing the debugger needs an actual file on the disk to work with
I'm getting "Unable to find file" error messages every time I try to attach.
|
|
|
|
|
it needs a running process - and a process needs a .EXE .
what file is it not finding?
|
|
|
|
|
Well, that's the thing, I don't have an .EXE
I'm launching a process from a file stored in the resource section ( NOT a file on disk ), so I'm guessing the debugger is looking for this file so it can display the assembly.
|
|
|
|
|
ah... in that case, you've moved beyond my sphere of knowledge
|
|
|
|
|
Cool, one of the experts "doesn't know" ;P
|
|
|
|
|
WalderMort wrote: Cool, one of the experts "doesn't know"
Experts are also HUMAN
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
I've begun using C++ again after mainly using C# for the past several years. I was wondering what is considered the best way to pass a collection of objects to a function assuming the use of the Standard Template Library.
The function that's receiving the collection doesn't care if the collection is a vector or list or whatever, it just wants the objects. Is there a way to pass a collection that decouples the collection type, e.g vector, list, etc., from the function receiving the collection?
|
|
|
|
|
Leslie Sanford wrote: The function that's receiving the collection doesn't care if the collection is a vector or list or whatever, it just wants the objects.
how does that work ?
|
|
|
|
|
Chris Losinger wrote: how does that work ?
Well, that's kind of the question I'm asking. What I'm doing now is this:
void MyClass::SomeFunction(const std::vector<SomeObject *> *collection)
{
std::vector<SomeObject *>::iterator it;
for(it = collection.begin(); it != collection.end(); it++)
{
}
}
The function just wants to iterate over the collection. If I were in C#, I'd pass an IEnumerable object. The function could iterate over it without having to know what the underlying collection is. I'm not sure how to do the same thing in C++ with the Standard Template Library.
|
|
|
|
|