ページ 11

c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 00:22
by helloworld1853
c言語のソースコードをアセンブルに変換し,

インラインでc言語のソースコード中に埋め込みたいのですが

なかなかうまくいきません。

gcc -S で出てきたソースコードは余計?なものが付属してしまい

コンパイルしようとしたらエラーが出まくりました。

純粋?なアセンブルコードだけを出す方法はありませんでしょうか。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 00:25
by softya(ソフト屋)
特殊なことをしない限りインラインアセンブラは必要ないと思いますが、C言語のコード丸写しで良いインラインアセンブラのコードが必要な理由を聞かせてもらって良いですか?

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 00:44
by helloworld1853
プログラムを難読化するソフトを少し興味があって作ろうとしているのですが、

普通の方法で難読化するとPEヘッダを収集したりしていろいろと難易度が高そうだったので

僕にも簡単に難読化できる方法を考えていたところ、

http://mimumimu.net/blog/2011/11/17/c%E ... %E3%80%82/

を参考に

c言語に機械語を埋め込み~(説明が下手なので省略します。)~すると

難読化できるのではないかと思いました。

ここのサイトを見る限り、アセンブル->機械語の順でやっているようなので

インラインアセンブルを利用するのがよいのではないかと思ったわけです。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 10:03
by softya(ソフト屋)
helloworld1853 さんが書きました:プログラムを難読化するソフトを少し興味があって作ろうとしているのですが、

普通の方法で難読化するとPEヘッダを収集したりしていろいろと難易度が高そうだったので

僕にも簡単に難読化できる方法を考えていたところ、

http://mimumimu.net/blog/2011/11/17/c%E ... %E3%80%82/

を参考に

c言語に機械語を埋め込み~(説明が下手なので省略します。)~すると

難読化できるのではないかと思いました。

ここのサイトを見る限り、アセンブル->機械語の順でやっているようなので

インラインアセンブルを利用するのがよいのではないかと思ったわけです。
それは全然難読化ではありません。
少なくとも難読化はバイナリデータが自在に操れないと作れるものではないですし、プログラムのメモリ構造の理解も必須、機械語レベルでAPI/DLLの呼び出しの仕組みも理解していないと無理だと思います。
あとDLLインジェクションやデバッガによる命令書き換えなど幾つもある攻撃手段を理解している必要もあります。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 10:53
by h2so5
わざわざそんな事しなくても、ソースコードを非公開にしてバイナリだけ公開すれば同じ事では?

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 12:47
by softya(ソフト屋)
ちなみに最低でもこれぐらいしないと難読化とは言えません。

「VC++プロジェクト向け難読化ツールの開発」


【補足】
この方法は静的な難読化なので、最も効果的な難読化は暗号化並びに動的な命令の書き換えだと言われています。
まぁ下手のことするとウィルス対策ソフトにウィルスと間違われますが。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 15:37
by ISLe
helloworld1853 さんが書きました:ここのサイトを見る限り、アセンブル->機械語の順でやっているようなので
インラインアセンブルを利用するのがよいのではないかと思ったわけです。
バイナリコードを得たければ、実行ファイルを作ってバイナリエディタで開いたら良いのでは?
必ずしもインラインアセンブラを使う必要はないと思いますけど。
あるいはニーモニック表眺めながらハンドアセンブルとか。

バイナリデータが静的データ領域(あるいはオペランド)に置かれるので単純に逆アセンブルしても実行コードとして解釈されないという意味では難読化と言えるかもしれません。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 22:11
by box
helloworld1853 さんが書きました:c言語のソースコードをアセンブルに変換し,
アセンブリ言語(あるいはアセンブリー言語)と書くのが正しいような気がします。
C言語:名詞
アセンブル(assemble):動詞
という風に品詞が異なるので、同じ土俵に乗せるのはあまり適切ではないような気がします。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 22:58
by helloworld1853
みなさま 返信ありがとうございます。

僕の説明が足りないような気がしたので

僕が考えていた難読化ソフトの流れを説明します。


プログラムを読み込む
      ↓
なんらかの方法で実行可能な機械語を取り出す
      ↓
