Entwickler-Ecke

Dateizugriff - Löschen einer Datei auch wenn Sie geöffnet ist!!


Freeman1982 - Sa 02.04.05 20:43
Titel: Löschen einer Datei auch wenn Sie geöffnet ist!!
Hallo,

hBe eine Datei z.B Artikel.dat in der verschiedene daten gespeicht werden und geladen werden. Gib es ein Befehl wo datei löscht auch wenn das Programm noch darauf zugreifft. Oder Sie noch offfen ist??

MfG

Freeman 1982


MSCH - So 03.04.05 20:01

nein, die Sperrung führt das BS für dich durch. Es gibt keine (mir bekannte) Möglichkeit, eine geöffnete Datei on the fly zu löschen. Desgleichen trifft für Dateien die Anwendungen sind und grad laufen zu.

grez
msch


Delete - So 03.04.05 20:04

Autsch. Was würdest du dazu sagen, wenn eine andere Anwendung dir den Teppich unter den Füßen wegzieht? :roll:


MSCH - So 03.04.05 20:06

würde mich interessieren, wie diese dass schafft, meine laufende Anwendung zu löschen.
grez
msch


Delete - So 03.04.05 20:17

Die Forensuche, das unbekannte Wesen: http://www.delphi-forum.de/topic_sich+ein+Programm+selber+loeschen_11730.html

Sorry, war Mist.


MSCH - So 03.04.05 20:36

jeap grosser mist, hihi, ein sich selbst ständig wiederholender Löschversuch.
Nett, wenn die CPU Auslastung auch noch voll ausschlägt. :-)

Selbst windows himself brauch für sowas einen neustart um geöffnete Dateien zu überschreiben.

grez
msch


Sprint - So 03.04.05 20:48

user profile iconMSCH hat folgendes geschrieben:
würde mich interessieren, wie diese dass schafft, meine laufende Anwendung zu löschen.

http://www.catch22.net/tuts/selfdel.asp


MSCH - Mo 04.04.05 16:50

hallo, ich sagte laufende Anwendung!!!
Das geht nicht.
grez
msch


Sprint - Mo 04.04.05 18:46

user profile iconMSCH hat folgendes geschrieben:
hallo, ich sagte laufende Anwendung!!!
Das geht nicht.

Link hab ich dir gepostet. Lesen musst du schon alleine.


MSCH - Di 05.04.05 16:10

wer lesen kann ist klar im Vorteil:

solche Sachen wie:

Quelltext
1:
2:
3:
4:
5:
:Repeat
del "C:\MYDIR\MYPROG.EXE"
if exist "MYPROG.EXE" goto Repeat
rmdir "C:\MYDIR"
del "\DelUS.bat"


löschen keine laufende Anwendung sondern versuchen dies, bis die Anwendung geschlossen ist, immer wieder.


Quelltext
1:
2:
3:
BOOL MoveFileEx(LPCTSTR lpExistingFileName, 
                LPCTSTR lpNewFileName, DWORD dwFlags); 
This API call moves a file to a new location. When you pass NULL as the second parameter, this causes the file to be moved "nowhere", effectively deleting the file. Now, ordinarily this would fail if you tried this with the path to the current executable. However, if we specify MOVEFILE_DELAY_UNTIL_REBOOT in the dwFlags parameter, this tells Windows not to move (or delete) the file until the system is shutdown or rebooted.


auch so ein "trick". Der nichts weiter macht, als beim nächsten Booten die Datei zu löschen - auch da darf sie nicht offen sein.

ES gibt keine Methode, nur pseudoanweisungen die sich nicht auf geöffnete Dateien beziehen.


grez
msch


Sprint - Di 05.04.05 21:40

user profile iconMSCH hat folgendes geschrieben:
ES gibt keine Methode, nur pseudoanweisungen die sich nicht auf geöffnete Dateien beziehen.

Warum hast du den Artikel nicht bis zum Ende gelesen?


opfer.der.genauigkeit - Di 05.04.05 22:16

user profile iconSprint hat folgendes geschrieben:
user profile iconMSCH hat folgendes geschrieben:
ES gibt keine Methode, nur pseudoanweisungen die sich nicht auf geöffnete Dateien beziehen.

