본문 바로가기

개발/서버

프로그래밍 - gdb , objdump

grep -A10 main.:   <-- main에서부터 10줄 출력
----------------------------------------------------------------------
[root@localhost sock]# objdump -D test.exe | grep -A10 main.:
08048628 <main>:
 8048628:       55                      push   %ebp
 8048629:       89 e5                   mov    %esp,%ebp
 804862b:       57                      push   %edi
 804862c:       56                      push   %esi
 804862d:       83 ec 50                sub    $0x50,%esp
 8048630:       83 e4 f0                and    $0xfffffff0,%esp
 8048633:       b8 00 00 00 00          mov    $0x0,%eax
 8048638:       29 c4                   sub    %eax,%esp
 804863a:       8d 7d a8                lea    0xffffffa8(%ebp),%edi
 804863d:       be a0 88 04 08          mov    $0x80488a0,%esi
----------------------------------------------------------------------
========================================================================
 
[ objdump intel 문법으로 출력 ]
 
-M intel  <-- intel 문법으로 출력

----------------------------------------------------------------------
[root@localhost sock]# objdump -M intel -D test.exe | grep -A10 main.:
08048628 <main>:
 8048628:       55                      push   ebp
 8048629:       89 e5                   mov    ebp,esp
 804862b:       57                      push   edi
 804862c:       56                      push   esi
 804862d:       83 ec 50                sub    esp,0x50
 8048630:       83 e4 f0                and    esp,0xfffffff0
 8048633:       b8 00 00 00 00          mov    eax,0x0
 8048638:       29 c4                   sub    esp,eax
 804863a:       8d 7d a8                lea    edi,[ebp-88]
 804863d:       be a0 88 04 08          mov    esi,0x80488a0
----------------------------------------------------------------------
==========================================================================================
 
[ gdb 시작시 인텔문법으로 설정하기 ]
 
홈 디렉토리의 .gdbinit 파일에 앞의 명령어를 입력하면 된다.
----------------------------------------------------------------------
[root@localhost root]# echo "set dis intel" > ~/.gdbinit
[root@localhost root]# cat ~/.gdbinit
set dis intel
[root@localhost root]#
----------------------------------------------------------------------

====================================================================================
 
[ 함수프롤로그 ]

#include <stdio.h>
int main()
{
        int i = 0;
        return 0;
}

(gdb) disas main
Dump of assembler code for function main:
0x080482f4 <main+0>:    push   ebp
0x080482f5 <main+1>:    mov    ebp,esp
0x080482f7 <main+3>:    sub    esp,0x8
0x080482fa <main+6>:    and    esp,0xfffffff0
0x080482fd <main+9>:    mov    eax,0x0
0x08048302 <main+14>:   sub    esp,eax
0x08048304 <main+16>:   mov    DWORD PTR [ebp-4],0x0
0x0804830b <main+23>:   mov    eax,0x0
0x08048310 <main+28>:   leave
0x08048311 <main+29>:   ret
0x08048312 <main+30>:   nop
0x08048313 <main+31>:   nop
End of assembler dump.
(gdb)
 
------------여기서부터----------------
0x080482f4 <main+0>:    push   ebp
0x080482f5 <main+1>:    mov    ebp,esp
0x080482f7 <main+3>:    sub    esp,0x8
0x080482fa <main+6>:    and    esp,0xfffffff0
0x080482fd <main+9>:    mov    eax,0x0
0x08048302 <main+14>:   sub    esp,eax
----------여기까지가 -----------------
함수 프롤로그(Function Prologue )라고 한다.
main() 함수의 나머지 전역 변수를 위한 메모리를 할당하고
컴파일러가 생성한 것이다. 변수들이 C에서 선언돼야 하는 어느 정도의
이유는 코드 생성을 돕기 위해서다.
====================================================================================
 
[ gdb 메모리값 출력 ]
 
