zoomzoomzoom

解決方法の共有に主眼を置くブログ・他雑談

大熱血!アセンブラ入門part4メモ

part2の延長の章?という印象。様々なCPUのアセンブラを読む。

 

知っていると役に立つアセンブラ業界用語

・インライン展開:関数の中で他の関数の呼び出しをしている場合に、その「他の関数」の内容を、呼び出し元の関数の内容として埋め込んでしまうこと。呼び出し処理がいらなくなる。

・積和演算:MAC演算とも呼ばれる。積の和を求める演算の事。

・飽和演算:上限で止める演算の事。

・ベクトル演算:SIMD命令とも呼ばれる。4つの加算をへ並列で一気に行う演算。この演算をするCPUでは演算だけでなくロード/ストアも並列に行う。

プログラマ:内蔵フラッシュROMへの書き込み器のこと。

・rot:ローテート命令。ビットシフトすることではみ出したビット部分を、反対側に戻す処理を行う。

FPGAField Programmable Gate Array。ソフトウェアCPU。内部回路をソフトウェア的に組み替え可能なデバイスの事。

・ISA:Instruction Set Architecture。命令セットアーキテクチャ。利用できる命令(機械語コード)、レジスタの数、種類、割り込み方式、例外処理方式、メモリ領域の方式などを定めたもの。ISAが同じなら異なるCPU上でも機械語コードを動作させることが出来る。

・ゼロページ:アドレスが0x0000-0x00ffの256バイトの領域のみ、アドレス指定を1バイトとした小さいサイズの命令で読み書きできるというもの。

 

 

これからのアセンブラリーディングの際、覚えておくべき情報:

gcc -gオプションを利用すると、実行ファイルにデバッグ情報が付加される。

コンパイラの過剰な最適化はデバッグ時のアセンブラリーディングの際に、障害となる。(インライン処理になってしまい、ブレークが適切にできない等。)

・最適化されているソースのデバッグ時は、表示されている引数や自動変数の値を信用することはできない。

・関数末尾にjmp命令=呼び出し先の関数をそのまま返す処理だな、という推測が出来る。

・命令によっては、複数の処理を1命令で行ってしまうものもある。例えば、レジスタ復旧、スタックフレーム解放、戻り先アドレス取り出し、そこへジャンプまでを1命令で行う場合がある。

・実際のプログラムでは、演算命令は少ない。反対にデータ転送命令が多い。

・セミコロンの行(コメント行)を省いてみると読みやすくなる。

・旧来のマイコンでは、よく使われる命令を1バイトにして、機械語コードのサイズを節約していた。

アセンブラを理解するために、CPUのエミュのソースコードを読むという方法もある。

windowsの上のvmwareの上のvirtualboxのゲストOSにsshログインした話

virtualboxの上に乗せるOSは32bitしか選択肢がありませんでした。

仮想化機能がvmware上で有効になっていないために64bitを選択できなくなっていると考えております。。。解決策をご存知の方教えてくださいまし。

 

構成:

ホストOS(vmware上、"クライアント側"):Ubuntu16.04_64bit

ゲストOS(vmware上のvirtualhost上、"ホスト側"):Ubuntu16.04_32bit

virtualboxのネットワーク設定:ブリッジ接続

 

>||

#ゲスト側。deb関連のコメントを外します

vi  /etc/apt/sources.list

 

#openssh-server導入

sudo apt-get update

sudo apt-get install openssh-server

 

#PasswordAuthenticationをyesにします。

vi /etc/ssh/sshd_config

 

#ゲスト側でIPアドレスを確認。inet addrの値を確認。

ifconfig 

 

#クライアント側からパスワード接続(単なる接続確認)

ssh 接続先ホストユーザ名@接続先IPv4アドレス

exit

 

 

#パスワード認証無しで次からログインするための鍵作成から渡しまでのコマンド↓ 

#クライアント側

ssh-keygen

#Enter連打して作成完了。homeディレクトリの下に作成される。

scp 作成したキー 接続先ホストユーザ名@接続先IPv4アドレス:~/

 

#ホスト側

cd ~/

mkdir .ssh

chmod 700 .ssh

cat id_rsa.pub >> ./ssh/authorized_keys

chmod 600 ./ssh/authorized_keys

 

#クライアント側

ssh 接続先ホストユーザ名@接続先IPv4アドレス

||<

 