Warum hast du den Artikel nicht bis zum Ende gelesen?


MSCH meinte ja auch, daß es bei geöffneten Dateien nicht geht.

Ich habe mal das Tutorial durchgelesen und überall wird der entsprechende
Prozess erst geschlossen, bevor die Binary gelöscht wird.
Macht auch Sinn und anders wirst du es auch nicht hinbekommen es sei denn, du machst
dir ernsthaft die Mühe und holst dir alle Beziehungen, die das Programm am Laufen
hat und löschst sie direkt, aber die Fehlermeldungen, möcht ich nicht lesen müßen. :mrgreen:
Vor allem, wie erklärst du das dem BS, bin mir nicht sicher ob es selbstständig merkt,
daß das von ihm geschütze Programm sich "auflöst". ;)

Es geht alles irgendwie.. Lazarus z.B. kann sich selbst Kompilieren.
Also die laufende IDE kompiliert sich selbst.. geht auch nur über einen Trick,
da Windows sowas nicht zuläßt.

//Edit: Eine interessante Variante, die mir grad eingefallen ist, wäre es ja
ein externes Deleteprogramm zu starten, daß nur in den Arbeitsspeicher geladen wird.
Das Deleteprogramm beendet das Hauptprogramm (aus dem es gestartet wurde) und löscht es. Danach beendet sich das Deleteprogramm. Wenn ich richtig liege, müßte es dann im Arbeitsspeicher als tot gelten und somit entweder vom nächsten Prozess, der geladen wird überschrieben werden oder das BS löscht es sofort.
Bin aber absolut nicht sicher, was mit dem Deleteprog. passiert. :dance:


uall@ogc - Di 05.04.05 22:51

@opfer.der.genauigkeit

genau das macht die letzte methode die in dem link von Sprint beschrieben wird


man müsste die doch theoretisch in der dateizuordnungtabelle löschen können oder net?


opfer.der.genauigkeit - Di 05.04.05 22:54

user profile iconuall@ogc hat folgendes geschrieben:
@opfer.der.genauigkeit
genau das macht die letzte methode die in dem link von Sprint beschrieben wird


Ja? Ok, dann hab ich auch nicht genau hingesehen. :roll:

user profile iconuall@ogc hat folgendes geschrieben:

man müsste die doch theoretisch in der dateizuordnungtabelle löschen können oder net?


Nicht nur theoretisch, aber wie weit will man denn für so ein Programm auf die Systemebene gehen?
Wobei ich mich frage, ob das nicht auch wieder nur ne unbekannte Anzahl von Fehlermeldungen ausgibt?

//Edit: letzter Satz bezieht sich natürlich auf Änderungen während das Programm läuft.


florian - Di 17.01.06 16:04

user profile iconSprint hat folgendes geschrieben:

http://www.catch22.net/tuts/selfdel.asp


Hallo,

ist es möglich, das letzte Beispiel auch mit Delphi zu realisieren? Ich bin leider etwas eingerostet, weshalb ich sehr dankbar wäre, wenn mir einer mal unter die Arme greift! :)

Danke schonmal!

Gruß
Florian


F34r0fTh3D4rk - Di 17.01.06 16:45

das hier ?


C#-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:
#include <windows.h> 

#pragma comment(linker, "-export:CleanupA=_CleanupA@16­") 

extern "C" void CALLBACK CleanupA(HWND, HINSTANCE, PSTR, int) 
{ 
    static MEMORY_BASIC_INFORMATION mbi; 
    VirtualQuery(&mbi, &mbi, sizeof mbi); 
    PVOID module = mbi.AllocationBase; 

    CHAR buf[MAX_PATH]; 
    GetModuleFileName(HMODULE(module), buf, sizeof buf); 

    __asm 
    { 
        lea     eax, buf 
        push    0 
        push    0 
        push    eax 
        push    ExitProcess 
        push    module 
        push    DeleteFile 
        push    FreeLibrary 
        ret 
    }
}


florian - Di 17.01.06 21:15

nein, ich meine das hier:


