Witam
Czytałem sobie jakiś czas temu o DLL Injection i postanowiłem spróbować swoich sił.
Chciałbym uruchomić swój kod w obcym procesie.
Bawiłem się już z funkcją: CreateRemoteThread - sukces
A aktualnie walczę z nieudokumentowaną funkcją: NtCreateThreadEx
Oto co uzyskałem <kod>:
Dynamic Load Library:
#include <windows.h>
///Compilation with option -m32/-m64
extern "C" BOOL __stdcall DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
MessageBox( NULL, "MESSAGE FROM 32 BIT DLL", "Lorem ipsum", MB_ICONINFORMATION | MB_OKCANCEL );
return 0;
}
DLL Injector:
#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
/// 32 64 32 -FALIED (Status NtCreateThreadEx 1300)
/// 32 64 64 -FALIED (Status NtCreateThreadEx 1300)
/// 64 32 32 -FALIED (Status NtCreateThreadEx 1300)
/// 64 64 32 -FALIED (Status NtCreateThreadEx 1300)
/// 64 64 64 -FALIED (Status NtCreateThreadEx 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()
{
std::string pathToDLL;
int PIDOfProcess = 0;
pathToDLL = "C:\\dll32.dll";
DWORD PID = (DWORD)PIDOfProcess; ///PID
HANDLE HProcess = NULL; ///Handle to proces
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;
///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);
if(hThread == NULL)
{
std::cout << "Error of 'NtCreateThreadEx': ";
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;
}
Test App:
#include <iostream>
int main()
{
int a;
std::cout << "Podaj liczbe - get a number - Lorem IPSUM" << std::endl;
std::cin >> a;
return 0;
}
PROBLEM:
Udało mi się jedynie wstrzyknąć 32 bitowa DLL 32 bitowym injectorem do 32 bitowego procesu - patrz "tablica prawdy" w kodzie injectora
Czy ktoś wie dlaczego tak się dzieje ? Co robie nie tak ?
#EDIT 1
///TYPE OF(32/64 bits)
///INJECTOR===DLL===PROCESS===RESULT
/// 32 32 32 -SUCESS
/// 32 64 32 -FALIED (Status NtCreateThreadEx 1300)
/// 32 64 64 -FALIED (Status NtCreateThreadEx 1300)
/// 64 32 32 -FALIED (Status NtCreateThreadEx 1300)
/// 64 64 32 -FALIED (Status NtCreateThreadEx 1300)
/// 64 64 64 -FALIED (Status NtCreateThreadEx 1300)
Jest tu taka mała tabelka myśle że w miare przejrzysta.
W pierwszej kolumnie jest typ (architektura na jaką kompilowałem) programu wstrzykującego.
W drugiej kolumnie jest typ (architektura na jaką kompilowałem) biblioteki dynamicznie ładowanej.
W trzeciej kolumnie jest typ (architektura) programu atakowanego.
Pracuje na 64 bitowym systemie operacyjnym Microsoft Virus Windows 7.
Udało mi się jedynie wstrzyknąć 32 bitowa DLL 32 bitowym injectorem do 32 bitowego procesu
Jak wynika z tabelki tylko to udało mi się osiągnąć zaś w pozostałych próbach otrzymuje kod błędu 1300
Kod ten oznacza:
Nie wszystkie wywoływane uprawnienia lub grupy są przypisane komputerowi wywołującemu.
Kompilator nie zgłasza żadnych błędów podczas kompilacji tylko klika ostrzeżeń.
Do kompilacji na architekture 32-bit użyłem GNU GCC
g++ (tdm-2) 4.8.1
a na 64 bit
g++ (tdm64-1) 5.1.0
Chce jeszcze dodać że działam na koncie standardowym ale myśle że dla procesu uruchomionego w tym samym kontekście użytkownika nie powinno mieć to znaczenia.
Nie mam pomysłu co jest przyczyną niepowodzeń, niestety nie znalazłem niczego przydatnego w sieci.
======
Na podstawie
http://www.p-programowanie.pl/cpp/dll-injection/ - Dll Injection
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)