Explore "Full-Stack" in depth!

情報系の専門学校で、今は機械学習に的を絞って学習中。プログラミングを趣味でやりつつ、IT系のあらゆる知識と技術を身に付けるべく奮闘中。

ELF64バイナリについてできるだけまとめる[随時更新]

目次

  • 目次
  • 概要
  • ELFとは?速習
  • セクション
    • セクションヘッダ
      • sh_name
      • sh_type
      • sh_flags
      • sh_addr
      • sh_link,sh_info
      • sh_entsize
    • NULL Section
    • .interp
    • .text
    • .data
    • .rodata
    • .bss
    • .comment
    • .dynsym
    • .dynstr
    • .rela.dyn
    • .rela.plt
    • .init
    • .fini
    • .init_array
    • .fini_array
    • .eh_frame_hdr
    • .eh_frame
    • .symtab
    • .strtab
    • .shstrtab
  • セグメント
    • セグメントヘッダ(Program Header)
    • LOAD
    • INTERP
    • DYNAMIC
    • NOTE
    • GNU_EH_FRAME
    • GNU_STACK
    • GNU_RELEO
  • ELFヘッダ

概要

ネイティブコンパイラを実装する上で、
ELFバイナリの知識が必要なのは最早言うまでもありません。

ここでは ELF64バイナリを対象に、
今ある自身の知識を体系的にまとめておくことにします。

以下の環境で検証しています。

f:id:orangebladdy:20190530112001j:plain

なおこの記事は「保存版」であり、
随時更新していくものとします

いずれ自作リンケージエディタ、ELFローダを実装した際には、
より深い知識がついて内容が更新されると思います。

続きを読む

オブジェクトファイルのシンボルテーブルを最低限理解する。

目次

  • 目次
  • 概要
    • 対象読者
  • 本題
    • ELFフォーマット復習
  • シンボルテーブル
    • シンボル名 name
    • シンボルの情報を格納する info
      • ST_BIND
      • ST_TYPE
    • シンボルの可視性 Other
    • シンボルの実体 Value
  • 総評

概要

お久しぶりです。
最近やりたい事が沢山あってブログをかけずにいましたが、

に述べている通りです。

今日はELFバイナリに埋め込まれるシンボルテーブルについて軽く解説しようと思います。
自作コンパイラとかやってる人には ほぼ必須の知識ですし、
バイナリ解析( Exploitation勢含む)が好きな人には楽しいお話だと思います。

今回の記事を作成する上で、

docs.oracle.com

こちらのサイトを参考にしました。
ご存知Oracle社のドキュメントなので安心出来ますね。

解説中に登場するソースコードは基本的にGolangで記述されています。
対応する構造体等は /usr/include/elf.h に記載されているので参考にしてください。

対象読者

  • バイナリ解析大好きな人
    • でも触りはじめたばかりであまり良くわからない人
  • ネイティブコンパイラの自作やってる人
    • アセンブリコードの生成だけではなく機械語まで吐き出したい人
    • 正直 この方面の人の為の記事
続きを読む

C言語の文字列はどこに?-ELFバイナリに見る実行プログラムの挙動-

目次

  • 目次
  • 概要
  • .dataに格納される文字列
    • .dataセクションとは
  • .rodataに書き込まれる文字列
  • x64命令セット、movabs
  • おまけ:mallocによるヒープ領域のアロケート
  • 総評

概要

※注意!

Twitterでもご指摘があったように、
本記事はC言語の習熟度が低い人間
いろいろ試行錯誤しながらまとめたものになります。

あくまで勉強の一環として
作成した記事であるという事を前提に考えていただければと思います。

C言語で文字列の扱いにこまるという方は多いです。
私もコードを書いていてよくSIGSEGVで落ちることがあります。
それは単純にC言語に慣れていないだけなんですが…。

今回は自身が言語処理系の勉強をしているだけあって、
C言語は文字列をどのように管理しているか?という疑問を持ちました。

様々なコードを書きながら、
ELFバイナリがどのように文字列を保有しているのかについて探っていきます。

以下の点に注意して読み進めてください。

  • 指摘された内容については修正しましたが、正確性に欠ける可能性があります。
  • 示されるソースコードについてはC言語の優れたコーディング方法を示すというわけではない
    • あくまで 挙動を確認するため
続きを読む

フルスクラッチによるセルフホスティングCコンパイラ自作日記#1

目次

概要

以前から rui314/9ccをGoで再実装する勉強法を取っていた私ですが、

drumato.hatenablog.com

に述べたように、
Cプログラミングに慣れたいということと、
単純に自分で試行錯誤しながら作ってみたいというところから、
フルスクラッチコンパイラ自作をスタートしました。

github.com

ルールとしては、

  • C言語のコードは普通に調べる
    • ベストプラクティスを吸収したり
  • コンパイラ実装に関連するコードは、あくまでも 参考程度に
    • 概念・設計は参考にしてもいい
    • あくまで 自分の力で、 試行錯誤 することを念頭に

ことを掲げています。

今回は 字句解析コードについてお話します。

はてなブログMarkdownパーサーが壊れてるっぽいので、
全てGistのコード引用で紹介していきます。


本題

ヘッダファイル omo.h

まずはヘッダファイルを見ていきます。

例によって、全体のコードを貼った後に各コードについて解説を加えていきます。

util.c

様々な処理を簡易的に利用するための自作ライブラリという感じです。

ファイルストリームを開いたり、
内容を取得したり、ファイル情報を取得したり。

