2012-02-10 1 views
30

バイナリ形式のメッセージを含むバッファを検査しようとしていますが、文字列データも含まれています。例として、私はこのCのコードを使用しています:gdbからxxdのようにフォーマットされたメモリダンプ

int main (void) { 
    char buf[100] = "\x01\x02\x03\x04String Data\xAA\xBB\xCC"; 

    return 0; 
} 

私はそれが正確に一致だ場合、私は気にしないでください(xxdに似た形式で、bufに何の進ダンプを取得したいのですが、私が実際に探しているのは、印刷可能な文字が並んだ16進ダンプです)。細かいですが、それはそのように文字列を選ぶのは難しい...または私はそれが困難になり

(gdb) x /100bs buf 
0x7fffffffdf00: "\001\002\003\004String Data\252\273\314" 
0x7fffffffdf13: "" 
0x7fffffffdf14: "" 
0x7fffffffdf15: "" 
0x7fffffffdf16: "" 
0x7fffffffdf17: "" 
... 

を使用することができます

(gdb) x /100bx buf 
0x7fffffffdf00: 0x01 0x02 0x03 0x04 0x53 0x74 0x72 0x69 
0x7fffffffdf08: 0x6e 0x67 0x20 0x44 0x61 0x74 0x61 0xaa 
0x7fffffffdf10: 0xbb 0xcc 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf18: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf20: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf28: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf30: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf38: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf40: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf48: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf50: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffdf58: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 

:私はのようなものを使用することができますGDB内部

バイナリの部分を読むには...私が扱っている実際のメッセージにはascii nulもたくさんあるので、実際は混乱のように見えます。

(gdb) dump binary memory dump.bin buf buf+100 

、その後

$ xxd dump.bin 
0000000: 0102 0304 5374 7269 6e67 2044 6174 61aa ....String Data. 
0000010: bbcc 0000 0000 0000 0000 0000 0000 0000 ................ 
0000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 
0000060: 0000 0000        .... 

が、それはそのたびに行うには、痛みです:

私が思い付くことができる最高のは、これを行うことです。誰かがこれをgdbの中でやる方法を見つけたのかどうか疑問に思っています。加えて、この方法で元のメモリからアドレスを失います。

私はGDB 7.4でPythonサポートを組み込んでいますので、かなりのプリンタなどを使う考えはありますが、設定方法はわかりません。

答えて

52
(gdb) define xxd 
>dump binary memory dump.bin $arg0 $arg0+$arg1 
>shell xxd dump.bin 
>end 
(gdb) xxd &j 10 
0000000: 0000 0000 0000 0000 0000 0000 4d8c a7f7 ............M... 
0000010: ff7f 0000 0000 0000 0000 0000 c8d7 ffff ................ 
0000020: ff7f 0000 0000 0000 

は、あなたはおそらく同じことを行うには(現代のGDBのバージョンはPythonインタプリタが埋め込まれている)Pythonスクリプトを書くことができ、そして「シェルアウト」する必要性を取り除く

;-)簡単に十分なようです。

+0

ああ、良い考え。そのようなショートカットをGDBに追加するのは簡単だったことに気づいていませんでした。あなたが言及したように、私はこれをPythonでコーディングしましたが、私はそのイディオムを使用することができると確信しています。 – FatalError

+0

'$ arg0'が構造体へのポインタである場合、' $ arg1'はバイト数ではなくオブジェクトの数として扱われることに注意してください。それが問題になる場合は '$ arg0 + $ arg1'の代わりに'((void *)$ arg0)+ $ arg1'を使用してください。 –

+0

新しいバージョンの 'xxd'は' -o'フラグをサポートしているので、表示されるアドレス値にオフセットが追加されます。 –

23

だから、私はPythonインタフェースで遊んでしまったし、この思い付いた:

import gdb 
from curses.ascii import isgraph 

def groups_of(iterable, size, first=0): 
    first = first if first != 0 else size 
    chunk, iterable = iterable[:first], iterable[first:] 
    while chunk: 
     yield chunk 
     chunk, iterable = iterable[:size], iterable[size:] 

class HexDump(gdb.Command): 
    def __init__(self): 
     super (HexDump, self).__init__ ('hex-dump', gdb.COMMAND_DATA) 

    def invoke(self, arg, from_tty): 
     argv = gdb.string_to_argv(arg) 
     if len(argv) != 2: 
      raise gdb.GdbError('hex-dump takes exactly 2 arguments.') 
     addr = gdb.parse_and_eval(argv[0]).cast(
      gdb.lookup_type('void').pointer()) 
     try: 
      bytes = int(gdb.parse_and_eval(argv[1])) 
     except ValueError: 
      raise gdb.GdbError('Byte count numst be an integer value.') 

     inferior = gdb.selected_inferior() 

     align = gdb.parameter('hex-dump-align') 
     width = gdb.parameter('hex-dump-width') 
     if width == 0: 
      width = 16 

     mem = inferior.read_memory(addr, bytes) 
     pr_addr = int(str(addr), 16) 
     pr_offset = width 

     if align: 
      pr_offset = width - (pr_addr % width) 
      pr_addr -= pr_addr % width 

     for group in groups_of(mem, width, pr_offset): 
      print '0x%x: ' % (pr_addr,) + ' '*(width - pr_offset), 
      print ' '.join(['%02X' % (ord(g),) for g in group]) + \ 
       ' ' * (width - len(group) if pr_offset == width else 0) + ' ', 
      print ' '*(width - pr_offset) + ''.join(
       [g if isgraph(g) or g == ' ' else '.' for g in group]) 
      pr_addr += width 
      pr_offset = width 

