もっと詳しく
「Linux は、日常的なタスクを実行するための多くの独自の機能を考え出しました。 dlsym() 関数はその 1 つです。 dlsym() 関数の目的は、dlopen() 関数呼び出しによってアクセス可能になった DLL (ダイナミック リンク ライブラリ) で指定された定義済みシンボルのアドレスを見つけることです。 null で終わる文字列のファイル名で示される動的共有オブジェクト (共通リンク ライブラリ) ファイルをロードした後、関数 dlopen() は、ロードされたオブジェクトの匿名の「接続」を出力します。 名前付きシンボルは、dlopen() メソッドによってフェッチされたダイナミック リンク ライブラリ (DLL) で検索されます。 この記事では、dlsym() の使用について説明します。

目的のシンボルがその DLL に存在しない場合、その DLL の依存 DLL が検索され、その後、それらの依存関係が検索され、その後、目的のシンボルが見つかるか、すべての DLL が存在するまで幅優先方式で検索されます。この目的で検索されました。 同じレベルの依存 DLL が検索される順序は未定ですが、この検索順序によって、個別の DLL 内の重複シンボルがどのように識別されるかが決まります。 アンロードされた依存動的ライブラリは、依存 DLL の dlsym() 検索の結果として読み込まれないことに注意してください。 dlopen() 呼び出しの依存 DLL のコンポーネントとしてロードされた DLL のみがスキャンされます。」

RTLD_NOW: 従属 DLL のコレクション全体を dlsym() 関数への後続の呼び出しで使用できるようにする必要がある場合、このフラグを使用してダイナミック リンク ライブラリを呼び出します。

RTLD_LAZY: このフラグを使用すると、どの依存ダイナミック リンク ライブラリが読み込まれているかがわからないことがわかりません。

RTLD グローバル: 新しく読み込まれたライブラリは、このパッケージで指定されたシンボルを使用してシンボルを決定できます。

RTLD_LOCAL: どちらのフラグも言及されていないため、これは RTLD GLOBAL の反対であり、デフォルトです。

dlsym() コマンドの構文は次のとおりです。

#include

# void *dlsym(void *__restrict__ handler, const char *__restrict__ symbol_name);

dlsym() 関数が定義されているヘッダー ファイルは です。 「symbol_name」はシンボルの名前を表現した文字列、「handler」は dlopen() の呼び出しによって取得された値 (まだ dlclose() の要求によって返されていない) です。

dlopen() によって開かれた適切な DLL をハンドルが指していない場合は、NULL 値が返されます。 指定されたシンボル (シンボル名) と一致するハンドラにリンクされた DLL がない場合、dlsym() 関数によって NULL 値が返されます。

VIM エディターまたは任意のエディターを使用して dlsym.c ファイルを作成します。これには、nano などが含まれる場合があります。

前の手順で作成した C ファイルに、次の画面に示すコードを記述します。 ヘッダー ファイルは、以下のコード例の最初の 4 行のコードに含まれています。 続いて、main 関数が起動され、main 関数内に void 型のハンドラ ポインタが作成されます。 前のコード行では、void 型の文字エンコード ポインターを宣言しています。

それを使用して、dlopen メソッドを呼び出し、RTLD LAZY フラグと .so ファイル (Linux の動的共有ファイル) の場所を指定しました。 ハンドラ変数は、dlopen の結果を保持します。 1 を返すことにより、次の行は dlopen がダイナミック リンク ライブラリを正常にロードしたかどうかを判断します。 障害発生時は画面にエラーを書き込み、メイン機能を終了しました。

条件式の後、dlerror() メソッドを呼び出して既存のエラーを修正します。 定義した文字タイプのエンコードされたシンボルに整数 ASCII を 1 つ追加するとすぐに、値が「puts」になります。 文字列の長さは次の行で計算され、エンコードされた長さ変数に保存され、デコードに使用される for ループで使用されました。 終了記号「0」を使用して、for ループの後にコードを終了します。 その後、dlsym() メソッドを実行し、ハンドラーとデコードされたコード パラメーターを渡し、出力変数に結果が含まれています。

dlsym() 関数を呼び出して C ファイルをコンパイルする場合、C コンパイラでのコンパイル プロセスは、標準のコンパイル コマンドとは異なります。 「dlsym.c」というファイルにある場合は、次のコマンドを使用してプログラムを作成します。

$ gcc -rdynamic -o foo dlsym.c -ldl

コンパイルが正常に完了すると、出力ファイルが作成され、dlsym.out という名前が付けられます。 コマンド ./dlsym.out を入力して Enter キーを押すだけで、出力ファイルが実行されます。 ファイルの出力は、UNIX または Linux に似たオペレーティング システムの端末画面に表示されます。

vim エディターを使用して、C ファイルのコードの最後の行に小さな調整を加えました。 main 関数の最後の print ステートメントは、puts 関数に変換された出力に置き換える必要があります。 画面の二重引用符で、テキストが追加されました。

コードを再度コンパイルし、ターミナル画面で出力を確認します。 print ステートメントを使用せずに、puts 関数に変更された出力値を使用して画面に出力を取得します。 上記の特定のコード ファイルの出力を次に示します。

結論

この記事の冒頭の段落で、dlsym() 3 c 関数を使用して、DLL 内の特定の定義済みシンボルのアドレスを調べる方法について説明しました。 これについて、Kali Linux オペレーティング システムの C の 2 つの明確な例について説明し、詳しく説明しました。 どちらの例も非常に単純ですが、同時に非常に効率的であり、理解を深めるために dlsym() 関数の使用法を非常に明確に示しています。

The post Dlsym() 3 C 関数 appeared first on Gamingsym Japan.