"初期設定"って毎日やるようなものでもないから、都度調べながらという状態になり、時間がかかってしまう。要は習熟度を高めづらいってことなんだが、なんとかならんものか。

CTF問題集問2 メモ

問題に対してのアプローチ方法をまとめた。

「事象」に対して「正しい反応とその結果」という形でまとめてみる。

====こんな感じ====

(事象を説明)→(正しい反応と結果)

改行

(事象を説明)→(正しい反応と結果)

改行

================

 

zipファイルが存在→zipファイルを解凍してls -la

ファイルが存在→「ファイルなのでとりあえず」fileコマンドで分析。実行形式を見ると32ビット実行ファイル。

・実行ファイルが存在→実行権限つけて実行してみる。usageが見えた。

・usageがわかっている→とりあえず実行してみる。flagって見えたけど、何も見えない。

・usageがわかっている→ltraceコマンドでちょっと詳しく実行してみる。実行される関数が丸見え。

・実行される関数が丸見え→じっくり動作を確認する。利用されている関数の種類、引数の使い方、引数がアドレスのどこにマッピングされているのか、が判明。

・ある程度ファイルの動作がわかった→1命令ずつ詳しくデバッグ実行していく。そういうことができる道具gdb-padaを使う。関数呼び出し部分、条件分岐、文字列あたりの内容を確認する。関数呼び出しの後のeaxレジスタの値(戻り値)はその関数が利用するために確保したメモリの先頭アドレスという前提から、calloc関数によって確保したメモリの先頭アドレスをチェックする。先頭アドレスを見つけた。

gdb-pedaについてまとめてくれているブログ

CTFのための gdb/gdb-peda 頻出コマンドのメモ - teriyaki note

・先頭アドレスが判明→そのアドレスを利用している箇所を探す。関数が利用しているだろう(atoi関数)

・atoi関数が関係している→atoiの中身を分析する。check関数が利用されている。

・check関数が利用されていることが判明→check関数を分析する。sum関数が利用されていることが判明

・sum関数が利用されていることが判明→sum関数を分析する。動作がわかった。

・sum関数の動作条件を理解→動作条件を満たす数値を創りだす。ライブラリを使う(z3)。数値を創りだした。

・数値を入れてみて動作させる→フラグをゲットした。

・フラグをゲットした→ltraceで数値をいれてみて正常終了したかどうかを確認する。正常終了した。これが正解!

 

用語:

充足問題:与えられた制約(条件)を満たす解が存在する問題のこと。

 

この問題でわかったこれからしなければならないこと:

よく使われるライブラリ関数に精通すること(calloc,malloc,atoi,exit等)

gdb,gdb-pedaの基本操作(全部知る必要はないかな。まずは基本だけ。)

ツールを手足のように使えるように集中的に時間をかける。

 

その他所感:

デバッガの最低限の操作は、1命令ずつの実行と、特定のアドレスに飛ぶ動作、特定の関数に飛ぶ動作(関数内部をディスアセンブルして表示)。

それらをした時の、スタックとレジスタの内容の観察をする。

大熱血!アセンブラ入門part3メモ

アセンブラ出力環境を構築するためのpart。

 

アセンブラ出力までの流れ。

