How to solve LNK2019 unresolved external symbol DriverEntry referenced in function GsDriverEntry? - windows

While I was compiling this project https://github.com/namazso/hdd_serial_spoofer
I got the error message above ,how can I solve this ?
I'm using vs 2017 and wdk 10 .
(Must compile in release ,debug mode is not supported .There is no DriverEntry function in this project ,the EntryPoint(void* ntoskrn, void* image, void* alloc) function in hwid.cpp is the real entry point .)
I did a lot of research but still failed to get it work .I'm a noob in kernel mode driver development .

The project uses (an apparently ignored) option
<EntryPointSymbol> to define EntryPoint as the entry.
This is documented here, but current documentation appears to mean this is really only for .exe and .dll projects.
The form of the mesage called from the Windows driver system
NTSTATUS DriverInitialize(
_DRIVER_OBJECT *DriverObject,
PUNICODE_STRING RegistryPath
)
Is incompatible with the EntryPoint in the project
EntryPoint(void* ntoskrn, void* image, void* alloc)
This is not so bad, as none of the parameters which are called for EntryPoint are used.
So the simplest implementation would be
extern "C"
{
DRIVER_INITIALIZE DriverEntry;
_Use_decl_annotations_
NTSTATUS
DriverEntry(
struct _DRIVER_OBJECT *DriverObject,
PUNICODE_STRING RegistryPath
)
{
EntryPoint(NULL, NULL, NULL);
return STATUS_SUCCESS;
}
}
Kernel development is not for the faint hearted, and running invalid kernel code on your computer could make it difficult to boot, or in extream cases damage the computer. I did not review any of the code in the project for correctness.
Please run the code in a virtual machine (vmware, virtualbox, hyper-v) to limit the damage it could do

This is not a normal driver, the kind that WDF directly supports. It is a "driverless driver", it uses an undocumented hack that is appealing to the kind of programmers that write rootkits for fun and profit. The DriverEntry() function is not actually the entrypoint for a driver, it is callback. Much like the WinMain() function is not actually the entrypoint for a native Win32 program. The EntryPoint() function in the project's source code is the replacement for the native driver entrypoint. Beware that the project appears to have rootkitty-like behavior, designed to fool a simplistic copy-protection scheme that checks a drive serial number.
The GsDriverEntry() function is the real entrypoint in a normal KMDF driver. It performs essential initialization to support the /GS compiler option, designed to detect buffer overflow. After that's done it calls DriverEntry(). The project replaces this entrypoint with EntryPoint().
This project was written with an old version of the Visual Studio project template. Several changes are necessary to get it to build properly:
C/C++ > Code Generation > Security Check. Must be "Disable security check (/GS-)", the original project file got this right.
Same property page > Control Flow Guard. Must be set to "No" to prevent a linker error. This option adds additional security checks that cannot work and must be disabled.
C/C++ > General > SDL checks. Use the dropdown arrow to override to "inherit from parent" so the option appears blank. More security checks that needs to be disabled, suppresses a warning that sdl- is incompatible with /gs-.
Same property page > Warning level. Override to "Level3 (/W3)", suppresses warnings about function arguments not being used.
Linker > Input > Additional Dependencies. Click the dropdown arrow > Edit. Untick the "Inherit from parent" checkbox and change to $(DDK_LIB_PATH)ntoskrnl.lib. Note the $(KernelBufferOverflowLib) entry in the Inherited values listbox, resolves to bufferoverflowfastfailk.lib, that is the one that contains GsDriverEntry() and produced the linker error.
Linker > Advanced > Entry Point. Must be "EntryPoint", the original project template got that right.
After this it builds clean. I did not test the resulting hwid.sys, looks a bit too evil to expose my machine to it.

Don't use .cpp source files to write your driver. Change them to .c and it should work. That was the case for me.
I know it looks trivial, or unlikely but remember Windows Kernel code is C code and Visual Studio makes various assumptions given the file extension of your source files.

There are several causes that generate the problem. In my case, a try/except in the code, which compiles on x64, but doesn't compile on x86.
Linker Tools Error LNK2019
https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-error-lnk2019?view=msvc-170

Related

Hiding the console from D while linked with C-version SDL2

