I have written DLL injector. I used CreateRemoteThread to inject my DLL to process and all was good.
Now i am trying inject DLL to process by undocumented function - NtCreateThreadEx. I have written injector but he is not working.
When i use 32 bit injector to inject 32 bit DLL to 32 bit process
all working good.
Problem is when i use 64 bit injector to inject 64 bit DLL to 64 bit process.
My DLL code:
#include <windows.h>
///Compilation with option -m64
extern "C" BOOL __stdcall DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
MessageBox( NULL, "MESSAGE FROM 64 BIT DLL", "Lorem ipsum", MB_ICONINFORMATION | MB_OKCANCEL );
return 0;
}
My TestApp code
#include <iostream>
#include <windows.h>
int main()
{
std::cout << " Lorem IPSUM" << std::endl;
//HMODULE HDLL = LoadLibraryA("dll64.dll");
//std::cout << "Error: " << GetLastError() << std::endl;
while(1)
{
std::cout << "petla" << std::endl;
Sleep(5000);
}
return 0;
}
My injector code:
#include <iostream>
#include <string>
#include <windows.h>
/// 64 bit OS - Windows 7
///=====================
///* In this same user context ("User")
///TYPE OF(32/64 bits)
///INJECTOR===DLL===PROCESS===RESULT
/// 32 32 32 -SUCESS
/// 64 64 64 -FALIED (error: 1300)
//Handle to process,Address of'LoadLibraryA',see DllAdr
///TO DO
///* Inject DLL to process from normal user context ("User") to higher user context (Zarzadca)
///* Inject DLL to process from normal user context ("User") to other normal user context (User1)
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress, LPVOID lpSpace);
int privileges();
int main()
{
int PIDOfProcess = 0;
std::string pathToDLL = "dll64.dll\0"; ///find DLL in local directory
DWORD PID = (DWORD)PIDOfProcess; ///PID
HANDLE HProcess = NULL; ///Handle to process
LPVOID LibAddr = NULL; ///Address of procedure 'LoadLibraryA'
LPVOID DllAdr = NULL; ///Address of memory in other process
HANDLE hThread = NULL; ///Handle to remote thread
int WirteStatus = 0; ///Status of writing to memory of other process
std::cout << "ptr size = " << sizeof(void *) << std::endl;
std::cout << "Get PID of process" << std::endl;
std::cin >> PIDOfProcess;
PID = (DWORD)PIDOfProcess;
///std::cout << "Get path to DLL" << std::endl;
///std::cin >> pathToDLL;
if( privileges() != 0 )
{
std::cout << "Cannot get the right privileges" << std::endl;
}
HProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if(HProcess == NULL)
{
std::cout << "Could not find process" << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
DllAdr = (LPVOID)VirtualAllocEx(HProcess, NULL, pathToDLL.size() +1, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(DllAdr == NULL)
{
std::cout <<"Can not allocate memory." << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
WirteStatus = WriteProcessMemory(HProcess, (LPVOID)DllAdr, pathToDLL.c_str() ,pathToDLL.size()+1, NULL);
if(WirteStatus == 0)
{
std::cout << "Could not write to process's address space" << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
LibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(LibAddr == NULL)
{
std::cout << "Unable to locate LoadLibraryA" << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
hThread = NtCreateThreadEx(HProcess,LibAddr,DllAdr);
///DWORD threadId = 0;
///hThread = CreateRemoteThread(HProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LibAddr, DllAdr, 0, &threadId);
if(hThread == NULL)
{
std::cout << "Error: ";
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
system("pause");
}
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpSpace)
{
///The prototype of NtCreateThreadEx from undocumented.ntinternals.com
typedef DWORD (WINAPI * functypeNtCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD Unknown1,
DWORD Unknown2,
LPVOID Unknown3
);
HANDLE hRemoteThread = NULL;
HMODULE hNtDllModule = NULL;
functypeNtCreateThreadEx funcNtCreateThreadEx = NULL;
//Get handle for ntdll which contains NtCreateThreadEx
hNtDllModule = GetModuleHandle( "ntdll.dll" );
if ( hNtDllModule == NULL )
{
std::cout << "Cannot get module ntdll.dll error: " << GetLastError() << std::endl;
return NULL;
}
funcNtCreateThreadEx = (functypeNtCreateThreadEx)GetProcAddress( hNtDllModule, "NtCreateThreadEx" );
if ( !funcNtCreateThreadEx )
{
std::cout << "Cannot get procedure address error: " << GetLastError() << std::endl;
return NULL;
}
funcNtCreateThreadEx( &hRemoteThread, /*GENERIC_ALL*/0x1FFFFF, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, NULL );
std::cout << "Status NtCreateThreadEx " << GetLastError() << std::endl;
std::cout << "hRemoteThread: " << hRemoteThread << std::endl;
std::cout << "hNtDllModule: " << hNtDllModule << std::endl;
std::cout << "funcNtCreateThreadEx: " << funcNtCreateThreadEx << std::endl;
return hRemoteThread;
}
int privileges()
{
HANDLE Token;
TOKEN_PRIVILEGES tp;
if(OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token)) ///It opens the access token associated with a process.
{
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);///Function retrieves the locally unique identifier (LUID)
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(Token, false, &tp, sizeof(tp), NULL, NULL) != 0)///Function enables or disables privileges in the specified access token.
{
return 0; //OK
}
}
return 1;
}
When i use 64 bit injector to inject 64 bit DLL to 64 bit process, function NtCreateThreadEx return code of error 1300 and my DLL doesn't execute.
I use to compile on 64 bit architecture: g++ (tdm64-1) 5.1.0
I am working on Virus Windows 7 64 bit as normal user. Run as administrator doesn't help.
I dont know why it doesn't work, what i doing wrong.
PS: When i use 32 bit injector to inject 32 bit DLL to 32 bit process, function NtCreateThreadEx return code of error 1300 but my DLL execute.
In 32 bit version TestApp GetLastError return code 1114.
I use to compile on 32 bit architecture: g++ (tdm-2) 4.8.1
I include image
I based on:
http://www.p-programowanie.pl/cpp/dll-injection/ - Dll Injection (polish)
====
http://www.codeproject.com/Questions/369890/Ask-about-NtCreateThreadEx-in-Window-x
- Ask about NtCreateThreadEx in Window 7 x64!
=====
http://www.rohitab.com/discuss/topic/39535-code-injections-beginner-and-advanced/ Code Injections [beginner and advanced]
=====
http://securityxploded.com/ntcreatethreadex.php Remote Thread Execution in System Process using NtCreateThreadEx for Vista & Windows7
=====
http://cpp0x.pl/dokumentacja/WinAPI/Systemowe-kody-bledow-1300-1699/1470 Systemowe kody błędów (1300-1699) (polish)
Link to my topic on other forum (polish): http://forum.4programmers.net/C_i_C++/267735-dll_injection_w_windows_za_pomoca_nieudokumentowanej_funkcji_w_winapi?p=1234215#id1234215
My injector is working when i use him to inject DLL to other process in my user space (i am working as normal user)
but it is not working when
i am injecting to csrss.exe (or other system's process).
I get code of error 5 - Access Denied, when i run injector as Administrator i get code of error 0 (SUCCESS?) but my DLL not aborting process
( abort() - i try do BSoD).
I read about Session Separation and i think it is reason of my problem so i have one question: How i can hacking Windows :)
If it is imposibble can i inject DLL as normal user to proces in Administrator context (or other normal user's process) ?
Related
I'm using the following code to try to get the PID of notepad.exe, but it doesn't find the process.
I'm currently running on Windows 10 and compiling using VS Studio 19 as Release x64.
Also tried to find other processes, like chrome.exe, calculator.exe, etc, but couldn't find anything.
DWORD GetProcessId(LPCTSTR ProcessName)
{
PROCESSENTRY32 pt;
HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
std::wcout << "Error: " << GetLastError() << std::endl; // Error: 0
pt.dwSize = sizeof(PROCESSENTRY32);
std::wcout << "Error: " << GetLastError() << std::endl; // Error: 0
if (Process32First(hsnap, &pt)) { // must call this first
do {
if (!lstrcmpi(pt.szExeFile, ProcessName)) {
CloseHandle(hsnap);
return pt.th32ProcessID;
}
} while (Process32Next(hsnap, &pt));
}
std::wcout << "Error: " << GetLastError() << std::endl; // Error: 24
CloseHandle(hsnap); // close handle on failure
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD processId;
processId = GetProcessId(TEXT("notepad.exe"));
std::wcout << "processId: " << processId << std::endl;
return 0;
}
While debugging, I see the code is skipping the do while and jumping directly to CloseHandle(hsnap)
GetLastError() returns 24 at this line.
The image you posted of your debug output window shows pt.dwSize is set to 2168. This looks wrong. pt.dwSize is important, it used by Windows for version control.
On my computer sizeof(PROCESSENTRY32) is 556 (it depends on Windows version, I am using Windows 10). If project is not Unicode, the size should about half that. In VS, you can right click on PROCESSENTRY32 and it takes you to this definition:
typedef struct tagPROCESSENTRY32W
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
WCHAR szExeFile[MAX_PATH]; // Path
} PROCESSENTRY32W;
MAX_PATH should be 260. My guess is that you have redefined MAX_PATH or you have put the wrong #pragma statement somewhere. Or there is something weird happening. Try restarting Windows (use Restart instead of shutdown/start)
Also, zero the memory with PROCESSENTRY32 pt = {0}
PROCESSENTRY32 pt = { 0 };
pt.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hsnap, &pt))
{
DWORD err = GetLastError();
std::cout << "Process32First failed\n";
std::cout << pt.dwSize << " GetLastError : " << err << "\n";
CloseHandle(hsnap);
return DWORD(-1);
}
The only expected GetLastError is ERROR_NO_MORE_FILES as shown in Windows documentation. If the error is something else, it means the function has totally failed.
If your project is Unicode, as it should be, consider avoiding those T macros. Just use GetProcessId(L"notepad.exe"); and LPCWSTR etc.
Ps, I ran your code and it was fine in my computer. The only difference was sizeof(PROCESSENTRY32)
I am trying to inject a simple dll that creates a MessageBox in the target process. Using a injector from the www works without any issues. However using my own code to inject does not do anything at all (I am using it on notepad.exe)
I compiled both dll and this code as x64 debug in VS2017. Injector is created as Win32 console project.
All the stages in the code passes. I get a handle to the process and also the thread handle is valid. However the GetExitCode returns 0 so it fails all the time but I do not know why?
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (process == NULL)
{
std::cout << "Error opening process." << std::endl;
return false;
}
const char * dllString = "C:\\test.dll";
// load memory for dll
int bytes = sizeof(dllString);
PVOID mem = VirtualAllocEx(process, NULL, sizeof(dllString) + 1, MEM_COMMIT, PAGE_READWRITE);
if (mem == NULL)
{
std::cout << "Unable to allocate mem." << std::endl;
CloseHandle(process);
return false;
}
// write dll path to that location
SIZE_T bytesWritten;
BOOL status = WriteProcessMemory(process, mem, dllString, sizeof(dllString) + 1, &bytesWritten);
if (!status)
{
std::cout << "Writing dll path failed." << std::endl;
VirtualFreeEx(process, mem, sizeof(dllString) + 1, MEM_RELEASE);
CloseHandle(process);
return false;
}
FARPROC loadLibrary = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
HANDLE thread = CreateRemoteThread(process, NULL, NULL, reinterpret_cast<LPTHREAD_START_ROUTINE>(loadLibrary), mem, NULL, NULL);
if (thread == INVALID_HANDLE_VALUE)
{
std::cout << "Unable to create thread in remote process. " << std::endl;
VirtualFreeEx(process, mem, sizeof(dllString) + 1, MEM_RELEASE);
CloseHandle(process);
}
WaitForSingleObject(thread, INFINITE);
DWORD exitCode = 0;
GetExitCodeThread(thread, &exitCode);
if (exitCode != 0)
std::cout << "DLL loaded successfully." << std::endl;
else
std::cout << "DLL loading failed." << std::endl;
CloseHandle(thread);
VirtualFreeEx(process, mem, sizeof(dllString) + 1, MEM_RELEASE);
CloseHandle(process);
return true;
Just solved it myself. Actually a noob issue. sizeof in fact is returning the size of the pointer with is 64bits for x64 and not the length of the string for the memory I needed to allocate. So after changing it to strlen it worked.
So I'm trying to read Memory out of a running exe with ReadProcessMemory() as you can see in the code provided below.
The only problem I constantly run into is that I receive the Error 3E6 / 998 which seems to be NOACCESS but I cant find a solution to fix this.
And yes I tried to run the exe in Admin Mode without success...
#include <Windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <Psapi.h>
#include <tchar.h>
using namespace std;
int id = NULL;
HANDLE hProcess = NULL;
int getPID(const string name);
bool setHandle(int id, HANDLE &out);
DWORD64 GetModule(const string name);
int main()
{
bool success = false;
id = getPID("sample.exe");
string name = "SAMPLE";
cout << "Process Name: " << name << endl;
cout << "Process ID: " << id << endl;
success = setHandle(id, hProcess);
if (success)
{
cout << "Handle set..." << endl;
}
else if (!success)
{
cout << "You need to have SOMETHING opened..." << endl;
cout << "ERROR CODE: " << GetLastError() << endl;
system("pause");
return 1;
}
success = false;
DWORD64 baseAddress = GetModule("sample.exe");
DWORD64 ammo = 0x24ED13273A8;
DWORD64 addr = baseAddress + ammo;
cout << "Base Address: " << hex << uppercase << "0x" << baseAddress << endl;
cout << "Ammo Address: " << hex << uppercase << "0x" << ammo << endl;
cout << "Complete Address: " << hex << uppercase << "0x" << addr << endl;
int buffer = 0;
success = ReadProcessMemory(hProcess, (LPCVOID)addr, (LPVOID)&buffer, sizeof(&buffer), NULL);
if (success)
{
cout << "ReadProccess succeeded..." << endl;
system("pause");
return 0;
}
else if (!success)
{
cout << "ERROR CODE: " << GetLastError() << endl;
system("pause");
return 1;
}
system("pause");
return 0;
}
bool setHandle(int id, HANDLE &out)
{
out = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if (!out) return false;
return true;
}
int getPID(const string name)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry)) return NULL;
do
{
if (strcmp(entry.szExeFile, name.c_str()) == 0)
{
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return NULL;
}
DWORD64 GetModule(const string name)
{
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
string modName = szModName;
if (modName.find(name) != string::npos)
{
return (DWORD64)hMods[i];
}
}
}
}
return NULL;
}
I'm kinda new to c++... so sry? :)
There are actually two basic mistakes in your code, both of which, unfortunately for you, me and the rest of the civilised world, generate the same error code. Was it ever thus. There is also a logic error, but you are lucky enough to be getting away with it (just about). I commented the fix in the code I posted below.
There are also a number of 'good practise' shortcomings in your code, specifically:
NULL should not be used to represent integer zero
All error conditions should be checked for and (sensibly!) reported
You use the same string literal in two different places (so if you ever change it, you would need to change it in both places, and you might forget). So don't do that.
using namespace std; is widely frowned upon (because it causes such a lot of namespace pollution)
Why are id and hProcess global variables? This is just plain unnecessary.
You should give your functions more descriptive names, setHandle being the one I particularly have in mind. I got rid of that one completely.
When passing a std::string as a read-only function parameter, it is usually best to pass it as const ref, then it doesn't need to be copied.
Only use std::endl when you actually want to flush the buffer. It is inefficient.
Clean up after you (in this case, close any open handles). I know this is just a throwaway program but it's a good habit to get into.
OK, so here's some code that works (I have posted my own because I cleaned up all of the above). The substantive changes are:
To read the memory of another process, you need to give your user token the SE_DEBUG_NAME privilege. This in turn means you need to run your program as Administrator (aka elevated).
You cannot (obviously) read from a nonsense address in the target process so I just quietly fixed that.
Like I say, both of these generate the same error code. Huh!
OK, here you go. Enjoy:
#include <Windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <Psapi.h>
#include <tchar.h>
int getPID(const std::string& name);
DWORD64 GetModule(HANDLE hProcess, const std::string& name);
// Stolen from: https://learn.microsoft.com/en-gb/windows/desktop/SecAuthZ/enabling-and-disabling-privileges-in-c--
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
constexpr const char* theProcess = "notepad.exe";
int main()
{
HANDLE hToken;
BOOL ok = OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
if (!ok)
{
std::cout << "OpenProcessToken failed, error " << GetLastError() << "\n";
return 255;
}
ok = SetPrivilege (hToken, SE_DEBUG_NAME, TRUE);
if (!ok)
{
CloseHandle (hToken);
return 1;
}
int pid = getPID (theProcess);
HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == NULL)
{
std::cout << "OpenProcess failed, error " << GetLastError() << "\n";
CloseHandle (hToken);
return 1;
}
DWORD64 baseAddress = GetModule(hProcess, theProcess);
std::cout << "Base Address: " << std::hex << std::uppercase << "0x" << baseAddress << "\n";
int buffer = 0; // Note: sizeof (buffer) below, not sizeof (&buffer)
ok = ReadProcessMemory(hProcess, (LPCVOID)baseAddress, (LPVOID)&buffer, sizeof(buffer), NULL);
CloseHandle (hProcess);
CloseHandle (hToken);
if (ok)
{
std::cout << "ReadProcessMemory succeeded, buffer = " << buffer << "\n";
system("pause");
return 0;
}
std::cout << "ReadProcessMemory failed, error " << GetLastError() << "\n";
system("pause");
return 1;
}
int getPID(const std::string& name)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry)) return NULL;
do
{
if (strcmp(entry.szExeFile, name.c_str()) == 0)
{
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return NULL;
}
DWORD64 GetModule(HANDLE hProcess, const std::string& name)
{
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
std::string modName = szModName;
if (modName.find(name) != std::string::npos)
{
return (DWORD64)hMods[i];
}
}
}
}
return NULL;
}
Output (when run as Administrator):
Base Address: 0x7FF6D8470000
ReadProcessMemory succeeded, buffer = 905A4D
Output (when run as a normal user):
The token does not have the specified privilege.
You can also grab some code over at GitHub.
I have written DLL injector, to inject i use NtCreateThread to create remote thread into remote process
I work on 64 bit OS - Windows 7
To comiple i use
32 bit - g++ (tdm-2) 4.8.1
64 bit - g++ (tdm64-1) 5.1.0
Problem concerns 64 bit verion of my injector
I have 2 problems
1)
OK. My injector sometimes work and sometimes not work.
I dont know what is reason.
This is problematic line
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, (LPVOID)ntbuffer );
When i call function NtCreateThreadEx and in last argument is pointer to NtCreateThreadExBuffer, it not work.
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE /*GENERIC_ALL 0x1FFFFF/*Może tu jest błąd*/, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, **ntbuffer** );
When i give in last parametr NULL it works and I DONT KNOW WHY.
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE /*GENERIC_ALL 0x1FFFFF/*Może tu jest błąd*/, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, **NULL** );
Any idea?
2)
I use NtCreateThreadEx because i want inject code to SYSTEM PROCESS (like csrss.exe) because i like BSoD :).
Unfortunately, my injector can inject code ONLY to process in this same session.
Reason is ?Session Separation? (implemented on Vista and every later OS)
It is rise why i cannot use CreateRemoteThread
I have thought when i use NtCreateThreadEx separation of sessions is not a problem.
I try inject DLL to process in sesion 0.
I tried reduce the privileges
I replaced:
HProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
on
HProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, FALSE, PID);
etc. but it not work.
Can you tell me why NtCreateThreadEx() works in admin mode, but not in standard mode ?
Maby i should use other undocumented functions (like NtCreateThreadEx) for example NtOpenProcess to get handle to process with all access?
I need any idea what i should doing. Please help me.
#include <iostream>
#include <string>
#include <windows.h>
struct NtCreateThreadExBuffer;
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress, LPVOID lpSpace);
BOOL EnableDebugPrivilege();
int main()
{
int PIDOfProcess = 0;
std::string pathToDLL = "dll64.dll\0"; ///find DLL in local directory
DWORD PID = (DWORD)PIDOfProcess; ///PID
HANDLE HProcess = NULL; ///Handle to process
LPVOID LibAddr = NULL; ///Address of procedure 'LoadLibraryA'
LPVOID DllAdr = NULL; ///Address of memory in other process
HANDLE hThread = NULL; ///Handle to remote thread
int WirteStatus = 0; ///Status of writing to memory of other process
std::cout << "Get PID of process" << std::endl;
std::cin >> PIDOfProcess;
PID = (DWORD)PIDOfProcess;
if(EnableDebugPrivilege() == true)
{
std::cout << "Debug privilege was enabled with status: "<< GetLastError() << " [OK]" << std::endl;
}else std::cout << "Debug privilege was not enabled: "<< GetLastError() << " [FAILED]" << std::endl;
/*
NtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId );*/
/// NtOpenProcess();
HProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, FALSE, PID);
if(HProcess == NULL)
{
std::cout << "Could not find process: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "Process opened: [OK]" << std::endl;
DllAdr = (LPVOID)VirtualAllocEx(HProcess, NULL, pathToDLL.size() +1, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(DllAdr == NULL)
{
std::cout << "Cannot allocate memory in remote process: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "Region of memory in remote process allocated: [OK]" << std::endl;
WirteStatus = WriteProcessMemory(HProcess, (LPVOID)DllAdr, pathToDLL.c_str() ,pathToDLL.size()+1, NULL);
if(WirteStatus == 0)
{
std::cout << "Could not write to process's address space: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "A memory has written name of DLL: [OK]" << std::endl;
LibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(LibAddr == NULL)
{
std::cout << "Unable to locate LoadLibraryA: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "A address of procedure LoadLibraryA has found [OK]" << std::endl;
hThread = NtCreateThreadEx(HProcess,LibAddr,DllAdr);
if(hThread == NULL)
{
std::cout << "Could not create remote thread on process: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
}
system("pause");
}
struct NtCreateThreadExBuffer///This information is derived based on reverse engineering work.
{
ULONG Size;
ULONG Unknown1;
ULONG Unknown2;
PULONG Unknown3;
ULONG Unknown4;
ULONG Unknown5;
ULONG Unknown6;
PULONG Unknown7;
ULONG Unknown8;
};
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpSpace)
{
///The prototype of NtCreateThreadEx from undocumented.ntinternals.com
///typ_zwracanej_wartości (__konwencja_wywolania*nazwa_wskaźnika)(typ1 argument1, typ2 argument2);
/* 2OOO, 11 November http://undocumented.ntinternals.net/
NTSYSAPI NTSTATUS NTAPI NtCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PINITIAL_TEB InitialTeb,
IN BOOLEAN CreateSuspended );*/
typedef LONG64 (WINAPI * functypeNtCreateThreadEx)(
PHANDLE ThreadHandle, ///Handle to thread which will be created /// OUT
ACCESS_MASK DesiredAccess, ///possible: GENERIC_WRITE GENERIC_READ GENERIC_EXECUTE GENERIC_ALL//// IN
LPVOID ObjectAttributes, /// IN,OPTIONAL
HANDLE ProcessHandle, ///Handle to our process /// IN
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
/*DWORD*/LONG64 dwStackSize,
LONG64 SizeOfStackCommit,
LONG64 SizeOfStackReserve,
LPVOID lpBytesBuffer ///pointer to initialized object of NtCreateThreadExBuffer
);
NtCreateThreadExBuffer * ntbuffer = NULL;
HANDLE hRemoteThread = NULL;
HMODULE hNtDllModule = NULL;
functypeNtCreateThreadEx funcNtCreateThreadEx = NULL;
ntbuffer = new NtCreateThreadExBuffer;
memset (ntbuffer,0,sizeof(NtCreateThreadExBuffer));///fill buffer zeros
DWORD temp1 = 0;
DWORD temp2 = 0;
ntbuffer->Size = sizeof(NtCreateThreadExBuffer);
ntbuffer->Unknown1 = 0x10003;
ntbuffer->Unknown2 = 0x8;
ntbuffer->Unknown3 = &temp2;
ntbuffer->Unknown4 = 0;
ntbuffer->Unknown5 = 0x10004;
ntbuffer->Unknown6 = 4;
ntbuffer->Unknown7 = &temp1;
ntbuffer->Unknown8 = 0;
//Get handle for ntdll which contains NtCreateThreadEx
hNtDllModule = GetModuleHandle( "ntdll.dll" );
if ( hNtDllModule == NULL )
{
std::cout << "Cannot get module ntdll.dll error: " << GetLastError() << std::endl;
return NULL;
} std::cout << "A 'ntdll.dll' module has got: "<< GetLastError() << " [OK]" << std::endl;
funcNtCreateThreadEx = (functypeNtCreateThreadEx)GetProcAddress( hNtDllModule, "NtCreateThreadEx" );
if ( !funcNtCreateThreadEx )
{
std::cout << "Cannot get procedure address error: " << GetLastError() << std::endl;
return NULL;
} std::cout << "'NtCreateThreadEx' has executed: "<< GetLastError() << " [OK]" << std::endl;
///Here is problem - when in last argument i replace NULL
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE /*GENERIC_ALL 0x1FFFFF/*Może tu jest błąd*/, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, ntbuffer );
std::cout << "_______________________________________ " << std::endl;
std::cout << "NtCreateThreadEx' has status: " << GetLastError() << std::endl;
std::cout << "hRemoteThread: " << hRemoteThread << std::endl;
std::cout << "State of handle to DLL: " << hNtDllModule << std::endl;
std::cout << "Addres of prcoedure NtCreateThreadEx: " << funcNtCreateThreadEx << std::endl;
return hRemoteThread;
}
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
if(!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ))
{
return FALSE;
}
if(!LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ))
{
return FALSE;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL ))
{
return FALSE;
}
if(!CloseHandle( hToken ))
{
return FALSE;
}
return TRUE;
}
try: zwcreatethreatex function.
typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
if (NULL == ZwCreateThreadEx)
{
ShowError("GetProcAddress_ZwCreateThread");
return FALSE;
}
I am trying to do some dll injection. I think I tried everything I could but cound not solve the problem unfortunately. I always get ERROR CODE 127 which means ERROR_PROC_NOT_FOUND. I am using Windows 7 64 bit.
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
char FileToInject[] = "theDll.dll";
char ProcessName[] = "calc.exe";
typedef HINSTANCE (*fpLoadLibrary)(char*);
bool InjectDLL(DWORD processId);
int main() {
DWORD processId = NULL;
PROCESSENTRY32 pre32 = {sizeof(PROCESSENTRY32)};
HANDLE hProcSnap;
cout << "BEFORECreateToolhelo32Snapshot:" << GetLastError() <<endl;
while(!processId) {
system("CLS");
cout << "Searching..." << endl;
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
cout << "CreateToolhelo32Snapshot:" << GetLastError() <<endl;
if(Process32First(hProcSnap, &pre32)) {
do {
if(!(strcmp(pre32.szExeFile, ProcessName))) {
processId = pre32.th32ProcessID;
break;
}
}
while(Process32Next(hProcSnap, &pre32));
}
Sleep(1000);
}
cout << GetLastError() <<endl;
while(!InjectDLL(processId)) {
cout << "DLL Injection failed" << endl;
Sleep(1000);
}
cout << "DLL Injected successfully" << endl;
getchar();
CloseHandle(hProcSnap);
return 0;
}
bool InjectDLL(DWORD processId) {
HANDLE hProc;
LPVOID paramAddr;
cout << "START:" << GetLastError() <<endl;
HINSTANCE hDll = LoadLibrary("KERNEL32");
cout << "LoadLibrary:" << GetLastError() <<endl;
fpLoadLibrary LoadLibraryAddr = (fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
cout << "LoadLibraryArr:" << GetLastError() <<endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
cout << "OpenProcess:" << GetLastError() <<endl;
char DllPath[250] = "C:\\Hacks\test.dll";
paramAddr = VirtualAllocEx(hProc, 0, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
cout << "VirtualAlloxEx:" <<GetLastError() <<endl;
bool MemoryWritten = WriteProcessMemory(hProc, paramAddr, DllPath, strlen(DllPath) + 1, NULL);
cout << "WriteProcessMemory:" << GetLastError() <<endl;
CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryAddr, paramAddr, 0, 0);
cout << "CreateRemoteThread:" <<GetLastError() <<endl;
CloseHandle(hProc);
return MemoryWritten;
}
The output is the following:
Searching...
CreateToolhelp32Snapshot: 18 ERROR_NO_MORE_FILES
LoadLibrary:18 ERROR_NO_MORE_FILES
LoadLibraryArr:127 ERROR_PROC_NOT_FOUND
OpenProcess:127 ERROR_PROC_NOT_FOUND
VirtualAlloxEx:127 ERROR_PROC_NOT_FOUND
WriteProcessMemory:127 ERROR_PROC_NOT_FOUND
CreateRemoteThread:5 ACCESS DENIED
DLL Injected successfully
The program finds the calc.exe as a process with no problem, but after that something goes wrong. Could someone please help me with this?
Thank you,
Tamas
This is one problem:
char DllPath[250] = "C:\\Hacks\test.dll";
The last backslash is not escaped. Change to:
char DllPath[250] = "C:\\Hacks\\test.dll";
The function is called LoadLibraryA(), not LibraryLoadA():
fpLoadLibrary LoadLibraryAddr =
(fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
A few other suggestions:
Only check GetLastError() if the previous WINAPI function failed.
Only continue processing if the previous WINAPI code (or other code) succeeded.
In
fpLoadLibrary LoadLibraryAddr = (fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
you should rather resolve the string LoadLibraryA. The
OpenProcess:127 ERROR_PROC_NOT_FOUND
VirtualAlloxEx:127 ERROR_PROC_NOT_FOUND (<-- sic)
WriteProcessMemory:127 ERROR_PROC_NOT_FOUND
errors are caused because you're using GetLastError even though these functions maybe didn't even fail. So before calling GetLastError, make sure that these functions yield an error return value (NULL or the like).