Hatena::Groupprogram

lnzntのプログラミング日記 このページをアンテナに追加 RSSフィード

2010年11月03日(水)

MBR をダンプする ruby スクリプト(ツール)

| 00:40 |  MBR をダンプする ruby スクリプト(ツール) - lnzntのプログラミング日記 を含むブックマーク はてなブックマーク -  MBR をダンプする ruby スクリプト(ツール) - lnzntのプログラミング日記  MBR をダンプする ruby スクリプト(ツール) - lnzntのプログラミング日記 のブックマークコメント

MBR をダンプするスクリプト。(非実用品)

#!/usr/bin/env ruby

module MBR
    class MBR
        class PartitionTable < Array
            class Entry
                class CHS
                    def initialize(data)
                        @cylinder   = (data[1] & 0xc0) << 2 | data[2]
                        @header     = data[0]
                        @sector     = data[1] & 0x3f
                    end
                    attr_reader :cylinder,:header,:sector
                end

                def initialize(data)
                    flag,chs_s,kind,chs_e,lba,lba_size = data.unpack("Ca3Ca3LL")
                    @flag       = (flag != 0)
                    @kind       = kind
                    @chs_start  = CHS.new(chs_s)
                    @chs_end    = CHS.new(chs_e)
                    @lba        = lba..(lba+lba_size-1)
                end
                attr_reader :flag,:kind,:lba,:lba_size,:chs_start,:chs_end
            end

            def initialize(data)
                data.scan(/.{16}/)[0,4].each {|entry|
                    push(Entry.new(entry))
                }
            end
        end

        def initialize(data)
            @boot_strap, partition, aa55 = data.unpack("a446 a64 v")

            @boot_strap.freeze
            @partition = PartitionTable.new(partition)
            @valid = (aa55 == 0xaa55)
        end

        attr_reader :boot_strap, :partition

        def valid? ; @valid ; end

        def valid! ; @valid or raise('MBR is invalid') ; end
    end

    module_function

    SIZE = 512
   def create(data)
        if data == ARGF || data.kind_of?(IO)
            data = data.read(SIZE)
        end

        MBR.new(data)
    end
end

if __FILE__ == $0
  require 'pp'

  mbr = MBR.create(ARGF)
  mbr.valid!
  pp mbr.partition
end

使い方。(MBR は /dev/sda にあるとする。実際は環境依存)

MBR を読み出す作業は慎重に!!! (誤操作でシステムを壊す恐れがあります)

$ sudo dd if=/dev/sda of=sda.mbr bs=512 count=1 # MBR を読み出す。(慎重に!!!)
$ ruby mbr.rb sda.mbr

PC互換機 の MBR

| 00:38 |  PC互換機 の MBR - lnzntのプログラミング日記 を含むブックマーク はてなブックマーク -  PC互換機 の MBR - lnzntのプログラミング日記  PC互換機 の MBR - lnzntのプログラミング日記 のブックマークコメント

MBR について(構造など)は下記参照

gas ソース

# ipl.s

# generate real mode code
.code16

    jmp begin
    nop

# BPB
name:           .ascii  "Name    "
sector_size:    .word   0x0200
cluster_size:   .byte   0x01
fat_pos:        .word   0x0001
fat_cnt:        .byte   0x02
root_size:      .word   0x00e0
sector_cnt:     .word   0x0b40
media_type:     .byte   0xf0
fat_size:       .word   0x0009
sector_cnt_pt:  .word   0x0012
head_cnt:       .word   0x0002
bpb_pos:        .long   0x0000
sector_cnt_l:   .long   0x00000b40
drive_no:       .byte   0x00
reserved:       .byte   0x00
ext_boot_code:  .byte   0x29
volume_serial:  .long   0xffffffff
disk_name:      .ascii  "DISK       "
fat_name:       .ascii  "FAT12   "

    # boot begin
begin:
    # infinite loop
    jmp begin

# boot signature.
. = 510
.short 0xaa55
アセンブル
$ as -o ipl.o ipl.s
バイナリ変換
$ objcopy -S -O binary ipl.o ipl.bin
FD イメージ作成 (エミュレーション用)
$ dd if=/dev/zero of=fd.img count=2880
$ dd if=ipl.bin of=fd.img conv=notrunc
QEMU での実行
$ qemu -m 128 -fda fd.img
QEMU での実行(Cygwin)
$ ./qemu/qemu.exe -L ./qemu -m 128 -fda fd.img

制御転送命令

| 00:37 |  制御転送命令 - lnzntのプログラミング日記 を含むブックマーク はてなブックマーク -  制御転送命令 - lnzntのプログラミング日記  制御転送命令 - lnzntのプログラミング日記 のブックマークコメント

x86CPU 制御転送命令

  1. 制御転送命令
    1. 無条件ジャンプ
    2. 条件付きジャンプ
    3. ループ
    4. サブルーチンのコールとリターン
    5. 割り込み・例外の発生とリターン
    6. スタック・フレームの作成と解放
  2. その他の命令

ジャンプ命令

far ジャンプ
異なるセグメントへのジャンプ. (E)IP, (E)CS を更新.
near ジャンプ
同じセグメントへのジャンプ. (E)IP を更新.
short ジャンプ
相対オフセットが -128〜127 の範囲の near ジャンプ.
相対オフセット・ジャンプ
ジャンプ命令の直後を0としたバイト・オフセットを指定.
絶対オフセット・ジャンプ
飛び先の絶対番地を指定.
(記述例)
   jmp label01    # ラベル 'label01' へジャンプ
   jmp 1b         # 直前の数字ラベル '1' へジャンプ
   jmp 1f         # 直後の数字ラベル '1' へジャンプ
   jmp *%ebx      # 絶対オフセット指定の場合は「*」を付ける

逆アセンブル

| 00:36 |  逆アセンブル - lnzntのプログラミング日記 を含むブックマーク はてなブックマーク -  逆アセンブル - lnzntのプログラミング日記  逆アセンブル - lnzntのプログラミング日記 のブックマークコメント

gas

16bitコード: objdump -m i8086 -b binary -D hoge.bin

32bitコード: objdump -m i386 -b binary -D hoge.bin

nasm

16bitコード: ndisasm hoge.bin

32bitコード: ndisasm -u hoge.bin

empty_8042

| 00:35 |  empty_8042 - lnzntのプログラミング日記 を含むブックマーク はてなブックマーク -  empty_8042 - lnzntのプログラミング日記  empty_8042 - lnzntのプログラミング日記 のブックマークコメント

(x86 asm) empty_8042

キーボードバッファを空にする (8042 はキーボード・コントローラ)

.code16
empty_8042:
    push      %cx
    mov       $0xffff, %cx
empty_8042_loop:
    dec       %cx
    jz        empty_8042_end_loop

    call      delay
    in        $0x64, %al
    test      $0x1, %al
    jz        no_output
    call      delay
    in        $0x60, %al
    jmp       empty_8042_loop
no_output:
    test      $0x2, %al
    jnz       empty_8042_loop
empty_8042_end_loop:
    pop       %cx
    ret

参考