コンパイルすると難読化するであろうソースコードを出力する


あとこのプログラムが出力するソースコードの形式を

下にのせておきます。

皆様には
・このプログラムは実現可能か。
・実現できたとして難易度は高いか。
・出力したソースコードをコンパイルすると難読化されているかどうか。
をお答えいただきたいです。

コード:

#include <windows.h>
#include <stdio.h>
 
/************************************************

普通の難読化プログラムはPEヘッダを収集したりいろいろするので
めんどくさいですが・・・
VirtualProtectを使って機械語をメモリ上に機械語を展開し暗号化したり
すれば間単に
難読化できるのではないかと思いました。
説明が下手なのでソースコードをご覧になってください。
(といってもソースコードは汚いですが・・・)
あくまでも動作を皆様に知ってもらうためなので
動作しません。

************************************************/
 
int main()
{
	DWORD d;
	char packed_code[]={//暗号化された機械語
		0x33,0x3D,0x7A, 
		//省略            
		0xCC,0x3D,0x12
	};

	char unpacked_code[10000];//解凍された機械語を入れる

	int packed_code_size = strlen(packed_code);

	int i;

	for(i = 0; i != packed_code_size; i++)//メモリ上に解凍した機械語を展開
	{
	    unpacked_code[i] = packed_code[i];//ここが展開ルーチン
		                                  //実際はもっと複雑です。
		                                  //ここでのコードは暗号化されていません。
	}

	printf("VirtualProtect : %s\n\n",VirtualProtect(
        unpacked_code,
        128,
        PAGE_EXECUTE_READWRITE,
        &d
        ) == NULL ? "[SUCCESS]" : "[ERROR]");
     
    return 0;
}

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月13日(水) 23:36
by softya(ソフト屋)
これだとISLeさんの言うところの軽い難読化ですね。
いくら暗号化してもデバッガでAPIでトラップされるとトレースされる可能性があります。
【補足】
既に当初のものと違いISLeさん案に成っている気がしますが・・・。

コード:

#include <windows.h>
#include <stdio.h>
 
/************************************************
 
普通の難読化プログラムはPEヘッダを収集したりいろいろするので
めんどくさいですが・・・
VirtualProtectを使って機械語をメモリ上に機械語を展開し暗号化したり
すれば間単に
難読化できるのではないかと思いました。
説明が下手なのでソースコードをご覧になってください。
(といってもソースコードは汚いですが・・・)
あくまでも動作を皆様に知ってもらうためなので
動作しません。
 
************************************************/
 
int main()
{
    DWORD d;
    char packed_code[]={//暗号化された機械語
	/*← 実行されるアドレスに合わせて書き換えが必要になるかも知れません。実行時にアドレスが確定するDLLの呼び出しが有ってはいけません。 */
        0x33,0x3D,0x7A, 
        //省略            
        0xCC,0x3D,0x12
    };
 
    char unpacked_code[10000];//解凍された機械語を入れる
 
    int packed_code_size = strlen(packed_code);	/*← テキストでも無いものをstrlenしてはいけません。*/ 
    int i;
 
    for(i = 0; i != packed_code_size; i++)//メモリ上に解凍した機械語を展開
    {
        unpacked_code[i] = packed_code[i];//ここが展開ルーチン
                                          //実際はもっと複雑です。
                                          //ここでのコードは暗号化されていません。
    }
 
    printf("VirtualProtect : %s\n\n",VirtualProtect(	/*←	仮想記憶の仕組みを無視してVirtualProtect関数を使ってはいけません。VirtualAllocとセットで使いましょう。*/
        unpacked_code,
        128,
        PAGE_EXECUTE_READWRITE,
        &d
        ) == NULL ? "[SUCCESS]" : "[ERROR]");
     
    return 0;
}
【さらに補足】
試してないですがVirtualProtectを静的領域に行えるかも知れません。出来てもウィルスと誤認されないかは自信ありません。
あとデータ実行防止 (DEP)と言う機能がXP SP2から追加されているらしいのでハードウェアが対応していると、それにも対処が必要です。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 00:06
by helloworld1853
>既に当初のものと違いISLeさん案に成っている気がしますが・・・。

