c++ deleting current program

Started by
24 comments, last by Tayron 14 years, 7 months ago
Quote:Original post by Tayron
Quote:Original post by daviangel
I have no idea why you would want to do this but i seems like this is not as obscure as I thought since I just ran across some code that will do this in Windows:
An tricky little piece of code that will destroy itself!

this can be useful when making an updater and stuff like that.
If you're making an updater, then you can delete the old file from within the new process.
Advertisement
I coded up a solution:

#include <iostream>#include <cstdio>#include <cstdlib>int main (int argc, char *argv[]) {        //std::cout << argv[0];        if (argc > 1) {                std::cout << "trying to remove " << argv[1] << '\n';                while (0 != remove (argv[1])) {}                std::cout << "remove okay.\n";        } else {                if (FILE *src = fopen (argv[0], "rb")) {                        std::cout << "source okay.\n";                        if (FILE *dst = fopen ("heh.exe", "wb")) {                                std::cout << "target okay.\n";                                while (!feof (src))                                        fputc (fgetc (src), dst);                                fclose (dst);                        }                        fclose (src);                }                #if defined(_WIN32)||defined(_WIN64)                system ((std::string("start heh.exe \"") + argv[0] + "\"").c_str());                #elif defined (__linux)                system ("chmod u+x heh.exe");                system ((std::string("heh.exe \"") + argv[0] + "\" &").c_str());                #else                #    error                #endif        }}


Bit dirty, sorry, but there's only line of code that contains non-portable code (note, however, that no file extension is needed on linux; also note that I did not test on linux; thirdly: note that this whole fluff would not be needed on linux, in case the binary has write rights upon itself (normally, this is not the case unless run as root)).

It opens itself in binary-read-only, then copies itself into a new binary, then starts the new binary in a new shell * and with an argument. If the binary finds that you have given her an argument, it will try to remove the file you told her.

You could tweak this and instead of copying yourself to "heh.exe", you could target the temporary directory.



One question though: Is this for kicks or for malicious purposes?


* Or better, in the same shell that our initial process runs in, so that the initial process doesn't have any child process to wait for.

sidenote: I remember there was something security related with forbidding of executing binaries in the /tmp folder on linuxes; can't remember what it was (AppArmor or SELinux, maybe?).


edit: bah! why does even gd.net put zero-indent before preprocessor directives? (at least where the #if is)

[Edited by - phresnel on September 24, 2009 10:10:52 AM]
Quote:Original post by Evil Steve
Quote:Original post by Tayron
Quote:Original post by daviangel
I have no idea why you would want to do this but i seems like this is not as obscure as I thought since I just ran across some code that will do this in Windows:
An tricky little piece of code that will destroy itself!

this can be useful when making an updater and stuff like that.
If you're making an updater, then you can delete the old file from within the new process.


I'm not making an updater. I just gave an example.Just thought it'd be fun to try and do this. it might be useful later on.
Quote:Original post by phresnel

One question though: Is this for kicks or for malicious purposes?


kicks:)

Quote:Original post by phresnel
I coded up a solution:

*** Source Snippet Removed ***

Bit dirty, sorry, but there's only line of code that contains non-portable code (note, however, that no file extension is needed on linux; also note that I did not test on linux; thirdly: note that this whole fluff would not be needed on linux, in case the binary has write rights upon itself (normally, this is not the case unless run as root)).

It opens itself in binary-read-only, then copies itself into a new binary, then starts the new binary in a new shell * and with an argument. If the binary finds that you have given her an argument, it will try to remove the file you told her.

You could tweak this and instead of copying yourself to "heh.exe", you could target the temporary directory.



One question though: Is this for kicks or for malicious purposes?


* Or better, in the same shell that our initial process runs in, so that the initial process doesn't have any child process to wait for.

sidenote: I remember there was something security related with forbidding of executing binaries in the /tmp folder on linuxes; can't remember what it was (AppArmor or SELinux, maybe?).


