• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[RAD Studio C++ Builder] Bilbioteka Łączona dynamicznie, błąd Access Violation .

VPS Starter Arubacloud
0 głosów
253 wizyt
pytanie zadane 28 sierpnia 2018 w C i C++ przez PatrykK96 Nowicjusz (170 p.)
Witam, na wstępie chciałbym przedstawić sytuację, chciałem nauczyć się programować a jednocześnie robić GUI w c++ builderze, w dodatku potrzebuję własnie takowego GUI w formie nie aplikacji, a DLL dołączanej do programu zewnętrznego. Zrobiłem pusty projekt biblioteki i dodałem do niego pusty Form, w roli testów zacząłem sprawdzać czy form się pojawia poprzez dołączanie DLL przez iniekcję do programów, rzeczywiście w większości przypadków się pojawił niestety w 3 programach w których najbardziej mi zależało na jego działaniu dołączenie programu zwraca mi błąd najpierw "Access violation at address 74E30D4A in module 'USER32.dll' a następnie "A call to an OS function failed". Tak jakbym próbował odnieść się do miejsca pamięci nie zarezerwowanego dla aplikacji / biblioteki. Niestety o ile umiem napisać program to nie mam pojęcia co taki błąd oznacza i jak go w tym przypadku naprawić. Jeżeli są potrzebne jakieś dane, których nie umieściłem prosiłbym o napisanie mi w komentarzu, postaram się niezwłocznie je dodać. Będę wdzięczny za wszelką pomoc.
komentarz 28 sierpnia 2018 przez j23 Mędrzec (194,920 p.)
Skoro to tylko prosty projekt DLL-ki z oknem, to dawaj kod, bo bez niego ciężko będzie coś zaradzić.
komentarz 28 sierpnia 2018 przez PatrykK96 Nowicjusz (170 p.)
MAIN.CPP

#include <vcl.h>
#include <windows.h>

#pragma hdrstop
#pragma argsused
#include <tchar.h>

USEFORM("MainWindowMH.cpp", MainForm);

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{

	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
		Application->CreateForm(__classid(TMainForm), &MainForm);
		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");

		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
        }
    }
	return 0;
}


-----------------------------------------------------------------------------------------------------

MainWindow.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainWindowMH.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------

MainWindow.h

//---------------------------------------------------------------------------

#ifndef MainWindowMHH
#define MainWindowMHH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TMainForm : public TForm
{
__published:	// IDE-managed Components
	TTabControl *TabControl1;
	TPanel *Panel1;
	TPanel *Panel2;
	TPanel *Panel3;
private:	// User declarations
public:		// User declarations
	__fastcall TMainForm(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TMainForm *MainForm;
//---------------------------------------------------------------------------
#endif

Praktycznie tylko dodałem VCL Form i nic więcej.

1 odpowiedź

0 głosów
odpowiedź 28 sierpnia 2018 przez j23 Mędrzec (194,920 p.)
wybrane 28 sierpnia 2018 przez PatrykK96
 
Najlepsza

DllEntryPoint powinien inaczej wyglądać. Masz tam parametr reason, który może przybrać wartości DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH i DLL_PROCESS_DETACH. Jak łatwo się domyśleć, ta funkcja może być wywoływana wielokrotnie, na pewno dwa razy - przy ładowaniu i zwolnieniu biblioteki.

 

Druga sprawa: jeśli mnie pamięć nie myli, w DllEntryPoint nie powinno się wywoływać funkcji niekernelowych, ergo - tworzenie okien odpada. W DLL_PROCESS_ATTACH stwórz wątek, który robi to, co teraz robi twój dll-entry, a w DLL_PROCESS_DETACH daj sygnał do zamknięcia okna i czekaj aż wątek się skończy (WaitForSingleObject).

 

To tyle...

komentarz 28 sierpnia 2018 przez PatrykK96 Nowicjusz (170 p.)
#include <vcl.h>
#include <windows.h>
#include <process.h>

#pragma hdrstop
#pragma argsused
#include <tchar.h>

HANDLE hThread;

USEFORM("MainWindowMH.cpp", MainForm);

void __cdecl ThreadProc( void * args)
{

	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
		Application->CreateForm(__classid(TMainForm), &MainForm);
		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");

		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
        }
	}
}


BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    switch( fdwReason )
    {
		case DLL_PROCESS_ATTACH:
		{
			hThread =( HANDLE ) _beginthread( ThreadProc, 0, NULL );
        }
		case DLL_THREAD_ATTACH:
			break;
		case DLL_THREAD_DETACH:
			break;
		case DLL_PROCESS_DETACH:
		{   Application->Terminate();
			WaitForSingleObject( hThread, INFINITE );
        }
    }
	return TRUE;
}

Nie do końca jestem pewny czy wszystko zrobiłem, ale jeżeli tak to niestety dalej przy próbie wstrzyknięcia DLL mam ten sam błąd :

A następnie 

Przy innych programach tak jak napisałem w głowym temacie okno pokazuje się bez żadnego błędu, więc zaczynam podejrzewać, że to wina programów do których próbuję wstrzyknąć moją DLL. 

 

komentarz 29 sierpnia 2018 przez j23 Mędrzec (194,920 p.)
edycja 29 sierpnia 2018 przez j23

Problem w tym, że używasz biblioteki, która nie wiadomo co robi zanim pojawi się okno (np. obiekt wskazywany przez Application jest tworzony przed wywołaniem DllMain). Nie napisałeś, jakie aplikacje powodują błąd, ale niewykluczone, że mogą mieć jakieś zabezpieczenia przed takim wstrzykiwaniem.

 

Próbowałeś opcję z dynamicznym/statycznym linkowaniem runtime'ów do twojej DLL-ki?

 

No i najważniejsze: czy przypadkiem nie próbujesz wstrzyknąć 32-bitowej biblioteki do 64-bitowej aplikacji (lub na odwrót)?

komentarz 29 sierpnia 2018 przez PatrykK96 Nowicjusz (170 p.)

Spróbuję z dynamicznym statycznym linkowaniem runtime'ów, jestem pewny co do tego, że aplikacja jest 32 bitowa i moja biblioteka też. Postaram się przeanalizować i zastosować to co napisałeś, ale sądzę że to jakieś zabezpieczenie programu, nie będę tutaj pytał jak obejść takie zabezpieczenie bo wydaje mi się, że to nie kontent tego forum, więc mogę  tylko podziękować Ci za pomoc i poświęcony czas.smiley

komentarz 29 sierpnia 2018 przez j23 Mędrzec (194,920 p.)

Zrób prosty test: stwórz DLL-kę pustą, bez biblioteki VCL (tworzenie wątku zostaw; daj jakiś Sleep), i spróbuj wstrzyknąć do procesu, z którym są problemy. Jeśli zadziała, to będziesz wiedział, że problem leży po stronie biblioteki VCL. A jeśli nie - widocznie proces jest zabezpieczony lub coś tam coś tam.

Podobne pytania

0 głosów
1 odpowiedź 162 wizyt
0 głosów
1 odpowiedź 332 wizyt
pytanie zadane 8 stycznia 2018 w C i C++ przez niezalogowany

92,452 zapytań

141,262 odpowiedzi

319,077 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...