해당 글의 원문은 아래 주소에서 확인할 수 있다.

bpsecblog.wordpress.com/2016/05/20/gdb_memory_3/

 

(完)우리집에 GDB 있는데… 메모리 보고갈래?(3)

우리집에 GDB 있는데… 메모리 보고 갈래?(3) Day #3. 이쯤 했으면 이제 그만 엔터치자 오늘부터 1일♡ 1) Debugging  (IDA, GDB 사용) 우리는 이미 tomato.c 소스가 있지만, 보통 소스는 잘 안주잖아여 없다

bpsecblog.wordpress.com

소스 코드가 없을 경우 IDA의 헥스레이 기능을 활용하면 다음과 같이 바이너리를 디컴파일 하여 원본 코드와 흡사한 소스를 보여준다. f5 단축키를 이용하여 사용할 수 있다. (헥스레이 기능이 매우 편리할 것 같아서 조만간 IDA나 헥스레이 기능이 있는 무료 툴인 기드라를 설치해야 겠다.)

IDA에서 8번째 라인을 보면 strcpy((char *) &v4, argv[1]); 코드에서 버퍼오버플로우 취약점이 있다. argv[1]을 v4 변수에 복사할 때 버퍼 크기를 검증하는 코드가 없기 때문이다. 변수 v4와 v5는 지역변수 이기 때문에 스택에 할당되고, length가 검증되지 않은 v4에 argv[1]의 값이 복사될 때 v4는 할당받은 공간 그 이상을 사용하게 되고, v5가 v4보다 높은 주소에 할당되어 있다면 v5에 원하는 값을 삽입할 수 있다. strcpy는 버퍼오버플로우 취약점이 발생할 가능성이 있기 때문에 strcpy_s로 대체하여 사용하는것을 권고하고 있다.

main 함수의 어셈 코드는 다음과 같다.

strcpy 함수의 주소는 0x08048515이므로 이 위치에 breakpoint를 걸고 strcpy가 실행되기 전후의 스택을 확인할 것이다.

0xbffff022는 esp가 가리키는 값 즉, v4이고, 0xbffff2d7은 esp+0x4가 가리키는 값 즉 argv[1]이다. strcpy 호출 전에는 argv[1]에만 값이 들어 있다가 strcpy로 v4에도 값이 들어간 것을 확인할 수 있다.

다음은 main의 어셈코드 일부이다. 

cmp는 비교하는 명령으로 첫번째 값에서 두번째 값을 뺄 때 마이너스가 되면 CF=1, 0이면 ZF=1 플래그가 설정된다. 플래그는 CPU의 플래그 레지스터에 저장되는 처리 데이터 이다. 플래그의 설정에 따라 분기문 조건이 다르다. 아래 jne의 경우 jump not equal로 비교 결과가 다르면 main+108 주소로 점프한다. 이 주소로 점프할 경우 system 함수를 실행하지 않는다. 따라서 ebp-0xc의 값이 0x1 이여야 system 함수를 실행하는 것이다.

현재 스택의 구조는 다음과 같다.

v4의 값이 흘러 넘치면 v5에도 영향을 미칠수 있다.

v4의 범위가 벗어나서 이후 메모리에 42(B)가 들어간 것을 확인할 수 있다.

v4의 값을 흘러넘치게 해서 v5가 0x00000001이 되면 셸을 띄울 수 있을것이다.
B로 채워진 부분들이 0x00000001이 되면 조건문은 일치시켜서 셸을 띄울 수 있을 것 같다.

다음과 같이 넣으면 gdb로 확인했을 때 다음과 같다.

메모리에 들어가는 값을 보면 0x00000001이 아닌 다른 값이 들어가는 것을 확인할 수 있다. 문자열 00000001이 들어가는 것이다. hex값을 메모리에 넣으려면 다음과 같이 python 이나 perl 같은 스크립트 언어를 사용하여 넣어야 한다.

python -c 옵션을 사용하면 command 라인에서 출력할 수 있고, 커맨드의 출력값은 `(백틱)을 이용해서 넘길 수 있다. tomato 파일의 인자로 백틱으로 감싼 파이썬 명령을 넣으면 v5 변수에 0x00000001을 덮어쓸 수 있다.

파이썬 명령어가 tomato 파일의 인자로 들어가서 v4 변수를 덮어쓰고 v5 도 0x00000001로 채워서 셸이 따지는 것을 확인할 수 있다.

 

+ Recent posts