Error C2197: 'FARPROC', I need a soliution

Hello.
I can't get this c code work in visual cpp compiler.

I found this information:
http://support.microsoft.com/kb/117428

Could anyone tell me what I need to edit here?

Thanks in advance.
//
//	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;
}

Open in new window

makasbrgAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Infinity08Commented:
What line does the error point to ?
0
makasbrgAuthor Commented:
error C2197: 'FARPROC' : too many arguments for call through pointer-to-function
Lines: 61, 62, 65

fatal error C1903: unable to recover from previous error(s); stopping compilation

0
Infinity08Commented:
Probably these :

                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;

FARPROC is a pointer to a function that takes no arguments and returns an int.

You're trying to assign different types of functions to it ... You need to use the proper function pointer typedefs. For example, for WaitForSingleObject, that would be :

        typedef DWORD (*FunPtrToWFSO)(HANDLE, DWORD);

ie. a pointer to a function taking a HANDLE and a DWORD as arguments and returning a DWORD. Then :

        FunPtrToWFSO fnWaitForSingleObject;

and you can assign the function pointer :

        local.fnWaitForSingleObject = (FunPtrToWFSO) WaitForSingleObject;

Similarly for the others.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

Infinity08Commented:
>> Lines: 61, 62, 65

Yes, that would be the result of using the wrong function pointer typedef ;)
0
makasbrgAuthor Commented:
I am only begginer so I guess I will need some more help :\

I modified code like shown, code compiles, but program crashes on execution and doesn't delete itself.


I also get these warnings:
12.cpp(123) : warning C4311: 'type cast' : pointer truncation from 'BYTE *' to 'DWORD'
12.cpp(123) : warning C4312: 'type cast' : conversion from 'unsigned long' to 'PVOID' of greater size
12.cpp(141) : warning C4312: 'type cast' : conversion from 'DWORD' to 'SELFDEL *' of greater size
12.cpp(147) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
12.cpp(148) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
12.cpp(150) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
#include "stdafx.h"
//	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 DWORD (*PWaitForSingleObject)(HANDLE, DWORD);
PWaitForSingleObject fnWaitForSingleObject;
typedef DWORD (*PCloseHandle)(HANDLE);
PCloseHandle fnCloseHandle;
typedef DWORD (*PSleep)(int);
PSleep fnSleep;
typedef DWORD (*PDeleteFile)(TCHAR[260]);
PDeleteFile fnDeleteFile;
typedef DWORD (*PExitProcess)(int);
PExitProcess fnExitProcess;
 
 
typedef struct _SELFDEL
{
	struct _SELFDEL *Arg0;			// pointer to self
 
	BYTE	opCodes[CODESIZE];		// code 
 
	HANDLE	hParent;				// parent process handle
 
	(PWaitForSingleObject) fnWaitForSingleObject;
	(PCloseHandle) fnCloseHandle;
	(PDeleteFile) fnDeleteFile;
	(PSleep) fnSleep;
	(PExitProcess) fnExitProcess;
	(PCloseHandle) fnRemoveDirectory;
	(PCloseHandle) 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		= (PWaitForSingleObject)WaitForSingleObject;
		local.fnCloseHandle				= (PCloseHandle)CloseHandle;
		local.fnDeleteFile				= (PDeleteFile)DeleteFile;
		local.fnSleep					= (PSleep)Sleep;
		local.fnExitProcess				= (PExitProcess)ExitProcess;
		local.fnRemoveDirectory			= (PCloseHandle)RemoveDirectory;
		local.fnGetLastError			= (PCloseHandle)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 _tmain(int argc, _TCHAR* argv[])
{
	SelfDelete(TRUE);
	return 0;
}

Open in new window

0
Infinity08Commented:
>> I also get these warnings:

The first two are because of your FUNC_ADDR macro :

        #define FUNC_ADDR(func) (PVOID)(*(DWORD *)((BYTE *)func + 1) + (DWORD)((BYTE *)func + 5))

func is a function address - you can't just cast it to BYTE*. You also can't just cast a BYTE* to a DWORD. What is this macro supposed to do ?


>> 12.cpp(141) : warning C4312: 'type cast' : conversion from 'DWORD' to 'SELFDEL *' of greater size

points to this line :

            local.Arg0 = (SELFDEL *)entrypoint;

entrypoint is defined as a DWORD ... You can't just cast it to a pointer. You really have to use the proper types everywhere. You probably don't want entrypoint to be a DWORD, but rather a SELFDEL* (or at least a compatible pointer type).


>> 12.cpp(147) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
>> 12.cpp(148) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
>> 12.cpp(150) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size

Similarly, you try to cast a DWORD (entrypoint) to a pointer type (PVOID) ...
0
Infinity08Commented:
>> but program crashes on execution and doesn't delete itself.

What's the exact crash message ? If you run it in a debugger, what line does it crash on ?
0
makasbrgAuthor Commented:
>      12.exe!memcpy(unsigned char * dst=0x0012f794, unsigned char * src=0xecc30b50, unsigned long count=512)  Line 171      Asm
0
Infinity08Commented:
>> >      12.exe!memcpy(unsigned char * dst=0x0012f794, unsigned char * src=0xecc30b50, unsigned long count=512)  Line 171      Asm

Yes, that's most likely related to your FUNC_ADDR macro - see my previous post.
0
Infinity08Commented:
Notice that 0xecc30b50 is probably not a valid address ...
0
makasbrgAuthor Commented:
I left only
#define FUNC_ADDR(func) func
and it doesn't crash.

But, unfortunately, program doesn't work as it should (doesn't delete itself).

