Friday, July 6, 2012

高度なShellcodingテクニック - Darawkによって



はじめに

本論文では、基本的なshellcoding技術の知識を前提とx86アセンブリ、私はこの論文で焼き直し、これらを行うことができません。私はあなたが小さく、優れたシェルコードを書くことができます私が拾っていることをあまり知られていshellcoding技術のいくつかを教えることを願っています。私は、DIV命令を使用するものを除き、これらのテクニックのいずれかを発明したと主張しません。



MULの多様性

この手法はもともとdarkircop.netのソルボによって開発されました。 MUL命令は、表面には、世俗的に見えるかもしれません、それは明白な目的です。ただし、シェルコードを縮小するのは困難な課題に直面したとき、それは非常に有用であることを証明しています。 MUL命令自体の最初のいくつかの背景情報を表示します。

MULは2つの整数の符号なし乗算を行います。これは、オペランドを1つだけ取る他のは、暗黙的に%eaxレジスタによって指定されます。したがって、共通のMUL命令は、次のようになります。

$ 0x0aという、%eaxにしMOVL
MUL $ 0x0aという

これは、この場合には* 10であろうMULのオペランドで%eaxに格納された値を乗算します。 EAX:結果は、暗黙のうちにEDXに格納されています。それはおそらく(これはいくつかのケースに格納されている方法浮動小数点もあり、興味深い追記など)を単一のレジスタの容量を超えて、以前の値よりもかなり大きくなる可能性を秘めているため、結果は、2つのレジスタのスパンで格納されている。

だから、今までに重要な質問をしています。シェルコードを書くときにどのように我々の利点にこれらの属性を使用することができますか?それは非常に一般的な命令であるので、まあ、の第二のために考えさせ、命令は、したがって、オペランドを1つだけ取る、それは我々の最終的なシェルコードの2バイトだけを生成します。それは、%eaxレジスタに格納されている値によってそれに渡されたものを乗算し、%EDXと%eaxレジスタの両方に値を格納し、完全に格納するために、かかわらず、それがそうする必要があるかどうかの、両方のレジスタの内容を上書きする乗算の結果。の第二のために私たちの数学の帽子に入れ、これを考えてみましょう、何が0で乗算の唯一​​の可能な結果ですか?答えは、あなたが推測している可能性があるので、0になります。私はそれがいくつかのサンプルコードのための時間だと思うので、ここでは、次のとおりです。

xorl%のECX、ECX%
MUL%のECX

このシェルコードは何をやっている?まあ、それは0%ECXは、XOR命令を使用して、登録外なので、我々は今、その%のECXが0である知っている。 EAX:それは我々だけで学んだようにMUL%のECXは、EDXでこの乗算の結果を格納するための収入、それは%eaxにの値によってオペランドの乗算、及びません。したがって、関係なく%eaxレジスタの以前の内容を、%eaxには0でなければなりません。しかし、すべてではありませんつまり、%EDXも今0'dされているため、オーバーフローが発生しないにもかかわらず、それはまだ%eaxに符号ビット(最も左のビット)で%EDXレジスタを上書きします。他の方法(私が知っている)によってそれは少なくとも6つを取ったであろう一方で、このテクニックを使用して、我々は唯一の3バイトの3つのレジスタをゼロにすることができます。


DIV命令

div要素はそれだけで一つのオペランドを取り、暗黙のうちに%eaxにの値によってオペランドを分けるという点で、MULと非常に似ています。また、のようなMULは、%eaxに除算の結果が格納されています。再び、我々はこの命令を活用できる​​方法を見つけ出すために我々の脳の数学的側面が必要になります。しかし、最初のは、通常、%eaxレジスタに格納されている内容について考えてみましょう。 %eaxレジスタは、関数、および/またはシステムコールの戻り値を保持します。 shellcodingで使用されているほとんどのシステムコールは-1(失敗)またはいくつかの種類の正の値を返しますが、まれにしか彼らは、0(それが発生しても)返しません。我々はシステムコールが実行された後、%eaxには、非ゼロ値を持つことになり、命令divl%eaxは%eaxにの結果をそれ自体で%eaxにを分割し、格納されることがわかっている場合はそう、我々は実行すると言うことができますシステムコールの後にdivl%eaxに命令が%eaxに値1を配置します。だから...これはどのようにshellcodingに適用されるでしょうか?さて、彼らは、%eaxにはために使用されている別の重要なことであり、それはあなたが$ 0x80をint型にコールしたい特定のシステムコールを渡すことです。それだけで値1に対応するシステムコールがexit()であることを起こる。今例:

      
xorl%ebxに、%ebxに
MUL%ebxに
%EDXを押してください
PUSHL $ 0x3268732f
PUSHL $ 0x6e69622f
MOV%のesp、%ebxに
%EDXを押してください
%ebxにを押してください
MOV%のesp、%のECX
movb $は0xB、%アル#はexecve()システムコール、障害が発生しない限り、それは-1を返し、その場合には、まったく返されません
$ 0x80をint型

