29 Aug 2014, 13:24

他人のコードに INCEPTION する!coursera で The Hardware/Software Interface を受けた

coursera で The Hardware/Software Interface を受けた感想です.

目的

組込みソフトの知識を身につけるため

私はいちおう組込みエンジニアなのだが, 組込みソフトの知識がない.

すごく, そのことに危機感を感じている. 組込みソフトの知識は, 実際に業務で取り組まないと身につける機会が少ない.

しかし, 仕事ではいつまで待っていても新しいプロジェクトには移動できな い.仕事を通して知識を身につけようなんて思っていたら, 10 年経っても身 につかない気がする.

メモリ管理・プロセス管理・アセンブラ言語などなど, このあたりの知識がほしい.

アセンブラ言語の知識を身につけるため

この講座では, アセンブラ言語についても学ぶことができる.

職場でも, アセンブラ言語を利用しているという話はたまにきくので, 学んでいれば, 新しい業務にもつながることを期待.

感想

C 言語のことをなにもボクは知らなかった

一番感じたことは, 自分は C 言語のことについて理解したつもりになってい たが, それはまだまだ不十分だったということだ.

たとえば, この講義では, malloc, free の原理について解説される. そして, malloc, free を自分で実装するような課題が出される.

ヒープ領域, スタック領域がどういう役割していて, それぞれどういうようにプログラムでは利用されているか, 自分は理解していなかった. それなのに, C 言語なんて全部わかったよ! なんて思っていた自分が恥ずかしい.

まるでそれはインセプション!

課題がどれも難しく, 毎週 10 時間以上かかった. しかし, 今まで受けてきた MOOC の課題の中ではもっともおもしろかった.

そのなかでもとくにおもしろかったのは, バッファオーバーフローについての課題.

与えられたプログラムのセキュリティホールに対して バッファオーバーフローアタックを仕掛けて, まったく関係ない関数を実行したり, さらにはセキュリティホールから自分で書いたアセンブラコードを注入し て実行させたりする.

それはまるで, 映画”インセプション” のような興奮だ!

映画では, ディカプリオが他人の夢の中に侵入して,思い通りの記憶を埋め込む. そして私は, 他人のプログラムのなかに侵入して, 思い通りのコードを埋め込む.

ハッカーはこの快感をもとめて悪さをするのだろう.

内容

シラバスからそのまま引用.

Topics:
    Number representation
    Assembly language
    Basics of C
    Memory management
    Operating-system process model
    High-level machine architecture
    Memory hierarchy
    Implementation of high-level languages

Number representation

ビット演算について学ぶ.

まず, 驚いたことは, if や while のような制御文は ビット演算でかけてしまうということだ.

C 言語なんて楽勝でしょと思っていたら, しょっぱなから出鼻を折られるという..

また, コンピュータは 0 と 1 の世界で, プログラミング言語はそれを置き換 えたものに過ぎないという, 基本的なことを気づかされる.

Assembly language

x86-64 アセンブリ言語の文法を学ぶ. 意外にネットや書籍での情報が多く, 参考になった.

昔のテレビゲームは, アセンブラ言語でかかれていたときく. こんな世界でガリガリコーディングをするなんて, すごいな.

Memory management

メモリがどのように利用されているかのお話.

プログラムがどうやって動いているのかをアセンブラレベルで理解して, 今までなにもわかっていなかったんだと自覚. とともに, 仕組みが分かって感動.

2^n-1
|---------------------|
| Stacks              | ローカル変数, プロシージャの内容
|                     |
| Dynamic Data (Heap) | new や malloc で獲得できる領域
| Static Data         | グローバル変数など.
| Literals            | 文字列
| Instructions        | プログラム. 関数
|---------------------|
0

Memory hierarchy

キャッシュアーキテクチャとその制御アルゴリズム, 仮想メモリについて. C 言語通じて, コンピュータアーキテクチャも学べる.

| registers          |             |
| L1 Cache           | SRAM        |
| L2 Cache           | SRAM        |
| Memory             | DRAM        |
| local 2nd storage  | local disks |
| remote 2nd storage | Web Servers |

私は, ストレージ屋だ. (そしてもうやめたい) キャッシュ技術を学ぶと, ストレージを支える技術というものは, かなりの部分がキャッシュが関わっているのだと思った.

  • Disk の性能をあげるためには?
  • ホスト I/O の性能をあげるためには?

とりあえず, 特許でこまったらキャッシュを思い出す. 講義でも, CS の世界での問題解決の常套手段が関節参照だ! と力説してた.