There are these warnings:
12.cpp(138) : warning C4312: 'type cast' : conversion from 'DWORD' to 'SELFDEL *' of greater size
12.cpp(144) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
12.cpp(145) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
12.cpp(147) : warning C4312: 'type cast' : conversion from 'DWORD' to 'PVOID' of greater size
0
Infinity08Commented:
>> and it doesn't crash.

And does the FUNC_ADDR macro still do what you want it to do ? What was that btw ?


>> But, unfortunately, program doesn't work as it should (doesn't delete itself).

What do you mean by "delete itself" ?


>> There are these warnings:

See my earlier post ... I already addresses these ;)
0
makasbrgAuthor Commented:
>> And does the FUNC_ADDR macro still do what you want it to do ? What was that btw ?
Well, this isn't my code, I don't know what it should do :x
I'm just trying to get it work in vc++

>>What do you mean by "delete itself" ?
Program should delete itself when executed ("Self deleting executable").

>>>> There are these warnings:
>>See my earlier post ... I already addresses these ;)
I don't know how to fix them :x Is it possible that because of these program doesn't work?
0
Infinity08Commented:
>> Program should delete itself when executed ("Self deleting executable").

I assume this is where you got the code from :

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

Did you compile it as C or as C++ ? It should be compiled with a C compiler ...

In any case, the technique used seems pretty dodgy to me, and I wouldn't recommend using it ...
Take a look at the other techniques presented on the same page - they might be more interesting ...


>> Is it possible that because of these program doesn't work?

Well, if you're not sure what the code does, then it's entirely possible that some of the code is not doing what it's supposed to do ;)

Using proper types all the time will solve a lot of problems. Changing entrypoint to a SELFDEL* for example will get rid of those warnings.
0
jkrCommented:
Help, that code is overkill... Jeffrey Richter introduced the following for the same purpose:
#include <Windows.h>
#include <stdlib.h>
#include <tchar.h>
 
/////////////////////////////////////////////////////////////////////
 
int WINAPI WinMain(HINSTANCE h, HINSTANCE h2, LPSTR psz, int n) {
 
   // Is this the original EXE ther Clone?
   // The original EXE receives one argument,
   // the clone more.
   if (__argc == 1) {
 
      // Original EXE: Start the Clone.
 
      // Copy EXE to the temporary directory
      TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH];
      GetModuleFileName(NULL, szPathOrig, _MAX_PATH);
      GetTempPath(_MAX_PATH, szPathClone);
      GetTempFileName(szPathClone, __TEXT("Del"), 0, szPathClone); 
      CopyFile(szPathOrig, szPathClone, FALSE);
 
      // Open the Clone using FILE_FLAG_DELETE_ON_CLOSE
      HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL,
                           OPEN_EXISTING,FILE_FLAG_DELETE_ON_CLOSE);
 
      // Start the Clone. Pass the PID and the fully qualified path
      // of the original file
      TCHAR szCmdLine[512];
      HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,
                                        GetCurrentProcessId());
      wsprintf(szCmdLine, __TEXT("%s %d \"%s\""), szPathClone, 
               hProcessOrig, szPathOrig);
      STARTUPINFO si;
      ZeroMemory(&si, sizeof(si));
      si.cb = sizeof(si);
      PROCESS_INFORMATION pi;
      CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, 
                    NULL, NULL, &si, &pi);
      CloseHandle(hProcessOrig);
      CloseHandle(hfile);
 
      // now the original process may terminate
      } else {
 
      // Clone-EXE: Delete the  original EXE after termination
      HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]);
      WaitForSingleObject(hProcessOrig, INFINITE);
      CloseHandle(hProcessOrig);
      DeleteFile(__targv[2]);
   }
   return(0);
}

Open in new window

0
jkrCommented:
0
Infinity08Commented:
Note that the code jkr posted is the "DELETE_ON_CLOSE method" that was also explained on the site I posted. (Or in code selfdel01.c)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.