class HexDumpAlign(gdb.Parameter): 
    def __init__(self): 
     super (HexDumpAlign, self).__init__('hex-dump-align', 
              gdb.COMMAND_DATA, 
              gdb.PARAM_BOOLEAN) 

    set_doc = 'Determines if hex-dump always starts at an "aligned" address (see hex-dump-width' 
    show_doc = 'Hex dump alignment is currently' 

class HexDumpWidth(gdb.Parameter): 
    def __init__(self): 
     super (HexDumpWidth, self).__init__('hex-dump-width', 
              gdb.COMMAND_DATA, 
              gdb.PARAM_INTEGER) 

    set_doc = 'Set the number of bytes per line of hex-dump' 

    show_doc = 'The number of bytes per line in hex-dump is' 

HexDump() 
HexDumpAlign() 
HexDumpWidth() 

私はそれが最も美しく、エレガントな解決策ではないかもしれません実現が、それは仕事を取得し、として機能します最初のドラフト。そして、そのような上記のプログラムで使用することができ

python 
sys.path.insert(0, '/path/to/module/dir') 
import hexdump 
end 

(gdb) hex-dump buf 100 
0x7fffffffdf00: 01 02 03 04 53 74 72 69 6E 67 20 44 61 74 61 AA ....String Data. 
0x7fffffffdf10: BB CC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf60: 00 00 00 00          .... 

そして、良い対策のためのいくつかの他のタッチ:

(gdb) set hex-dump-align on 
Determines if hex-dump always starts at an "aligned" address (see hex-dump-width 
(gdb) hex-dump &buf[5] 95 
0x7fffffffdf00:     74 72 69 6E 67 20 44 61 74 61 AA  tring Data. 
0x7fffffffdf10: BB CC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 
0x7fffffffdf60: 00 00 00 00          .... 

(gdb) set hex-dump-width 8 
Set the number of bytes per line of hex-dump 
(gdb) hex-dump &buf[5] 95 
0x7fffffffdf00:     74 72 69  tri 
0x7fffffffdf08: 6E 67 20 44 61 74 61 AA ng Data. 
0x7fffffffdf10: BB CC 00 00 00 00 00 00 ........ 
0x7fffffffdf18: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf20: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf28: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf30: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf38: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf40: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf48: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf50: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf58: 00 00 00 00 00 00 00 00 ........ 
0x7fffffffdf60: 00 00 00 00    .... 

ありませんが、それは次のように~/.gdbinitに含めることができますバグはないと約束しています:)。人々が興味を持っているならば、私はそれをギブスや何かに押しつけるかもしれません。

GDB 7.4でのみテストしました。

+1

+1このソリューションは元のアドレスを保持するので、非常に便利です! –

+0

私は 'ImportError:no modulesという名前のモジュールがありません.'エラー – haneefmubarak

+0

スクリプトをhexdump.pyとして保存し、.gdbinitのパスが正しいことを確認してください。 – FatalError

2

ユーザーの溶液の適合バージョンあるFatalError