Basically, I get a console window I don't want to see while writing SDL-windowed applications.
In C, the answer is simple: change your linker SubSystem to Windows; then SDL does the rest. It has a macro that redefines your main to SDL_main, which it calls from inside its own hidden WinMain function. Just make sure you take arguments in your main function and all goes smoothly.
In D, I'm having a little more trouble with it. Upon simply changing the subsystem by passing -L/SUBSYSTEM:WINDOWS to the linker, it informs me that I have declared main, SDL has declared WinMain, and it doesn't know how to deal. I thought changing the signature from void main() to extern(C) int SDL_main(int argc, char*[] argv) would solve the problem, but then the linker says it can't locate any of D's runtime symbols. Might have something to do with the entry point being written in C?
On the other side, my problem might be with how I have set up Derelict. I am working from this repository, which is a live-updated amalgam of all the different Derelict repositories on GitHub. In my VisualD solution, I have three relevant projects: a home-brewed Derelict project containing the source to SDL2 and the Utilities library, and the C-API SDL2 and SDL2main projects as found here. I compile and link to all three resulting libraries -- Derelict and SDL2main are static, SDL2 is dynamic. I am less inclined to say this setup is to blame, because it works just fine save the undying console window.
In the command line passed to DMD, add the linker option -L/SUBSYSTEM:WINDOWS
In case you use dub (which i recommend) and gdc, insert the following into your dub.json file:
"dflags": ["-Wl,--subsystem,windows"]

wxWidgets and Visual Studio Linker Error When Compiling with a Static Library

I'm getting this linker error when compiling wxWidgets in Visual Studio 2010.
msvcrt.lib(wcrtexew.obj) : error LNK2001: unresolved external symbol _wWinMain#16
Now here's the problem. The entry point for wxWidgets is this macro:
IMPLEMENT_APP(MyApp)
Which means I don't use wWinMain() as an entry.
I've tried disabling the entry point when I compile (/NOENTRY), but no dice. Nothing seems to work because if I define wWinMain(), then wxWidgets won't start because the entry is IMPLEMENT_APP.
I only receive this error when I compile as static. If I don't compile as static I'll have to supply the DLLs: msvcp100d.dll and msvcr100d.dll on Windows Server 2008 (and maybe more DLLs on older versions of Windows that don't have the library installed).
Now I understand I am linking again the debug library, but it shouldn't matter if I link again the release because I should receive the same error (unresolved external symbol _wWinMain#16).
Any solutions?
When you link to static libraries you have to ensure that the libraries were built with the EXACT SAME parameters as you used to build the application code.
So: go through all the compiler options for the library build and the application build and ensure that they match. Also, make sure that the application build is linking to the static libraries there were built using the configuration you have matched.
It is a pain! You have to decide wether you want to deal with this problem, or the problem of installing the correct DLLs on the target machine. Either way, you have to solve configuration management problems.
In your particular problem, I see the linker is looking for _wWinMain#16 which suggests that you have build your application code with unicode switched on, but are linking to a non unicode static library.
First compile wxWidgets' Library (wxWidgets\build\msw) all with the same settings you have in your project. So I enable "/MT", "Use MFC in a Static Library", and output the projects as "Release". Same exact settings on my wxWidgets' application I coded.
Now Comment out:
IMPLEMENT_APP(MyApp)
And use this for your entry point:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
char *buf;
buf = new char[wcslen(lpCmdLine) + 1];
wcstombs(buf, lpCmdLine, wcslen(lpCmdLine) +1);
wxApp::SetInstance( new MyApp());
wxEntry(hInstance, prevInstance, buf, nShowCmd);
wxEntryCleanup();
}
Do you have
IMPLEMENT_APP(MyApp)
In a .cpp file? It is typically in the accompanying file to where IMPLEMENT_APP(MyApp) is located.
I am using wxWidgets as a static library and that is what I do to compile.
I had the same problem after I changed my project's character set to unicode. My project uses multi-threaded Debug DLL (/MDd). Above workaround worked for me, too, but I wanted to find out what was actually causing the problem and use IMPLEMENT_APP.
After I changed "Use of MFC" to "Use Standard Windows Libraries" I was able to successfully build the project.

