오늘은 소스코드를 어셈블리어로 보고 이해를 할수 있게 정리자료를 적어보고자 한다.
일단 레지스터를 알아보기전에 메모리의 구조가 어떻게 이루어지는지 보겠다. 0x00000000
0xffffffff
Code 영역은 말그대로 코드 자체를 구성하는 메모리 영역이다.
Data 영역은 전역변수,정적변수,배열,구조체 등이 저장된다고한다.
추가로 초기화 된 데이터는 Data 영역에 저장되고 초기화 되지 않은 데이터는 BSS(Block Stated Symbol)영역에 저장된다고한다.
Heap 영역은 필요로 의해서 메모리를 할당 하고자 할떄 위치하는 메모리영역이다.
예를 들어 C의 malloc()함수를 사용하면 이 영역에 데이터를 저장 할 수 있다고한다.
Stack 영역은 매개변수,지역변수,리턴 값 및 연산 시 일어나는 값들을 임시로 저장한다.
Stack 영역은 LIFO(Last In First Out)로 이루어진다.
LIFO란?
사진과 같이 마지막으로 들어간것이 처음으로 나온다는 뜻이다.
레지스터는 목적에 따라서 4가지의 레지스터로 범용 레지스터,세그먼트 레지스터,플래그 레지스터,인스트럭션 포인터로 나뉜다고한다.
범용레지스터에는 EAX,EBX,ECX,EDX,ESI,EDI,EBP.ESP가 있다.
EAX 레지스터는 산술을 수행하며 함수의 반환값이 이레지스터에 저장된다.
EBX,ECX,EDX,ESI,EDI도 각각의 쓰임새가있겠지만 저장공간이라 생각하면 된다.
EBP는 지역변수를 가르키는 포인터이다.
ESP는 스택의 진행상항을 가르키는 포인터이다.
세그먼트 레지스터는 특정 세그먼트를 가리키는 포인터 역활을 한다.
CS세그먼트는 Code Segment
DS세그먼트는 Data Segment
SS세그먼트는 Stack Segment를 가리킨다.
인스트럭션 포인터는 EIP로 현재 코드의 진행상황을 가르키는 포인터이다.
이제부터는 func.c라는 이름의 소스코드를 GDB를 이용해서 분석해보고자 한다.
GDB를 이용해서 소스코드와 비교하면서 보기위해 일단은 소스코드를 보겠다.
debug함수에 3개의 인자 1,2,3을 넘겨서 그값을 모두 더한 후 result변수에 저장을한후
반환값으로 result를 넘긴후 그값을 ret에 넣는 소스코드이다.
그럼 GDB로 이 소스코드를 열어보도록 하겠다.
GDB를 사용할수 있는 명령어들을 알아야 GDB를 할 수 있기 때문에
GDB에 관한 명령어는 http://egloos.zum.com/psyoblade/v/2653919를 참고하면 될 것 같다!
일단은 disasa명령어를 이용해서 func프로그램에 있는 함수 두개를 어셈블리코드로 바꿔 줄 것 이다.
첫째로 main함수를 분석하겠다.
일단 main+0,main+1,main+3까지 분석해 보겠다.
push %ebp란 이전 함수의 EBP(base pointer)를 저장하면 ESP(stack pointer)는 4바이트 아래를 가리키게 될것이다.
(간단하게 함수복귀 지점을 넣는다고 생각하면 될 것 같다.)
GDB를 이용해 정말로 4바이트 아래를 가르키는지 확인해 보겠다.
break포인트를 main+0번과 main+1번에 걸어서 비교를 해보겠다.
main+0번에 옆에 보면 break가 걸려있는것이 보인다.
ESP의 값은 0xffffd63c로 되어있다.
이번에는 main+1번에 걸고 실행 시킨 값을 보겠다.
ESP값을 보면 4바이트 아래인 0xffffd638을 가르치는 것을 알 수 있다.
main+3에 break포인트를 걸겠다.
EBP의 값과 ESP의 값이 같아진 것을 볼 수 있을것이다.
그럼 mov %esp,%ebp줄이 무슨 행동을 하는지 알 수 있을것이다.
그렇다 mov는 왼쪽에있는 값을 오른쪽으로 복사해주는 기능이다.
mov %esp,%ebp를 통해 함수의 EBP와ESP가 같은 지점을 가리키게 된다.
main+6 break포인트를 걸겠다.
sub $0x10,%esp 라는 줄을 실행을 했다.
그런데 EBP와ESP의 값을 보면 10이 차이가 나는 것을 알 수 있다.
그럼 sub $0x10,%esp 이 줄이 무엇을 하는지 알 것이다.
그렇다 esp의값에서 10을 빼는 명령어 sub인것이다.
sub을 해주는 이유는 지역변수의 공간을 할당해주는 것이다.
여태까지 실행한 세개의 줄은 Procedure prelude과정이라고 한다.
이번에는 break포인트를 main+12에 걸겠다.
소스코드와 비교를해보면 main+6,main+8,main+10이 무엇을 하는지 알 수 있을것이다.
1,2,3을 debug 함수에 넘기기 위해서 메모리에 올려놓은 것을 볼 수 있다.
main+12줄은 설명을 하겠다.
call 명령어는 함수를 호출하는 기능을한다.저 줄은 debug함수를 호출하는 문장인 것 이다.
그럼 debug함수로들어가서 분석을 해보겠다.
.
일단 debug+0,debug+1,debug+3은 메인 함수에서 했으므로 건너뛰겠다.
break포인트를 debug+9에 걸겠다.
그 후 실행을 시켜본후 i r을 해보면 edx에 1이 들어가있는걸 볼 수 있다.
그럼 이줄은 무슨의미일까?
ebp+8에있는 위치에 값을 edx에 넣는다는 의미이다.
그럼 정말로 edx에 값이들어가있는지 ebp+8위치에 1이 있는지 보겠다.
edx를 보면 1이 들어가있는 것이 보인다.
edx의 값을 확인 했으니 ebp+8을 해보겠다.
ebp의 값이 0xffffd614인데 +8을 해서 0xffffd61c이 된것이다.
0xffffd61c에도 1이라는 값이 들어있는것을 볼 수 있다.
debug+9줄도 똑같은 의미로 ebp+c에 있는 값을 eax에 넣는 것이다(ebp+c에는 2가 들어있다).
이번에는 break포인트를 debug+14에 걸겠다.
break포인트를 건후 i r을해서 무엇이 변했는지 보겠다.
add %eax,%edx를 실행시켰다.
edx의 값을 보면 3이들어있는 것을 보인다.
그렇다 add는 왼쪽과오른쪽의값을더해서 오른쪽에 저장을 하는 것 이다.
debug+14,debug+17까지도 무슨의미인지 알것이라고 생각한다.
debug+17줄에서 최종적으로 eax에 6이라는 값이 들어간다.
이번에는debug+19줄을 해석해보겠다.
eax에 있는 값을 ebp-4에다 복사해서한다.
debug+22줄은 그 값을 다시 eax 넣는다고한다.
마지막으로 leave와ret
leave는 Procedure prelude과정을 되돌리는 일을 한다.
그것을 함으로써 esp값을 찾을수있다.
ret은 return address가 POP되어 EIP에 저장된다.
그럼이제 main으로 다시 돌아가겠다.
break포인트를 main+20에 걸고 main+17이 무슨 줄인지 보겠다
esp에+c 즉 12바이트를 줄인다는 것이다.
add를한다고 공간을 넓힌다고 생각하면 안된다.
stack은 높은주소에서 낮은주소로 자라기 때문이다.
main+20줄은 ebp-4공간에 eax의 값 6을 넣는 것이다.
그후 eax를 0으로 초기화시켜준후 프로그램이 끝난다
소스코드와 일치하도록 분석을 해보았다.
'SYSTEM HACKING > 기법' 카테고리의 다른 글
DAY-6 Return To Library (0) | 2017.11.11 |
---|---|
DAY-5 쉘코드 작성 (0) | 2017.11.10 |
DAY-4 프로세스 디버깅 (0) | 2017.11.02 |
DAY-3 버퍼오버플로우를 풀어보자 (0) | 2017.10.23 |
DAY-1 Command Injection (0) | 2017.10.16 |