C#-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:
159:
//
//  selfdel.c
//
//  Self deleting executable for Win9x/WinNT (all versions)
//
//  J Brown 1/10/2003
//
//  This source file must be compiled with /GZ turned OFF
//  (basically, disable run-time stack checks)
//
//  Under debug build this is always on (MSVC6)
//
//
#include <windows.h>
#include <tchar.h>

#pragma pack(push, 1)

#define CODESIZE 0x200

//
//  Structure to inject into remote process. Contains 
//  function pointers and code to execute.
//
typedef struct _SELFDEL
{
  struct _SELFDEL *Arg0;      // pointer to self

  BYTE  opCodes[CODESIZE];    // code 

  HANDLE  hParent;        // parent process handle

  FARPROC  fnWaitForSingleObject;
  FARPROC  fnCloseHandle;
  FARPROC  fnDeleteFile;
  FARPROC  fnSleep;
  FARPROC  fnExitProcess;
  FARPROC fnRemoveDirectory;
  FARPROC fnGetLastError;

  BOOL  fRemDir;

  TCHAR  szFileName[MAX_PATH];  // file to delete

} SELFDEL;

#pragma pack(pop)

#ifdef _DEBUG
#define FUNC_ADDR(func) (PVOID)(*(DWORD *)((BYTE *)func + 1) + (DWORD)((BYTE *)func + 5))
#else
#define FUNC_ADDR(func) func
#endif

//
//  Routine to execute in remote process. 
//
static void remote_thread(SELFDEL *remote)
{
  // wait for parent process to terminate
  remote->fnWaitForSingleObject(remote->hParent, INFINITE);
  remote->fnCloseHandle(remote->hParent);

  // try to delete the executable file 
  while(!remote->fnDeleteFile(remote->szFileName))
  {
    // failed - try again in one second's time
    remote->fnSleep(1000);
  }

  // finished! exit so that we don't execute garbage code
  remote->fnExitProcess(0);
}

//
//  Delete currently running executable and exit
//  
BOOL SelfDelete(BOOL fRemoveDirectory)
{
  STARTUPINFO      si = { sizeof(si) };
  PROCESS_INFORMATION pi;

  CONTEXT        context;
  DWORD        oldProt;
  SELFDEL        local;
  DWORD        entrypoint;

  TCHAR        szExe[MAX_PATH] = _T("explorer.exe");

  //
  //  Create executable suspended
  //
  if(CreateProcess(0, szExe, 0, 0, 0, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, 0, 0, &si, &pi))
  {
    local.fnWaitForSingleObject    = (FARPROC)WaitForSingleObject;
    local.fnCloseHandle        = (FARPROC)CloseHandle;
    local.fnDeleteFile        = (FARPROC)DeleteFile;
    local.fnSleep          = (FARPROC)Sleep;
    local.fnExitProcess        = (FARPROC)ExitProcess;
    local.fnRemoveDirectory      = (FARPROC)RemoveDirectory;
    local.fnGetLastError      = (FARPROC)GetLastError;

    local.fRemDir          = fRemoveDirectory;

    // Give remote process a copy of our own process handle
    DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), 
      pi.hProcess, &local.hParent, 0, FALSE, 0);

    GetModuleFileName(0, local.szFileName, MAX_PATH);

    // copy in binary code
    memcpy(local.opCodes, FUNC_ADDR(remote_thread), CODESIZE);

    //
    // Allocate some space on process's stack and place
    // our SELFDEL structure there. Then set the instruction pointer 
    // to this location and let the process resume
    //
    context.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
    GetThreadContext(pi.hThread, &context);

    // Allocate space on stack (aligned to cache-line boundary)
    entrypoint = (context.Esp - sizeof(SELFDEL)) & ~0x1F;
    
    //
    // Place a pointer to the structure at the bottom-of-stack 
    // this pointer is located in such a way that it becomes 
    // the remote_thread's first argument!!
    //
    local.Arg0 = (SELFDEL *)entrypoint;

    context.Esp = entrypoint - 4;  // create dummy return address
    context.Eip = entrypoint + 4;  // offset of opCodes within structure

    // copy in our code+data at the exe's entry-point
    VirtualProtectEx(pi.hProcess,   (PVOID)entrypoint, sizeof(local), PAGE_EXECUTE_READWRITE, &oldProt);
    WriteProcessMemory(pi.hProcess, (PVOID)entrypoint, &local, sizeof(local), 0);

    FlushInstructionCache(pi.hProcess, (PVOID)entrypoint, sizeof(local));

    SetThreadContext(pi.hThread, &context);

    // Let the process continue
    ResumeThread(pi.hThread);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

    return TRUE;
  }

  return FALSE;
}


