I am getting the error on compile in VS:
LNK2001 unresolved external symbol _main File: MSVCRT.lib(exe_main.obj)
This error only occurs when compiling in Release x86, and not Debug x86.
#include "includes.h"
BOOL APIENTRY DllMain(
HINSTANCE handle,
DWORD fdwReason,
LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
AllocConsole();
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
_beginthreadex(NULL, 0, directxThread, 0, 0, 0);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
This is likely a problem with your IDE/compiler command. If possible, you should check the exact command sent to cl.exe (the Microsoft compiler) when release mode is enabled, and ensure that MSVCRT.lib is present in the compiler command. See this link for more information.
If MSVCRT.lib is not in your compile command, you will have to add MSVCRT.lib as an additional input/dependency to your compiler in your project settings, if you're using an IDE like Visual Studio. If you're using the command line, you can simply add the term.
Related
I'm able to call function from DLL created in C (.c file), but i can't do it from DLL created in C++ (.cpp file). I want to find out why it doesn't work in .cpp file.
I'm trying to call function printword() from a simple DLL, created with Visual Studio 2022:
// FILE: dllmain.cpp
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) void printword() {
std::cout << "word" << std::endl; //with printf() doesn't work too
}
And when i call function the way like this:
int main() {
HMODULE dll;
if ((dll = LoadLibrary(L"D:\\Visual Studio projects\\Dll1\\x64\\Debug\\Dll1.dll")) == NULL) {
return GetLastError();
}
FARPROC func;
if ((func = GetProcAddress(dll, "printword")) == NULL) {
return GetLastError();
}
func();
return 0;
}
GetProcAddress throws error ERROR_PROC_NOT_FOUND
But if i create DLL in file with .c suffix printword() function calls correctly (with same code above):
// FILE: dllmain.c
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) void printword() {
printf("word\n");
}
The exported function's name will get mangled when the DLL is compiled. You must use the mangled name in GetProcAddress() in order for it to work. For example, the mangled name
in MSVC is:
GetProcAddress(dll, "?printword##YAXXZ");
Or, you could add this to the function's body to tell the compiler not to mangle it:
__declspec(dllexport) void printword() {
#pragma comment(linker, "/EXPORT:" __FUNCTION__"=" __FUNCDNAME__)
printf("word\n");
}
Alternatively, adding extern "C" will also solve the problem.
Review and try the recommendations from this article:
https://learn.microsoft.com/sr-cyrl-rs/cpp/build/exporting-cpp-functions-for-use-in-c-language-executables?view=msvc-170
Example
// MyCFuncs.h
extern "C" __declspec( dllexport ) int MyFunc(long parm1);
Key part being extern "C"
[I accidentally posted the link for importing instead of exporting earlier - corrected for the export article]
I created a simple DLL that open cmd.exe.
I did it with these options:
In the default dlllmain.cpp I added a code that creates a new cmd.exe:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <Windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
BOOL h = CreateProcessW(L"C:\\Windows\\System32\\cmd.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
These three lines below the DLL_PROCESS_ATTACH worked for me when I tested it with a console application.
I am expecting that every process that will load this DLL will open cmd.exe.
I tried to load the DLL with PowerShell:
Add-Type -TypeDefinition #"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class Kernel32
{
[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary(
[MarshalAs(UnmanagedType.LPStr)]string lpFileName);
}
"#
$LibHandle = [Kernel32]::LoadLibrary("C:\tmp\myDll.dll")
But nothing happens, the value of the $LibHandle was 0.
What I am doing wrong ?
I found what was the problem.
My system is 64 bit and the file was compiled in 32 bit.
I needed to specify in Visual Studio that I am compiling it in x64 bit.
I didn't check it in the beginning because I thought that when I am compiling it on "Any CPU" mode, it compile the file in 64 bit automatically as the OS architecture.
Now it works fine.
I am hooking FindNextFile() using MS Detours. I have configured the Detours library successfully and wrote a dll named "Detuors.dll" and an application named "FNFSend.exe". The following is the code:
DLL:
#include <cstdio>
#include <stdio.h>
#include <windows.h>
#include "detours.h"
#pragma comment (lib,"detours.lib")
//Prototypes
extern "C" __declspec(dllexport) BOOL (WINAPI *pFNF)(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) = FindNextFile;
extern "C" __declspec(dllexport) BOOL WINAPI MyFNF(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData);
//Log File
FILE* pFNFLogFile;
int counter = 0;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pFNF, MyFNF);
if(DetourTransactionCommit() == NO_ERROR)
OutputDebugString("FNF() detoured successfully");
else
OutputDebugString("FNF() not detoured");
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin(); //Detach
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)pFNF, MyFNF);
DetourTransactionCommit();
break;
case DLL_THREAD_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pFNF, MyFNF);
if(DetourTransactionCommit() == NO_ERROR)
OutputDebugString("FNF() detoured successfully");
else
OutputDebugString("FNF() not detoured");
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
//Open file, write contents, close it
extern "C" __declspec(dllexport) int WINAPI MyFNF(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
{
counter ++;
fopen_s(&pFNFLogFile, "C:\\FNFLog.txt", "a+");
fprintf(pFNFLogFile, "%s\n", counter);
fclose(pFNFLogFile);
return pFNF(hFindFile, lpFindFileData);
}
Both the codes compiled successfully with no errors. The application calls FindNextFile() recursively and the dll hooks it and write the counter to a file.
I then used the tool named "withdll.exe" that is provided by detours library itself to create a process with a dll injected in it. So I injected my dll into the application using command:
withdll /d:Detuors.dll "C:\FNFSend.exe"
After injection, the function is hooked successfully, i.e. the file is made in the dirctory but suddenly the application crashes. After debugging in visual studio, I saw the exception in "output.c" as follows:
Unhandled exception at 0x6265984f (msvcr90d.dll) in FNFSend.exe: 0xC0000005:
Access violation reading location 0x00000001.
Kindly help in rectifying the problem.
%s is not a valid format string for printing out a number. Use %d instead.
By specifying %s you're telling fprintf to read the memory at address counter as a string. The first value you try calling fprintf with is 1 which is why there is an access violation at address 0x00000001.
I am using MS detours 3.0 Express to create a DLL that detours a function of an application.
I have used StudPE to enter the dll API and hook it to the application.
Everything works fine except for it won't work on windows XP.
Windows 7 works fine though. And I'm running out of idea's as to why it just won't work on windows XP.
I compiled it on a Windows 7 x64 machine with Microsoft Visual Studio 2012.
I'm calling the DllMain My code is: (just the relevant code - incomplete)
extern "C" __declspec(dllexport) INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason) {
case DLL_PROCESS_ATTACH: //Do standard detouring
DisableThreadLibraryCalls(hDLL);
//AllocConsole();
//
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pSend, MySend);
if(DetourTransactionCommit() == NO_ERROR) {
cout << "[" << MySend << "] successfully detoured." << endl;
}
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin(); //Detach
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)pSend, MySend);
DetourTransactionCommit();
break;
}
return TRUE;
}
On WinXP nothing happens when I try to run the hooked application.
I try to implement password filter, so I write a simple password filter.
I followed the document in the MSDN, and make sure that the functions are declared correctly.
I compile in VS 2010.
.def file:
LIBRARY myFilt
EXPORTS
InitializeChangeNotify
PasswordFilter
PasswordChangeNotify
.cpp file:
#include <windows.h>
#include <stdio.h>
#include <ntsecapi.h>
void writeToLog(const char* szString)
{
FILE* pFile = fopen("c:\\work\\logFile.txt", "a+");
if (NULL == pFile)
{
return;
}
fprintf(pFile, "%s\r\n", szString);
fclose(pFile);
return;
}
// Default DllMain implementation
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(L"DllMain");
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
BOOLEAN __stdcall InitializeChangeNotify(void)
{
OutputDebugString(L"InitializeChangeNotify");
writeToLog("InitializeChangeNotify()");
return TRUE;
}
BOOLEAN __stdcall PasswordFilter(
PUNICODE_STRING AccountName,
PUNICODE_STRING FullName,
PUNICODE_STRING Password,
BOOLEAN SetOperation
)
{
OutputDebugString(L"PasswordFilter");
return TRUE;
}
NTSTATUS __stdcall PasswordChangeNotify(
PUNICODE_STRING UserName,
ULONG RelativeId,
PUNICODE_STRING NewPassword
)
{
OutputDebugString(L"PasswordChangeNotify");
writeToLog("PasswordChangeNotify()");
return 0;
}
I put myFilt.dll in %windir%\system32, add "myFilt" to "Notification Packages" in the registry, restart the computer, change the password, and nothing happens.
I opened depends.exe and saw that the functions are correctly:
InitializeChangeNotify
PasswordChangeNotify
PasswordFilter
Where is the mistake??
Thanks.
I found the problem! I changed the runtime library from Multi-threaded Debug DLL (/MDd) to Multi-threaded Debug (/MTd) and it works perfect! :)
– user1375970 May 5 at 10:38
Notification Packages
Specifies the dynamic-link libraries (DLLs) that are loaded or called when passwords are set or changed. To specify more than one file, list the file names one above the other by pressing ENTER between each file name.
above the other!