변수의 메모리 배치 확인 및 GDB 사용법에 대해서
사용시스템
- HackMe(level9/apple)
1. 변수의 메모리 배치
변수의 메모리 배치를 확인하기 위해서 프로그램을 만들어 보자.
변수와 변수의 사이에 dummy 라는 공간확인(정확한 배열을 위함)
여러개의 지역변수를 많이 할당한 것을 배열이라고 한다.(순차적)
[level9@ftz level9]$ ls -l
합계 12 -rw-r--r-- 1 root root 391 11월 13 2002 hint drwxr-xr-x 2 root level9 4096 2월 24 2002 public_html drwxrwxr-x 2 root level9 4096 1월 16 2009 tmp |
[level9@ftz level9]$ cd tmp
[level9@ftz level9]$ vi distance.c 중간에 공백의 여부(dummy)를 판별하는 방법
#include <stdio.h>
int main() { char AA; <-- 1char = 1byte char strAA[1]; char strBB[2]; sizeof = 크기(길이) char strCC[3]; sizeof(strAA) 와 AA - strAA의 값이 동일한지 비교 char strDD[5]; 더미 공간이 있는지 확인할 수 있다. char strEE[9]; char strFF[17];
printf("AA's address: 0x%x, sizeof: 0x%x\n", &AA, sizeof(AA)); printf("strAA[1]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strAA, sizeof(strAA), &AA - strAA); /* 동일하면 공간이 없다는 뜻 printf("strBB[2]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strBB, sizeof(strBB), strAA - strBB); /*전체 크기에서 AA-BB주소공간을 빼기 printf("strCC[3]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strCC, sizeof(strCC), strBB - strCC); /* 나머지도 다 같은 뜻 printf("strDD[5]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strDD, sizeof(strDD), strCC - strDD); printf(" strEE[9]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strEE, sizeof(strEE), strDD - strEE); printf("strFF[17]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strFF, sizeof(strFF), strEE - strFF);
return 0; } |
=> 메모리가 꼭 순서대로 할당받지 않는 것을 알 수 있다. 중간에 더미 공간이 있을 수도 없을 수도 있다.
컴파일러가 CPU가 읽어들이기 좋은 배치에다가 배열을 해준다. 공간들은 2의 배수로만 늘어난다.
[예상] 스택의 구조가 아래와 같이 할당되는가?
<-- 낮은주소(0x00000000) 높은주소(0xFFFFFFFF) -->
+------+---------+--------+--------+--------+--------+--------+--+-------+
|......|strFF[17]|strEE[9]|strDD[5]|strCC[3]|strBB[2]|strAA[1]|AA|.......|
+------+---------+--------+--------+--------+--------+--------+--+-------+
주소1 주소2 주소3 주소4 주소5 주소6 주소7
=> 더미공간이 있는지를 판단하는것이 가장 중요하다
높은주소 - 낮은주소 = AA - strAA 가 strAA의 크기와 동일 하다면 더미공간은 존재하지 않는다.
printf("strAA[1]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strAA, sizeof(strAA), &AA - strAA);
[level9@ftz tmp]$ gcc -o distance distance.c
[level9@ftz tmp]$ ./distance
AA's address: 0xbfffe2ef, sizeof: 0x1 strAA[1]'s address: 0xbfffe2ee, sizeof: 0x1, distance: 0x1 /* &AA - strAA */ strBB[2]'s address: 0xbfffe2ec, sizeof: 0x2, distance: 0x2 /* strAA - strBB */ strCC[3]'s address: 0xbfffe2d0, sizeof: 0x3, distance: 0x1c /* strBB - strCC */ 25차이 strDD[5]'s address: 0xbfffe2c0, sizeof: 0x5, distance: 0x10 /* strCC - strDD */ strEE[9]'s address: 0xbfffe2b0, sizeof: 0x9, distance: 0x10 /* strDD - strEE */ strFF[17]'s address: 0xbfffe290, sizeof: 0x11, distance: 0x20 /* strEE - strFF */ |
====================================================================
메모리주소 변수명 변수의크기 메모리공간
====================================================================
0xbfffe6ee strAA[1] 0x1 (1 bytes) 0x1 (1 bytes) /* &AA - strAA */
0xbfffe6ec strBB[2] 0x2 (2 bytes) 0x2 (2 bytes) /* strAA - strBB */
0xbfffe6d0 strCC[3] 0x3 (3 bytes) 0x1c(28 bytes) /* strBB - strCC */
0xbfffe6c0 strDD[5] 0x5 (5 bytes) 0x10(16 bytes) /* strCC - strDD */
0xbfffe6b0 strEE[9] 0x9 (9 bytes) 0x10(16 bytes) /* strDD - strEE */
0xbfffe690 strFF[17] 0x11(17bytes) 0x20(32 bytes) /* strEE - strFF */
====================================================================
-> 실제 메모리 공간은 2의 배수 형태로 운영체제와 컴파일러마다 최고의 성능을 낼수 있도록 기본 원칙을 어기지 않는 범위 안에서 약간의 변형을 가한다.
(예상)
<-- 낮은주소(0x00000000) 높은주소(0xFFFFFFFF) -->
+------+---------+--------+--------+--------+--------+--------+--+-------+
|......|strFF[17]|strEE[9]|strDD[5]|strCC[3]|strBB[2]|strAA[1]|AA|.......|
+------+---------+--------+--------+--------+--------+--------+--+-------+
주소1 주소2 주소3 주소4 주소5 주소6 주소7
(실제)
+------+---------+--------+--------+--------+---+--------+--------+--+-------+
|......|strFF[17]|strEE[9]|strDD[5]|strCC[3]|25 |strBB[2]|strAA[1]|AA|.......|
+------+---------+--------+--------+--------+---+--------+--------+--+-------+
주소1 주소2 주소3 주소4 주소5 주소6 주소7
==============================================================================
2. gdb 사용법
gdb 사용법
-------------------------------------------------------------------------------
명령어 설명
-------------------------------------------------------------------------------
gdb <파일이름> 지정된 파일을 gdb로 열기
list gcc 컴파일시 -ggdb 옵션을 지정한 경우 소스 확인 가능
disassemble 주소/함수명 지정된 함수를 디스어셈블해 실행
run 지정된 파일을 실행
continue 브레이크 걸린 상태에서 계속 진행
break 주소/함수명 주소나 함수에 브레이크 포인터를 걸기
x/32x 주소 주소에서 32개를 16진수로 출력(x/32s는 문자열)
info registers 레지스터의 값을 출력
nexti 함수 내부로 들어가지 않고 한 라인 실행
stepi 함수 내부로 들어가면서 한 라인 실행
help 도움말 출력
backtrace 프로그램 실행의 스택 추적 결과 출력
quit gdb 종료
-------------------------------------------------------------------------------
[level9@ftz tmp]$ vi bof.c (# cat ../hint > bof.c ; vi bof.c)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> main() { char buf2[10]; char buf[10]; printf("It can be overflow : "); fgets(buf, 40, stdin); if(strncmp(buf2, "go", 2) == 0) { printf("Good Skill!\n"); setreuid(3010, 3010); system("/bin/bash"); } } |
필요하면 적당하게 편집작업을 한다.
[level9@ftz tmp]$ gcc -ggdb -o bof bof.c 원본 소스가 같이 내장된다. 디버깅 용도
[level9@ftz tmp]$ gdb bof ($ gdb /home/level9/tmp/bof)
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"... (gdb) quit |
[level9@ftz tmp]$ gdb
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu". (gdb) file /home/level9/tmp/bof Reading symbols from /home/level9/tmp/bof...done. (gdb) help /* 카테고리 커맨드 검색 List of classes of commands:
aliases -- Aliases of other commands breakpoints -- Making program stop at certain points data -- Examining data files -- Specifying and examining files internals -- Maintenance commands obscure -- Obscure features running -- Running the program stack -- Examining the stack status -- Status inquiries support -- Support facilities tracepoints -- Tracing of program execution without stopping the program user-defined -- User-defined commands
Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb) help data /* disassemble 커맨드를 볼 수 있다. Examining data.
List of commands:
append -- Append target code/data to a local file call -- Call a function in the program delete display -- Cancel some expressions to be displayed when program stops delete mem -- Delete memory region disable display -- Disable some expressions to be displayed when program stops disable mem -- Disable memory region disassemble -- Disassemble a specified section of memory display -- Print value of expression EXP each time the program stops dump -- Dump target code/data to a local file enable display -- Enable some expressions to be displayed when program stops enable mem -- Enable memory region inspect -- Same as "print" command mem -- Define attributes for memory region output -- Like "print" but don't put in value history and don't print newline print -- Print value of expression EXP printf -- Printf "printf format string" ptype -- Print definition of type TYPE restore -- Restore the contents of FILE to target memory set -- Evaluate expression EXP and assign result to variable VAR ---Type <return> to continue, or q <return> to quit--- set variable -- Evaluate expression EXP and assign result to variable VAR undisplay -- Cancel some expressions to be displayed when program stops whatis -- Print data type of expression EXP x -- Examine memory: x/FMT ADDRESS
Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb) list /* -ggdb옵션을 줘야 볼 수 있다. 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 main() 6 { 7 char buf[10]; 8 char buf2[10]; 9 10 printf("It ca be overflow : "); (gdb) list 1,20 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 main() 6 { 7 char buf[10]; 8 char buf2[10]; 9 10 printf("It ca be overflow : "); 11 fgets(buf, 40, stdin); 12 13 if(strncmp(buf2, "go", 2) == 0) 14 { 15 printf("Good Skill!\n"); 16 setreuid(3010, 3010); 17 system("/bin/bash"); 18 } 19 } (gdb) disassemble main Dump of assembler code for function main: 0x08048420 <main+0>: push %ebp 0x08048421 <main+1>: mov %esp,%ebp 0x08048423 <main+3>: sub $0x28,%esp 0x08048426 <main+6>: and $0xfffffff0,%esp 0x08048429 <main+9>: mov $0x0,%eax 0x0804842e <main+14>: sub %eax,%esp 0x08048430 <main+16>: sub $0xc,%esp 0x08048433 <main+19>: push $0x8048554 0x08048438 <main+24>: call 0x8048350 <printf> 0x0804843d <main+29>: add $0x10,%esp 0x08048440 <main+32>: sub $0x4,%esp 0x08048443 <main+35>: pushl 0x8049698 0x08048449 <main+41>: push $0x28 0x0804844b <main+43>: lea 0xffffffe8(%ebp),%eax 0x0804844e <main+46>: push %eax 0x0804844f <main+47>: call 0x8048320 <fgets> 0x08048454 <main+52>: add $0x10,%esp 0x08048457 <main+55>: sub $0x4,%esp 0x0804845a <main+58>: push $0x2 0x0804845c <main+60>: push $0x8048569 0x08048461 <main+65>: lea 0xffffffd8(%ebp),%eax 0x08048464 <main+68>: push %eax ---Type <return> to continue, or q <return> to quit--- 0x08048465 <main+69>: call 0x8048330 <strncmp> 0x0804846a <main+74>: add $0x10,%esp 0x0804846d <main+77>: test %eax,%eax 0x0804846f <main+79>: jne 0x80484a6 <main+134> 0x08048471 <main+81>: sub $0xc,%esp 0x08048474 <main+84>: push $0x804856c 0x08048479 <main+89>: call 0x8048350 <printf> 0x0804847e <main+94>: add $0x10,%esp 0x08048481 <main+97>: sub $0x8,%esp 0x08048484 <main+100>: push $0xbc2 0x08048489 <main+105>: push $0xbc2 0x0804848e <main+110>: call 0x8048360 <setreuid> 0x08048493 <main+115>: add $0x10,%esp 0x08048496 <main+118>: sub $0xc,%esp 0x08048499 <main+121>: push $0x8048579 0x0804849e <main+126>: call 0x8048310 <system> 0x080484a3 <main+131>: add $0x10,%esp 0x080484a6 <main+134>: leave 0x080484a7 <main+135>: ret End of assembler dump. (gdb) run Starting program: /home/level9/tmp/bof It ca be overflow : AAAA
Program exited with code 0221. 비정상 적으로 종료 되었다. 하고 끝난다(221) 그 중간에 코드를 분석하기 위해 브레이크 포인트를 건다. (gdb) break *0x08048438 break pointer를 정한다.(b *main+000) Breakpoint 1 at 0x8048438: file bof.c, line 10. 동적분석시 b.p 위치 매우 중요 (gdb) break *0x0804844f 입출력이 있는곳에 b.p 위치 권장 Breakpoint 2 at 0x804844f: file bof.c, line 11. printf 는 권장하지 않는다. (gdb) break *0x080484a6 입력받기 전 상태, 해당 코드 실행전 Breakpoint 3 at 0x80484a6: file bof.c, line 19. (gdb) run Starting program: /home/level9/tmp/bof Breakpoint 1, 0x08048438 in main () at bof.c:10 10 printf("It ca be overflow : "); (gdb) continue Continuing.
Breakpoint 2, 0x0804844f in main () at bof.c:11 11 fgets(buf, 40, stdin); (gdb) continue Continuing. It ca be overflow : AAAA
Breakpoint 3, main () at bof.c:19 19 } (gdb) x/s buf s는 string이란 뜻, buf안에 string을 해석 0xbfffedf0: "AAAA\n" (gdb) x/x buf x/x 버퍼에 있는 내용을 16진수로 출력 x/b 10진수로 출력 0xbfffedf0: 0x41414141 (gdb) info registers eax 0xffffffad -83 ecx 0xffffffad -83 edx 0x67000005 1728053253 ebx 0x42130a14 1108544020 esp 0xbffff1d0 0xbffff1d0 ebp 0xbffff1f8 0xbffff1f8 esi 0x40015360 1073828704 edi 0x80484d8 134513880 <-- 앞 16진수 / 뒤 10진수 형태 eip 0x80484a6 0x80484a6 변형이 안되는 레지스터는 둘다 16진수 eflags 0x282 642 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x33 51 (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y 아직 끝나지 않았는데 재시작 Starting program: /home/level9/tmp/bof
Breakpoint 1, 0x08048438 in main () at bof.c:10 10 printf("It ca be overflow : "); (gdb) nexti 현재 함수에서 다음번 째 코드로 이동 0x0804843d 10 printf("It ca be overflow : "); (gdb) nexti 11 fgets(buf, 40, stdin); (gdb) stepi 서브함수 : 함수안에서 명령어 라인 하나씩 이동 0x08048443 11 fgets(buf, 40, stdin); (gdb) stepi 한 개의 라인씩 실행된다.(멈춰있는 것이 아니다.) 0x08048449 11 fgets(buf, 40, stdin); (gdb) help List of classes of commands:
aliases -- Aliases of other commands breakpoints -- Making program stop at certain points data -- Examining data files -- Specifying and examining files internals -- Maintenance commands obscure -- Obscure features running -- Running the program stack -- Examining the stack status -- Status inquiries support -- Support facilities tracepoints -- Tracing of program execution without stopping the program user-defined -- User-defined commands
Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb) help backtrace Print backtrace of all stack frames, or innermost COUNT frames. With a negative argument, print outermost -COUNT frames. Use of the 'full' qualifier also prints the values of the local variables.
(gdb) backtrace #0 0x08048449 in main () at bof.c:11 #1 0x42015574 in __libc_start_main () from /lib/tls/libc.so.6 (gdb) quit The program is running. Exit anyway? (y or n) y |
break pointer는 어디에다 걸어야 하나?
1. 모든 함수에다 break pointer를 건다. (printf 제외)
2. 입력 받는 전후 부분에다가 break pointer를 건다.
3. 감각 부분 (점프 부분)
'Learning > └◆Reversing' 카테고리의 다른 글
09_Level9 -> Level10[FTZ] 버퍼 오버 플로우 소개 (0) | 2017.01.29 |
---|---|
[참고] 버퍼 오버 플로우 (0) | 2017.01.29 |
08_Level8 -> Level9[FTZ] 로컬/원격 패스워드 크랙 (0) | 2017.01.29 |
07_Level7 -> Level8[FTZ] 암호학(2진수 <->10진수 <-> 16진수) (0) | 2017.01.29 |