How to get the Process Environment Block (PEB) from extern process? - delphi

I want to get the PEB from the "notepad.exe" process. Does someone know how to do it?
I tried the GetModuleHandle API, but it doesn't return a valid pointer (it return zero every time) because I have to be the caller process of that module.
For that reason, I want to know how to get it to work with EnumProcessModules or CreateToolhelp32Snapshot.

Matt Pietrek described how to do that in a 1994 Under the Hood column. It was about how to get the environment variables of another process, where the first step is to get a pointer to the PEB. To do that, he says, call NtQueryInformationProcess. The PROCESS_BASIC_INFORMATION structure it fills contains the base address of the PEB structure. (You'll need to use ReadProcessMemory to read it since the address will be in the context of the external process's address space, not yours.)
To call NtQueryInformationProcess, you'll need a handle to the process. If you started the process yourself (by calling CreateProcess), then you already have a handle. Otherwise, you'll need to find the process ID and then call OpenProcess. To get the process ID, search for the process you want with EnumProcesses or Process32First/Process32Next. (I prefer the latter because it provides more information with less work.)

Related

script variable should not be used for call processing?

sir,
I am trying to create stateful proxy in opensips 2.4.
I just wanted a variable to hold received message information and process it.
So i checked "core variable" in opensips manual.it says, script variable are process wise. So i should not use to hold header value in script value like $var(Ruri)=$ru?? it will be overwritten by other call??
$var(userName)=$rU;
$var(removePlus) = '+';
# Search the string starting at 0 index
if($(var(userName){s.index, $var(removePlus)})==0){
$rU=$(var(userName){s.substr,1,0});
}
$var variables are process-local, meaning that you can't share them with other SIP workers even if you wanted to! In fact, they are so optimized that their starting value will often be what the same process left-behind during a previous SIP message processing (tip: you can prove this by running opensips with children = 1 and making two calls).
On the other hand, variables such as $avp are shared between processes, but not in a "dangerous" way that you have to worry about two INVITE retransmissions processing in parallel, each overwriting the other one's $avp, etc. No! That is taken care of under the hood. The "sharing" only means that, for example, during a 200 OK reply processed by a different process than the one which relayed the initial INVITE, you will still be able to read and write to the same $avp which you set during request processing.
Finally, your code seems correct, but it can be greatly simplified:
if ($rU =~ "^+")
strip(1);

GetModuleFileNameEx of Thread ID?

