11日目 ファイルアクセス

⛷☃️がすごく降ってましたね。

さいたま市の救急車はノーマルタイヤだったんですね。サイレン鳴らしてたのに徐行すぎて驚きました。

 

さて、本題に入りますが今日はファイルアクセスをやります、読み書きとかそこらへんです。

 

Cのファイルアクセスは大抵、ファイル記述子かファイルストリームを使うことになります。

ファイル記述子は低水準関数、

ファイルストリームは(低水準関数で構築された)高水準関数を使用します。

 

これはプログラミングしやすいor細かいとこまで弄れるかどっちを取るかということです。

 

今回はファイル記述子中心にやります。

 

ファイル記述子を使用する関数は

open(),close(),read(),write()の4つ

これらはエラーが発生すると-1を返す仕様です。

 

ファイルを読み書きするにはまず、オープン(open())します。

open()の引数はファイル名を指すポインタとアクセスモード指定のためのフラグです。(後後勉強します)

ファイル記述子というオープンしてるファイルを識別する固有の値(整数値)を返します。

このファイル記述子はオープンされてるファイルに対するポインタのように機能します。

 

ほかの関数の引数として使えます。

close()の引数はファイル記述子です。

またread(),write()の引数はファイル記述子、読み込み先や書き込み元のメモリ領域のポインタ、読み書きするバイト数です。

 

でまあ、ファイル記述子を使った簡易プログラムがこちら

f:id:simauma1203:20180124000254p:image

f:id:simauma1203:20180124000314j:image

tmp/notesというファイルの内容の末尾にargv[1]を付け足すものです。

確認しましたがうまく動いてます↓

f:id:simauma1203:20180124000340j:image

 

注目すべきは34行目です。

open()の第2、第3引数はフラグです。

これらのフラグははfcntl.hで定義されてます。

0_RDONLY 読み込み専用でオープン

0_WRONLY 書き込み専用でオープン

0_RDWR 読み書き両用でオープン

0_APPEND ファイルの末尾にデータを足す

0_TRUNC ファイルが既に存在していたら、ファイルの長さを0に切り詰める(上書き)

0_CREAT ファイルがなければ作成

といったフラグがあります。

これらは定数で論理和をとって兼用可能です

 

本ではここから延々とビット演算の説明ですが、一応わかっているつもりなので飛ばします。

 

内容は薄かったですが今回はここまでにします

次はファイルの権限についてやります。

おやすみなせ

 

 

 

ksnctf#3

#3Crawling Chaos