○ o : 8진법으로 보여준다.
○ x : 16진법으로 보여준다.
○ u : 부호가 없는 unsigned 표준 10진법으로 보여준다.
○ t : 2진법으로 보여준다.
info register eip 는 i r eip 로 줄여 쓸 수도 있다.
------------------------------------------------------------------------------------
(gdb) b main
Breakpoint 1 at 0x80482fa
(gdb) r
Starting program: /root/test.exe
Breakpoint 1, 0x080482fa in main ()
(gdb) i r eip
eip            0x80482fa        0x80482fa
(gdb) x/o 0x80482fa
0x80482fa <main+6>:     027074162203
(gdb) x/x $eip
0x80482fa <main+6>:     0xb8f0e483
(gdb) x/u $eip
0x80482fa <main+6>:     3102794883
(gdb) x/t $eip
0x80482fa <main+6>:     10111000111100001110010010000011
(gdb)
------------------------------------------------------------------------------------
 
[ gdb 메모리값에서 여러개 출력하기 ]

------------------------------------------------------------------------
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /root/test.exe
Breakpoint 1, 0x0804832e in main ()
(gdb) x/2x $eip
0x804832e <main+6>:     0xb8f0e483      0x00000000
(gdb) x/12x $eip
0x804832e <main+6>:     0xb8f0e483      0x00000000      0x45c7c429      0x000000fc
0x804833e <main+22>:    0xfc45c700      0x00000000      0x09fc7d83      0x17eb027e
0x804834e <main+38>:    0x680cec83      0x08048418      0xffff0de8      0x10c483ff
(gdb)
---------------------------------------------------------------------------------
메모리의 단일 유닛의 기본 크기는 4바이트 이다.
○ b : 단일 바이트  - 1 bytes
○ h : 2바이트의 하프워드 (Halfword) - 2 bytes
○ w : 4바이트의 워드
○ g : 8바이트의 자이언트 (Giant)
---------------------------------------------------------------------------
(gdb) x/8xb $eip
0x804832e <main+6>:     0x83    0xe4    0xf0    0xb8    0x00    0x00    0x00    0x00
(gdb) x/8xh $eip
0x804832e <main+6>:     0xe483  0xb8f0  0x0000  0x0000  0xc429  0x45c7  0x00fc  0x0000
(gdb) x/8xw $eip
0x804832e <main+6>:     0xb8f0e483      0x00000000      0x45c7c429      0x000000fc
0x804833e <main+22>:    0xfc45c700      0x00000000      0x09fc7d83      0x17eb027e
(gdb)
---------------------------------------------------------------------------

====================================================================================
 
[ gdb 메모리값에서 명령어로 출력하기 ]
 
○ i : 역어셈블된 어셈블리 언어의 명령 메모리를 볼 수 있다. (instruction)
------------------------------------------------
End of assembler dump.
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /root/test.exe
Breakpoint 1, 0x0804832e in main ()
(gdb) i r $eip
eip            0x804832e        0x804832e
(gdb) x/i $eip
0x804832e <main+6>:     and    esp,0xfffffff0
(gdb) x/3i $eip
0x804832e <main+6>:     and    esp,0xfffffff0
0x8048331 <main+9>:     mov    eax,0x0
0x8048336 <main+14>:    sub    esp,eax
(gdb)
(gdb) x/3xb $eip
0x804832e <main+6>:     0x83    0xe4    0xf0   
(gdb)
------------------------------------------------
[root@localhost root]# objdump -d test.exe | grep -A10 main.:
08048328 <main>:
 8048328:       55                      push   %ebp
 8048329:       89 e5                   mov    %esp,%ebp
 804832b:       83 ec 08                sub    $0x8,%esp
 804832e:       83 e4 f0                and    $0xfffffff0,%esp
 8048331:       b8 00 00 00 00          mov    $0x0,%eax
 8048336:       29 c4                   sub    %eax,%esp
 8048338:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
 804833f:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
 8048346:       83 7d fc 09             cmpl   $0x9,0xfffffffc(%ebp)
 804834a:       7e 02                   jle    804834e <main+0x26>
