Discussion:
mingw / msvcrt, C , Funktions-Adresse
(zu alt für eine Antwort)
Robert Hartmann
2015-07-18 06:09:15 UTC
Permalink
Hallo zusammen,


Warum liefern

printf("%p\n",(void*)vfprintf);

und

printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");

verschiedene Ausgaben (compiliert mit mingw32 gcc,
mingw32 linkt per default gegen msvcrt.dll).


Irgend etwas offensichtliches hab ich übersehen - nur was?

Gruß Robert

P.S. Hier drin hab ich vieles gefunden, mit dem ich mir
ein Hello-PE-Header-Programm gebaut habe.
"Microsoft PE and COFF Specification":
https://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx



====Beispiel Code code.c ====

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

#include<windows.h>

int main(int argc, char* argv[]){

HMODULE msvcrt_dll=GetModuleHandle(TEXT("msvcrt.dll"));
assert(msvcrt_dll);
PROC vfprintf_getProcAdress = GetProcAddress(msvcrt_dll,TEXT("vfprintf"));

printf("vfprintf: %p \n vfprintf_getProcAdress: %p \n",(void*)vfprintf,
(void*)vfprintf_getProcAdress);
assert ((DWORD_PTR) vfprintf == (DWORD_PTR) vfprintf_getProcAdress);
return 0;
}