(https://ksnctf.sweetduet.info/problem/3)

 

ksnctfの3問目を解いて見たいと思います。

 

問題文がURLだったので、

とりあえず飛んで、ソースを見てみます

f:id:simauma1203:20180121162354j:image

こんなふうにスクリプトのとこ、よくわからない文字列がでてきます

にゃるこさんですね

わからなさ過ぎたので調べると、javascriptエンコードの一種でこれ正規表現をつかってるとか何とか。

このソースをまるまるダウンロードして12行目のjavascriptの行を丸々console.log()でくくります

 

それでchromeで見てみるとコンソールにユニコードの塊が出力されてました

 f:id:simauma1203:20180121162442j:image

returnの後が変換後のスクリプトっぽかったので、文字に変換します、

↓が変換後。

 f:id:simauma1203:20180121162456j:image

これは見やすそうな感じに改行しましたが、

jsは触ったことないので変かもしれません。

これ、よくわかりませんが入力された文字のチェックをしてますね(そりゃそう。

 

で、ここから逆にフラグを求めるプログラムを書きました↓

 f:id:simauma1203:20180121162507j:image

 

 

実行したらそのままフラグがでてきておわりです

 f:id:simauma1203:20180121162522j:image

 

むずかしかったです

結構時間かかった

 

 

ksnctf#2

調べたところksnctfという大規模な常設CTFを見つけたので少しずつ解いていこうと思います(解けない

 

初めてなので簡単そうな問題から解いていこうと思います

 

Easy cipher

↓問題文

EBG KVVV vf n fvzcyr yrggre fhofgvghgvba pvcure gung ercynprf n yrggre jvgu gur yrggre KVVV yrggref nsgre vg va gur nycunorg. EBG KVVV vf na rknzcyr bs gur Pnrfne pvcure, qrirybcrq va napvrag Ebzr. Synt vf SYNTFjmtkOWFNZdjkkNH. Vafreg na haqrefpber vzzrqvngryl nsgre SYNT.

 

 なんかこういうやつ見たこと有馬富士

ピリオドとスペースから平文が英語と仮定します。

となるとFLAGを文に含むはずなので

SYNT=FLAGとわかります。

あと見た感じn=a、gur=the、vf=isとかわかります。そんなこんなで冒頭がRot XIIIで始まっているのが分かるので、

文まるまるRot13で復号しする、

するとInsert an underscore、、ってあるのでその通りにFlagに手を加えて終わり。

10日目 メモリのセグメント化その6

おはようございます。さむいですね

メモリセグメントの勉強がこれでおわるので頑張ります。

 

今回はヒープの使用についてやります。

ヒープにメモリを確保するためにはmalloc()を使います。voidへのポインタ(先頭のポインタ)を返します。

これで確保したメモリはfree()で解放できます。

引数には解放するメモリの先頭アドレスを与えれます。

 

以下のプログラムでヒープの使用方法について見ていきます(長かったので切れてます許してw)

f:id:simauma1203:20180120183027j:image

f:id:simauma1203:20180120183034j:image

 

ヒープからargv[1]バイトを割り当て、char_ptrに代入。(デフォルトで50バイト)

ヒープから12バイト割り当て、int_ptrに代入。

char_ptrが指すメモリを解放。

ヒープから15バイト割り当て、char_ptrに代入。

int_ptrが指すメモリを解放。

char_ptrが指すメモリを解放。

という感じです。

 

コマンドライン引数なしの実行結果

 

f:id:simauma1203:20180120183104j:image

メモリがどんどん高位に割り当てられてますね。最初に割り当てた50バイト分は解放して後に再利用されてません。

 

でそれと比較するために引数ありでやってみます

 

コマンドライン引数に200を入れた場合

 

f:id:simauma1203:20180120183113j:image 

はい。この通り最初に200バイト確保して解放したメモリが再利用されてます。

因みに100だと再利用されませんでした。

200以上は再利用されました。

この基準はなんなんでしょう、ういーん。

 

要するに、巨大なメモリを割り当てて解放した後にメモリを割当てると解放したところが再利用されるということです。

 

 

次にエラー判定付きのmalloc()関数の紹介です。

これプログラム。

 

 

はい、さっきのプログラムと殆ど変わりません。

が、malloc()のエラー処理、一々書くのめんどいよね?

ということで関数にして楽に書けるようにしただけです

 

ちなみにプロトタイプ宣言と言うのは定義関数を呼び出す行より後ろの行目 に書いていい代わりに、呼び出す前の行で関数名と引数と返り値くらいは宣言しておきましょうというものです。

詳しいことは分かりませんがコンパイラのためらしいです。

 

これでメモリのセグメント化は終わりです。

長かった、、

 

次はファイルアクセスについてやります。

おやすみなせ✋

 

 

9日目 メモリのセグメント化その5

おはようございます。

 今回はヒープについて(も)やりたいと思います。

ヒープというのは細かくは分かりませんが、

プログラムで制御できるメモリのセグメントらしいです。

 

C言語だとmalloc()というメモリ割り当て関数がありますね。使ったことないけどよく目にします。

ヒープセグメントのメモリは使用に先立ってこれを使う必要があります。

普通はポインタを使ってヒープ上のメモリにアクセスします。

 

今回は↓のプログラムを使っていきます。

f:id:simauma1203:20180119235532j:image 

 

変数は変数名のとおりです。

global(大域),static(静的),stack(スタック),initialized(初期化された)みたいな感じです。

18行目の(int*)malloc(4)ですが、これはヒープから4バイト割り当てるための文です。

malloc()はvoidのポインタを返すので整数のポインタにキャストしてます。

 

以下が実行結果です

 f:id:simauma1203:20180119235527j:image

 

ここでのポイントは初期化を行ってない変数、

static_varとglobal_varがbssセグメントに確保されるところです。

これは初期化をしてるglobal_initialized_var、static_initialized_varと比べれば確認できます。

(ちなみにbssセグメントは初期化を行ってない変数が確保されるところ、データセグメントは初期化を行った変数が確保されるところ)

 

bssセグメントはデータセグメントの直下にあるのでbssセグメントの方が少しだけ高位になってますね😀

 

heap_var_ptrはヒープを指すポインタです。

ヒープセグメントに確保されています。

ヒープセグメントはbssセグメントの直下にあります。

 

ちなみにヒープセグメントは動的なメモリ割り当てのためにサイズが非固定です。

 

あと局所変数stack_var(function内)とstack_var(main内)はスタックセグメントにあるのでそこそこ大きいアドレス値です。

 スタックセグメントはメモリの高位から低位に成長するのに対して、ヒープセグメントは低位から高位に成長します。

 

 今回は短いですがここまでです。

継続は力なりということで、これからも少しずつやっていきます。

あと観てくれた方ありがとうございます。

 

 

 

malloc()使ったことなかったのでメモ

http://www.wakhok.ac.jp/~kanayama/C/03/node152.html

わかりやすいサイト↑

char *s;

s=malloc(sizeof(char)*20);

こんな風にしてcharのサイズ*20分のメモリを確保できる

malloc()ってvoidのポインタ返すからキャストしなきゃいけないはずだけど、sizeof使ってるから使ってるからキャスト不要ということでいいんですかね(-_-) ←有識者の方ご教授お願いします

1/20/0:30追記

voidへのポインタは他の方との互換性があって相互代入可能ということを忘れてました。

教えてくださったMIKIさん(@mikiconfigさん)ありがとうございました

8日目 メモリのセグメント化 その4

今日はvanellopeさん(@vane11opeさん)に沢山教えていただきました

ありがとうございます🙌

 

まず、radare2っていうツールがあるらしいです。

apt-get install radare2ってやって

取り敢えずインストールしてみました。

カラフルでとても見やすいです。

操作も楽しい。

 

これで前回できなかったスタックの成長とかを観察していきたいと思います。

 

r2 -d ./a.out

これでデバッガで起動できました。

dcu main

でmain関数まで実行できます

V

ってやるとvisual modeというモードになるらしいです。とりあえず

p

を押します。するとrip周辺の命令が表示されました。hjklで移動できるみたいですね。

ここで訳分からん処理のとこに来てしまったら

戻って、

dr

これでripの値を確認して

<ripの値>

これだけ入力すれば見てる対象のメモリを移動できます(日本語でおk

 

次にripよりちょっと小さいアドレスにtest_functionので0x40055aの直前まで動かしてみます

 f:id:simauma1203:20180117225623j:image

 

こんな風になりました。

ripの位置が移動してるのが一目瞭然ですね。

 

それに合わせてスタックも確認してみます。

ripの直前の4行で引数をrbp-0xNNに渡しているので、rbp-0x34辺りをみてみます。

 

f:id:simauma1203:20180117225525j:image

はい。ちゃんと引数がありました。

よかったあ

 

次に戻り値も確認します。

x64-86ではrbp+0x08にあるらしいので

そのアドレスを見てみます。

因みにrbp+0x08=0x7ffcda7e6188

なので、戻りアドレスは0x004005a8のはずです。

これはtest_func関数を終了した直後の命令のアドレスとちゃんと一致していました。

f:id:simauma1203:20180117225931j:image 

 

f:id:simauma1203:20180117225939j:image 

 

 なんか、うまく行きました。

 操作も適当でよくわからなかったので、慣れていこうと思います。

 

 

 

参考にさせてもらったサイト

ヴァネろぴさんのところ

http://vane11ope.hatenablog.com/entry/2017/12/25/104653

7日目 メモリのセグメント化その3

前回の続き

 

GDBでスタックフレームが作られる様子を確認してみましょう

 f:id:simauma1203:20180116000536j:image

こんな風に関数の行と関数名でbreakするように設定すると、最初のブレークポイントが引数のプッシュ直前になって、次のブレークポイントが関数プロローグの直後になるらしい

 f:id:simauma1203:20180116230953j:image

x/5i $ripでそれが確認できる。

お引数を渡す直前なってますね👏

 

あとrip,rbp,rspの確認も。

復習ですが、これらはそれぞれ命令のアドレス、スタックフレームの局所変数のアドレス、スタックの一番上を指すレジスタです。

 

f:id:simauma1203:20180116000606j:image 

contつって進める

2つ目のブレークポイントに来たので関数プロローグが終わった直後ですね

ここでまたレジスタ確認。

rspの値もrbpの値も減ってますね。

スタックが積まれたからですね🎉

(スタックは低位アドレスに成長する為。)

 

 f:id:simauma1203:20180116000708j:image

 

ここでtest_funcを逆アセンブル

+20のfs:0x28って何だろ

わからん、+33まで何してるかわからん、、

とまあ、ここは飛ばしましょう!w

 f:id:simauma1203:20180116000724j:image

 

とまあ、取り敢えずflagとbuffer[0]のアドレスを指定してprint。

そしてx/16xw $rspってやる

 

すると上段が引数であることに気づきます

 

あれ、本の言ってることと違うなあ

高位アドレスにスタック伸びてるようにみえる。

 http://itpro.nikkeibp.co.jp/article/OPINION/20051018/222943/?ST=spleaf

このサイト見た感じこれ仕様な気がしますね

 

知識ある方ご教授下さい(-_-)