int main(void)
{
  SelfDelete(TRUE);
  return 0;
}


Gruß
Florian


galagher - Di 17.01.06 21:19

Man müsste Windows vorgaukeln, dass das zu löschenden Programm nicht geöffnet ist, selbst, wenn es das ist. Oder, auch möglich, man versetzt es von aussen in einen Zustand, der dem "Hängen" eines Programmes entspricht. Windows wird bemerken, dass das Program nicht reagiert und wird es beenden bzw. zumindest einen Dialog öffnen, damit der User es beendet. Dann kann man es auch löschen.

Bleibt nur noch eine lästige Kleinigkeit: Wie? :mrgreen:


Coder - Di 17.01.06 22:44

Er will doch eine Datei löschen?
Da gibt es doch beim Öffnen mit einem Stream einen Parameter mit dem man IMHO auch steuern kann das andere Programme schreibrechte haben.


galagher - Di 17.01.06 23:10

user profile iconCoder hat folgendes geschrieben:
Er will doch eine Datei löschen?

Ja. Sorry!


wolke - Di 17.01.06 23:58

hallo?
habt ihr auch verstanden was die letzte methode macht?
auch die löscht die datei natürlich erst, nachdem der prozess beendet wurde.

Zitat:
- The injected code waits for the parent-process to exit.
- The parent-process is then deleted.


das einzige was natürlih (von aussen) möglich ist: feststellen wer die datei nutzt, diesen aus dem speicher werfen (freundlich oder unfreundlich), um dann die datei zu löschen.


uall@ogc - Mi 18.01.06 18:28

Hab hier mal was gemacht, womit man keine Batch Dateien braucht.


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:
procedure AsmBegin;
asm
  //int 3
  NOP
  NOP
  NOP
  PUSH $64                    // TaskSwitch
  CALL DWORD PTR [$00000000]  // Sleep
  PUSH DWORD PTR [$00000018]  // ProcessHandle
  PUSH 0
  PUSH PROCESS_ALL_ACCESS
  CALL DWORD PTR [$00000004]  // OpenProcess
  TEST EAX, EAX
  JZ @@Terminated
  PUSH EAX
  CALL DWORD PTR [$00000008]  // TerminateProcess
  TEST EAX, EAX
  POP EAX
  CALL DWORD PTR [$0000000C]  // CloseHandle
  PUSH 1000                   // TaskSwitch [Process terminating]
  CALL DWORD PTR [$00000000]  // Sleep

@@Terminated:
  PUSH [$0000001C] // StringOffset
  CALL [$00000010] // DeleteFileA
  PUSH 0
  CALL [$00000014] // ExitProcess
  RET
end;
procedure AsmEnd; asm end;

procedure CloseAndDeleteMe;
var pTempMem: Pointer;
    pTargetMem: Pointer;
    sFile: String;
    dwMemSize: DWord;
    dwAsmSize: DWord;
    lpStartupInfo: TStartupInfo;
    lpProcessInformation: TProcessInformation;

    pSleep: Pointer;
    pOpenProcess: Pointer;
    pTerminateProcess: Pointer;
    pCloseHandle: Pointer;
    pDeleteFileA: Pointer;
    pExitProcess: Pointer;

    dwKernelHandle: DWord;
    dwBytesWritten: DWord;
    dwThreadID: DWord;
