2011-07-24 15 views
6

をプログラムで使用する方法はありますかC source fileは潜在的に危険ですか?有害なCソースファイルチェック?

私は何のチェックは、100%の精度が得られないことを知って- しかし、いくつかの表現/キーワードが見つかった場合は赤い旗を発生させますいくつかの基本的なチェックを行うことが少なくとも興味を持っています。何を探すべきなのか?

注:私が検査されるファイルのサイズは、すべてのメモリを操作する数値解析機能を実現(最大でラインの数百)、比較的小さいです。コードでは、外部ライブラリ(math.hを除く)は使用されません。また、I/Oを使用しないでください(関数はメモリ内配列で実行されます)。上記の

は、少なくとも有害なコードを検出するためのをしようと、私はに行うことができ、いくつかのプログラムチェックがありますか?

注:コードはI/Oなければ、私は、任意のI/Oを期待していないので、 - それは有害なと考えられています。

+0

まあ、 '#include'ディレクティブをチェックして、ヘッダーの「ホワイトリスト」以外のものが含まれているかどうかを調べることができます。 –

+0

スタティックコード解析。あなたの禁止された機能や許可されていない#includeを調べるだけです。もし何かホワイトリストを作成し、whitelistに含まれていないものがあるかどうかを確認するには、math.h、関数呼び出しがローカルになければなりませんファイル関数またはmath.h関数などで... –

+4

"有害な"を定義します。 –

答えて

3

何かが許可されていないことを確認したい場合は、コードをコンパイルし、リンク先を調べます(nmなど)。 "プログラム的"な方法でこれをやっているので、python/perl/bashを使ってコンパイルし、オブジェクトファイルの名前リストをスキャンしてください。

静的に定義されたバッファのバッファオーバーライトについては、あまりできませんが、動的に割り当てられたバッファオーバーランを防ぐために、電気フェンスタイプのメモリアロケータにリンクすることができます。

問題のCファイルをvalgrindで実行中に一般的なデータを提供するドライバとコンパイルしてリンクすることもできます。これは悪質または悪意のあるコードの検出に役立ちます。

しかし、最終的には、「このルーチンは終了しますか?」という質問に対しては、常に決心しています。これは決めることができないことで有名です。これを実践する方法は、あなたのプログラムをコンパイルし、適切な時間の一定期間後にalarm -outとなるドライバから実行することです。

EDITnmの使用を示す例:

#include <stdio.h> 
foo() { 
    FILE *fp = fopen("/etc/passwd", "r"); 
} 

-cでコンパイルし、次いで得られたオブジェクト・ファイルを見:

fopenを呼び出し定義関数fooをスニペットCを作成します

$ gcc -c foo.c 
$ nm foo.o 
0000000000000000 T foo 
       U fopen 

ここで、yオブジェクトファイルfoo.oに2つのシンボルがあることがわかります。 1つは定義されている、foo、私たちが書いたサブルーチンの名前。1つは定義されていません。fopenは、オブジェクトファイルが他のCファイルと必要なライブラリとリンクされているときにその定義にリンクされます。このメソッドを使用すると、コンパイルされたオブジェクトが独自の定義の外にあるものを参照していて、ルールによって「悪い」と考えられるかどうかをすぐに確認できます。

+0

マーク、ありがとうございます。あなたは 'nm'とその使い方について詳しく説明できますか? – user3262424

+0

@ user3262424 - 更新されたテキスト2は、 'nm'の使用例を示しています。また、manページ(man nmなど)もあります。 – unpythonic

+0

マーク、ありがとう - これは非常に有益です。 – user3262424

0

ネットワークIOやアセンブリブロックのような "不正な"関数呼び出しに対して、何らかの明白なチェックを行うことができます。それを超えて、私はCファイルだけでできることは考えられません。

Cの性質を考えれば、コンパイルして起動するだけで済みます。マクロなどは、Cコードの静的解析をかなり困難にします。

+0

Andrew White、ありがとう。 「マクロス」を特定する良い方法はありますか?また、「アセンブリブロック」をどのように識別できますか? – user3262424

+0

'#'を探したり、gcc -Eを使ってマクロを自動的に展開したりすることができます。 –

+0

おかげでアンドリュー。あなたは 'gcc -E'についてもっと詳しい情報を提供することができますか? – user3262424