[root@localhost root]#
------------------------------------------------
우의 결과를 보면 프로그램은 GDB에서 main()에 중지점이 설정돼 실행됬고,
EIP 레지스터는 기계어 명령이 있는 메모리를 가리키고 있으므로 훌륭하게
역어셈블할 수 있다.
objdump 역어셈블로 EIP가 실제 가리키는 일곱 바이트는 해당 어셈블리 명령어를 위한
기계어임을 확인할 수 있다.
------------------------------------------------
804832e:       83 e4 f0                and    $0xfffffff0,%esp
------------------------------------------------
 
------------------------------------------------
(gdb) disas main
Dump of assembler code for function main:
0x08048328 <main+0>:    push   ebp
0x08048329 <main+1>:    mov    ebp,esp
0x0804832b <main+3>:    sub    esp,0x8
0x0804832e <main+6>:    and    esp,0xfffffff0
0x08048331 <main+9>:    mov    eax,0x0
0x08048336 <main+14>:   sub    esp,eax
0x08048338 <main+16>:   mov    DWORD PTR [ebp-4],0x0
0x0804833f <main+23>:   mov    DWORD PTR [ebp-4],0x0
------------------------------------------------
------------------------------------------------
(gdb) b *(main+23)
Breakpoint 1 at 0x804833f
(gdb) r
Starting program: /root/test.exe
Breakpoint 1, 0x0804833f in main ()
(gdb) i r ebp
ebp            0xbfffdd28       0xbfffdd28
(gdb) x/4xb $ebp - 4
0xbfffdd24:     0x00    0x00    0x00    0x00
(gdb) x/4xb 0xbfffdd24
0xbfffdd24:     0x00    0x00    0x00    0x00
(gdb) print $ebp - 4
$1 = (void *) 0xbfffdd24
(gdb) x/4xb $1
0xbfffdd24:     0x00    0x00    0x00    0x00
(gdb) x/xw $1
0xbfffdd24:     0x00000000
(gdb)
------------------------------------------------
print 명령은 간단한 계산을 할 때 사용될 수 있고, 결과는 디버거의 임시 변수에 저장된다.
$1 변수는 메모리에서 특정 부분을 빠르게 재접근할 때 사용된다.

--------------------------------------------------------------------------
#include <stdio.h>
int main()
{
        int i = 0;
        for(i=0; i<10; i++)
        {
                printf("I am Hacker!!\n");
        }

        return 0;
}
--------------------------------------------------------------------------
[root@localhost root]# gcc -g ./test.c -o ./test.exe

--------------------------------------------------------------------------
(gdb) print $ebp - 4
$1 = (void *) 0xbfffe3a4
(gdb) x/4xb $1
0xbfffe3a4:     0x60    0x53    0x01    0x40
(gdb) nexti
7               for(i=0; i<10; i++)
(gdb) x/4xb $1
0xbfffe3a4:     0x00    0x00    0x00    0x00
(gdb)
(gdb) x/dw $1
0xbfffe3a4:     0
(gdb)
(gdb) x/i $eip
0x804833f <main+23>:    mov    DWORD PTR [ebp-4],0x0
(gdb) nexti
0x08048346      7               for(i=0; i<10; i++)
(gdb) i r eip
eip            0x8048346        0x8048346
(gdb) x/i $eip
0x8048346 <main+30>:    cmp    DWORD PTR [ebp-4],0x9
(gdb) x/x $1
0xbfffe3a4:     0x00000000
(gdb) x/10i $eip
0x8048346 <main+30>:    cmp    DWORD PTR [ebp-4],0x9
0x804834a <main+34>:    jle    0x804834e <main+38>
0x804834c <main+36>:    jmp    0x8048365 <main+61>
0x804834e <main+38>:    sub    esp,0xc
0x8048351 <main+41>:    push   0x8048418
0x8048356 <main+46>:    call   0x8048268 <printf>
0x804835b <main+51>:    add    esp,0x10
0x804835e <main+54>:    lea    eax,[ebp-4]
0x8048361 <main+57>:    inc    DWORD PTR [eax]
0x8048363 <main+59>:    jmp    0x8048346 <main+30>

