Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call With Another Arguments #3

Open
PeterHevesi opened this issue Aug 19, 2021 · 4 comments
Open

Call With Another Arguments #3

PeterHevesi opened this issue Aug 19, 2021 · 4 comments

Comments

@PeterHevesi
Copy link

PeterHevesi commented Aug 19, 2021

Hi,
I found your program and is very cool :) So thanks so much !!!
But I have a question: Is it possible to have the same program executed as it should originally but with some arguments added?
To explain it more, I need to add debug arguments to javaw.exe to be able to run something in debug mode.
It's called from one process like this: javaw.exe --lots-of-original-arguments.
what I need to do is to intercept javaw.exe with your tool and do this:
javaw.exe --few-added-arguments --lots-of-original-arguments.

And actually, to say exactly what are those arguments of mine, I want to call it like this:
javaw.exe -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 --lots-of-original-arguments

Is it possible?
Thanks so much!!!

@PeterHevesi
Copy link
Author

PeterHevesi commented Aug 20, 2021

I kinda solved it by creating small console app, that was called instead, received all arguments, that was originally passed to javaw.exe and then modyfing them and calling it in a right way. But I couldn't solve recursive calls to my console app, so it run in cycle.
But I fixed this recursion by calling java.exe instead of javaw.exe, which is basically the same thing, but only javaw.exe was intercepted, so it's kinda working now :)

But still, the problem is, that it changes something for that process, so it crashes after I do all of this.
So what I would like to do, is to try not to mess anything for that process, just like you said in your article:

"After all that said, we can finally proceed to the most exciting part: How to spoof an arbitrary process on the fly without messing things up for it. In theory, it sounds simple. There are several apparent steps we should take when re-launching the program after the interception. The process might depend on the inherited handles or the current directory, so we need to reproduce everything as precisely as possible. Which means:

  1. Passing the same command-line parameters.
    
  2. Using the same STARTUPINFO structure and the current directory.
    
  3. Letting the process inherit the same handles we did.
    
  4. Waiting for the target to exit and then exiting with the same code (to transfer it along the chain to the caller).
    
  5. And… another trick that I will explain a bit later.....
    

But would you please explain it a little bit more, exactly how you achieve this? For example, I can't achieve to use same StartupInfo

@diversenok
Copy link
Owner

Image File Execution Options can determine which file to execute after interception either based on the image name or on the full path (when UseFilter is enabled; note that ExecutionMaster does not support this functionality). As you can see, it does not make decisions based on the supplied arguments, so you cannot simply instruct it to replace javaw.exe --lots-of-original-arguments with javaw.exe --few-added-arguments --lots-of-original-arguments. Even if you try so, you end up with recursive calls.

I kinda solved it by creating small console app, that was called instead, received all arguments, that was originally passed to javaw.exe and then modyfing them and calling it in a right way. But I couldn't solve recursive calls to my console app, so it run in cycle.

I think you're on the right track with this approach. To avoid recursion, you can start the new process via CreateProcess supplying DEBUG_PROCESS in dwCreationFlags and then detach from it by calling DebugActiveProcessStop. This way, IFEO won't interfere.

But still, the problem is, that it changes something for that process, so it crashes after I do all of this.
So what I would like to do, is to try not to mess anything for that process, just like you said in your article:

Hmm... If you are sure that the arguments for the new process are correct, maybe it gets the wrong current directory. Some tools, such as Process Hacker, can help you to check these things.

But would you please explain it a little bit more, exactly how you achieve this? For example, I can't achieve to use same StartupInfo

All these steps try to mimic the way the original process was created as close as possible. CreateProcess has multiple parameters that control a few of these things:

  • To set up the same current directory, pass the result of GetCurrentDirectory in lpCurrentDirectory.
  • To copy the startup info, use GetStartupInfo and pass it in lpStartupInfo
  • To inherit handles, set bInheritHandles to TRUE
  • To wait for the new process (if you decide that you need it), use WaitForSingleObject on the process handle that CreateProcess returns in lpProcessInformation.
  • To get the exit code, there is GetExitCodeProcess
  • Re-parenting is most likely overkill and is a bit more complex; it requires using UpdateProcThreadAttribute with PROC_THREAD_ATTRIBUTE_PARENT_PROCESS

In the end, you should get something similar to the executable from #2 which does everything mentioned above but preserves the arguments. Note that, when replacing arguments, you cannot simply prefix the string with javaw.exe --few-added-arguments because it will result in javaw.exe --few-added-arguments javaw.exe --lots-of-original-arguments which is incorrect.

@PeterHevesi
Copy link
Author

Wooow, you are awesome man, thanks soooo much for your help :)
I will try to follow your tips and I believe I can solve it now :)

But anyway, wouldn't you consider to update this utility to create another option to change silently the arguments of that intercepted executable without messing anything? That would be a fantastic feature, because you can do it now by programing it yourself as I am trying to do and using your last option to call another .exe instead of original, but then there is this problem that you already solved that anybody would have to solve again :D

@PeterHevesi
Copy link
Author

PeterHevesi commented Aug 31, 2021

I already solved it for myself successfully, so thanks again bro :)

But I overcame recursion by switching javaw.exe with java.exe, but I will try to modify it to work with just a single executable by using DEBUG_PROCESS and NtRemoveProcessDebug(), because for my use case, DebugActiveProcessStop wasn't working, probably because of what you said in your article:

The second option allows us to proceed as usual after calling DebugActiveProcessStop. Though, the last function can fail under some circumstances since it re-opens the target process by PID. A better way is to use NtRemoveProcessDebug.

I will post this solution here immediately after I successfully do it, so you can improve this fantastic utility by this ability to modify arguments silently :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants