대망의 마지막 문제의 힌트입니다.


bleh이라는 이름의 크기로 버퍼가 80의 크기로 주어져있네요 
fgets란 함수로 문자열을 입력받지만 79의 크기로 제한을 한 보안 코딩이 되어있네요
버퍼 오버플로우는 사실상 힘들거같습니다(제 짧은 지식상..)


setreuid로 다음 레벨의 권한을 얻을 수 있을거같습니다만 쉘을 실행시키는 명령어가 없으므로 쉘 코드가 필요한것을 알 수 잇겠습니다 


헌데 printf(bleh) 어디서 많이 본 친구 아닌가요 ?
바로 LEVEL11에서 만나본 포맷스트링버그를 이용해보면 될거같습니다

포맷 스트링 버그에 대해서 제가 공부한 지식으로 짧게나마 설명 해 보겠습니다 .
이 문서 저 문서 한번쯤 휙휙 본 지식이기에 출처를 적을 수가 없는점 양해부탁드립니다.

포맷스트링버그는 프로그래머의 작은 실수로 일어나는 해킹기법입니다 
보통 printf 함수를 사용할때는 printf("%d",i); 이런 방법과 저 코드처럼 printf(bleh); 아예 배열을 printf에 넣어버리는 방법이 존재합니다 .

허나 후자의 경우에는 문제점이 존재합니다 bleh안에 "서식문자"가 존재하는 경우에 문제가 발생하게 됩니다 .
bleh을 출력하다가 %d와 같은 서식문자를 만나게되면 출력해야 하는 문자열이 아닌 서식문자로 인식을해버리는 곳에서 문제가 발생하게됩니다.

서식문자를 만나면 메모리의 다음 4바이트를 출력 해버리는 현상이 발생합니다.
만약에 해당 코드에 AAAA%x를 입력하게 되면 뭐가 나오게 될까요 ?

level20은 심볼을 다 날려버려서 gdb도 안열려서 스택을 확실히 알 방법이 제 현재 지식으로는 없네요 ..대충 예상이라도 해봅시다 

print(bleh)          ----낮은 주소 

fgets

setreuid

bleh[80]

dummy

sfb

ret                   ----높은 주소 

AAAA%x를 입력하면 현재 esp위치에서 (print(bleh)) 4바이트 증가한 메모리의 내용을 16진수로 출력하는것인데 
AAAA가 증가햇으니 0x41414141이 출력되야 하는것이 정상이겠지요 

근데 4f가 나오네요 ? bleh[80]이 제대로 읽히지 않은것을 보아하니
print(bleh) bleh[80] 사이에 값들이 추가적으로 존재하는것을 예상할 수 있습니다 

그렇다면 서식문자를 몇개 넣어줘야지 bleh[80]에서 제대로 값을 읽어오나 봐보겠습니다.


서식문자를 네번 써주니 41414141이 제대로 출력되는것을 볼 수 있습니다 .

스택상의 거리는 4개라고 생각할 수 있습니다 .(dummy가 12BYTE라고 예상가능)

서식문자 %n에 대하여 적어보겠습니다.

%n은 다른 서식문자들과는 다른 역할을 합니다
%n이 나오기 전에 출력된 자릿수를 계산한 후 스택의 다음 4바이트에 있는 내용을 주소로 생각하고 그 주소에 계산햇던 자릿수를 입력합니다.

예를 들어서 %10000c%n이라고 표현을 한다면 10000이라는 숫자를 넣을 수 있습니다.
ret 주소에 쉘 코드의 주소를 넣을 수 있다는 뜻입니다 .


여기서 %임의정수c를 이용하면 %n이 인식하는 자릿수를 입맛대로 정할 수 있게됩니다.
근데 저 %임의정수c에도 %c라는 서식문자가 존재하기 때문에 4바이트도 함께 입력을 해주어야합니다 .

이제 쉘코드의 주소를 입력해볼겁니다
헌데 일반적인 시스템에서는 너무 큰 숫자는 지정할 수 없으니 10진수로 바꿔서 입력을 하되 4바이트 (12345678) 를 2바이트씩 (1234/5678)로 나누어서 입력합니다.
ret주소를 구해야 하는데 gdb가 심볼이 날라가서 안열리는군요 ?
그렇다면 LEVEL11에서 적어놨던 .dtors를 이용합시다!

.dtors = main 함수가 끝난 후 실행을 하는 명령이 존재 하는 곳

자 여기에 쉘코드를 덮어 써서 실행을 시키면 될거같습니다 

.dtors주소를 알아보겠습니다!



08049594 네요 여기서 이제 +4 즉 08049598을 하면 ret값입니다!

ret주소에는 08049598에 쉘 주소의 절반(2바이트)를 입력하고 
2바이트가 증가한 0804959a에 쉘 주소의 나머지 절반을 입력해줍니다 . 

내킨김에 쉘 주소도 에그를 이용해서 구해봅시다 




0xbffff2cb가 나왔습니다 .

아까 위해서 설명했던거처럼 쉘코드의 주소를 2바이트씩 나누고 10진수로 바꿔서 입력을 해봅시다 .

bfff / f2cb 

f2cb = 62125

bfff = 49151 

자 그럼 여기까지 구한 정보로만 페이로드를 짜보겠습니다 

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%62125c%n%49151c%n 이 되겠네요 

여기서 8x란 쉘코드가 들어갈 ret의 주소가 bleh내에 존재하기 떄문에 esp를 bleh문까지 넘기기 위함이며 굳이 %8x를 쓰는경우는 8바이트를 정확히 출력하기 위하여 입니다 

허나 이대로만 하면 권한을 취득할 수가 없습니다 무엇이 문제냐 하면

아까 %n은 자신이 나오기 전의 모든 자릿수를 계산한다고 드렸습니다 그렇다면 

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x

4 + 4+ 4+ 4 +8 + 8+ 8  = 16 + 24 = 40 

40 바이트를 계산하겠네요 그렇다면 아까 구한 62125에서 40을 빼면 

62085겟네요 

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%62085c%n%49151c%n

근데 이렇게 해도 실패합니다 또 뭐가문제냐 하면 

%n이 뒤에 하나 더잇네요 49151 부분에 말이죠 앞에 자릿수를 모두 계산한 값이

아까 40을 뺏던 62805입니다 근데 49151에서 62125를 빼면 음수가 되버리네요 ?

bfff : 49151 에서 앞에 1을 붙이면 1bfff : 114687이 나옵니다 

이렇게 나온114687에서 62125를 빼면 52562가 나오네요 

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%62085c%n%52562c%n 최종으로 이렇게 나왔습니다 .

.(대충 값 정리)
dummy | .dtors Address(1) | dummy | .dtors Address(2) | %08x | %08x | %08x |
%shell(1)c | %n | %sheel(2)c | %n


clear했습니다 




수고하셨습니다 이해가 안되시는 점이나 궁금하신점은 질문 주시면 제가 알고잇는 지식이나 직접 알아봐서 알려드리겠습니다

p.s ( AAAA는 제 생각에는 더미값이라 생각되어서 반드시 넣어줘야 한다고 생각하는데 안넣어줘도 된다는 의견이 존재하는데 혹여나 이러한식으로 푸신분이 계시면 페이로드좀 보여주시면 감사하겠습니다 


'해커스쿨 ftz' 카테고리의 다른 글

FTZ - level19 Chaining RTL  (1) 2016.06.12
FTZ 정리  (0) 2016.05.22
FTZ-LEVEL19  (0) 2016.04.25
FTZ-LEVEL18  (0) 2016.04.24
FTZ-LEVEL17  (0) 2016.04.24

+ Recent posts