8

はい、あなたに関係する条件をプログラムで検出する方法があります。

  1. は、それが標準で定義し、非I/O機能のものを除く任意の関数を呼び出すことはありません:

    あなたが理想的な静的解析ツールは、コードの前処理されたバージョンがいることを確認したい私には思えますライブラリ、

  2. ポインタで悪いことはしません。

前処理を行うと、マクロ、おそらくは悪質な内容、マクロの実際の使用状況を検出する問題を取り除くことができます。また、標準のCヘッダーのすべてのマクロ定義を網羅したくはありません。彼らはあなたの魂を傷つけるでしょう、なぜなら彼らが含んでいるすべての歴史的な荒れ狂いのためです。

標準のライブラリで独自の関数と信頼できる関数のみを呼び出すコードでは、何か厄介なものを呼び出すことはありません。 (注意:ポインタを介していくつかの関数を呼び出すかもしれないので、このチェックでは、関数点解析または間接関数呼び出しのバーボッテンが必要です。数値解析を行うコードではおそらく妥当でしょう)。

ポインタで悪いものをチェックする目的は、悪質なコードを作成して制御を渡すためのポインタを乱用しないようにすることです。これは、intがどこにあるのかわからないため、「intからのポインタへのキャストはありません」ということを意味します。 - }

who-does-it-callチェックでは、コードと名前/すべてのシンボルを解決し、コールサイトをチェックして、どこに行くかを確認します。ポインタ/関数ポインタを許可する場合は、完全なポイント・ツー・アナリシスが必要です。

標準的なスタティックアナライザツール会社(Coverity、Klocwork)は、コードブロックがどの機能を呼び出すかを制限する何らかの方法を提供する可能性があります。それでも問題が解決しない場合は、DMS Software Reengineering ToolkitC Front Endのようなより一般的な分析機械に戻らなければなりません。 DMSは、フロントエンドとして提供される言語記述のために、任意のスタティック・アナライザを構築するためのカスタマイズ可能な機械を提供します。 DMSは、前処理ステップを含むテスト1)を正確に行うように構成することができます。ポイントツーチェックにも使用できるフルポイントツーアナライザーとファンクションポイントツーアナライザーを備えています。

2) "ポインタを悪意のある使用しない"の場合、やはり標準的な静的分析ツール会社がポインタチェックを提供します。しかし、ここでは、チューリングマシンについて静的に推論しようとしているので、ここではもっと難しい問題があります。彼らの解決策は、ミスケースか偽陽性の報告です。私たちのCheckPointerツールは、の動的な分析です。つまり、実行中のコードを監視し、ポインタを誤って使用しようとすると、CheckPointerは問題のある場所を直ちに報告します。ああ、はい、CheckPointerはintからポインタへのキャストを禁止します: - } CheckPointerは静的な診断を提供しません。 "このコードは不正な行為をする"ことができますが、実際に不正行為を試みると診断されます。 CheckPointerにはかなりのオーバーヘッドがあります(すべてのチェックにはコストがかかります)ので、しばらくの間コードを実行して、何も悪いことが起こらないと信じて、それを使用しないようにします。

EDIT:もう1つのポスターにはがあります。静的に定義されたバッファーのバッファーオーバーライトについては、多くはありません。 CheckPointerはこれらのテストなどを行います。

+1

スタックオーバーフローと無限ループが有害であるとみなされるかどうかの問題もあります。もしそうなら、そのようなケースのチェックを追加する必要があります。これはかなり難しいかもしれません。 「有害」を定義することは自明ではありません。 – luiscubal

+1

真。 OPはすでに完璧な答えを得られなかったことに同意した。彼はコールグラフ(DMSはこれを行います)を構築し、サイクルをチェックすることによって検出できる直接的または間接的な再帰を主張することによって、スタックオーバーフローを排除することができます。無限ループはおそらく停止するのが難しいですが、緊張していると自分のタイマー機構を構築することで制御できます。 –

+0

最後のコメントで言及して忘れたが、ローカル関数変数(例えば、int x [10000000];)のサイズ/数を制限することも、おそらく良い考えであろう。私はこれがこの回答(私はupvoteを行った)の否定的な批判であることを意味するものではなく、ちょうど補足的な情報です。 – luiscubal

関連する問題