본문 바로가기

System Programming/CSAPP Lab

[Buffer Lab] Level 1, Stack Corruption 이용하여 함수 argument 조작하기

Level 1의 목표

Level 1에서는 fizz 함수로 흐름을 우회하되, 여기서 cookie를 함수의 argument로 넘겨준 것과 같은 효과를 주도록 해야 한다. 그래서 if 문으로 들어와 문자열을 출력하는 것이 목표이다.

 

즉, 함수의 흐름을 바꾸는 것은 Level 0과 같지만, 함수의 argument에 대해 분석해본다는 점에서 다를 것임을 알 수 있다.

 

fizz 함수의 시작 주소 값을 확인한다

시작 주소 값은 0x08048c42 이다. Level 0를 풀었으므로, getbuf 함수에서 stack corruption을 발생시켜 원하는 주소 값으로 jump 하는 방법을 알고 있다. exploit string file만 바꿔준다.

실행 결과, fizz 함수에는 도달하였으나, val==cookie 조건을 만족하지 못해 if-else 문까지는 원하는 대로 흐름을 바꾸지 못하였다.

 

fizz 함수 내의 분기문 확인

fizz 함수 전체의 assembly code를 보면 다음과 같다.

분기문은 9줄에 하나 있고, validate 함수를 호출하는 부분을 통해 15줄에서 jump하지 않는 부분이 if 문, jump 하는 부분이 else 문임을 알 수 있다. 우리가 원하는 동작은 jump를 하지 않는 것이다.

 

지금 상태에서 9줄에 breakpoint를 걸어두고 eax 레지스터 값을 확인하면 1이다. 그리고 비교의 대상이 되는 값을 주소로 하여 메모리 값을 참조해보면, 여기에 cookie 값이 저장되어 있다.

그러면 이제 해야 할 일은 eax 레지스터 값을 cookie 값으로 만들어야 한다.

 

스택 값의 추적

fizz 함수의 assembly code를 바탕으로 스택 포인터의 변화를 분석해보면 아래 그림과 같다.

새로운 정보의 저장과 기존 정보의 저장을 위헤 esp, ebp 레지스터의 값을 적절히 더하고 빼는 것은 크게 중요하지 않아보인다. 여기서는 결국 eax 레지스터에 값을 할당할 때 어느 주소 값을 접근하냐가 중요한데, 이를 살펴보면 0x ~ 7c 부분이다. 참고로, 스택 주소 상위 6-bit은 항상 0x55683c ~로 같기 때문에 그림에는 하위 2-bit만 표시하였다.

 

이전 Level 0에서의 분석 결과와 합쳐보면, 스택에 정보가 저장되는 방식은 다음 그림과 같다.

이전에는 0x ~ 74의 부분을 바꿔주어 함수의 return address를 조작한 것이었고, 이번에는 0x ~ 7c 부분을 바꿔주어 함수 내에서 비교 대상이 되는 값을 바꿔주어야 한다. 처음에 assembly code에 익숙하지 않아 cmp의 operand를 상수 값인지, 메모리 주소 값이어서 메모리를 참조해야 하는지가 헷갈리는데, $ 기호가 붙은 것이 상수이고 그렇지 않으면 메모리를 참조한다는 것이다.

 

그러면 이전 Level 0처럼 문자열을 입력하되, 0x ~ 78에 저장될 값은 상관 없으니 00 으로 적절히 채워주고, 0x ~ 7c에 저장되는 값을 eax 레지스터의 비교 값인 cookie 631743dd로 입력해주면 된다. 물론 byte 순서는 반대로 해주어야 한다.

 

Stack Corruption을 일으키도록 input string 바꾸기

Level 0 바탕으로 처음으로 작성했던 문자열에서 마지막 한 줄을 더 추가해주면 된다.

이제 이를 hex2raw 프로그램에 넣고 변환시킨 뒤, bufbomb 프로그램을 실행시키면 다음과 같이 성공했다는 결과를 얻을 수 있다.