======================
gcc -DDEBUG -D_DEBUG code.c -o code.exe
======================
Claus Reibenstein
2015-07-18 14:15:59 UTC
Permalink
Post by Robert Hartmann
Warum liefern
printf("%p\n",(void*)vfprintf);
und
printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");
verschiedene Ausgaben
Weil Letzteres syntaktisch falsch ist.
Post by Robert Hartmann
(compiliert mit mingw32 gcc
Das da oben hat garantiert _nicht_ compiliert.

Gruß
Claus
Olaf Schmitt
2015-07-18 15:04:05 UTC
Permalink
Post by Claus Reibenstein
Post by Robert Hartmann
Warum liefern
printf("%p\n",(void*)vfprintf);
und
printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");
verschiedene Ausgaben
Weil Letzteres syntaktisch falsch ist.
Post by Robert Hartmann
(compiliert mit mingw32 gcc
Das da oben hat garantiert _nicht_ compiliert.
Da hast du Recht :-)
Das sollte wohl:
printf("%p\n",
(void*)GetProcAddress(GetModuleHandle((LPCWSTR)"msvcrt.dll"), "vfprintf"));
heißen.

Mal ins Blaue:
Bei seinem "Problem" denke ich, dass er gegen eine statische LIB compiliert.
Da hat vprinft natürlich eine andere Adresse als die von der DLL.


Olaf
Robert Hartmann
2015-07-28 19:54:27 UTC
Permalink
Post by Claus Reibenstein
Post by Robert Hartmann
Warum liefern
printf("%p\n",(void*)vfprintf);
und
printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");
verschiedene Ausgaben
Weil Letzteres syntaktisch falsch ist.
Post by Robert Hartmann
(compiliert mit mingw32 gcc
Das da oben hat garantiert _nicht_ compiliert.
Mag sein, dass die Posting Formatierung kaputt ist;

jedenfalls der komplett Quelltext auch im original Posting angegeben
kompiliert einwandfrei mit den von mir angegebenen gcc Aufruf.
Post by Claus Reibenstein
Post by Robert Hartmann
====Beispiel Code code.c ====
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>
int main(int argc, char* argv[]){
HMODULE msvcrt_dll=GetModuleHandle(TEXT("msvcrt.dll"));
assert(msvcrt_dll);
PROC vfprintf_getProcAdress = GetProcAddress(msvcrt_dll,TEXT("vfprintf"));
printf("vfprintf: %p \n vfprintf_getProcAdress: %p \n",(void*)vfprintf, (void*)vfprintf_getProcAdress);
assert ((DWORD_PTR) vfprintf == (DWORD_PTR) vfprintf_getProcAdress);
return 0;
}
======================
gcc -DDEBUG -D_DEBUG code.c -o code.exe
======================
C:\Dokumente und Einstellungen\Standart\Eigene
Dateien\C-CPP\small_test>gcc -DDEBUG -D_DEBUG code.c -o code.exe

C:\Dokumente und Einstellungen\Standart\Eigene Dateien\C-CPP\small_test>code
vfprintf: 00401C90
vfprintf_getProcAdress: 77C120CF
Assertion failed: (DWORD_PTR) vfprintf == (DWORD_PTR)
vfprintf_getProcAdress, file code.c, line 14

This application has requested the Runtime to terminate it in an unusual
way.
Please contact the application's support team for more information.

C:\Dokumente und Einstellungen\Standart\Eigene Dateien\C-CPP\small_test>


Gruß Robert

Stefan Kanthak
2015-07-18 13:22:22 UTC
Permalink
Post by Robert Hartmann
Hallo zusammen,
Warum liefern
printf("%p\n",(void*)vfprintf);
Wie und wo hast Du das Symbol vfprintf definiert?
Wie loest der Linker seine Adresse auf?
Und welche Adresse loest der Linker auf?
Post by Robert Hartmann
und
printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");
verschiedene Ausgaben
Normales Verhalten!
Post by Robert Hartmann
(compiliert mit mingw32 gcc,
mingw32 linkt per default gegen msvcrt.dll).
MSVCRT.DLL ist NICHT fuer die allgemeine Nutzung freigegeben!
Post by Robert Hartmann
Irgend etwas offensichtliches hab ich übersehen - nur was?
GRUNDLAGEN: hier statisches und dynamisches Laden einer DLL und die IAT!

wehret den Anfaengern!
Stefan
[
--
Die unaufgeforderte Zusendung werbender E-Mails verstoesst gegen §823
Abs. 1 sowie §1004 Abs. 1 BGB und begruendet Anspruch auf Unterlassung.
Beschluss des OLG Bamberg vom 12.05.2005 (AZ: 1 U 143/04)


--- news://freenews.netfront.net/ - complaints: ***@netfront.net ---
Stefan Reuther
2015-07-19 11:14:13 UTC
Permalink
Post by Robert Hartmann
Warum liefern
printf("%p\n",(void*)vfprintf);
und
printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");
verschiedene Ausgaben (compiliert mit mingw32 gcc,
mingw32 linkt per default gegen msvcrt.dll).
Ersteres liefert die Adresse des PLT-Eintrags/Thunks der Funktion
vfprintf, während letzteres die Adresse der Funktion in der DLL liefert.

Um die Menge zur Laufzeit zu patchenden Codes zu minimieren, setzt der
Linker nicht an jeder Stelle, wo vfprintf aufgerufen/verwendet wird, die
Adresse aus der DLL ein, sondern erzeugt einen Thunk; bei mir sieht der
so aus:
00401840 <vfprintf>:
401840: ff 25 14 51 40 00 jmp *0x405114
401846: 90 nop
401847: 90 nop
0x405114 ist die Adresse in der Global Offset Table, in der der Runtime
Linker die aufgelöste Adresse aus der DLL einträgt. In dieser Variablen
findet sich dann der gleiche Wert wie der, den du mit GetProcAddress
erhältst.

Wenn man dem Compiler mittels __declspec(dllimport) o.ä. mitteilt, dass
die Funktion aus einer DLL kommt, erzeugt er den Zugriff direkt über die
Global Offset Table ('call *0x405114' statt 'call 0x401840'), aber das
tut MinGW offenbar standardmäßig nicht. Mit -D__USE_CRTIMP kann man ihn
anweisen, das zu tun, dann bekommt man auch für beide deiner printfs das
gleiche Ergebnis.

Disclaimer: Terminologie aus der Unix-Welt, in Windows heißt das
bestimmt alles anders :)


Stefan
Robert Hartmann
2015-07-28 19:42:00 UTC
Permalink
Hallo Stefan,
Post by Stefan Reuther
Post by Robert Hartmann
Warum liefern
printf("%p\n",(void*)vfprintf);
und
printf("%p\n",(void*)GetProcAddress(GetModuleHandle("msvcrt.dll"),"vfprintf");
verschiedene Ausgaben (compiliert mit mingw32 gcc,
mingw32 linkt per default gegen msvcrt.dll).
Ersteres liefert die Adresse des PLT-Eintrags/Thunks der Funktion
vfprintf, während letzteres die Adresse der Funktion in der DLL liefert.
Danke.
Post by Stefan Reuther
Um die Menge zur Laufzeit zu patchenden Codes zu minimieren, setzt der
Linker nicht an jeder Stelle, wo vfprintf aufgerufen/verwendet wird, die
Adresse aus der DLL ein, sondern erzeugt einen Thunk; bei mir sieht der
401840: ff 25 14 51 40 00 jmp *0x405114
401846: 90 nop
401847: 90 nop
0x405114 ist die Adresse in der Global Offset Table, in der der Runtime
Linker die aufgelöste Adresse aus der DLL einträgt. In dieser Variablen
findet sich dann der gleiche Wert wie der, den du mit GetProcAddress
erhältst.
Wieder was gelernt.
Post by Stefan Reuther
Wenn man dem Compiler mittels __declspec(dllimport) o.ä. mitteilt, dass
die Funktion aus einer DLL kommt, erzeugt er den Zugriff direkt über die
Global Offset Table ('call *0x405114' statt 'call 0x401840'),
Auch für diese Ausführung danke ich.
Post by Stefan Reuther
aber das
tut MinGW offenbar standardmäßig nicht. Mit -D__USE_CRTIMP kann man ihn
anweisen, das zu tun, dann bekommt man auch für beide deiner printfs das
gleiche Ergebnis.
Disclaimer: Terminologie aus der Unix-Welt, in Windows heißt das
bestimmt alles anders :)
:-)

Gruß Robert
Lesen Sie weiter auf narkive:
Loading...