begin
  dwKernelHandle := GetModuleHandle('kernel32.dll');

  pSleep := GetProcAddress(dwKernelHandle,'Sleep');
  pOpenProcess := GetProcAddress(dwKernelHandle,'OpenProcess');
  pTerminateProcess := GetProcAddress(dwKernelHandle,'TerminateProcess');
  pCloseHandle := GetProcAddress(dwKernelHandle,'CloseHandle');
  pDeleteFileA := GetProcAddress(dwKernelHandle,'DeleteFileA');
  pExitProcess := GetProcAddress(dwKernelHandle,'ExitProcess');

  sFile := Paramstr(0);

  dwAsmSize := DWord(@AsmEnd)-DWord(@AsmBegin);
  dwMemSize := dwAsmSize+DWord(Length(sFile))+1+$20*Sizeof(DWord);
  ZeroMemory(@lpStartupInfo,SizeOf(lpStartupInfo));
  lpStartupInfo.cb := SizeOf(lpStartupInfo);
  if CreateProcessA(nil,'explorer',nil,nil,false,CREATE_SUSPENDED,nil,
    nil,lpStartupInfo,lpProcessInformation) then
  begin
    pTempMem := VirtualAlloc(nil,dwMemSize,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if (pTempMem = nil) then
      Exit;
    pTargetMem := VirtualAllocEx(lpProcessInformation.hProcess,nil,dwMemSize,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if (pTargetMem = nil) then
    begin
      VirtualFree(pTempMem,dwMemSize,MEM_RELEASE);
      Exit;
    end;
    CopyMemory(pTempMem,@AsmBegin,dwAsmSize);
    CopyMemory(Pointer(DWord(pTempMem)+$20+dwAsmSize),@sFile[1],Length(sFile));

    PPointer(DWord(pTempMem)+dwAsmSize+$00)^ := pSleep;
    PPointer(DWord(pTempMem)+dwAsmSize+$04)^ := pOpenProcess;
    PPointer(DWord(pTempMem)+dwAsmSize+$08)^ := pTerminateProcess;
    PPointer(DWord(pTempMem)+dwAsmSize+$0C)^ := pCloseHandle;
    PPointer(DWord(pTempMem)+dwAsmSize+$10)^ := pDeleteFileA;
    PPointer(DWord(pTempMem)+dwAsmSize+$14)^ := pExitProcess;
    PDWord(DWord(pTempMem)+dwAsmSize+$18)^ := GetCurrentProcessID;
    PDWord(DWord(pTempMem)+dwAsmSize+$1C)^ := DWord(pTargetMem)+dwAsmSize+$20;

    PDWord(DWord(pTempMem)+07)^ := DWord(pTargetMem)+dwAsmSize+$00;
    PDWord(DWord(pTempMem)+26)^ := DWord(pTargetMem)+dwAsmSize+$04;
    PDWord(DWord(pTempMem)+37)^ := DWord(pTargetMem)+dwAsmSize+$08;
    PDWord(DWord(pTempMem)+46)^ := DWord(pTargetMem)+dwAsmSize+$0C;
    PDWord(DWord(pTempMem)+57)^ := DWord(pTargetMem)+dwAsmSize+$00;
    PDWord(DWord(pTempMem)+69)^ := DWord(pTargetMem)+dwAsmSize+$10;
    PDWord(DWord(pTempMem)+77)^ := DWord(pTargetMem)+dwAsmSize+$14;

    PDWord(DWord(pTempMem)+13)^ := DWord(pTargetMem)+dwAsmSize+$18;
    PDWord(DWord(pTempMem)+63)^ := DWord(pTargetMem)+dwAsmSize+$1C;

    if WriteProcessMemory(lpProcessInformation.hProcess,pTargetMem,pTempMem,dwMemSize,dwBytesWritten)
      and (dwBytesWritten = dwMemSize) then
      CreateRemoteThread(lpProcessInformation.hProcess,nil,0,pTargetMem,nil,0,dwThreadID);
    ExitProcess(0);
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  CloseAndDeleteMe;
end;


florian - Mo 23.01.06 08:27

Danke, werde das daheim dann gleich mal ausprobieren. :)


AXMD - Mo 23.01.06 09:38

Reicht es nicht, dem Prozess, dem die Datei gehört, einfach das entsprechende Handle wegzunehmen? Process Explorer ([url]http://www.sysinternals.com[/url]) macht das IIRC so - hab aber keine Ahnung wie.

AXMD