"Vista-only" heap corruption in a MFC application

Ours is a MFC application, which links to a win32 DLL. When the application invokes this DLL function, the argument "buffer" becomes a "Bad Pointer", after entering the function stack. This results in an application crash.
static MyClass* Instance(string& buffer);
I changed the argument type to "char *", but it only pushes the crash to next statement in the function. How to detect this heap corruption?
Few hints
This crash is reproducible, even if I invoke this DLL function from the very start of our application (CWinApp constructor). Could this memory corruption be caused by loading of resources, manifest etc?
The crash is ocurring in Vista and Win7, but not in XP.
Both these projects were recently migrated from Visual Studio 2002 to VS2008.
Code that invokes the function
CString data = "some string";
string str = data.GetBuffer();
data.ReleaseBuffer();
MyClass *obj = MyClass::Instance(str);
There were two mistakes:
Couple of custom built C++ files were not compiled with MD switch. We had to add -MD to the custom build script to make the CRT consistant with other objects.
There were LNK2005 conflicts between LIBCMT.LIB and MSVCRT.LIB, which were otherwise ignored due to the /FORCE switch. We resolved these conflicts by removing LIBCMT.LIB in Linker->Input
Thanks all for your help.
My guess is this is wrong usage of calling conventions or a CRT mismatch (i go with calling conventions).
Try building a stub DLL with the same function signature (which does nothing) and make it work with your MFC app.
Here's an example...
HTH

Producing small Windows binaries

