IE Injection Failure

closed account (G309216C)
Hi,

Currently I am building a, Global Injection unit into a project I am working on and the Global Injection works on every single process which is x86 but Internet Explorer is not getting injected.

I have debugged, I can see that I do open the process successfully being Opened with maximum access. The Memory allocation & Writing code is successful but when I call the Code from IE, nothing happens. Is this due to any type of proactive defense IE has when in Protected Mode?

I even turned off the Protected mode and yet it fails. Although I managed to bypass "ielowutil.exe" , an child process of Internet Explorer.

Is there anything abnormal or wrong why this injection into IE is failing.

***NOTE*** This injection will not work for Google Chrome because it was not intended to inject into it because it can cause a security risk.

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <Windows.h>
#include<iostream>
#include<TlHelp32.h>
using namespace std;
typedef int (WINAPI* msgparam) (HWND, LPSTR , LPSTR , UINT);
struct PARAMETER
{
DWORD MsgInj;
char Caption[500];
char MSGText[5000];
int msgButtons;
};
DWORD getPid(std::string procName);
int privileges();
DWORD InjectorThread();
int Injector(std::string ProcessName);
static DWORD Injection(PARAMETER* dataneeded);
static DWORD SizeFunctionStub();
int main()
{
privileges();
HANDLE Thread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)InjectorThread(),(LPVOID)0,0,0);
return 0;
}
DWORD InjectorThread()
{
	PROCESSENTRY32 Process;
HANDLE hProcess;
hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
Process32First(hProcess,&Process);
while(Process32Next(hProcess,&Process))
{
  Injector(Process.szExeFile);
}
return 0;
}
int Injector(std::string ProcessName)
{
  DWORD Pid;
  Pid = getPid(ProcessName);
if(Pid == 0) return 1;
HANDLE OpenRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,false,Pid);
if(OpenRemoteProcess == 0) return 1;
PARAMETER injecteddata;
strcpy_s(injecteddata.Caption,"Epic");
strcpy_s(injecteddata.MSGText,"System Wide Injection- cool!");
injecteddata.msgButtons = MB_OK|MB_ICONERROR| MB_NOFOCUS| MB_APPLMODAL;
injecteddata.MsgInj = (DWORD) GetProcAddress(LoadLibrary("User32.dll"),"MessageBoxA");
DWORD szFunctionSize = (PBYTE) SizeFunctionStub - (PBYTE) Injection;
LPVOID szFunctionAddress = VirtualAllocEx(OpenRemoteProcess,0,szFunctionSize,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(OpenRemoteProcess,szFunctionAddress,(void*)Injection,szFunctionSize,0);
LPVOID szParameterAddress = VirtualAllocEx(OpenRemoteProcess,0,sizeof(PARAMETER),MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
WriteProcessMemory(OpenRemoteProcess,szParameterAddress,&injecteddata,sizeof(PARAMETER),0);
HANDLE RemoteThread = CreateRemoteThread(OpenRemoteProcess,0,0,(LPTHREAD_START_ROUTINE)szFunctionAddress,szParameterAddress,NULL,NULL);

if (RemoteThread != 0)
{
  WaitForSingleObject(RemoteThread,1);
}
return 0;
}
DWORD getPid(std::string procName){
   HANDLE hsnap;
   PROCESSENTRY32 pt;
   hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   pt.dwSize = sizeof(PROCESSENTRY32);
   do{
    if(!strcmp(pt.szExeFile, procName.c_str())){
    DWORD pid = pt.th32ProcessID;
    CloseHandle(hsnap);
    return pid;
    }
   } while(Process32Next(hsnap, &pt));
   CloseHandle(hsnap);
   return 0;   
}
int privileges(){
  HANDLE Token;
  TOKEN_PRIVILEGES tp;
  if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token))
  {
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL)==0){
	  return 1; //FAIL
  }else{
	  return 0; //SUCCESS
  }
   }  
   return 1;
}
static DWORD Injection(PARAMETER* dataneeded)
{
msgparam msgbox = (msgparam) dataneeded->MsgInj;
if( msgbox(0,dataneeded->MSGText,dataneeded->Caption,dataneeded->msgButtons) == MB_OK)
  {
}
return 0;
}
static DWORD SizeFunctionStub(){
return 0;
}


I have deliberately put static function\thread next to few coded calls here. The reason for this is because some times leaving it as a plain DWORD generates unwanted Breaking of the stack due to the VS compilers generating: push value and not mov dword ptr ss:[arg + p], value so if I add static it will instead optimize out push value & replace it with mov dword ptr ss:[arg + p], value
This way the memory locations will remain static and therefore the relative offset would be positive rather than negative.

This trick will quickly trick the compiler into GCC for a short period of time before changing back to VS again.


Thanks!
closed account (G309216C)
UPDATE:

I made a schoolboys error but, not checking the error and failure Values.

I added more error checking and found that Internet Explorer was isolating itself using the Terminal Services which isolates each terminal session by design.

So I used RtlCreateUserThread(). Now I can inject into all process even Chrome and Firefox which would now make my Injection System-Wide in all x86 bit Computers.

I am not trying NtCreateThreadEx becuase it is far too Malware Like and will cause Unwanted Issues with AV's not only that but the Way NtCreateThreadEx calls thread is too complicated and also undocumented which would mean I need to Reverse Engineer it. Which is a waste of Time.

RtlCreateUserThread() in my opinion is not that bad although it creates too much memory pressure on the stack but I can easily break the stack using a union DWORD usage.

Topic archived. No new replies allowed.