I've written two COM classes in C++, contained in a single MFC DLL. They're being loaded as plugins by a 3rd party application.
How can I get the file name, and version number, of the DLL from within those classes?
The main dll entry gives you the handle of your dll.
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
and
GetModuleFileName(hInstance, buffer, MAX_PATH);
can be used to get the filename of the dll.
GetFileVersionInfoSize
GetFileVersionInfo
will be used to get the file version.
TCHAR fileName[MAX_PATH + 1];
GetModuleFileName(hInstance, fileName, MAX_PATH);
Where hInstance is the one you get in the DllMain function. Don't use GetModuleHandle(0), because that returns the HINSTANCE of the host application.
CString GetCallingFilename(bool includePath)
{
CString filename;
GetModuleFileName(AfxGetInstanceHandle(), filename.GetBuffer(MAX_PATH), MAX_PATH);
filename.ReleaseBuffer();
if( !includePath )
{
int filenameStart = filename.ReverseFind('\\') + 1;
if( filenameStart > 0 )
{
filename = filename.Mid(filenameStart);
}
}
return filename;
}
CString GetCallingVersionNumber(const CString& filename)
{
DWORD fileHandle, fileVersionInfoSize;
UINT bufferLength;
LPTSTR lpData;
VS_FIXEDFILEINFO *pFileInfo;
fileVersionInfoSize = GetFileVersionInfoSize(filename, &fileHandle);
if( !fileVersionInfoSize )
{
return "";
}
lpData = new TCHAR[fileVersionInfoSize];
if( !lpData )
{
return "";
}
if( !GetFileVersionInfo(filename, fileHandle, fileVersionInfoSize, lpData) )
{
delete [] lpData;
return "";
}
if( VerQueryValue(lpData, "\\", (LPVOID*)&pFileInfo, (PUINT)&bufferLength) )
{
WORD majorVersion = HIWORD(pFileInfo->dwFileVersionMS);
WORD minorVersion = LOWORD(pFileInfo->dwFileVersionMS);
WORD buildNumber = HIWORD(pFileInfo->dwFileVersionLS);
WORD revisionNumber = LOWORD(pFileInfo->dwFileVersionLS);
CString fileVersion;
fileVersion.Format("%d.%d.%d.%d", majorVersion, minorVersion, buildNumber, revisionNumber);
delete [] lpData;
return fileVersion;
}
delete [] lpData;
return "";
}
Related
My project contains managed part(dotnet) and native(C++) part. I want to hook Winapi CreateFiles in my project by detours and log callstack. Now I have obtained a native callstack by invoking CaptureStackBackTrace and SymFromAddr api in dbghelp. But I meet some troubles when those functions are used in dotnet. as shown in the following picture, it can obtain correct callstack of native code(22, 21, 1, 0) but not work for managed code(20-2). may I have some methods to obtain both managed(dotnet) and un-managed(C++) callstack correctly? or maybe you have the best method to get callstack, could you help me?
dotnet produce:
public class CreateFileOrFolder
{
public void writeToFile(string pathString) {
System.IO.File.Create(pathString);
}
static void Main()
{
System.Console.WriteLine("Press any key to start.\n");
System.Console.ReadKey();
string fileName = "c.txt";
string pathString = System.IO.Path.Combine(#"D:\JunFiles\testDotNetProceduce", fileName);
// Verify the path that you have constructed.
Console.WriteLine("Path to my file: {0}\n", pathString);
CreateFileOrFolder creater = new CreateFileOrFolder();
if (!System.IO.File.Exists(pathString)) {
creater.writeToFile(pathString);
}
else
{
System.IO.File.Delete(pathString);
Console.WriteLine("File \"{0}\" already exists. but now it is deleted\n", fileName);
creater.writeToFile(pathString);
}
}
}
detours hook function:
HANDLE(*__stdcall oldCreateFile)(LPCWSTR,
DWORD,
DWORD,
LPSECURITY_ATTRIBUTES,
DWORD,
DWORD,
HANDLE) = CreateFileW;
HANDLE WINAPI newCreateFile(
_In_ LPCWSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
) {
static BOOL state = FALSE;
printStack();
symbolSolve(process);
printf("HOOK sucess!\n");
std::cout << current_working_directory() << endl;
wchar_t newFileName[] = L".\\newFile.txt";
return oldCreateFile(
newFileName, // L".\\NewFile.txt", // Filename
//lpFileName,
dwDesiredAccess, // Desired access
dwShareMode, // Share mode
lpSecurityAttributes, // Security attributes
dwCreationDisposition, // Creates a new file, only if it doesn't already exist
dwFlagsAndAttributes, // Flags and attributes
NULL);
}
get callstack:
#define STACK_INFO_LEN 200
static HANDLE process;
unsigned int i;
void* stack[100];
unsigned short frames;
SYMBOL_INFO* symbol;
std::queue<std::pair<void*, unsigned short>> myQueue;
PDWORD hashValue = (PDWORD)malloc(sizeof(DWORD));
void printStack(void)
{
frames = CaptureStackBackTrace(0, 100, stack, hashValue);
void* stackTmp = stack;
}
DWORD WINAPI symbolSolve(LPVOID p) {
int myqueue_size = myQueue.size();
char* szBriefInfo = NULL;
static const int MAX_STACK_FRAMES = 12;
void* pStack[MAX_STACK_FRAMES];
static char szStackInfo[STACK_INFO_LEN * MAX_STACK_FRAMES];
static char szFrameInfo[STACK_INFO_LEN];
if (szBriefInfo == NULL) {
strcpy_s(szStackInfo, "stack traceback:\n");
}
else {
strcpy_s(szStackInfo, szBriefInfo);
}
symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
IMAGEHLP_LINE line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD displacementLine = 0;
std::string strs = "";
strs += std::to_string(*hashValue);
for (i = 0; i < frames; i++) {
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
BOOL ret = SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &displacementLine, &line);
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), "%i: %s - 0x%0X ", frames - i - 1, symbol->Name, symbol->Address);
strcat_s(szStackInfo, szFrameInfo);
if (ret) {
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), " | %s at %o \n", line.FileName, line.LineNumber);
strcat_s(szStackInfo, szFrameInfo);
}
else {
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), "|error %d \n", GetLastError());
strcat_s(szStackInfo, szFrameInfo);
}
}
printf("%s \n", szStackInfo);
free(symbol);
return 0;
}
result:
The short answer is that dbhlp can't help with the managed parts of the stack walk.
It can be done, as windbg can do mixed mode stacks but it's specific to the version of .net and it also requires access to the full process memory to do it. I don't think the results from CaptureStackBackTrace will be enough, although since you are doing this in-process you may get away with it.
See the Mixed Mode Stackwalk article, which should give you pointers in the right direction.
I'm trying make a hook in MessageBoxA api in a remote process made by me using IAT hook tecnique. I'm using Process Hacker software for inject my dll file into my process and until here works fine.
My unique trouble is that MessageBoxA never is intercepted when i will call this api from my application.
I have discovered that this api don't can be found in table of import of my process.
So, i want know any suggestion about how i can find this api on table.
Here is code that i use:
#include <windows.h>
#include <string.h>
#include <stdio.h>
void HookFunction(char* funcName, LPDWORD function);
LPDWORD FoundIAT(char* funcName);
int WINAPI HookMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
BOOL APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
{
MessageBox(NULL, "Injeted with success!", "Hello", NULL);
HookFunction("MessageBoxA", (LPDWORD)&HookMessageBoxA);
}
return TRUE;
}
void HookFunction(char* funcName, LPDWORD function)
{
LPDWORD pOldFunction = FoundIAT(funcName);
DWORD accessProtectionValue , accessProtec;
int vProtect = VirtualProtect(pOldFunction, sizeof(LPDWORD), PAGE_EXECUTE_READWRITE, &accessProtectionValue);
*pOldFunction = (DWORD)function;
vProtect = VirtualProtect(pOldFunction, sizeof(LPDWORD), accessProtectionValue, &accessProtec);
}
int WINAPI HookMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
return MessageBoxA(hWnd, "Hello", "DLL answering here!", uType);
}
LPDWORD FoundIAT(char* funcName)
{
DWORD test = 0;
LPVOID pMapping = GetModuleHandle(NULL);
if (pMapping == NULL)
exit(-1);
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER) pMapping;
if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
exit(-1);
PIMAGE_NT_HEADERS NtHeaders = (PIMAGE_NT_HEADERS) ((char*) DosHeader + DosHeader->e_lfanew);
if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
exit(-1);
PIMAGE_DATA_DIRECTORY DataDirectory = &NtHeaders->OptionalHeader.DataDirectory[1];
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) ((char*) DosHeader + DataDirectory->VirtualAddress);
PIMAGE_THUNK_DATA32 OriginalFirstThunk = (PIMAGE_THUNK_DATA32)((char*) DosHeader + ImportDescriptor->OriginalFirstThunk);
while(OriginalFirstThunk != 0)
{
DWORD name = (DWORD)((char*) pMapping + ImportDescriptor->Name);
OriginalFirstThunk = (PIMAGE_THUNK_DATA32)((char*) DosHeader + ImportDescriptor->OriginalFirstThunk);
PIMAGE_THUNK_DATA32 FirstThunk = (PIMAGE_THUNK_DATA32)((char*) DosHeader + ImportDescriptor->FirstThunk);
while(OriginalFirstThunk->u1.AddressOfData != 0)
{
PIMAGE_IMPORT_BY_NAME NameImg = (PIMAGE_IMPORT_BY_NAME)((char*) DosHeader + (DWORD)OriginalFirstThunk->u1.AddressOfData);
test = (DWORD)OriginalFirstThunk->u1.Function & (DWORD)IMAGE_ORDINAL_FLAG32;
if (test == 0)
{
if(strcmp(funcName, (const char*)NameImg->Name) == 0)
{
MessageBox(NULL, NameImg->Name, "", NULL);
return (LPDWORD)&(FirstThunk->u1.Function);
}
}
OriginalFirstThunk++;
FirstThunk++;
}
ImportDescriptor++;
}
return 0;
}
Source
EDIT 1:
I have seen with more datails, that now this code is able to find MessageBoxA api :D, but still when i'll call this api from my application (made in Delphi), the hook don't work.
:-(
My Delphi code here:
procedure TForm1.btn1Click(Sender: TObject);
begin
MessageBoxA(Application.Handle, 'Delphi application here!', 'Hello',0);
end;
EDIT 2:
This can be a definitive solution, but link is offline. Someone can help me about how it can be adapted to my code above please?
I have some code which is fine in C++/CLI console application.
unsigned char* res2buffer()
{
HMODULE HInstance = 0x00;
try
{
HRSRC hrsrc = ::FindResourceW( HInstance, L"IDR_1251", RT_RCDATA);
if( hrsrc == NULL)
{
return nullptr;
}
const size_t nsize = ::SizeofResource( HInstance, hrsrc );
HGLOBAL hglob = ::LoadResource( HInstance, hrsrc );
LPVOID rdata = LockResource(hglob);
fuzzyRus = new unsigned char[ nsize ];
::memcpy( fuzzyRus, rdata, nsize );
UnlockResource(hglob);
::FreeResource(hglob);
return fuzzyRus;
}
catch(...)
{
}
return nullptr;
}
But is does not work in code made as Stored Procedure. Any clue? I guess I have to pass HInstance as a number is different then 0x00. The question is "Instance of what?"
You can get the HMODULE for your DLL like this:
HMODULE HInstance = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)res2buffer,
&HInstance
);
Make solution in managed way: File must be attached in linker option Input->Embeded Managed Resource File-> resource\rustbl.bin
static const unsigned char* GetRusTables() // get data from the resource file
{
Reflection::Assembly^ ca = Reflection::Assembly::GetExecutingAssembly();
IO::BinaryReader^ rusres = gcnew IO::BinaryReader( ca->GetManifestResourceStream( "rustbl.bin" ) );
array<unsigned char>^ buffPtr = rusres->ReadBytes( 413032 );
pin_ptr<unsigned char> fuzzyRus = &buffPtr[0];
return fuzzyRus;
}
I have a DLL that I want to call from within another DLL. I made a C++ MFC DLL with this code:
extern "C" INT PASCAL EXPORT Locale()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
typedef BOOL(WINAPI* LPFNDLLGetStringLabel)( CWnd *, int, LPTSTR , CWinApp *, LPSTR , LPCTSTR );
int bRes = 0; //false;
char achEvent[ 250 ];
HINSTANCE hDLL;
hDLL = LoadLibrary( L"C:\\1.dll" );
if ( hDLL != NULL )
{
CString ocStrInfo;
ocStrInfo += "Alfa";
ocStrInfo += ";";
ocStrInfo += "Alfa";
ocStrInfo += ";";
ocStrInfo += "Alfa";
LPFNDLLGetStringLabel lpfnDllFunc;
lpfnDllFunc = (LPFNDLLGetStringLabel)GetProcAddress( hDLL, "GetStringLabel");
if ( lpfnDllFunc )
if( lpfnDllFunc( NULL, 111, (LPTSTR)ocStrInfo.GetBuffer(), AfxGetApp(), achEvent, NULL )) {
return bRes=1;
}else{
return bRes=0;
}
FreeLibrary( hDLL );
}
}
The following code is calling the second DLL, but it isn't working right:
int main(){
HINSTANCE dllHandle = LoadLibrary(L"C:\\2.dll");
if(dllHandle == NULL ){
std::cout << "alarm";
}
typedef int(*Locale)(void);
FARPROC pTest = GetProcAddress(HMODULE (dllHandle),"Locale");
if(pTest == NULL ){
std::cout << "alarm";
}
Locale con = Locale(pTest);
int r= 1;
r =con();
cout << r;
FreeLibrary(dllHandle);
getchar();
return 0;
}
But dllhandle equal with null... can anybody help me?
You might have a look at Dependency Walker. Using this tool in profile mode will show you whether the dependencies between your binaries (EXE - DLL1 - DLL2) can be resolved at runtime.
One reason might be: DLL1 cannot be started because DLL2 has not been found.
You should also take a look that the way you export Locale (extern "C" INT PASCAL EXPORT) is correct!
As already mentioned, you should also have a look at GetLastError.
For troubleshooting library dependencies in windows you could monitor your program with procmon. See (http://technet.microsoft.com/en-ca/sysinternals/bb896645.aspx)
I am trying to write a program that can get the window title of a process.
Before I describe the problem, here is the code:
#include <Windows.h>
#include <string>
#include <Psapi.h>
#include <algorithm>
std::string window_title;
std::string search_for;
BOOL CALLBACK EnumWindowCallback(HWND hWindow, LPARAM param)
{
if ( IsWindow( hWindow ) == TRUE )
{
DWORD pid = 0;
if ( GetWindowThreadProcessId( hWindow, &pid ) != 0 )
{
HANDLE hProcess;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
if ( hProcess != 0 )
{
std::string path;
CHAR name[MAX_PATH];
GetModuleFileNameExA( hProcess, NULL, name, sizeof(name) / sizeof(CHAR) );
path = name;
unsigned int slash = path.find_last_of('\\');
if ( slash != std::string::npos ){
std::string proc_name = path.substr( slash + 1, path.length() );
std::transform(proc_name.begin(), proc_name.end(), proc_name.begin(), ::tolower);
if ( proc_name == search_for )
{
CHAR finalTitle[MAX_PATH];
ZeroMemory( finalTitle, sizeof(finalTitle) );
SendMessageA( hWindow, WM_GETTEXT, (WPARAM)sizeof(CHAR)/sizeof(MAX_PATH), (LPARAM)finalTitle );
window_title = finalTitle;
return FALSE;
}
}
}
}
}
return TRUE;
};
const char* __stdcall GetWinTitleByProcessName( const char* title )
{
search_for = title;
std::transform(search_for.begin(), search_for.end(), search_for.begin(), ::tolower);
if ( EnumWindows( (WNDENUMPROC)EnumWindowCallback, 0 ) == FALSE )
{
return window_title.c_str();
}
return "NOTFOUND";
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
MessageBoxA( NULL, GetWinTitleByProcessName("chrome.exe"), "Test", MB_OK);
}
The program works so far, until I want to get the actual title of the window.
I tried GetWindowText and SendMessage, as shown here.
Both methods return empty strings.
How can I get the window title?
The following code works for a similar problem. In my case I am looking for the windows handle of an application so that I can parent a dll. I identify the app by its caption. Its C++Builder code so some parts may be unfamiliar. I'll comment the differences I spot. The main one is the use of Application, I'm not sure what the non-Embarcadero equivalent is, but each running instance of code has an Application instance that manages the message loop and so on. I set my dll's Application->Handle to the calling apps hWnd to keep it off the taskbar, among other things. This code works on xp, vista 32 and win7 64.
void HideDLL() {
if (Application->Handle == 0) {
SearchObject *so = new SearchObject();
so->Caption = L"MyCallingApp";
so->Handle = 0;
EnumWindows((WNDENUMPROC)EnumWindowsProc, (long)so);
Application->Handle = so->Handle;
delete so;
}
}
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lparam) {
bool result;
SearchObject *so = (SearchObject*)lparam;
wchar_t *caption = new wchar_t[STR_DEFAULT];
GetWindowTextW(hWnd, caption, STR_DEFAULT);
// String is an Embarcadero type representing UnicodeString
String Caption = caption;
// Pos is a wrapper around strstr I think
// the actual caption in my case is decorated with some other stuff
// I only know that it will start with the name of the app
if (Caption.Pos(so->Caption) > 0) {
so->Handle = hWnd;
result = false;
} else {
result = true;
}
delete caption;
return result;
}
Hope this helps.
It seems that (WPARAM)sizeof(CHAR)/sizeof(MAX_PATH) would return you zero, because sizeof(char) will be defenetly smaller then the max path, so you say to WinAPI that your variable has zero length, that's why it returns empty string to you.
Specify there MAX_PATH value instead.