I am trying to get the file path of a thread id.
I was hoping that this will work..but it doesn't
NtOpenThread(#hProc, THREAD_ALL_ACCESS, #ObjAttr, #ClientID) ;
pBuf := AllocMem(MAX_PATH);
GetModuleFileNameEx(hProc, 0, pBuf, MAX_PATH);
Any idea how it is done ?
GetModuleFileNameEx requires a process handle, not a thread handle, which explains why your code doesn't work. There are two main ways to get a process handle. The first is from CreateProcess, but that's no good unless you're the one starting the process, and if you're doing that, you don't need GetModuleFileNameEx in the first place.
The second way to get a process handle is from OpenProcess. That requires a process ID. You can get a thread's process ID with GetProcessIdOfThread, which takes a thread handle. You already know how to get a thread handle from a thread ID with NtOpenThread, although the usual function is plain old OpenThread.
If your Windows version doesn't support GetProcessIdOfThread, you can go another route with Thread32First and Thread32Next. Call CreateToolhelp32Snapshot, and then walk the thread list. Look for an entry where th32ThreadID equals the thread ID you're interested in. When you find it, th32OwnerProcessID will hold the corresponding process ID. Call OpenProcess and proceed as above.
Also note that you should not have to request ALL_ACCESS permissions when opening threads or processes, and attempting to do so may cause your program to fail. Request only the minimum permissions you need to accomplish your task. Requesting all access is the lazy way when you don't know what you need, but it will only work when your program already has administrative privileges. Instead, spend the time to figure out what permissions you really need.

How to check if queue with auto-generated name (amq.gen-*) exists?

In case of non-generated names it's enough to call #'queue.declare' to get newly created queue or existing one with given name. However, when using auto-generated names (beginning with amq.gen- prefix) it's not as trivial. First of all, amq. is restricted prefix, so there is no way to call #'queue.declare'{queue=<<"amq.gen-xxx">>}.
I also tried to play with passive=true option and although I may pass restricted name, I get an exit error when queue does not exists. Following is error report:
** Handler sse_handler terminating in init/3
for the reason exit:{{shutdown,
{server_initiated_close,404,
<<"NOT_FOUND - no queue 'amq.gen-wzPK0nIBPzr-dwtZ5Jy58V' in vhost '/'">>}},
{gen_server,call,
[<0.62.0>,
{call,
{'queue.declare',0,
<<"amq.gen-wzPK0nIBPzr-dwtZ5Jy58V">>,
true,false,false,false,false,[]},
none,<0.269.0>},
infinity]}}
Is there any way to solve this problem?
EDIT: Here is a short story behind this question. Disclaimer: I'm erlang newbie, so maybe there is better way to make it working :)
I have a gen_server based application holding SSE (server-side events) connections with web browsers. Each connection is bound to rabbitmq queue. SSE connection when broken, automatically tries to reconnect after given timeout - this is something that web browser supports out of the box. To reuse previously created queue I'm trying to check if queue of given name (taken from request cookie) already exists. It's all done in init callback.
You can declare a queue with the prefix amq. if the queue already exists. You would get Declare-Ok if the queue exists or access-refused if not. (My question is why would you, though? ;)
Furthermore, you can use the passive option to check if it already exists. According to AMQP reference the server treats it as not-found error if the queue doesn't exist. In order to catch this in your Erlang client you could try something around the lines of this:
try
%% declare queue with passive=true
queue_exists
catch exit:{{shutdown, {server_initiated_close,404,_},_,_} ->
queue_does_not_exist
end

CAB file API clarification

Since I'm not really seeing any content anywhere that doesn't point back to the original Microsoft documents on this matter, or source code that really doesn't seem to answer the questions I'm having, I thought I might ask a few things here. (Delphi tag is there because that's what my dev environment is on the code I'm making from this)
That said, I had a few questions the API document wasn't answering. First one: fdi_notify messages. What is "my responsibility" is in coding these: fdintCABINET_INFO: fdintPARTIAL_FILE: fdintNEXT_CABINET: fdintENUMERATE: ? I'll illustrate what I mean by an example. For fdintCLOSE_FILE_INFO, "my responsibility" is to Close a file related to handle given me, and set the file's date and time according to the data passed in fdi_notify.
I figure I'm missing something since my code isn't handling extracting spanned CAB files...any thoughts on how to do this?
What you're more than likely running into is that FDICopy only reads the cab you passed in. It will use fdintNEXT_CABINET to get spanned data for any files you extract in response to fdintCOPY_FILE, but it only calls fdintCOPY_FILE for files that start on that first cab.
To get a directory listing for the entire set, you need to call FDICopy in a loop. Every time you get a fdintCABINET_INFO event, save off the psz1 parameter (next cab name). When FDICopy returns, check that. If it's an empty string you're done, if not call FDICopy again with the next cab as the new path.
fdintCABINET_INFO: The only responsibility for this is returning 0 to continue processing. You can use the information provided (the path of the next cabinet, next disk, path name, nad set ID), but you don't need to.
fdintPARTIAL_FILE: Depending on how you're processing your cabs, you can probably ignore this. You'll only see it for the second and later images in a set, and it's to tell you that the particular entry is continued from a previous cab. If you started at the first cab in the set you'll have already seen an fdintCOPY_FILE for the file. If you're processing random .cabs, you won't really be able to use it either, since you won't have the start of the file to extract.
fdintNEXT_CABINET: You can use this to prompt the user for a new directory for the next cabinet, but for simple spanning support just return 0 if the passed in filename is valid or -1 if it isn't. If you return 0 and the cab isn't valid, or is the wrong one, this will get called again. The easiest approach (if you don't request a new disk/directory), is just to check pfdin^.fdie. If it's FDIError_None it's equal the first time being called for the requested cab, so you can return 0. If it's anything else it's already tried to open the requested cab at least once, so you can return -1 as an error.
fdintENUMERATE: I think you can ignore this. It isn't covered in the documentation, and the two cab libraries I've looked at don't use it. It may be a leftover from a previous API version.

How to track down access violation "at address 00000000"

I know how to create a .map file to track down access violation errors when the error message includes an actual address.
But what if the error message says
Access violation at address 00000000. Read of address 00000000.
Where do I start looking for the cause of this problem... ?
The accepted answer does not tell the entire story.
Yes, whenever you see zeros, a NULL pointer is involved. That is because NULL is by definition zero. So calling zero NULL may not be saying much.
What is interesting about the message you get is the fact that NULL is mentioned twice. In fact, the message you report looks a little bit like the messages Windows-brand operating systems show the user.
The message says the address NULL tried to read NULL. So what does that mean? Specifically, how does an address read itself?
We typically think of the instructions at an address reading and writing from memory at certain addresses. Knowing that allows us to parse the error message. The message is trying to articulate that the instruction at address NULL tried to read NULL.
Of course, there is no instruction at address NULL, that is why we think of NULL as special in our code. But every instruction can be thought of as commencing with the attempt to read itself. If the CPUs EIP register is at address NULL, then the CPU will attempt to read the opcode for an instruction from address 0x00000000 (NULL). This attempt to read NULL will fail, and generate the message you have received.
In the debugger, notice that EIP equals 0x00000000 when you receive this message. This confirms the description I have given you.
The question then becomes, "why does my program attempt to execute the NULL address." There are three possibilities which spring to mind:
You have attempt to make a function call via a function pointer which you have declared, assigned to NULL, never initialized otherwise, and are dereferencing.
Similarly, you may be calling an "abstract" C++ method which has a NULL entry in the object's vtable. These are created in your code with the syntax virtual function_name()=0.
In your code, a stack buffer has been overflowed while writing zeros. The zeros have been written beyond the end of the stack buffer, over the preserved return address. When the function later executes its ret instruction, the value 0x00000000 (NULL) is loaded from the overwritten memory spot. This type of error, stack overflow, is the eponym of our forum.
Since you mention that you are calling a third-party library, I will point out that it may be a situation of the library expecting you to provide a non-NULL function pointer as input to some API. These are sometimes known as "call back" functions.
You will have to use the debugger to narrow down the cause of your problem further, but the above possiblities should help you solve the riddle.
An access violation at anywhere near adress '00000000' indicates a null pointer access. You're using something before it's ever been created, most likely, or after it's been FreeAndNil()'d.
A lot of times this is caused by accessing a component in the wrong place during form creation, or by having your main form try and access something in a datamodule that hasn't been created yet.
MadExcept makes it pretty easy to track these things down, and is free for non-commercial use. (Actually, a commercial use license is pretty inexpensive as well, and well worth the money.)
You start looking near that code that you know ran, and you stop looking when you reach the code you know didn't run.
What you're looking for is probably some place where your program calls a function through a function pointer, but that pointer is null.
It's also possible you have stack corruption. You might have overwritten a function's return address with zero, and the exception occurs at the end of the function. Check for possible buffer overflows, and if you are calling any DLL functions, make sure you used the right calling convention and parameter count.
This isn't an ordinary case of using a null pointer, like an unassigned object reference or PChar. In those cases, you'll have a non-zero "at address x" value. Since the instruction occurred at address zero, you know the CPU's instruction pointer was not pointing at any valid instruction. That's why the debugger can't show you which line of code caused the problem — there is no line of code. You need to find it by finding the code that lead up to the place where the CPU jumped to the invalid address.
The call stack might still be intact, which should at least get you pretty close to your goal. If you have stack corruption, though, you might not be able to trust the call stack.
If you get 'Access violation at address 00000000.', you are calling a function pointer that hasn't been assigned - possibly an event handler or a callback function.
for example
type
TTest = class(TForm);
protected
procedure DoCustomEvent;
public
property OnCustomEvent : TNotifyEvent read FOnCustomEvent write FOnCustomEvent;
end;
procedure TTest.DoCustomEvent;
begin
FOnCustomEvent(Self);
end;
Instead of
procedure TTest.DoCustomEvent;
begin
if Assigned(FOnCustomEvent) then // need to check event handler is assigned!
FOnCustomEvent(Self);
end;
If the error is in a third party component, and you can track the offending code down, use an empty event handler to prevent the AV.
When I've stumbled upon this problem I usually start looking at the places where I FreeAndNil() or just xxx := NIL; variables and the code after that.
When nothing else has helped I've added a Log() function to output messages from various suspect places during execution, and then later looked at that log to trace where in the code the access violation comes.
There are ofcourse many more elegant solutions available for tracing these violations, but if you do not have them at your disposal the old-fashioned trial & error method works fine.
It's probably because you are directly or indirectly through a library call accessing a NULL pointer. In this particular case, it looks like you've jumped to a NULL address, which is a b bit hairier.
In my experience, the easiest way to track these down are to run it with a debugger, and dump a stack trace.
Alternatively, you can do it "by hand" and add lots of logging until you can track down exactly which function (and possibly LOC) this violation occurred in.
Take a look at Stack Tracer, which might help you improve your debugging.
Use MadExcept. Or JclDebug.
I will second madExcept and similar tools, like Eurekalog, but I think you can come a good way with FastMM also. With full debugmode enabled, it should give you some clues of whats wrong.
Anyway, even though Delphi uses FastMM as default, it's worth getting the full FastMM for it's additional control over logging.
Here is a real quick temporary fix, at least until you reboot again but it will get rid of a persistent access. I had installed a program that works fine but for some reason, there is a point that did not install correctly in the right file. So when it cannot access the file, it pops up the access denied but instead of just one, it keeps trying to start it up so even searching for the location to stop it permanently, it will continue to pop up more and more and more every 3 seconds. To stop that from happening at least temporarily, do the following...
Ctl+Alt+Del
Open your Task Manager
Note down the name of the program that's requesting access (you may see it in your application's tab)
Click on your Processes tab
Scroll through until you find the Process matching the program name and click on it
Click End Process
That will prevent the window from persistently popping up, at least until you reboot. I know that does not solve the problem but like anything, there is a process of elimination and this step here will at least make it a little less annoying.

Resources