Study/CS

Lab3: Attacklab (phase 1)

mgchem 2023. 10. 29. 18:44

Attacklab

 

 

시스템프로그래밍 Lab3 Attacklab이 나왔다. Bomblab에 이어 assembly를 다루는 과제이다.

Bomblab이 gdb로 한 줄 씩 실행하며 폭탄이 터지지 않는 입력값을 찾는 문제였다면,

Attacklab에서는 주어진 코드의 취약점을 파악하고 원하는 결과를 내는 입력값을 찾는다.

그 과정에서 Code injection(phase 1, 2, 3)과 return-oriented programming(phase 4, 5) 기법을 사용하게 된다.

 

 


 

Overview

 

(gdb) disas getbuf
(gdb) disas touch1

getbuf, touch1 함수의 구성을 살펴보자.

 

우리의 목표는 비정상적으로 긴 길이의 입력값을 이용해 return address를 덮어씌워 touch1의 주소값으로 바꾸는 것이다.

getbuf 함수 시작할 때 %rsp를 0x18만큼 줄이는 부분에 주목하자.

Gets 함수는 입력값을 받아 stack에 저장하는 함수일 것이고, 그 외에 특별한 점은 없다.

 


 

To call touch1()

 

getbuf 함수가 실행되면 %rsp를 0x18만큼 줄인다 == stack 크기를 24만큼 늘린다.

늘어난 stack의 크기가 곧 buffer의 크기다. 주소값 1당 용량은 1B, 총 24B를 채우기 위해서는 24개의 char가 필요하다.

String은 마지막에 null character 하나가 추가되어 입력되므로 24자리의 임의의 string을 입력하면

null(00)이 buffer 용량을 초과하여 return address (hex) 마지막 두 자리를 00으로 바꾼다.

 

'1' 24개를 입력하면 마지막에 추가되는 null character에 의해 return address가 바뀌어 segmentation fault가 발생하지만,

'1' 23개를 입력하면 null character 하나까지 포함해도 buffer 용량 24B를 초과하지 않아 문제가 발생하지 않는다.

 

getbuf 마지막에 ret에서 touch1 함수로 가기 위해서는 return address를 touch1 함수의 주소인 0x4018c7로 바꿔야 한다.

Little endian은 byte 순서가 반대이므로 24자리 임의의 string에 c7, 18, 40과 대응하는 문자 세 개를 순서대로 붙여서 입력하면 된다.

 

'1'은 ascii로 31과 대응하므로 

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 c7 18 40

를 txt 파일(1.txt)로 저장하고 hex2raw를 통해 이에 대응하는 string을 txt 파일(1-raw.txt)로 저장한다.

$ ./hex2raw < 1.txt > 1-raw.txt
$ ./ctarget < 1-raw.txt

string이 들어있는 txt파일(1-raw.txt)을 입력값으로 하여 ctarget을 실행하면,

 

String 입력만으로 우리가 원하는 touch1 함수를 실행하는데 성공하였다.