edit: bah! why does even gd.net put zero-indent before preprocessor directives? (at least where the #if is)


hmm, nice code...but I can't compile it...here's the error report from compilation (Visual Studio 9):
1&gt;main.cpp1&gt;.\main.cpp(12) : warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.1&gt;        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\stdio.h(237) : see declaration of 'fopen'1&gt;.\main.cpp(14) : warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.1&gt;        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\stdio.h(237) : see declaration of 'fopen'1&gt;.\main.cpp(23) : error C2784: 'std::_String_iterator&lt;_Elem,_Traits,_Alloc&gt; std::operator +(_String_iterator&lt;_Elem,_Traits,_Alloc&gt;::difference_type,std::_String_iterator&lt;_Elem,_Traits,_Alloc&gt;)' : could not deduce template argument for 'std::_String_iterator&lt;_Elem,_Traits,_Alloc&gt;' from 'char *'1&gt;        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\xstring(440) : see declaration of 'std::operator +'1&gt;.\main.cpp(23) : error C2784: 'std::_String_const_iterator&lt;_Elem,_Traits,_Alloc&gt; std::operator +(_String_const_iterator&lt;_Elem,_Traits,_Alloc&gt;::difference_type,std::_String_const_iterator&lt;_Elem,_Traits,_Alloc&gt;)' : could not deduce template argument for 'std::_String_const_iterator&lt;_Elem,_Traits,_Alloc&gt;' from 'char *'1&gt;        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\xstring(300) : see declaration of 'std::operator +'1&gt;.\main.cpp(23) : error C2784: 'std::reverse_iterator&lt;_RanIt&gt; std::operator +(_Diff,const std::reverse_iterator&lt;_RanIt&gt; &)' : could not deduce template argument for 'const std::reverse_iterator&lt;_RanIt&gt; &' from 'char *'1&gt;        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\xutility(2229) : see declaration of 'std::operator +'1&gt;.\main.cpp(23) : error C2784: 'std::_Revranit&lt;_RanIt,_Base&gt; std::operator +(_Diff,const std::_Revranit&lt;_RanIt,_Base&gt; &)' : could not deduce template argument for 'const std::_Revranit&lt;_RanIt,_Base&gt; &' from 'char *'1&gt;        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\xutility(2029) : see declaration of 'std::operator +'1&gt;.\main.cpp(23) : error C2676: binary '+' : 'std::basic_string&lt;_Elem,_Traits,_Ax&gt;' does not define this operator or a conversion to a type acceptable to the predefined operator1&gt;        with1&gt;        [1&gt;            _Elem=char,1&gt;            _Traits=std::char_traits&lt;char&gt;,1&gt;            _Ax=std::allocator&lt;char&gt;1&gt;        ]1&gt;.\main.cpp(23) : error C2228: left of '.c_str' must have class/struct/union
Quote:Original post by phresnel

One question though: Is this for kicks or for malicious purposes?



I wouldn't worry about maliciousness. If he wanted to do something malicious (which he said he doesn't), he could do much better using pre-built scripts and rootkits.
ok, I've fixed it:)
here's the working code:
#include <iostream>#include <cstdio>#include <cstdlib>int main (int argc, char *argv[]) {        //std::cout << argv[0];        if (argc > 1) {                std::cout << "trying to remove " << argv[1] << '\n';                while (0 != remove (argv[1])) {}                std::cout << "remove okay.\n";        } else {                if (FILE *src = fopen (argv[0], "rb")) {                        std::cout << "source okay.\n";                        if (FILE *dst = fopen ("heh.exe", "wb")) {                                std::cout << "target okay.\n";                                while (!feof (src))                                        fputc (fgetc (src), dst);                                fclose (dst);                        }                        fclose (src);                }                #if defined(_WIN32)||defined(_WIN64)				char a[256]="start heh.exe \"";				strcat(a,argv[0]);				strcat(a,"\"");                system (std::string(a).c_str());                #elif defined (__linux)                system ("chmod u+x heh.exe");                system ((std::string("heh.exe \"") + argv[0] + "\" &").c_str());                #else                #    error                #endif        }}

thanks for the help:)
hmm..sorry, still doesn't work...it works if you compile it with ctrl+f5, but if you start it directly, it locks up at "trying to delete...."..
hmmm...
Can you fork in windows?
If yes: wouldn't it be possible to fork(), end the parent process, and then delete the exe from the child?
One solution has already been posted, that is to spawn a copy of the process, and make the main args determine whether or not the process will run normally or function as a delete program.

I don't like that approach because it requires you to modify the main program, instead of just calling a function, and does a bunch of unnecessary file copying.


Here's a self contained function that you can use in any version of Windows. It uses cmd.exe to delete the process. You need to exit the current process immediately after calling this function. There is a race condition here so if you don't exit immediately, it may not be deleted.

BOOL SelfDelete(){	TCHAR szFile[MAX_PATH], szCmd[MAX_PATH];	if((GetModuleFileName(0,szFile,MAX_PATH)!=0) &&		(GetShortPathName(szFile,szFile,MAX_PATH)!=0))	{		//open cmd.exe and tell it to del the file		sprintf_s(szCmd, MAX_PATH, "/c del %s >> NUL", szFile );				if((GetEnvironmentVariable("ComSpec",szFile,MAX_PATH)!=0) &&			((INT)ShellExecute(NULL,0,szFile,szCmd,0,SW_HIDE)>32))			return TRUE;			}	return FALSE;}

This topic is closed to new replies.

Advertisement