divl%eaxに#-1 / -1 = 1
$ 0x80をint型

今、我々はそれが5バイトだったように前に3バイトのexit関数を持っています。しかし、漁獲量はどのようなシステムコールが0を返す場合は、何ですか?よく株式会社%eaxにのように、あなたはいろいろなことを行うことができ、発生する可能性があった奇妙な状況、12月の%eaxにではなく、%eaxに非ゼロになります%eaxには何インチ一部の人々は、あなたのコードが正常かどうか、それが終了にかかわらず実行されますので、その出口のは、シェルコードに重要ではありませんと言う。彼らはあまりにも正しい、あなたが本当にどこかであなたのシェルコードに合うように3バイトを保存する必要がある場合は、exit()を維持する価値はありません。ただし、コードが完了しない場合、それはかなり奇妙なエラーである可能性が最も高いSIG ILL(不正な命令)を生成し、あなたの最後の命令の後にあったものを実行しようとすると、システムによって記録されます。だから、exit()は単にそれが失敗したり、すべてのログを拭くことができない場合であっても、あなたの存在は、少なくともこの部分が明確になるように、あなたの攻撃にステルスの余分なレイヤを追加します。



リールのパワーロックを解除する

レアル命令は、それは非常に有用であるにもかかわらず、シェルコードにしばしば無視命令です。シェルコードのこの短い作品を検討してください。

xorl%のECX、ECX%
レアルは0x10(%ECX)、%eaxに

これは、eaxに値17をロードして、eaxレジスタの余分なビットをすべてクリアします。レアル命令はそれdesitinationのオペランドにlong型の変数をロードするために発生します。それは通常の使用では、このため、ある種のポインタを作成し、レジスタに変数のアドレスをロードします。 ECXは、0'd、0 17 = 17であるのでしかし、我々は、実際のアドレスの任意の種類の代わりに、eaxレジスタに値17をロードします。通常のシェルコードでは、同じことを達成するために、このような何かをするでしょう:

xorl%eaxに、%eaxに
movb $ 0x10を、%eaxに

私はあなたが言って聞くことができますが、そのシェルコードは、レアルのものより短いバイトであり、あなたは全く正しいです。しかし、実際のシェルコードでは、すでにECX(または他の任意のレジスタ)のようなレジスタを0にする必要がありますので、レアルシェルコードでxorl命令はカウントされません。ここでの例は次のとおりです。

xorl%eaxに、%eaxに
xorl%ebxに、%ebxに
movb $ 0x17、%のアル
$ 0x80をint型
      
xorl%ebxに、%ebxに
レアル0x17(%ebxに)、%アル
$ 0x80をint型

他の8でそれを行いながら、これらのシェルコードのコールのsetuid(0)の両方が、一つは7バイトでそれを行います。再び、私はあなたが言って聞くだけの1バイトは、それがそれほどの差がありません、あなたが正しいとしていること、ここに大きな違いを(コンテスト= P放尿シェルコード·サイズのを除いて)ことはありませんしかし、多くの関数呼び出しを持っていると頻繁にこのようなことを行う必要がはるかに大きいシェルコードに適用されるとき、それはスペースのかなりを保存することができます。



結論

私はあなたのすべてが何かを学んだ願って、と小さく、優れたシェルコードを作成するために外出すると、あなたの知識を適用します。あなたはレアル技術を発明した人知っていれば、教えてください、私は彼/彼女を信用します。