これから

今までセキュアコーディングなんてまったく意識したことがなかった. 無知のまま脆弱性をプログラムに仕込んでしまうことは恐ろしいと思った. もうすこし, セキュアコーディングについて学んでおこうと思った.

アセンブリ言語はこれ以上は深堀りしなくていいかな… なんとなくだけれども, プログラムの仕組みが理解できたし, あまりおもしろいものではないので.

21 Jul 2014, 13:27

アセンブリ言語の中心でHello, Worldを叫ぶ

はじめに

世界の中心で愛を叫ぼうとしたが、そもそも世界の中心がどこかわからなかった。 ということで、アセンブリ言語の中心で愛を叫ぶことにした。

Environment

  • ArchLinux 64bit.
  • intel corei7 x86-64 ISA

C言語の世界

以下のコードが対象。test.c

#include <stdio.h>

int main() {
  printf("Hello, World!!");
  return 0;
}

デバッグ情報つきでコンパイル。

gcc -g test.c

a.outができる。

アセンブリ言語の世界へ

次に、アセンブラファイルを生成。test.sができる。

gcc -S test.c
    .file   "test.c"
    .section    .rodata
.LC0:
    .string "Hello, World!!"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.9.0 20140604 (prerelease)"
    .section    .note.GNU-stack,"",@progbits

objdump -d a.outでディスアセンブルすると詳細なアセンブリ情報を得られる。

それでは自力で書いてみる

カンペ情報がいろいろ手に入ったので、自力で書いてみる。

    .globl  main # mainからはじまる
main:
    pushq   %rbp # ベースレジスタ退避
    movq    %rsp, %rbp # ベースレジスタにスタックポインタ設定
    movl    $.LC0, %edi # $ediレジスタに文字列格納
    movl    $0, %eax   # $eaxに戻り値が入るので0初期化
    call    printf     # printfをcall  
    movl    $0, %eax   # 戻り値を除去
    popq    %rbp # ベースレジスタ取り出し
    ret     # 終了
.LC0:
    .string "Hello, World!!"

gcc test2.sでコンパイルして、a.outができた。

gdbで解読

gdbで解読。自分が書いたアセンブリコードと違う!どういうことだ??

(gdb) b main
(gdb) disas
Dump of assembler code for function main:
   0x0000000000400506 <+0>: push   %rbp
   0x0000000000400507 <+1>: mov    %rsp,%rbp
   0x000000000040050a <+4>: mov    $0x400520,%edi
   0x000000000040050f <+9>: mov    $0x0,%eax
   0x0000000000400514 <+14>:    callq  0x4003e0 <printf@plt>
   0x0000000000400519 <+19>:    mov    $0x0,%eax
   0x000000000040051e <+24>:    pop    %rbp
   0x000000000040051f <+25>:    retq   
   0x0000000000400520 <+26>:    rex.W
   0x0000000000400521 <+27>:    gs
   0x0000000000400522 <+28>:    insb   (%dx),%es:(%rdi)
   0x0000000000400523 <+29>:    insb   (%dx),%es:(%rdi)
   0x0000000000400524 <+30>:    outsl  %ds:(%rsi),(%dx)
   0x0000000000400525 <+31>:    sub    $0x20,%al
   0x0000000000400527 <+33>:    push   %rdi
   0x0000000000400528 <+34>:    outsl  %ds:(%rsi),(%dx)
   0x0000000000400529 <+35>:    jb     0x400597
   0x000000000040052b <+37>:    and    %esp,%fs:(%rcx)
   0x000000000040052e <+40>:    or     (%rax),%al
End of assembler dump.

(gdb) x /s 0x400520
0x400520 <main+26>: "Hello, World!!\n"

(gdb) info register
rax            0x400506 4195590
rbx            0x0  0
rcx            0x0  0
rdx            0x7fffffffe858   140737488349272
rsi            0x7fffffffe848   140737488349256
rdi            0x1  1
rbp            0x7fffffffe760   0x7fffffffe760
rsp            0x7fffffffe760   0x7fffffffe760
r8             0x7ffff7dd7e50   140737351876176
r9             0x7ffff7deb470   140737351955568
r10            0x7fffffffe600   140737488348672
r11            0x7ffff7a4df10   140737348165392
r12            0x400410 4195344
r13            0x7fffffffe840   140737488349248
r14            0x0  0
r15            0x0  0
rip            0x40050a 0x40050a <main+4>
eflags         0x246    [ PF ZF IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0