| Code Kitchen Allgemeines Coder-Forum rund um das Programmieren eigenständiger, ausführbarer Programme. |
Diskussion: Beispielprogramm zu Codeinjection im Forum Code Kitchen, in der Kategorie Software Home; Anzeige Hallo allerseits, erstmal vorweg, ich hab die Frage auch schon in einem anderen Forum gestellt, dort konnte mir aber ...
![]() |
| | #1 (permalink) |
| Registriert seit: 10.10.11 ![]() Likes: 0 | Anzeige Hallo allerseits, erstmal vorweg, ich hab die Frage auch schon in einem anderen Forum gestellt, dort konnte mir aber nicht zur Lösung weitergeholfen werden. C/C++ Forum :: Beispielprogramm zu Codeinjection Ich versuch ein Programm zur Codeinjection zu schreiben und hab dazu ein Programm gefunden, dass in Assembler vorliegt und wollte das in C++ übersetzen und ausprobieren. Hier ist erstmal der code was ich bisher hab: Code: #include <iostream>
#include <windows.h>
using namespace std;
void injectedThread();
int main()
{
//get imagebase address
HMODULE mHandle = GetModuleHandle(0);
/*HMODULE mHandle;
if(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, , mHandle) == 0)
{
cout << "GetModuleHandleEx() hat ein Problem" << endl;
return 0;
}*/
//PE headers stuff
DWORD *mHandlePtr = reinterpret_cast<DWORD*>(&mHandle);
mHandlePtr += 60; // 3Ch = 60d ... 3Ch = DOS_PREOFFSET
DWORD mHandleEx = reinterpret_cast<DWORD>(mHandle) + *mHandlePtr;
mHandleEx += 4;
mHandleEx += 20; //14h = 20d
mHandlePtr = &mHandleEx;
//DWORD dwSize = *(mHandlePtr + 56);
DWORD dwSize = 1884160;
//Internet Explorer fenster finden:
HWND hIExplorer = FindWindow("IEFrame", 0);
//HWND hIExplorer = FindWindow(0, "OllyDbg");
if(hIExplorer == 0)
cout << "Internet Explorer nicht gestartet." << endl;
else
cout << "Internet Explorer gefunden" << endl;
DWORD dwPID;
GetWindowThreadProcessId(hIExplorer, &dwPID);
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, false, dwPID);
if(process == 0)
cout << "Process konnte nicht geoeffnet werden" << endl;
else
cout << "Process geoeffnet" << endl;
LPVOID baseAddrOfAllcRgn = VirtualAllocEx(process, mHandle, dwSize, MEM_COMMIT || MEM_RESERVE,PAGE_EXECUTE_READWRITE);
//LPVOID baseAddrOfAllcRgn = VirtualAllocEx(process, NULL, 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;
bool bVFE = VirtualFreeEx(process, mHandle, 0, MEM_RELEASE);
if( bVFE == 0)
{
cout << "VirtualFreeEx hat ein Problem: " << GetLastError() << endl;
return 0;
}
else
cout << "VirtualFreeEx hat speicher freigegeben" << endl;
SIZE_T nBytesWritten;
WriteProcessMemory(process, baseAddrOfAllcRgn, mHandle, dwSize, &nBytesWritten);
LPDWORD lpNULL;
CreateRemoteThread(process, 0, 0, (LPTHREAD_START_ROUTINE)injectedThread, mHandle, 0, lpNULL);
ExitProcess(0);
return 0;
}
void injectedThread()
{
LoadLibrary("user32.dll");
MessageBox(0, "IExplorer", "Hello from iExplorer", 0);
ExitThread(0);
} |
| | |
| | #2 (permalink) |
| Senior Member Registriert seit: 10.03.07 ![]() Likes: 19 | Du solltest anhand der Dokumentation mal die übergebenen Parameter (vor allem die Anzahl) überprüfen. VirtualAllocEx function VirtualFreeEx function Ansonsten mal alle Kompilerwarnungen aktivieren und hier posten, da steht bestimmt irgendetwas, das auf den Fehler deuten könnte. |
| | |
| HaBOT | - Anzeige - |
| |
| | #3 (permalink) | |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Also, vom Kompiler bekomm ich keine Warnungen. Ein Fehler beim VirtualAllocEx war die Verknüpfung von Code: MEM_COMMIT | MEM_RESERVE Zitat:
So, GetModuleHandle liefert mir ja 0x400000 zurück, was ich ja auch dem VirtualAllocEx übergebe. Über das Memory Map(von Olly) hab ich erfahren, das OllyDbg an dieser Stelle bei Access nur read stehen hat. Deswegen hab ich mich nun für die addresse 0x4B4000 entschieden. Ab hier beginnt das Daten segment, in welches ich auch schreiben kann(leider aber nicht ausführen). Nunja, führe ich nun VirtualAllocEx mit dieser Addresse aus, bekomm ich von GetLastError den Fehlercode 6 (INVALID_HANDLE). So langsam weiß ich nicht mehr weiter. Ich probier schon alles mögliche aus, komme aber einfach nicht voran | |
| | |
| | #4 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Du versucht Speicher an Adresse zu reservieren, die schon belegt ist. Kann und wird nicht gut gehen Entweder mit VirtualProtectEx den Speicher auf beschreibbar setzen (wobei man mit VirtualQuery noch am besten die Größe ermitteln sollte) und den Code hineinschreiben oder vorher mit ZwUnmapViewOfSection "entladen": ZwUnmapViewOfSection routine (Windows Driver Kit) oder eben nicht belegten Speicher wählen.
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #5 (permalink) |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Wie finde ich denn unbelegten Speicher? |
| | |
| | #6 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Möglichkeit1: raten VirtualQueryEx liefert einen MEM_FREE Möglichkeit2: den belegten Speicher durchgehen. korrekt sollte es so funktionieren: GetSystemInfo liefert eine SYSTEM_INFO SYSTEM_INFO structure unter anderem Code: LPVOID lpMinimumApplicationAddress; LPVOID lpMaximumApplicationAddress; also sowas wie: Code: act = min;
while act < max:
VirtualQueryEx(bla, act, info)
if info.State == MEM_FREE:
break;
else:
act = act + info.RegionSize die VirtualQueryEx zurückgibt - da ist die RegionSize Angabe dabei (sowie beim Raten einer beliebigen Adresse die "Basis"). Man erfährt also, wo der nächste Speicherblock anfängt. Edit: hier ist mal ein Programm samt (MASM) Quelltext, macht im Prinzip nichts anderes. Allerdings ist da auch GUI Kram dabei, was den Quelltext etwas größer erscheinen lässt. Die relevanten Zeilen sind so ab 500 bis 636 VirtualProtectEx() schlägt immer fehl, wieso???
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #7 (permalink) |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Erstmal vielen Dank für die Antworten. Ich hab jetzt mit der Methode von CDW beschreibaren Speicher gefunden, allerdings bekomm ich von GetLastError immer noch den Fehlercode 487, dass ich an der Addresse nicht schreiben kann. Hier ist jetzt erstmal der Code, den ich nach OpenProcess angefügt hab. Über VirtualQueryEx such ich nach freien Speicher, und mit VirtualProtectEx möchte ich den Speicherbereich beschreibbar und ausführbar machen. Code: //nach beschreibbarn speicher suchen
_SYSTEM_INFO info;
GetSystemInfo(&info);
cout << info.lpMinimumApplicationAddress << endl;
cout << 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;
}
//*actualAddr += memInfo.RegionSize;
}
cout << "Freien Speicher an der Speicherstelle " << actualAddr << " mit der size " << memInfo.RegionSize << " gefunden" << endl;
DWORD previousProtection;
if(VirtualProtectEx(process, actualAddr, memInfo.RegionSize, PAGE_EXECUTE_READWRITE, &previousProtection) == 0)
cout << "VirtualProtect hat ein Problem: " << GetLastError() << endl; |
| | |
| | #8 (permalink) | |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Zitat:
diese Methode geht den kompletten Speicher durch und gibt quasi den Zustand der jeweiligen Bereiche aus. MEM_FREE => ist frei. Also nicht alloziert. Wäre auch blöd, da dann jedes 32-bit Programm per Default 2-3 GB Speicher belegen würde Um irgendwas mit dem MEM_FREE Speicherbereich anzustellen, muss man zuerst VirtualAllocEx aufrufen (dem man auch gleich die die richtigen Parameter übergeben kann) - hier wären eventuell fehlende Rechte die mögliche Fehlerquelle. Das macht durchaus Sinn, da erst bei diesem Aufruf das System auch tatsächich versucht, den Speicherbereich "verfügbar" zu machen (d.h entweder den physikalischen RAMbereich dafür zu reservieren oder Swap). Im übrigen kann und sollte man bei VirtualAllocEx nur die gewünschte Größe reservieren (auch wenn der Block deutlich größer wird) - dann wird der Rest zum freien Block VirtualProtect braucht man nur, wenn man Zugriffseigenschaften des "vorhandenen" Speichers nutzen möchte.
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. | |
| | |
| | #9 (permalink) |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Ich hatte VirtualProtectEx eigentlich aufgerufen, da ich dachte, die gefundenen Bytes sind zwar MEM_FREE, aber das recht da rein zu schreiben hab ich deswegen nicht automatisch... Du sagst ja, VirtualQueryEx geht denn kompletten Speicher durch, das wäre ja der RAM. GetSystemInfo() liefert mir ja lpMaximumApplicationAddress. Dieser Wert liegt bei mir bei 0x7ffeffff. Die Angabe ist doch in Bytes, oder? Naja, den Wert jetzt in Dezimal umgewandelt und zweimal durch 1024 geteilt erhalte ich 2047, ~ 2GB. Ich hab aber 8GB Arbeitsspeicher, was ist mit dem Rest, oder kann ein Win32 Programm nur maximal ~2GB belegen? Würde ja sinn machen, oder warum erwartet VirtualQueryEx einen HANDLE zum Prozess als erstes Argument? Nun zum VirtualAllocEx: Ich hab das VirtualProtectEx auskommentiert und VirtualAllocEx die gefundene Addresse mit dem nicht belegten Speicher übergeben. Als size hab ich erstmal nur 1000 genommen. Code: VirtualAllocEx(process, actualAddress, 1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); Sobald mein Programm nun diese Funktion erreicht gehts nicht mehr weiter. Wie es scheint wird die Funktion nicht verlassen. Die CPU auslastung beträgt immer so rund 12-13%. Der nachfolgende Code wird nicht ausgeführt. Was geht da vor sich? [Edit] Der kursive Teil kann überlesen werden, da stimmte irgendwas nicht, hab den Computer nochmal neu gestartet und nun lässt sich das Programm auch wieder ausführen und VirtualAllocEx liefert mir wieder den Fehlercode 487. Eigentlich müsste ich den bereich doch jetzt allokieren können. Die Size von 1000 ist jedenfalls deutlich kleiner als die Regionsize aus der SystemInfo struktur. Warum funktioniert das nicht? Geändert von seux (11.10.11 um 18:33 Uhr) |
| | |
| | #10 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Um sicher zu gehen, dass es nicht an Rechtemangel liegt (bei "ALL_ACCESS" müsste man sich eigentlich "SeDebugPriviledge" Token verschaffen: http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx), teste mal den Code statt mit OpenProcess mit "CreateProcess(blub)". Lass Dir mal die ganzen Zwischenwerte ausgeben (vor allem, den gefundenen Speicherbereich und die Rückgabewerte von VirtualQueryEx bei der Suche) oder steppe es mal im Debugger durch.
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #11 (permalink) |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Ich krieg den Process mit CreateProcess nicht gestartet. Ich hab schon sehr viel ausprobiert, aber ich bekomm immer nur den Fehler 87, das ein parameter falsch ist. Code: STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
char szExe[] = "D:\\OllyDbg 2.0\\ollydbg.exe";
if(CreateProcess((LPCTSTR)szExe, 0, 0, 0, false, 0, 0, 0, &startupInfo, &processInfo) != 0)
{ |
| | |
| | #12 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | ZeroMemory / memset(blub,0) für startup/processinfo. Zumindest startup ist ein "input" Parameter und ist sonst als Stackvariable mit 99% Sicherheit mit irgendwelchen Werte "vorinitialisiert", die nicht hingehören. Creating Processes
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #13 (permalink) |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Ah, wunderbar Okay, wenn ich den Process via CreateProcess erstelle, ist VirtualAllocEx in der Lage Speicher zu reservieren und auch VirtualFreeEx liefert keine Fehlermeldungen (wird VirtualFreeEx denn eigentlich noch gebraucht?). Damit habe ich jetzt wohl bei OpenProcess ein Rechteproblem, oder? Wenn ich CreateProcess benutze funktioniert das Programm bis zum WriteProcessMemory anstandslos, wo ich dann mal wieder den Fehler 487 bekomme ![]() Hier nochmal zur kurzübersicht nur die Funktionen und ihre Argumente: Code: LPVOID baseAddrOfAllcRgn = VirtualAllocEx(process, actualAddr, 1000, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE); VirtualFreeEx(process, actualAddr, 0, MEM_RELEASE); SIZE_T nBytesWritten; WriteProcessMemory(process, baseAddrOfAllcRgn, actualAddr, 1000, &nBytesWritten) |
| | |
| | #14 (permalink) | ||||
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Vermutlich. Wie gesagt, Du solltest mal ALLE Rückgabewerte prüfen. In Deinem Code sehen ich nämlich kein "SeDebugPrivilege" Anforderung. CreateProcess gibt dem "Vater" nämlich automatisch die "ALL_ACCESS" Rechte. Bei OpenProcess wird es komplizierter: Explizit besagt die Doku zum CreateRemoteThread: Zitat:
Zitat:
Zugegeben, so ganz durchgestiegen bei den Rechtezuordnungen bin ich auch nicht (die Doku ist imho nicht ganz eindeutig) meine aber, dass CreateRemoteThread bei "Fremdprocessen" den "SeDebugPrivilege" erfordert (diese habe ich zumindest in solchen Fällen dem Prozess immer erteilt) Beispielcode: Enabling and Disabling Privileges in C++ Zitat:
VirtualAlloc == malloc VirtualFree == free d.h zuerst wird Speicher alloziert, dann freigegeben und dann versucht, einen Inhalt reinzuschreiben. Im "normalen" C fällt es nicht sofort auf und man nennt das "dangling pointers" Zitat:
Wenn an der Adresse nichts ist, wird CreateRemoteThread auch nichts hinüberkopieren (woher auch Nochmal zusammengefasst: 1. eine freie Speicheradresse mit der VirtualQueryEx suchen 2. Speicher mit richtigen Flags per VirtualAllocEx reservieren 3. Inhalt mit WriteProcessMemory schreiben 4. Ausführen mit CreateRemoteThread 5. Optional: wenn die Ausführung fertig ist(WaitForSingleObject), Speicher mit VirtualFreeEx freigeben
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. | ||||
| | |
| | #15 (permalink) |
| Themenstarter Registriert seit: 10.10.11 ![]() Likes: 0 | Bevor ich jetzt wieder zum OpenProcess() wechsel und somit mich dann erstmal mit der Rechtebeschaffung beschäftige, würde ich das jetzt ganz gerne mal mit CreateProcess ausprobieren. Immerhin hab ich jetzt ja schon speicher allokiert und das recht dorthin zu schreiben. Mit WriteProcessMemory kann ich erfolgreich an die Addresse schreiben. Nun möchte ich den Code von der injectedThread Funktion an die besagte Addresse speichern. Code: WriteProcessMemory(process, baseAddrOfAllcRgn, (LPCVOID)injectedThread, dwSize, &nBytesWritten) Dieser Wert ist in meinen Augen jetzt extrem hoch für so eine kleine Funktion wie die injectedThread eine ist. Meine vermutung ist jetzt, dass nicht nur die injectedThread Funktion (wenn ich sie überhaupt korrekt übergeben habe) an diese Addresse geschrieben wird, sondern auch noch die Bytes, die danach kommen. Das heißt, dass ich die größe der Funktion ermitteln müsste. Kann ich die Size einer Funktion rausbekommen? Ich mein ungefähr sowas wie Code: dwSize = sizeof(injectedThread); |
| | |
![]() |
| - Anzeige - | |
| |
| Themen-Optionen | |
| Ansicht | |
| |