後は配列の長さを調べる関数とか、
文字列のチェックを行う関数ですね。

util.cに記述された実際の定義を見てみます。

このようにutilityを充実させることがプログラミングをスムーズに進めるコツだと思っていて、
普段からちょっとした処理を関数に切り出すようにしています。

今回一番重要なのは、

ですね。
これにはCプログラミングを行う上で注意しなければいけない点が詰まっています。

についてですが、

まずは(type*)malloc(size_t nmemb);のように
汎用ポインタを即座にキャストします。

これは JPCERTのセキュアコーディング規約 に記載がありました。

www.jpcert.or.jp

また、fread()関数はnull終端が保証されていない為に、
手動で終端に \0を入力する必要があります。

ヌルバイトを挿入しないことによる脆弱性については、

codezine.jp

が参考になると思います。

また、先述した セキュアコーディング規約にも、

www.jpcert.or.jp

www.jpcert.or.jp

www.jpcert.or.jp

などに、
nullバイトに関する記述がありました。


token

ここではトークンの構造体を定義しつつ、
enumによって定数を定義しています。

これは 種類を識別するため に使われるもので、
int型によって列挙しています。

トークンの構造体の各フィールドを紹介します。

  • ty列挙したトークンの種類の定数が代入される
  • intvalリテラルの値を評価し、ここに代入
    • floatval も未対応ではあるが使い方は同じ
    • 具体的な代入方法については後述
  • str… 文字列リテラル保有場所
    • これについても代入方法は後述
  • input… 具体的にどのような文字列をトークンとしたのか、というフィールド
    • 例を見せます

main.c

Token->inputをダンプしてみましょう。

main.cを見てみます。

-tオプション によって表示する事が出来るようになっています。

f:id:orangebladdy:20190502110306j:plain

16進数もきちんと表示できている事がわかるかと思います。

因みに-sオプションではcat <filepath>とした出力と同じものが得られます。


logger.c

これもほぼutil.cの考え方と同じです。

ログファイルに出力する関数を置いています。
これは ファイルが開けなかった時等のエラーをダンプするものではなく、

コンパイル時に入力されたコードの良し悪しを判断して、
Warningのような役割でログを吐くようにしようと思っています。

ほぼ手を付けていないので結構無駄がありそうですね。
変数宣言相当多いかも。


目玉:lex.c

今回の本題、 字句解析のコードを見ていきます。

コード量めちゃくちゃ多いので気をつけてくださいね。

  • number literal
  • string literal
  • identifier

等を解析する関数について見ていきましょう。

char型やり忘れてたので後でやります。

因みにこれら、
char の種類を判別する関数は、

ctype.h に定義されているんですよね。既に。

どうせなら自分でやろうと思って作りましたが、
その関数を使ったほうがいいと思います。

現在見ているASCIIコードが範囲内かどうかチェックしながら、
readchar()によってオフセットを進めるという典型的な実装です。

token->intval = strtol(token->input, NULL, base);として文字列を変換し、
Token構造体に格納しています。

次に文字列リテラルですね。

実装はとてもシンプルです。

最後に識別子の解析ですが、
鋭い人ならわかると思いますがC言語の仕様に準拠していません。

要は途中で数字とかを許容できていないんですよね。
これは今日中に直します。

解析した識別子は、
lookup_identifier()という関数を用いて
予約語なのかユーザ定義なのかをチェックします。


総評

ここまでで実に3日ぐらいかかっています。

Cプログラミング本当に下手なんです…許してください。

とてもやりがいがあるので、少しずつですが頑張っていきます。

令和だし自身のやってること、やらなければいけないことを整理

目次

  • 目次
  • 概要
  • ここ最近やっていること
    • コンパイラ自作の実践
      • 何が足りない?
    • AttnGAN風T2Iモデルの実装
    • 何が足りない?
    • 自作OS
  • 具体的な勉強計画
  • 参考にしたい書籍
  • 総評

概要

元号、令和になりましたね。
あいも変わらず技術力が足りない私ですが、
これからも精進して強くなっていきます。

今回は 大きな節目ということで、
またもや 勉強計画を立てていこうと思います。

私はこの 定期的に振り返る事をとても大事にしていて、
勉強する中で常に具体的なイメージが持てると思っています。


続きを読む

IA-32 Architectures Developer's Manual 6章まとめ

目次

  • 目次
  • 概要
  • プロシージャ・コールのタイプ
  • スタック
    • スタックのセットアップ
    • スタックのアライメント
    • プロシージャのリンクに関する情報
  • CALLとRETによるプロシージャコール
    • farコール・リターン
  • 総評

概要

IA-32マニュアルを読み始めました。

無料で読めるドキュメントとしては破格の詳しさなので、 システムプログラミングに興味のある人は全員読むべきです。

今回はこのマニュアルのうち6章の内容をベースにしながら、 自身で調べたことをガンガン追記しつつ紹介していこうと思います。

続きを読む

IA-32 Architectures Developer's Manual 4章まとめ

目次

  • 目次
  • 概要
  • 基本データ型
    • 各データ型のアライメント
  • 数値のデータ型
  • ポインタ型
  • ビットフィールドデータ型
  • ストリング・データ型
  • パックドSIMD データ型
  • 総評

概要

IA-32 マニュアルを読み始めました。

無料で読めるドキュメントとしては破格の詳しさなので、 システムプログラミングに興味のある人は全員読むべきです。

今回はこのマニュアルのうち4章の内容をベースにしながら、 自身で調べたことをガンガン追記しつつ紹介していこうと思います。

続きを読む