最初からこの案でした。

>【さらに補足】
>試してないですがVirtualProtectを静的領域に行えるかも知れません。出来てもウィルスと誤認されないかは自信ありません。
>あとデータ実行防止 (DEP)と言う機能がXP SP2から追加されているらしいのでハードウェアが対応していると、それにも対処が必要です。


難しいですね。

では、たとえばgoto文を入れまくったり

意味のないfor文,if文を入れまくったりするのはどうでしょう。

文字通り難読化されそうですが・・・

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 00:13
by softya(ソフト屋)
helloworld1853 さんが書きました: 難しいですね。

では、たとえばgoto文を入れまくったり

意味のないfor文,if文を入れまくったりするのはどうでしょう。

文字通り難読化されそうですが・・・
リリースビルドすると無意味な処理は全て整理されてなくなります。
あとAPIをトラップされると、そこから辿られるのでごちゃごちゃやっても流れがバレます。
クラッカーはAPIのIN/OUTや関数のreturn処理の戻り値ぐらいしか注目しませんので。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 00:19
by helloworld1853
よい案はほかにありませんか。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 00:23
by softya(ソフト屋)
helloworld1853 さんが書きました:よい案はほかにありませんか。
少なくとも高度なクラッカーを相手にするなら複雑なことを勉強にするしかありません。
厨房クラッカー程度ならとISLeさんの案で十分ですが機械語のある程度の理解やVirtualAllocなど仮想記憶の理解は必要です。
それにプログラムの何処の部分を隠すのかで難易度が変わると思います(全部というのは無茶です)。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 00:28
by helloworld1853
たとえばAPI周辺の処理を隠すならば難易度は高いですか?

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 00:35
by softya(ソフト屋)
helloworld1853 さんが書きました:たとえばAPI周辺の処理を隠すならば難易度は高いですか?
私は耐タンパー性の専門家では無いのでなんとも言えませんが、APIのDLLViatulAllocしたメモリ上で実行したプログラムからLoadLibrary()で任意にロードすればかなり解析が困難になるとは思います。 ※これもLoadLibrary()から辿られそうな気がしてきた・・・。
「Win32API(C言語)編 第58章 LoadLibrary()によるDLLロード」
http://www.geocities.jp/ky_webid/win32c/058.html

まぁ、普通のプログラム側に戻る時に戻り値で見え見えの値を返してしまうと難読化の意味が無いんですけどね。

【補足】
今まで色々書いてきましたが、とりあえず難読化の目的がシリアルコード解析や試用期間の延長などのクラッキングを防ぐことなのか、プログラムの逆アセンブルによる解読の阻止なのか、内部に持つ暗号データを盗まれるの防ぐ限定的な難読化なのかで話が違ってきます。そこをはっきりさせてもらったほうが良いでしょう。
あと結構提示してもらったソースは技術的な問題を無視して書かれているので暗号化の前にデータ化したプログラム(関数?)を走らせられるか確認したほうが良いでしょう。
もうひとつ、技術的な問題を無視してこの話は語れないので自分出来る範囲に限定したほうが良いと思います。

【補足2】
次のような本を紹介しておきます。
「デバッガによるx86プログラム解析入門」や「クラッカー・プログラム大全」
あるいはタイトルがアレですが
「解析魔法少女美咲ちゃん マジカル・オープン」
中級レベルの対策でも、このぐらいは理解できないと対策できないと思いますので自分で出来ることをよく考えてみてください。

Re: c言語をアセンブルに変換する方法

Posted: 2012年6月14日(木) 17:31
by helloworld1853
あまり方向性が決まっていなく

技術的にもまだ未熟なので

「デバッガによるx86プログラム解析入門」

を熟読し、また出直したいです。

とりあえず今回で分かったことは
・難読化は思ったより難しい
・リリースビルドすると無意味な処理は全て整理されてなくなること(初めて知ったのは僕だけですか?)
・難読化はAPIが重要

大体の事が決まり、技術的にもだいぶ理解できるようになったら

また質問します。

皆様ありがとうございました。