views:

513

answers:

5

I've made a driver for Windows, compiled it and tried to start it via SC manager, but I get the system error from the SC manager API:

ERROR_PROC_NOT_FOUND The specified procedure could not be found.

Is there a way to get more information about why exactly the driver fails to start? WinDbg or something? If I comment out all code in my DriverEntry routine, the driver starts.

The only thing I'm calling is a procedure in another source module (in my own project, though). I can comment out all external dependencies and I still get the same error.

Edit:
I've also tried different DDKs, i.e. 2003 DDK und Vista WDK (but not Win7 WDK)

Edit2: Here is my driver sour code file driver.cpp:

#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <ntstrsafe.h>
#ifdef __cplusplus
}; // extern "C"
#endif

#include "../distorm/src/distorm.h"

void DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
}

#define MAX_INSTRUCTIONS 20

#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
 UNICODE_STRING pFcnName;

 // Holds the result of the decoding.
 _DecodeResult res;
 // Decoded instruction information.
 _DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
 // next is used for instruction's offset synchronization.
 // decodedInstructionsCount holds the count of filled instructions' array by the decoder.
 unsigned int decodedInstructionsCount = 0, i, next;
 // Default decoding mode is 32 bits, could be set by command line.
 _DecodeType dt = Decode32Bits;

 // Default offset for buffer is 0, could be set in command line.
 _OffsetType offset = 0;
 char* errch = NULL;

 // Buffer to disassemble.
 char *buf;
 int len = 100;

 // Register unload routine
 DriverObject->DriverUnload = DriverUnload;

 DbgPrint("diStorm Loaded!\n");

 // Get address of KeBugCheck
 RtlInitUnicodeString(&pFcnName, L"KeBugCheck");
 buf = (char *)MmGetSystemRoutineAddress(&pFcnName);
 offset = (unsigned) (_OffsetType)buf;

 DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf);
 // Decode the buffer at given offset (virtual address).

 while (1) {
  res = distorm_decode(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
  if (res == DECRES_INPUTERR) {
   DbgPrint(("NULL Buffer?!\n"));
   break;
  }

  for (i = 0; i < decodedInstructionsCount; i++) {
   // Note that we print the offset as a 64 bits variable!!!
   // It might be that you'll have to change it to %08X...
   DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size, 
    (char*)decodedInstructions[i].instructionHex.p,
    (char*)decodedInstructions[i].mnemonic.p,
    (char*)decodedInstructions[i].operands.p);
  }

  if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) {
   break; // All instructions were decoded.
  }

  // Synchronize:
  next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset);
  next += decodedInstructions[decodedInstructionsCount-1].size;

  // Advance ptr and recalc offset.
  buf += next;
  len -= next;
  offset += next;
 }

 DbgPrint(("Done!\n"));
 return STATUS_SUCCESS;
}

#ifdef __cplusplus
}; // extern "C"
#endif

My directory structure is like this:

base_dir\driver\driver.cpp
        \distorm\src\all_the_c_files
        \distorm\distorm.h
        \distorm\config.h

My SOURCES file:

# $Id$
TARGETNAME=driver
TARGETPATH=obj
TARGETTYPE=DRIVER

# Additional defines for the C/C++ preprocessor
C_DEFINES=$(C_DEFINES) -DSUPPORT_64BIT_OFFSET

SOURCES=driver.cpp \
     distorm_dummy.c \
        drvversion.rc

INCLUDES=..\distorm\src;

TARGETLIBS=$(DDK_LIB_PATH)\ntdll.lib \
        $(DDK_LIB_PATH)\ntstrsafe.lib

You can download diStorm from here: http://ragestorm.net/distorm/dl.php?id=8

distorm_dummy is the same as the dummy.c from the diStorm lib.

A: 

You can add deferred breakpoints in WinDbg.

If you specify a breakpoint, while the driver is not loaded (or with bu), it will be triggered, when the driver does get loaded and enters the function.

The command for specifiying breakpoints is :

bp <module_name>!<function_name>

e.g. :

bp my_driver!DriverEntry
Christopher
well as I said, the driver isn't even loaded at all. I need to know why this is the case
SDD
And for that, you specify your breakpoint in the DriverEntry function, so that, when the function is executed, your breakpoint fires and you get to single step throught your code.
Christopher
The bp never fires, because the driver entry function is never even called. The driver seems to fail *while* the OS is loading it - not after it has been loaded
SDD
Then my guess would be, that you alter the definition of your DriverEntry function by using your function. (STDCALL/CDECL/...)
Christopher
unfortunately not, see the declaration i posted above
SDD
+2  A: 

Enable "Show loader snaps" using gflags -- in the debug output, you should find information about which import the loader is not able to resolve.

Johannes Passing
doesn't seem to work. I'm using it like this: !glaf +sls, but the attached WinDbg doesn't show any debug messages
SDD
+1  A: 

Have you tried running Dependency Walker on the compiled .sys and see if there is actually some missing function imports?

tyranid
Dependencie Walker tells me 4 errors: "Error opening the file. The system cannot find the file specified (2)" for the files CI.DLL, CLFS.SYS, HAL.DLL and KDCOM.DLL
SDD
+1  A: 

Not surprisingly, you have all the information you need to solve this on your own.

ERROR_PROC_NOT_FOUND The specified procedure could not be found.

This, combined with your dependency Walker output, pretty much points to a broken Import Table

Why is your IT broken? I'm not sure, could be a problem with your build/linker settings, since rather obviously, HAL.DLL is right there in %windir%\system32.

Reasons for a broken load order are many and you'll have to track them down yourself.

Daniel Goldberg
The error was because I included TARGETLIBS=$(DDK_LIB_PATH)\ntdll.libAfter removing this from SOURCES, the driver works
SDD
A: 

Build it with the 6000 WDK/DDK (because with the "actual" Build 7600... it links against wdfldr.sys, but under Windows Vista and XP Systems this sys file is not available). I don't know where you can download it officially but i did use a torrent...