So, nach einer kleinen Pause wegen Studium und Zeit für die Tutorials hab ich mich nun nochmal dem Thema gewidmet. Ich denke mal, dass das Problem mit den Addressen nun behoben sein sollte. Meine Daten werden jetzt in eine struct geschrieben, welche vor dem Code in den Speicher geschrieben wird.
Ich hab zum Test mal ein zweites Programm geschrieben, welches mir die Addresse von MessageBoxA (via GetProcAddress) ausgibt, und dieselbe Addresse befindet sich in msgBoxA. Calls zu hardgecodeten Addressen sind nun auch nicht mehr vorhanden.
Code:
struct INJECTPARAMETER
{
MESSAGEBOXA msgBoxA;
LOADLIBRARYA loadlibraryA;
EXITPROCESS exitprocess;
char cCaption[15];
char cText[15];
char cDll[11];
};
Beim Aufruf von CreateRemoteThread hab ich mich da an den Weg aus der wiki gehalten. Meiner injectedThread Funktion wird die Addresse der struct mit übergeben.
So, ich hab dann mal versucht, den Code erstmal in meinem eigenem Process auszuführen, da aber VirtualAllocEx nun wieder den Fehler 487 zurückliefert, ist wohl nun der Punkt erreicht, um sich um das SeDebugPrivilege zu kümmern.
Diese Funktion liefert mir jedoch bei AdjustTokenPrivileges() den Fehlercode 6 (ERROR_INVALID_HANDLE).
Frage: Was muss ich machen, um das Privileg zu ändern? Immerhin hab ich doch das richtige Handle mit GetCurrentProcess() erhalten.
Zum Schluss nun die Aktuelle version des Codes:
So, ich hab dann mal versucht, den Code erstmal in meinem eigenem Process auszuführen, da aber VirtualAllocEx nun wieder den Fehler 487 zurückliefert, ist wohl nun der Punkt erreicht, um sich um das SeDebugPrivilege zu kümmern.
Code:
bool enableSeDebugPrivilege()
{
HANDLE myProcess = GetCurrentProcess();
TOKEN_PRIVILEGES pri;
LUID luid;
if(LookupPrivilegeValue(0, "seDebugPrivilege", &luid) == 0)
{
cout << "SE_PRIV: LookupPrivilegeValue: " << GetLastError() << endl;
return false;
}
pri.PrivilegeCount = 0;
pri.Privileges[0].Luid = luid;
pri.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(myProcess, false, &pri, sizeof(TOKEN_PRIVILEGES), 0, 0) == 0)
{
cout << "SE_PRIV: AdjustTokenPrivileges: " << GetLastError() << endl;
return false;
}
cout << "SeDebugPrivilege erfolgreich erhalten." << endl;
CloseHandle(myProcess);
return true;
}
Frage: Was muss ich machen, um das Privileg zu ändern? Immerhin hab ich doch das richtige Handle mit GetCurrentProcess() erhalten.
Zum Schluss nun die Aktuelle version des Codes:
Code:
#include <iostream>
#include <windows.h>
using namespace std;
typedef HMODULE (WINAPI *LOADLIBRARYA)(LPCTSTR);
typedef int (WINAPI *MESSAGEBOXA)(HWND, LPCTSTR, LPCTSTR, UINT);
typedef void (WINAPI *EXITPROCESS)(UINT);
struct INJECTPARAMETER
{
MESSAGEBOXA msgBoxA;
LOADLIBRARYA loadlibraryA;
EXITPROCESS exitprocess;
char cCaption[15];
char cText[15];
char cDll[11];
};
void injectedThread(INJECTPARAMETER *p);
void injectedThread_end();
bool enableSeDebugPrivilege();
int main()
{
HANDLE process;
INJECTPARAMETER injParameter;
strcpy(injParameter.cCaption, "Caption");
strcpy(injParameter.cText, "Hallo Welt");
strcpy(injParameter.cDll, "user32.dll");
injParameter.loadlibraryA = (LOADLIBRARYA)GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA");
injParameter.msgBoxA = (MESSAGEBOXA)GetProcAddress(LoadLibrary("user32.dll"), "MessageBoxA");
injParameter.exitprocess = (EXITPROCESS)GetProcAddress(LoadLibrary("kernel32.dll"), "ExitProcess");
//Wie groß ist die Funktion injectedThread?
DWORD InjThreadSize = reinterpret_cast<intptr_t>(&injectedThread_end) - reinterpret_cast<intptr_t>(&injectedThread);
cout << "Differenz: " << InjThreadSize << endl;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
ZeroMemory(&startupInfo, sizeof(startupInfo));
ZeroMemory(&processInfo, sizeof(processInfo));
/*char szExe[] = "D:\\OllyDbg 2.0\\ollydbg.exe";
if(CreateProcess((LPCTSTR)szExe, 0, 0, 0, false, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, 0, 0, &startupInfo, &processInfo) != 0)
{
cout << "CreateProcess war erfolgreich" << endl;
}
else
{
cout << "CreateProcess war nicht erfolgreich: " << GetLastError() << endl;
return 0;
}
process = processInfo.hProcess;*/
process = GetCurrentProcess();
if(process == 0)
cout << "Process konnte nicht geoeffnet werden" << endl;
else
cout << "Process geoeffnet" << endl;
if(enableSeDebugPrivilege() != true)
{
cout << "SeDebugPrivilege nicht erhalten" << endl;
return 0;
}
//nach beschreibbarn speicher suchen
_SYSTEM_INFO info;
GetSystemInfo(&info);
cout << "MinimumApplicationAddress: " << info.lpMinimumApplicationAddress << endl;
cout << "MaximumApplicationAddress: " << info.lpMaximumApplicationAddress << endl;
_MEMORY_BASIC_INFORMATION memInfo;
LPVOID actualAddr = info.lpMinimumApplicationAddress;
while(actualAddr < info.lpMaximumApplicationAddress)
{
VirtualQueryEx(process, (LPCVOID)actualAddr, &memInfo, sizeof(memInfo));
if(memInfo.State == MEM_FREE)
break;
else
{
SIZE_T act = (SIZE_T)actualAddr;
act += memInfo.RegionSize;
actualAddr = (LPVOID)act;
}
}
cout << "Freien Speicher an der Speicherstelle " << actualAddr << " mit der size " << memInfo.RegionSize << " gefunden" << endl;
DWORD dwSize = memInfo.RegionSize -10;
if(dwSize < InjThreadSize)
cout << "WARNUNG: nich genügend speicher mit MEM_FREE!!!" << endl;
LPVOID baseAddrOfAllcRgn = VirtualAllocEx(process, actualAddr, dwSize, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if(baseAddrOfAllcRgn == NULL)
{
cout << "VirtualAllocEx hat ein Problem: " << GetLastError() << endl;
return 0;
}
else
cout << "VirtualAllocEx hat speicher reserviert" << endl;
SIZE_T nBytesWritten;
if(WriteProcessMemory(process, baseAddrOfAllcRgn, (LPCVOID)&injParameter, sizeof(INJECTPARAMETER), &nBytesWritten) == 0)
{
cout << "struct konnte nicht an die angegebene addresse geschrieben werden: " << GetLastError() << endl;
return 0;
}
else
cout << "struct wurde mit " << nBytesWritten << " an die Addresse geschrieben." << endl;
if(WriteProcessMemory(process, (LPVOID)((DWORD)baseAddrOfAllcRgn+sizeof(INJECTPARAMETER)+7), (LPCVOID)&injectedThread, InjThreadSize, &nBytesWritten) == 0)
{
cout << "WriteProcessMemory hat ein Problem: " << GetLastError() << endl;
return 0;
}
else
cout << "WriteProcessMemory: " << nBytesWritten << " nBytesWritten" << endl;
cout << "Nun kommt CreateRemoteThread: "; getchar();
//return 0; //Befindet sich vorläufig hier, weil im moment CreateRemoteThread das Programm sonst zum absturz bringen würde
LPDWORD lpNULL;
//Hypothese zu dem Parameter, den CreateRemoteThread an injectedThread übergibt:
//musste eigentlich im moment eine hardgecodete Addresse sein, welche sich noch auf den nicht injecteted Process bezieht
//und die struct nicht richtig übergeben wird.
//daher eventuell baseAddrOfAllcRgn übergeben, weil dorthin die struct geschriben wird
HANDLE hThread = CreateRemoteThread(process, 0, 0, (LPTHREAD_START_ROUTINE)injectedThread, (LPVOID)&injParameter, 0, lpNULL);
if(hThread == NULL)
{
cout << "CreateRemoteThread hat ein Problem: " << GetLastError() << endl;
}
else
{
cout << "hTread = " << hThread << endl;
}
return 0;
}
void injectedThread(INJECTPARAMETER *p)
{
//Kein unerwünschter call mehr ;)
//char cPtr[] = {'u','s','e','r','3','2','.','d','l','l'};
p->loadlibraryA(p->cDll);
p->msgBoxA(0, p->cCaption, p->cText, 0);
p->exitprocess(0);
}
void injectedThread_end()
{
//Ist nur dafür da, um die größe von injectedThread() rauszubekommen
}
bool enableSeDebugPrivilege()
{
HANDLE myProcess = GetCurrentProcess();
TOKEN_PRIVILEGES pri;
LUID luid;
if(LookupPrivilegeValue(0, "seDebugPrivilege", &luid) == 0)
{
cout << "SE_PRIV: LookupPrivilegeValue: " << GetLastError() << endl;
return false;
}
pri.PrivilegeCount = 0;
pri.Privileges[0].Luid = luid;
pri.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(myProcess, false, &pri, sizeof(TOKEN_PRIVILEGES), 0, 0) == 0)
{
cout << "SE_PRIV: AdjustTokenPrivileges: " << GetLastError() << endl;
return false;
}
cout << "SeDebugPrivilege erfolgreich erhalten." << endl;
CloseHandle(myProcess);
return true;
}