adoxa / ansicon

Process ANSI escape sequences for Windows console programs.
http://ansicon.adoxa.vze.com/
Other
1.21k stars 130 forks source link

Incorrect inject method #65

Open VladimirSukhov opened 10 years ago

VladimirSukhov commented 10 years ago

Hi guys, would like to note that there is used incorrect method for dll injection in ansicon. There are few problems really.

  1. When ansicon injects from one process to another, it assumes the address of LoadLibrary function from kernel32.dll is same in all processes, but it is not correct. Since Windows 7 the kernel32.dll can be loaded by different addresses in different processes. Thus injection will fail.
  2. Another problem relate to the compatibility. For example, this problem happen if the application that use ansicon is protected with the software protection system, like Enigma Protector (http://enigmaprotector.com/ which developer I am). Protection (in our case it is Enigma Protector, but same techniques are used proactive protections, antivirus protections etc) hooks the functions, LoadLibrary in our case, and when you get a pointer to LoadLibrary in the source process it really points to protection code, and not to kernel32.dll. Of course, injection method fails in this case.

To fix problem, you have to use native functions from ntdll.dll for injection, because this is the one library that always located at the same address in all processes. You have to use it's function LdrGetProcedureAddress, and then by means this function fund an address of LoadLibrary in destination process, and only then use injection. This would be the correct injection method for you.

adoxa commented 10 years ago

What about extending the PEB method I use for 64->32 injection? I've also wanted to try a debug hook and let Windows do the injection itself.

VladimirSukhov commented 10 years ago

I did not have a chance to test this method, but I hope this should work, because as far as I know it is the one of the known methods of injection between 64->32 processes (so it should work).

My tests were made with 32-32 processes, and the two points I described in the first post will fail for you.

Btw, you may also use PEB method for 32-32 injection also, so using PEB you find an offset of kernel32.dll in remote process, then through ReadProcessMemory enumerate all its functions (using export directory) to find an offset to LoadLibrary. This would be also correct injection method.

adoxa commented 10 years ago

No, doesn't look like hooks will work with console processes.

VladimirSukhov commented 10 years ago

There is no matter if it is console application or no, hooks work for any processes.

OK, I just would like to report about incompatibilities and problems I found.

adoxa commented 10 years ago

The debug hook I meant was for SetWindowsHookEx, using that to inject. Unfortunately, none of those hooks seem to inject into console processes.

Is it necessary to use ReadProcessMemory when locating LoadLibrary via the PEB? Currently I just load kernel32.dll as a data file and search the exports that way.

VladimirSukhov commented 10 years ago

The hook with SetWindowsHookEx surely won't work for console processes. But I did not mean such kind of hook, it is useless in this case.

Regarding kernel32.dll - the problem that I descired in the first post is that you take the offset/handle/address of the kernel32.dll from the hooking process, and then do injection to the hooked process. The offset of the kernel32.dll may change between processes, and the way you are using will fail.

However, if you take the offset/handle/address of the kernel32.dll from hooked process using ReadProcessMemory by enumerating loaded modules in the PEB, and then take the offset of the LoadLibrary function by mapping kernel32.dll as data file in hooking process (using EXPORT directory), and then sum these offsets (offset of kernel32.dll + offset of LoadLibrary from the module start), then it will be the correct offset of LoadLibrary in the hooked process that you may use for injection. If you mean this way then this is correct way.

adoxa commented 10 years ago

That is what I mean and is what I currently do when a 64-bit process creates a 32-bit one. Although I only do it once, so the problem with a different address remains. Guess I better hop to it...