News:

Download Pelles C here: http://www.smorgasbordet.com/pellesc/

Main Menu

Cruel World

Started by czerny, May 03, 2014, 03:38:34 PM

Previous topic - Next topic

czerny

In the following site http://www.unix.com/programming/37678-c-brain-teaser.html is the following brainteaser:

Write a C program to do a small task(lets say just simply printing a "Hello World" or so) such that the program should only give output or the desired result only once after it got compiled and should never give the output nor do anything else. The program should not make use of files or any extrnal means of storing some data.

One of the solutions presented at that site is:

#include <stdio.h>
#include <io.h>

int main (int argc, char* argv[])
{
    printf ("Bye Bye Cruel World :-( \n");
    return (_unlink (argv[0]));
}


but this does not work neither in a windows environment nor in many unix environments.

What are other solutions?

frankie

#1
Hi Czerny,
It doesn't work because trying to delete the executable from inside it causes an access fault because the file is locked while it is executing.
I have seen the solution somewhere when I'll remember I'll tell you. But is something complicated as to inject code to a different process to delete file after the locking by OS has been removed, or something the like...

Start looking here, or here.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

jj2007

#2
One nasty trick (on 32-bit OS only) is to write a few bytes to disk containing a 16-bit DOS exe which kills the 32-bit parent process and then itself.

This works fine in assembler:

  CASE WM_DESTROY
   invoke PostQuitMessage, NULL
   Launch Cat$("cmd.exe /c del "+CL$(0)), SW_HIDE, 1  ; timeout 1 ms

... but no success with what seems to me the C equivalent:

   case WM_DESTROY:
      {
      char buffer[300];   // MAX_PATH+15, ca.
      lstrcpy(buffer, "cmd.exe /c del ");
      GetModuleFileName(0, buffer+15, 285);
      // MessageBox(0, buffer, 0, MB_OK);
      PostQuitMessage(0);
      system(buffer);
      }


GOTCHA!! Forget system...

   case WM_DESTROY:
      {
      char buffer[300];   // MAX_PATH+15, ca.
      lstrcpy(buffer, "cmd.exe /c del ");
      GetModuleFileName(0, buffer+15, 285);
      PostQuitMessage(0);
      WinExec(buffer, SW_HIDE);
      }

Bitbeisser

Quote from: jj2007 on May 03, 2014, 09:22:35 PM
One nasty trick (on 32-bit OS only) is to write a few bytes to disk containing a 16-bit DOS exe which kills the 32-bit parent process and then itself.

This works fine in assembler:<snip>
Maybe, but it is against the requirements of the task:
QuoteThe program should not make use of files or any extrnal means of storing some data.
Ralf

jj2007

Quote from: Bitbeisser on May 04, 2014, 01:52:57 AMMaybe, but it is against the requirements of the task:
QuoteThe program should not make use of files or any extrnal means of storing some data.
Ralf

The part below "GOTCHA" fits the requirement of the task.

TimoVJL

#5
Nice, it works.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

void KillMe(void)
{
    char szBuf[260+11] = "cmd /c del ";
    GetModuleFileName(0, &szBuf[11], 260);
    WinExec(szBuf, SW_HIDE);
}

int main(int argc, char **argv)
{
    KillMe();
    return 0;
}
May the source be with you

czerny


    KillMe();
Sleep(20); // works
Sleep(30); // doesn't work
    return 0;

There is not much time, not enough for a gui programm, I guess.
But that was not the challenge.

czerny

Here is an article about self-deleting exes: http://www.catch22.net/tuts/self-deleting-executables

But there should exist other ways (without deleting the exe) eventually!

Self-modifying code shouldn' be possible in this case? Or is it still possible?

Don't know, if the following solutions are not against the rules:
- use exe's creation time, last access time difference
- use the exe's attrib-flag as work/work not flag

jj2007

Quote from: czerny on May 04, 2014, 04:26:09 PM
There is not much time, not enough for a gui programm, I guess.

There is plenty of time. This works on my slow old machine.

   case WM_DESTROY:
      {
      char buffer[300];   // MAX_PATH+15, ca.
      lstrcpy(buffer, "cmd.exe /c del ");
      GetModuleFileName(0, buffer+15, 285);
      PostQuitMessage(0);
      WinExec(buffer, SW_HIDE);
      Sleep(30);  // just for fun
      }

czerny

Quote from: jj2007 on May 04, 2014, 07:42:54 PM
This works on my slow old machine.
There is always a slower machine. ;)

TimoVJL

How slow ?
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
...
KillMe();
return msg.wParam;
}
May the source be with you