프로그래밍 - gdb , objdump
2012. 2. 5. 22:48ㆍ개발/서버
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 |