Exécutable sans imports

Résolu
cs_Nebula Messages postés 787 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 7 juin 2007 - 9 oct. 2004 à 18:30
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 - 9 oct. 2004 à 21:42
Bonsoir à tous, comme le titre ne l'indique pas j'essaie (pour le fun) de faire un binaire contenant le moins d'imports possibles, voire même aucun (puisque les adresses sur kernel32 semblent fixes, je suppose qu'on peut mettre en dur les adresses de cette librairie - au pire deux imports suffisent, mais c'est déjà assez pour se faire hooker)... Malheureusement, le code suivant bugge atrocement et je ne vois pas trop ni pourquoi ni comment y remédier :-/
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

typedef HANDLE (*PGETSTDHANDLE)(DWORD);
typedef DWORD (*PFORMATMESSAGE)(DWORD, LPCVOID, DWORD, DWORD, LPTSTR, DWORD, va_list*);
typedef VOID (*PWRITECONSOLE)(HANDLE, LPCVOID, DWORD, LPDWORD, LPVOID);
typedef VOID (*PEXITPROCESS)(UINT);

static HANDLE hConsole = INVALID_HANDLE_VALUE;
static HINSTANCE hKernel = NULL;
static PGETSTDHANDLE pGetStdHandle = NULL;
static PFORMATMESSAGE pFormatMessage = NULL;
static PWRITECONSOLE pWriteConsole = NULL;
static PEXITPROCESS pExitProcess = NULL;

VOID print(LPCTSTR lpFormat, ...) {
  va_list lpValues;
  va_start(lpValues, lpFormat);
  LPTSTR lpMessage;
  DWORD n = pFormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, lpFormat, 0, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessage, 0, &lpValues);
  va_end(lpValues);
  pWriteConsole(hConsole, lpMessage, n, &n, NULL);
}

VOID mainCRTStartup(VOID) {
  hKernel = GetModuleHandle(TEXT("kernel32.dll"));
  pGetStdHandle = GetProcAddress(hKernel, "GetStdHandle");
  pFormatMessage = GetProcAddress(hKernel, "FormatMessageW");
  pWriteConsole = GetProcAddress(hKernel, "WriteConsoleW");
  pExitProcess = GetProcAddress(hKernel, "ExitProcess");
  hConsole = pGetStdHandle(STD_OUTPUT_HANDLE);
  print(TEXT("hKernel        = 0x%1!08x!%n" \
             "hConsole       = 0x%2!08x!%n" \
             "pGetStdHandle  = 0x%3!08x!%n" \
             "pFormatMessage = 0x%4!08x!%n" \
             "pWriteConsole  = 0x%5!08x!%n" \
             "pExitProcess   = 0x%6!08x!%n" ),
        hKernel, hConsole, pGetStdHandle, pFormatMessage, pWriteConsole, pExitProcess);
  print(TEXT("Hello World !%n"));
  print(TEXT("Hallo World !%n"));
  print(TEXT("Hi World !%n"));
  pExitProcess(0);
}


Après compilation et exécution, j'obtiens les résultats (corrects) suivants :
hKernel        = 0x7c800000
hConsole       = 0x00000007
pGetStdHandle  = 0x7c812ca9
pFormatMessage = 0x7c829047
pWriteConsole  = 0x7c839882
pExitProcess   = 0x7c81caa2
mais seul le premier print() est affiché, les autres semblent tourner dans le vide et le programme plante lors du pExitProcess, voici les informations retournées par le débugger :
tiny.exe caused an Access Violation at location 00000000 Reading from location 00000000.

Registers:
eax=00000001 ebx=7ffde000 ecx=7c81cbcb edx=00350608 esi=00000000 edi=00000010
eip=00000000 esp=0022ff9c ebp=0022ff88 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

Call stack:
AddrPC     AddrReturn AddrFrame  AddrStack  Params
00000000   00403050   0022FF98   0022FF9C   7C800000   00000007   7C812CA9   7C829047
00000000
00403050   00000001   0022FF88   0022FF9C   7C829037   003D0000   00000000   00403050
00403050  tiny.exe:00403050  mainCRTStartup  main.c:44
void mainCRTStartup()
...
  print(TEXT("Hallo World !%n"));
  print(TEXT("Hi World !%n"));
>	  pExitProcess(0);
}


Pourtant si on regarde les valeurs des pointeurs avec GDB, on trouve les adresses parfaitement valides, après plantage en règle du programme: Program received signal SIGSEGV, Segmentation fault. 0x00000000 in ?? () :
(gdb) print pGetStdHandle
$3 = 0x7c812ca9 <_libkernel32_a_iname+2084625457>
(gdb) print pFormatMessage
$4 = 0x7c829047 <_libkernel32_a_iname+2084716495>
(gdb) print pWriteConsole
$5 = 0x7c839882 <_libkernel32_a_iname+2084784138>
(gdb) print pExitProcess
$6 = 0x7c81caa2 <_libkernel32_a_iname+2084665898>


Je sèche... Si quelqu'un trouve, je lui offre un gigot sauce au poivre ! :p

5 réponses

racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
9 oct. 2004 à 19:18
Salut,
Je pense qu'il faut ajouter la convention d'appel des fonctions. Tu peux essayer de définir les types de pointeurs en ajoutant WINAPI (ou __stdcall) comme ceci:
typedef HANDLE (WINAPI *PGETSTDHANDLE)(DWORD);
typedef DWORD (WINAPI *PFORMATMESSAGE)(DWORD, LPCVOID, DWORD, DWORD, LPTSTR, DWORD, va_list*);
typedef VOID (WINAPI *PWRITECONSOLE)(HANDLE, LPCVOID, DWORD, LPDWORD, LPVOID);
typedef VOID (WINAPI *PEXITPROCESS)(UINT);
3
cs_Nebula Messages postés 787 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 7 juin 2007 2
9 oct. 2004 à 19:48
Mazette, c'était bien çà !!! Et j'y ai passé mon après-midi !! Argh !

Merci infiniment... Je me sens un peu bête de ne pas y avoir pensé d'ailleurs ;-) Bon je te dois un gigot sauce au poivre alors :p
0
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
9 oct. 2004 à 20:24
Dommage pour le gigot, je suis plutôt végétarien :) merci quand-même.
Moi aussi je m'étais intéressé à l'appel des API directement par leurs adresses. Le problème c'est que ces adresses, pour une même DLL, diffèrent d'un Windows à un autre (98/2000/XP etc...) . Et elles diffèrent aussi selon la version de cette DLL dans un même Windows.
A+
0
cs_Nebula Messages postés 787 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 7 juin 2007 2
9 oct. 2004 à 21:12
Hum embêtant... Bah, c'est toujours intéressant à savoir malgré tout :)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
9 oct. 2004 à 21:42
Très intéressant à savoir et à faire aussi si l'application est destinée à un seul PC (ou d'autres ayant le même OS et même version de DLL).
L'appel direct par adresse doit être plus rapide que l'appel par pointeur.
0
Rejoignez-nous