When developing and deploying native Windows applications, I often need to install a runtime before being able to run my binary, or statically link the library with my binary. For instance, after building a "Win32 Console" project with Visual Studio 2008, attempting to run the program on a fresh Windows 7 image results in:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
Issues like this one have been brought up in other posts on StackOverflow.
How does one develop applications that don't require runtimes that aren't already on the target OS (i.e. don't require installing redistributable packages or private/shared side-by-side assemblies)? How does one avoid using msvc[mpr]90.dll and just use the Windows API in \windows\system32*.{dll,sys}?
I'm thinking along the lines of the code that comes out of the demoscene, but that's frequently not made available.
Others have already responded with respect to linking CRT statically. If you also want a small binary at the same time, then your best bet is forego CRT entirely, and use only Win32 API functions as much as possible. You'll still get some CRT code, most notably related to startup (i.e. that which calls main) and shutdown (atexit handling etc), but otherwise the linker won't link CRT functions that you do not use.
You can avoid linking CRT altogether by using /Zl compiler switch. This means that main will no longer work, however - you'll need to define WinMain (name doesn't matter, but signature must match, and it must be __stdcall), and you will have to specify the name of your WinMain-like function as an entry point via linker /entry: switch. This will save you ~30Kb of CRT code (tested on a .cpp with an empty main).
If you go the latter route, you might also have to deal with issue of compiler intrinsics. There are some functions that are nominally defined by the CRT (and declared in its headers), but which are treated specially by the compiler, so that it inserts optimized assembly instructions at the point of the call where possible - examples are memset, strlen, and a good chunk of functions in <math.h>; a complete list can be found here. Since you don't have CRT, if you need these functions, or could avoid it but prefer the intrinsic because of improved performance (hard to do better than memset, for example), then you have to declare them yourself, and use #pragma intrinsic. E.g.:
// Contains macros and typedef only, so safe to include without CRT.
// We need it here for size_t.
#include <stddef.h>
extern "C"
{
int abs(int);
void* memset(void*, int, size_t);
}
#pragma intrinsic(abs, memset)
int __stdcall main(void*, void*, char*, int)
{
char tmp[10];
memset(tmp, abs(-123), 10);
return 0;
}
The above can be compiled with:
cl /c /Zl foo.cpp
link /entry:main foo.obj
Link the CRT statically via the /MT switch (and likewise MFC, if you're using it).
Static linking limits what you can do with DLLs somewhat, but for simple executables it works like a charm. (And if you're shipping DLLs, you can always ship private assemblies anyway.)
Use the static CRT. This doesn't create a dependency on msvc*.dll. The CRT is linked directly into your program. This doesn't create dependencies, but does increase the size of your executable.
More info on different CRT options here.
Statically link the runtime. MS Visual C++ has option /MT for that (default is /MD)
I think one way to do this is to just not use Visual Studio and instead rely on the command line SDK tools. (You can alternatively figure out how to config VS to do what you want, but that seems harder.) E.g.:
cl /c app.cpp
link app.obj ws2_32.lib

Strange VB6 build problems (related to nlog)

This I think is related to my use of the nlog C++ API (and my question on the nlog forum is here); the purpose of my asking this question here is to get a wider audience to my problem and perhaps to also get some more general ideas behind the VB6 IDE's failure to build in my particular scenario.
Briefly, the problem that I am having is that I am having trouble building VB6 components which reference unmanaged C++ components which have calls to nlog's C\C++ API (which is defined in NLogC.DLL). The build problems are not occurring during compile time, they are occurring when the binary is being built which suggests to me that it's some kind of linker type problem? Don't know enough about how VB6 binaries are produced to tell. The VB6 binary is produced, but it is corrupted and crashes shortly after it is invoked.
Has anyone had any similar experiences with VB6 (doesn't have to be related to nlog or C++)?
edit: Thanks for all the responses to this rather obscure problem. Still no headway unfortunately; my findings since I posted this:
'Tweaking' the compile options doesn't appear to help in this problem.
Adding a reference to the nlog-enabled C++ component from a 'blank' VB6 project doesn't crash it or cause weird build problems. So it isn't a 'native' VB6 issue, possibly an issue with the interaction between nlog and the various components and 3rd party libraries used by other referenced components?
As for C++ calling conventions: the nlog-enabled C++ component is - as far as I can see - compliant to these conventions and indeed works fine when referenced by VB6 as long as it is not making any nlog API calls. Not sure if the nlogc.DLL itself is VB6 compliant but I would have thought that that is immaterial since the API calls are being made from the C++ component; VB6 shouldn't know or care about what the C++ component is referencing (that's as far as my understanding on this goes...)
edit2: I should also note that the error message obtained during build is: "Errors during load. Please refer to "xxx" for details". When I bring up the log file, all that there is in there is: "Cannot load control xxx". Interestingly, all references to that particular control disappears from that particular project resulting in compile errors if I were to try to build again.
Got around the problem by using NLog's COM interface (NLog.ComInterop.DLL) from my unmanaged C++ code. Not as easy to do as the C\C++ API but at least it doesn't crash my VB6 components.
I would try tweaking some of the Compile options found in the Project, Properties menu, Compile panel to see if they yield any additional hints as to what is going wrong.
For example if you compile the executable to p-code rather than native code does it still crash on startup.
What error message do you get when you run your compiled binary?
I doubt the compiler/linker is the problem: project references in a VB6 project are not linked into the final executable. A project reference in VB6 is actually a reference to a COM type library (which may or may not be embedded in a .dll or other binary file type). Project references primarily serve two purposes:
The IDE extracts type information from the referenced type libraries which it then displays in the Object Browser (and in the Intellisense drop-down)
At compile-time, the compiler extracts the type information stored in the referenced libraries, including the CLSID of each class that you instantiate, and embeds this data into the executable. This allows your executable to create instances of classes contained in the libraries that you referenced.
Note that the compiled binary doesn't link to any code in the referenced libraries, and it doesn't even contain the filenames of the referenced libraries. The final executable only contains the CLSID's and other type information that it needs to instantiate COM objects at run-time.
It is much more likely that the issue is with NLog, or with how you are calling it from your code, rather than something gone awry in the VB6 compile process.
If you think it might be a linker problem, this should crash it the same way:
create a new standard project (of any kind)
add a new module and copy the "declare"-statements into it
compile
If it doesn't crash it is something else.
It would help an exact description of the error or a screenshot of what going on.
One thing to check is wherever NLogC.DLL or the C++ DLL you built have the correct calling convention defined. Basically you can't have the DLL function names mangled or use anything but the STDCALL calling convention. If the C++ DLL has not been created with those two things in mind then it will fail to work with VB6.
MSDN Article on Calling convention.
"Cannot load control xxx" errors can be caused by .oca files which were created from a different version of an .ocx than currently used. If that is the case, deleting the .oca files helps.

Resources