Domanda

Immagina di voler scrivere un programma che testi le funzioni in un file dll c++.Dovresti consentire all'utente di selezionare una DLL (supponiamo di parlare di DLL C++).Dovrebbe essere in grado di ottenere un elenco di tutte le funzioni esportate dalla dll.Quindi, l'utente dovrebbe essere in grado di selezionare un nome di funzione dall'elenco, inserire manualmente un elenco di argomenti (gli argomenti sono tutti di tipo base, come int, double, bool o array di caratteri (ad es.stringhe di tipo c)) e tentare di eseguire la funzione selezionata con gli argomenti specificati.Gli piacerebbe sapere se la funzione viene eseguita con gli argomenti specificati o se ne causano il crash (perché ad esempio non corrispondono alla firma).

Il problema principale è che il C++, essendo un linguaggio fortemente tipizzato, richiede di conoscere il numero e il tipo degli argomenti per una chiamata di funzione in fase di compilazione. E nel mio caso, semplicemente non so quali siano questi argomenti, finché non l'utente li seleziona in fase di esecuzione.

L'unica soluzione che ho trovato è stata quella di utilizzare l'assembly per inserire manualmente gli argomenti nello stack di chiamate.

Tuttavia, sono arrivato a capire che se voglio fare confusione con l'assembly, è meglio che mi assicuri di sapere quale convenzione di chiamata utilizzano le funzioni nella dll.

Quindi (finalmente :) ecco la mia domanda:posso dedurre la convenzione di chiamata a livello di codice?Dependency Walker non mi aiuterà e non ho idea di come leggere manualmente il formato PE.

È stato utile?

Soluzione

La risposta è Forse.

Se i nomi delle funzioni sono decorati in C++, puoi determinare il conteggio e i tipi di argomenti dalla decorazione del nome, questo è lo scenario migliore e abbastanza probabile se MSVC è stato utilizzato per scrivere il codice in primo luogo.

Se le funzioni esportate sono convenzioni di chiamata stdcall (l'impostazione predefinita per Windows API), è possibile determinare il numero di byte da inviare, ma non i tipi degli argomenti.

La cattiva notizia è che per la convenzione di chiamata del C non c'è modo di dirlo guardando i nomi dei simboli.Dovresti avere accesso al codice sorgente o alle informazioni di debug.

http://en.wikipedia.org/wiki/X86_calling_conventions

Il nome assegnato a una funzione durante l'esportazione non lo è necessario per avere qualche relazione con il nome visto dal linker, ma la maggior parte delle volte, il nome esportato e il nome del simbolo visto dal linker sono gli stessi.

Altri suggerimenti

Non ha specificato se si sta parlando a 32-bit o 64-bit qui, e le difficoltà delineate da voi e gli altri manifesti applica principalmente al codice a 32 bit. Su Windows a 64 bit, non c'è essenzialmente una sola convenzione di chiamata (è anche in questo articolo di Wikipedia collegate da John Knoeller), il che significa che fare conoscere la convenzione di chiamata (ovviamente con l'eccezione di nessuno cucinare la propria).

Inoltre, con i 64 di Microsoft convenzione di chiamata, non conoscendo il numero di parametri della funzione da chiamare non ti impedisce di chiamarlo, fornendo il maggior numero di parametri come desiderate / l'utente desidera. Questo perché voi come un chiamante mettere da parte lo spazio dello stack e pulirlo in seguito. -. Naturalmente, non fornendo il giusto [numero di] parametri può avere ancora la funzione chiamata fare cose stupide, perché si sta fornendo input non valido, ma questa è un'altra storia

Il codice compilato non si limita a dire 'Qui questa funzione è un fastcall, e questa qui è stdcall' purtroppo.

Nemmeno disassemblatori moderni come IDA cercano di dedurre tipi di chiamate di default (ci potrebbe essere un plugin o un'opzione da qualche parte idk).

In sostanza, se sei un uomo ti cn un'occhiata alle prime istruzioni e dire il 90% del tempo. Se sono ostacoli e spinta, la sua stdcall, se le sue params, che passa attraverso i registri (soprattutto ecx) allora la sua cdecl. Fastcall utilizza anche i registri, ma fa qualcosa di speciale .. dunno fuori dalla parte superiore della mia testa. Ma tutte queste informazioni è inutile perché il programma, ovviamente, non sarà un essere umano.

Se si sta facendo il test, Non avere almeno i file header ?? Questo è un modo terribilmente difficile per scuoiare un gatto ..

Se volete sapere che cosa convenzione di chiamata utilizza una funzione C ++, la vostra migliore speranza è quello di studiare

  1. L'intestazione che dichiara che la funzione, e
  2. La documentazione per il compilatore che ha compilato la DLL particolare.

Ma tutta questa faccenda sembra un po 'di confusione, onestamente. Perché il tuo amico vuole essere in grado di farlo, e perché non può ottenere le informazioni di cui ha bisogno per l'analisi di un colpo di testa che dichiara le funzioni rilevanti?

In questa pagina si descrivono le modalità di VC ++ 6 codifica dei parametri e chiamando informazioni convenzione in un nome simbolo: http://www.bottledlight.com/docs/mangle.html

Ho il sospetto che le versioni successive di VC ++ saranno compatibili ma non ho confermato.

Ci sono anche alcuni strumenti che automatizzano questo, che accompagnano il compilatore: http: //msdn.microsoft.com/en-us/library/5x49w699.aspx

Il nome pressare si applica solo per le funzioni C ++; se una funzione è ' 'C' extern' allora questo non funzionerà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top