パイソン3
    • 作品は
    • 任意ヘキサCOL-ヘッダ
    • 長パラメータは
    をHDに改名添加

    あるFatalErrorさんとgunthorのバージョンは私のために動作しませんでしたので、私は別のものにはまだ自分自身を書いた@ @ HD 0xbfffe4f1

    HD 0xbfffe4f1 500

    残念ながら
    import gdb 
    from curses.ascii import isgraph 
    
    def groups_of(iterable, size, first=0): 
        first = first if first != 0 else size 
        chunk, iterable = iterable[:first], iterable[first:] 
        while chunk: 
         yield chunk 
         chunk, iterable = iterable[:size], iterable[size:] 
    
    class HexDump(gdb.Command): 
        def __init__(self): 
         super (HexDump, self).__init__ ('hd', gdb.COMMAND_DATA) 
    
        def invoke(self, arg, from_tty): 
         argv = gdb.string_to_argv(arg) 
    
         addr = gdb.parse_and_eval(argv[0]).cast(
          gdb.lookup_type('void').pointer()) 
         if len(argv) == 2: 
          try: 
           bytes = int(gdb.parse_and_eval(argv[1])) 
          except ValueError: 
           raise gdb.GdbError('Byte count numst be an integer value.') 
         else: 
          bytes = 500 
    
         inferior = gdb.selected_inferior() 
    
         align = gdb.parameter('hex-dump-align') 
         width = gdb.parameter('hex-dump-width') 
         if width == 0: 
          width = 16 
    
         mem = inferior.read_memory(addr, bytes) 
         pr_addr = int(str(addr), 16) 
         pr_offset = width 
    
         if align: 
          pr_offset = width - (pr_addr % width) 
          pr_addr -= pr_addr % width 
         start=(pr_addr) & 0xff; 
    
    
         print ('   ' , end="") 
         print (' '.join(['%01X' % (i&0x0f,) for i in range(start,start+width)]) , end="") 
         print (' ' , end="")  
         print (' '.join(['%01X' % (i&0x0f,) for i in range(start,start+width)])) 
    
         for group in groups_of(mem, width, pr_offset): 
          print ('0x%x: ' % (pr_addr,) + ' '*(width - pr_offset), end="") 
          print (' '.join(['%02X' % (ord(g),) for g in group]) + \ 
           ' ' * (width - len(group) if pr_offset == width else 0) + ' ', end="")  
          print (' '*(width - pr_offset) + ' '.join(
           [chr(int.from_bytes(g, byteorder='big')) if isgraph(int.from_bytes(g, byteorder='big') ) or g == ' ' else '.' for g in group])) 
          pr_addr += width 
          pr_offset = width 
    
    class HexDumpAlign(gdb.Parameter): 
        def __init__(self): 
         super (HexDumpAlign, self).__init__('hex-dump-align', 
                  gdb.COMMAND_DATA, 
                  gdb.PARAM_BOOLEAN) 
    
        set_doc = 'Determines if hex-dump always starts at an "aligned" address (see hex-dump-width' 
        show_doc = 'Hex dump alignment is currently' 
    
    class HexDumpWidth(gdb.Parameter): 
        def __init__(self): 
         super (HexDumpWidth, self).__init__('hex-dump-width', 
                  gdb.COMMAND_DATA, 
                  gdb.PARAM_INTEGER) 
    
        set_doc = 'Set the number of bytes per line of hex-dump' 
    
        show_doc = 'The number of bytes per line in hex-dump is' 
    
    HexDump() 
    HexDumpAlign() 
    HexDumpWidth() 
    
  • 1

    、。これは、それがどのように見えるかです:xxd

    (gdb) xxd hello_string 0xc 
    00000001_00000f87:     48 656c 6c6f 0957 6f72   Hello.Wor 
    00000001_00000f90: 6c64 0a         ld. 
    

    新しいバージョン(常に0000000から開始します)表示された1つに追加するオフセットを指定することができます-oフラグをサポートしています。

    xxd -oが利用できない場合は、xxd 'の位置のアドレスを正しく並べて表示する代用品です。

    xxdコマンド:

    define xxd 
        dump binary memory /tmp/dump.bin $arg0 $arg0+$arg1 
        eval "shell xxd-o %p /tmp/dump.bin", $arg0 
    end 
    

    ザ・間違いなく醜いperlスクリプトxxd-o(オフセット付きxxd):

    #!/usr/bin/env perl 
    use IPC::Open2; 
    $SIG{'__WARN__'} = sub{ die "$0: $!\n" }; 
    
    my $offset = shift // "0"; 
    $offset = oct($offset) if $offset =~ /^0/; 
    my $base = $offset >= 2**32 ? 16 : 8; 
    
    my $zeroes = $offset % 16; 
    my $padding = 1 + int($zeroes/2) + 2*$zeroes; 
    my $bytestr = "\0" x $zeroes; 
    { local $/; $bytestr .= <> } 
    
    open2(\*XXD_OUT, \*XXD_IN, "xxd") or die "xxd is not available!"; 
    print XXD_IN $bytestr; close XXD_IN; 
    
    if ($zeroes) { 
        $_ = <XXD_OUT>; 
        s/^(.{50}).{$zeroes}/$1 . (' ' x $zeroes)/ge; 
        s/^([[:xdigit:]]+:).{$padding}/$1 . (' ' x $padding)/ge; 
        my $newoff = sprintf("%0${base}x",hex($1)+$offset) =~ s/^(.{8})(.{8})$/$1_$2/r; 
        s/^([[:xdigit:]]+):/$newoff:/g; 
        print 
    } 
    while (<XXD_OUT>) { 
        s/^([[:xdigit:]]+)(?=:)/sprintf("%0${base}x", hex($1)+$offset-$offset%16) =~ s[^(.{8})(.{8})$][$1_$2]r/ge; 
        print 
    } 
    

    改善は歓迎します! :-)

    +0

    On 'xxd -o':https://stackoverflow.com/q/10233526/8446 –

    関連する問題