본문 바로가기

ctf

[CodeGate 2015 CTF] systemshock

setuid 가 걸려있는 64bit ELF 바이너리이다.


소스코드를 간단히 분석해보면,

가장 먼저, sub_40075c() 함수로 진입하여 환경변수 영역을 초기화 한다. 그 후 argv[1] 의 값이 있는지 확인한 후, 값이 존재한다면 strcat() 함수를 사용하여 argv[1] 의 값을 &command 에 넣게 되는데 여기서 크기 검증을 하지 않기에 stack overflow가 발생한다. 그 후 __ctype_b_loc 함수를 통해 특수문자 검사를 하고, 특수문자가 존재하지 않는다면 system() 함수를 통해 어떤 명령을 실행시킬 수 있다.



ASLR, NX 가 걸려있고, Canary 또한 존재한다.


for 문을 확인해보면, strlen(argv[1])을 구해서 특수문자를 검사하게 되는데 argv[1] 의 주소는 스택에 있다.

즉, argv[1] 의 주소까지 접근하여 주소를 조작할 수 있다. 

정확히 argv[1] 의 주소를 조작하기 위해서 &command 부터 argv[1] 의 offset 을 구해야한다.


$rsi = argv[1] addr

$rdi = &command


0x7fffef7f1190 주소에 &argv[1] 이 존재한다.

offset = 0x7fffef7f1190 - $rdi(0x7fffef7f0f80) = 528byte

그러나, command 에 이미 "id " 문자열이 들어가 있기 때문에 3byte 만큼 빼주면 525byte 가 정확한 offset 임을 알 수 있다.


"A" * 525byte + "BBBBBB" => argv[1]의 주소를 조작한 것을 확인할 수 있다.


strlen(argv[1]) 리턴 값을 조작하기 위한 여러가지 방법이 있는데,

[*] argv[1] 주소를 Null 로 초기화 된 환경변수 영역으로 조작

[*] 64bit 고정된 주소인 vsyscall 영역으로 조작

[*] 521byte + ";sh;" 와 같이 크기에 맞춰 명령을 넣어주면 끝에 "\x00" 이 붙어서 조작할 수 있다.



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  exploit.py  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

import os


command = ";cat flag;sh;"

payload = "./shock " + "A" * (525 - len(command)) + command


os.system(payload)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



'ctf' 카테고리의 다른 글

[SECCON 2016 CTF] cheer_msg  (0) 2016.12.12
[CodeGate 2015 CTF] bookstore  (0) 2016.11.14
[CodeGate 2015 CTF] yocto  (0) 2016.07.06
[CodeGate 2014 CTF] 4stone  (0) 2016.06.24
[CodeGate 2014 CTF] dodoCrackme  (0) 2016.06.11