まず、高級言語のコード→オブジェクトコード(コンパイル

次に、オブジェクトコード→実行ファイル(リンク)←一般のmakeはここまで行う。

最後に、実行ファイル→アセンブラ(逆アセンブル)←大熱血提供のmakeはここまで行う。

高級言語のコードからいきなりアセンブラを作り出すこともできるし、オブジェクトコードからobjdumpで逆アセンブルしてアセンブラを作り出すこともできるが、一旦実行ファイルを作成した後逆アセンブルしたほうが、機械語の完全なバイトコードが手に入るとのこと。

 

環境構築:

「クロスコンパイル環境を準備するのはバージョン合わせがあって大変だから全部環境用意しておいたよ。仮想マシンで楽しんでね!」との著者の有難き心意気に感謝してVMで動作させることに。HDDの容量食うけど、環境構築で困るよりいい。この本のサポートサイトから仮想マシンをゲットしてVMで起動。その際、エラーメッセージが出たが、気にせずretryを押すと無事起動できた。

 

VMの使い方:

cross/sample ココに逆アセンブルコードが欲しいC言語のファイルを入れてmakeで実行

cross/exec コンパイル後、gdbでシミュレーションしたい時に利用。make→make runで実行。

 

その他:

環境構築のみ行ったので、APIを利用しないで(自分で対応するアセンブラを書いて)Hello Worldを出力させてみよう、という企画を楽しんでいない。機をみてトライしたい。

大熱血!アセンブラ入門part2メモ

このpartのエッセンスだと感じたことをメモ。

なお、part2はpart1で培ったアセンブラの読み方を使ってとにかく読み漁ってみようみたいなpartになっていました。アセンブラを適切なコーチングのもとに読む練習をしたいと思ってこの書籍を購入した私にとっては、待っていました!というようなpartでした。

 

・下記のようなアセンブラの業界用語を知っていると幸せになれる。

レジスタウィンドウ:仮想的にレジスタ層のようなものを作っておき、関数呼び出しの際に自動的にその層を切り替える。メリットはレジスタの保存の必要性がないこと。つまりレジスタの退避のための命令をせずに済むということ。

PC:Program Counterのこと。現在実行中のアドレスを保持するレジスタ

PC相対:ディスプレースメント付きレジスタ間接の反対語?アドレス指定の方法として、"PCの"アドレス値に即値を足すという方法を採用すること。

ディスプレースメント付きレジスタ間接:PC相対の反対語?アドレス指定の方法として、"レジスタの"アドレス値に即値を足すという方法を採用すること。

PIC:Position Independent Codeの略。共有ライブラリが仮想アドレス上のどのアドレスにマッピングされても動作可能なようになっている機械語のこと。

機械語:CPUが処理可能な情報。だいたい、バイナリ値のことを指す。

VLIW:数命令を並列に同時実行する仕組み。イメージ的には、まとめてドカーンという感じ。

メモリマップドI/O:I/Oレジスタをメモリアドレス上にマッピングして、ロードストア命令によって読み書きする。

プリデクリメント:フルスタックの場合に、スタックポインタを減算してからそこに値を格納すること。

フルスタック:使用中領域の終端をスタックポインタが表すこと。要は、スタックフレーム(関数の内容等)がぎっしり詰まっているメモリの先端アドレスをスタックポインタが示していること。

エンプティスタック:フルスタックとは違って、未使用領域のアドレスを指定すること。確保していない領域にいきなり値を設定した後に、スタックポインタを減算する。(ポストデクリメント)

ダイレクトアドレッシング:低位のアドレスをアドレス直接指定でアクセスすることでまるで汎用レジスタのように扱うこと。

命令の直交性:全ての命令で全てのオペランドを扱えるようにすること。CISCの思想。

パディング:決まったバイト列で空いてしまったバイト列を埋めること。」

アウトオブオーダー実行:OoOと略される。命令列の順番をCPUが適切に入れ替えながら実行すること。

 

・ディスプレースメントを利用しないでアドレスを取得する=加算処理でアドレス指定する

・引数を割り当てられるレジスタは暗記しておいたほうが読みやすい。

・戻り値をとるレジスタは暗記しておいたほうが読みやすい。

・中途半端な即値を表現するために、0付近の値を反転させて表現することがある。

例:0x11223344を0xffeeddccをビット反転させて表現する。

・関数呼び出しの際に、スタックポインタに数字"足していたら"上方伸長。スタックポインタから数字を"引いていたら"下方伸長。

・全ての処理に共通するような処理はわからなかったら「おまじないのようなものだろう」で読み飛ばす。

・PCの値を取得したい時に、次の命令に対して関数コールしてしまう常套手段がある。アセンブラ中に直後の命令を関数コールしていたらこの常套手段を利用している。

・(言われてみれば当たり前だが)or演算は加算のような繰り上がりが存在しない。特定のビット列にのみ演算をしたい場合には有効な手段。

・「多バイト値の演算は、値は付近において、PC相対でその値をロードして行う」というやり方を頭にいれておく。しかしPC相対でロードするにしても範囲指定を行うビットは限定されているので、そんなに遠くに置くことはできない。(ロードする値は、ロードしようとする命令の近くにあるということ。また範囲指定を行うビット列がいくつかを予め知っておけば最悪虱潰しにロード値を探すことができるということ)

 

part2を経て、最低限どのような意識で読めばいいのかを理解できる。しかし本気で詳細に理解したかったら、ある程度頭に入れておくべき情報がある。私が現時点で感じているのは下記。CTFではIntelアーキテクチャがでるのかな?

・引数レジスタ

・戻り値レジスタ

・3オペランドか2オペランド

・演算方向(→か←か)

・よく使われるオペコード

・上方伸長か下方伸長か

 

次はpart3。アセンブラ出力環境を構築する、というpartらしいので、詰まったポイントだけ記述する予定。

PowerShellのペイロードによく使われているオプションのお勉強

PowerShellを利用したペイロードによく使われているオプションの意味のメモ。

参考にさせていただいた記事:

EncodedCommandによるPowerShell攻撃を暴く - Palo Alto Networks

 

-NoP ユーザプロファイルを使用しないで起動する

-sta STAモードを利用する

-NonI ユーザー向けのインタラクティブ プロンプトの作成を阻止

-W Hidden コードを実行する際のPowerShellによるウィンドウの表示を阻止

$任意の変数名 = New-Object System.Net.WebClient ファイルをダウンロードするためのWebClientオブジェクトを生成

DownloadString("任意の情報ソースURI") URIから文字列を取得

 

ついでに:

PowerShell でコンピューターのハード情報を取得する

 

その他用語:

powershell empireとは?

https://null-byte.wonderhowto.com/how-to/use-powershell-empire-getting-started-with-post-exploitation-windows-hosts-0178664/

 

この記事を書こうと思ったきっかけ:

SensePost | Macro-less code exec in msword

 

 

WordやExcelすらも開いてはいけない世の中なのか。

大熱血!アセンブラ入門 Part1メモ

大熱血! アセンブラ入門|書籍情報|秀和システム を購入。

理由:正しいサポート付きでアセンブラを読む練習を積みたかったから。

 

本の序盤、「はじめに」からも学べることがあるとても良い本。

 

アセンブラを学習する上で参考になったこと、読む上で参考になったことを以下にメモ。

 

アセンブラ学習には、検体コードとコンパイラと逆コンパイラの3つが最低限必要

バイナリエディタも必要。 

 

アセンブラを読むときに失敗する一番の原因は、とにかく「きちんと読もうとすること」。

・「調べる」のではなく、「推理」「推測」をすること。

・一字一句解析していこうとすると、難しいですしつまらないです。「目的」を意識して読むことが大切です。

・大切なのは「処理の目的」を意識すること。一字一句正確に解読するのはその後の話。

→しかしこのためには、推理をする対象であるアセンブリ前の高級コードの存在が必須?

 

コンパイラ機械的に生成するアセンブラにはパターンがある。

1スタック確保

2スタックへのレジスタの退避や自動変数生成

3関数終端での戻り値準備とスタックからのレジスタ復旧処理

→ブロックとして処理を捉える

※自動変数:関数中で利用されるローカル変数のこと。 

 

・オペコードはバイト列の先頭にあることが多いが、先頭と終端に分かれていたり、はたまた中央に寄っていたりと個性的。

アセンブラの推理推測は類似処理の比較で行うが、その際には、16進だけでなく2進表現も比較してみると幸せになれるかもしれない。

 

・「アドレス」というのはメモリのお話。他方「オフセット」というのは実行ファイルの中でのあるポイントを先頭アドレスとした場合のその先頭からの距離の話。

 

アセンブラのオペコードのアルファベットに敏感になると、それだけで意味が推測できるかもしれない。

例:

w→word

h→half

s→short

l→long

b→byte

 

他のアセンブラ業界用語も覚えておくと読みやすくなる。

例:

pc→program counter(実行アドレスを格納)

lr→link register(関数からの戻り先アドレスを格納)

スタックポインタ:メモリ領域のどこまでを使用しているかを表すレジスタ

スタックフレーム:スタック領域の占有領域の区切りの単位のようなもの?

branch→条件分岐によるアドレス移動

jump→条件分岐によるアドレス移動

 

・スタックポインタの利用して自動変数を利用する時の手順:まず大きく下方伸長してスタック領域を確保する。次に下方伸長した位置から下方伸長開始時の位置まで戻って行くかのように順次自動変数に代入していく。

 

・長い処理を見るときのコツは対となる処理を見つけること。だいたいその関数の最初と最後に集まっている。

 

 

 

 

CTFとかでも絶対出てくるバイナリ関連の問題ですが、アセンブラ読解のお作法は最低限身に着けておかないとダメだなと、改めて思いました。次は2章。