--------------------------------------------------------------------------
 
 
 

--------------------------------------------------
#include <stdio.h>
#include <string.h>
int main()
{
        char str_a[20];
        strcpy(str_a, "Hello, world\n");
        printf(str_a);

        return 0;
}
--------------------------------------------------

--------------------------------------------------
[root@localhost debug]# gcc strcpy.c -g -o strcpy.exe
--------------------------------------------------
 
--------------------------------------------------
(gdb) list
1       #include <stdio.h>
2       #include <string.h>
3
4       int main()
5       {
6               char str_a[20];
7
8               strcpy(str_a, "Hello, world\n");
9               printf(str_a);
10
(gdb)
(gdb) b 7
Breakpoint 1 at 0x804836c: file strcpy.c, line 7.
(gdb) b strcpy
Breakpoint 2 at 0x804829c
(gdb) b 9
Breakpoint 3 at 0x8048380: file strcpy.c, line 9.
(gdb) run
Starting program: /home/debug/strcpy.exe
Breakpoint 2 at 0x42079dd4
Breakpoint 1, main () at strcpy.c:8
8               strcpy(str_a, "Hello, world\n");
(gdb) i r eip
eip            0x804836c        0x804836c
(gdb) x/5i $eip
0x804836c <main+16>:    sub    esp,0x8
0x804836f <main+19>:    push   0x8048444
0x8048374 <main+24>:    lea    eax,[ebp-40]
0x8048377 <main+27>:    push   eax
0x8048378 <main+28>:    call   0x804829c <strcpy>
(gdb)
(gdb) x/5i $eip
0x804836c <main+16>:    sub    esp,0x8
0x804836f <main+19>:    push   0x8048444
0x8048374 <main+24>:    lea    eax,[ebp-40]
0x8048377 <main+27>:    push   eax
0x8048378 <main+28>:    call   0x804829c <strcpy>
(gdb) continue
Continuing.
Breakpoint 2, 0x42079dd4 in strcpy () from /lib/tls/libc.so.6
(gdb) i r eip
eip            0x42079dd4       0x42079dd4
(gdb) x/5i $eip
0x42079dd4 <strcpy+4>:  mov    esi,DWORD PTR [ebp+8]
0x42079dd7 <strcpy+7>:  mov    edx,DWORD PTR [ebp+12]
0x42079dda <strcpy+10>: mov    eax,esi
0x42079ddc <strcpy+12>: sub    eax,edx
0x42079dde <strcpy+14>: lea    ecx,[eax-1]
(gdb)
(gdb) si
0x42079dd7 in strcpy () from /lib/tls/libc.so.6
(gdb) x/i $eip
0x42079dd7 <strcpy+7>:  mov    edx,DWORD PTR [ebp+12]
(gdb) i r esi
esi            0xbffff6e0       -1073744160
(gdb) ni
0x42079dda in strcpy () from /lib/tls/libc.so.6
(gdb) x/i $eip
0x42079dda <strcpy+10>: mov    eax,esi
(gdb) i r edx
edx            0x8048444        134513732
(gdb) x/s 0x8048444
0x8048444 <_IO_stdin_used+4>:    "Hello, world\n"
(gdb)
 

'개발 > 서버' 카테고리의 다른 글

RPM 사용법 정리  (0) 2013.06.14
nginx 구라에 속지말자  (0) 2013.06.14
네트워킹 - 작은 웹서버 , 웹서버 원리 제작  (0) 2012.02.05
[ gdb 로 스택 구조 확인 ]  (0) 2012.02.05
프로세스  (0) 2012.02.05