본문 바로가기

Wargame/LOB(Redhat)

[Lv.2] Gremlin

Gate에 이어, Gremlin을 풀이합니다.





Login :  gremlin

pass   : hello bof world


gremlin 환경에 주어진 cobolt.c 코드입니다. 1번과 다른점은, 버퍼(배열)가 작네요.


 이게 의미하는 건 기본적으로 redhat에서 동작하는 system("/bin/sh") 쉘코드가 24바이트인데 이걸 다 넣지 못한다는 거에요. 즉, 버퍼에 쉘코드를 삽입하는 방법은 쓰지 못하게 되었습니다.


하지만, 이 redhat 환경에서는 아무런 보호기법이 걸려있지 않기 때문에 스택의 어느곳이든 값을 넣을수만 있다면 쉘코드 실행이 가능합니다. 


가령, argv[] 나 환경변수 영역에 값을 넣어도 말이지요. (이 두 군데는 저희들이 임의로 값을 input할 수 있는 곳이고 스택의 주소값이 바뀌지 않기 때문에 [ASLR 기법 미적용] 쉽게 접근 가능합니다.)


굳이 쉘코드나 특정 값 바이너리(./cobolt와 같은 실행 프로그램) 에 정직하게(strcpy로 argv[1]에 있는 값을 복사한다고 해서 argv[1]만 이용하지 말라는 뜻입니다.) 넣지 말라는 뜻이지요.




각설하고, 배열이 제한되면 왜 쉘코드 삽입이 안되냐구요?




Linux 24byte Shellcode x86 : "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"


리눅스 쉘코드 중 16바이트는 버퍼에 들어갈 것이고, 남은 쉘코드의 8바이트 중 4바이트가 sfp(여러분이 흔히 알고 있는 ebp 영역.) 에 들어갑니다. 

그리고 마지막 4바이트가 return address 영역에 덮어지죠. 이렇게 되면 쉘코드가 위치한 곳을 가리킬 입력값을 넣을 수 없습니다.


이런 이유로 버퍼는 쓸 수 없게 되었습니다. 그러므로 저는 strcpy로 복사될 buffer 영역이 아닌, 


바이너리의 실행결과와는 상관없는 부분인 argv[2]를 가리키도록 하겠습니다. 바이너리에서는 이 argv[2]를 사용하지 않지만 저희가 바이너리에 input 값을 넣었기 때문에

스택의 어딘가에는 이 값이 존재합니다.



nopsled를 넣은건 디버거에서 확인한 주소와 실제 바이너리의 주소가 약간 차이가 나기 때문에 쉘코드를 편하게 가리키기 위해 넣었습니다.

(nopsled의 어디를 가리켜도 결국 쉘코드로 가기 때문입니다.)



gdb -q coo 로 바이너리를 열어 어셈블리코드를 확인합니다.

strcpy의 두번째 인자는 edx네요. (왜 두번째 인자가 edx냐면 Basic System Hacking Technique의 핸드레이 글을 참고해주세요.)


그리고 strcpy 후에 값이 어떻게 들어갔는지 확인하기 위해 0x8048465에 브레이크를 걸어줍니다.



argv[1]에 24바이트를 넣고, 저희가 입력값으로 사용할 input값을 argv[2]에 넣어 스택의 상태를 확인합니다.


*주의할 점은 저희가 입력한 값의 개수에 따라 입력값이 위치한 스택의 주소도 바뀌기 때문에 되도록이면 공격코드로 사용할 값과 디버거에서 사용한 값을 맞춰주시기 바랍니다.



edx 값이 0xbffffbe7 이었으므로 x/32wx 0xbffffbe7로 스택을 확인합니다.


nop sled가 보이네요!! 그럼 이 중 argv[]의 시작부분과 너무 가까운 곳은 안되고, 적당한 부분인 0xbffffbf7을 사용하도록 합니다.


payload : argv[1] = 더미값 20 byte + 0xbffffbf7

argv[2] = "\x90" * 100 + shellcode 


이렇게 argv[2]를 가리키면? 성공입니다. 


Login :  cobolt

pass   : hacking exposed



'Wargame > LOB(Redhat)' 카테고리의 다른 글

[Lv.1] Gate  (2) 2016.04.07
들어가기 전, 편한 환경에서 풀기 위한 환경세팅  (0) 2016.04.07