LOB 3번째는 cobolt를 잡고 goblin으로 레벨업 하는 문제입니다.

 

우선 goblin의 코드를 확인해 보도록 하겠습니다.

LOB 2번째와 마찬가지로 버퍼의 크기가 매우 작고, 바뀐 점이라면 매개변수를 통한 입력에서 표준입력으로 변경되었네요.

 

버퍼의 크기가 작기때문에 환경변수에 쉘을 등록하고, 그 주소값으로 ret를 덮어야 할것 같습니다.

 

우선 gdb를 통해 ret를 덮기 위해서 필요한 입력 수를 확인해 보도록 하겠습니다.

필요한 입력의 크기는 20byte임을 알 수 있네요.

 

이제 환경변수에 쉘코드를 입력하고 주소값을 확인하도록 하겠습니다.

0xbffffe31에 쉘코드가 올라가 있네요.

20byte입력을 하고 쉘코드 주소를 입력해 ret를 덮도록 하겠습니다.

됫네요. 정상적으로 goblin의 쉘을 획득 하였습니다.

 


goblin의 패스워드는 hackers proof이네요.

LOB 두번째는 cobolt를 무찌르는 겁니다.

우선 cobolt.c의 코드를 확인해 보도록 하겠습니다.

strcpy라는 취약한 함수를 이용해서 BOF 를 하면 되구요. Buffer 의 크기는 16byte밖에 되지 않네요.

gremlin때는 buffer에 직접 쉘코드를 넣을 수 있을 만큼 크기가 충분했으나 이번에는 크기가 작으니 쉘코드를 환경변수에 등록하고 ret를 환경변수의 쉘코드 주소로 변경해 주어야 할것 같습니다.

 

우선 gdb로 확인해 보도록 하겠습니다.

ebp-16에 값을 입력하네요. SFP까지 포함해서 20byte만 넣어주면 될듯 합니다.

 

그럼 환경변수에 쉘코드를 등록하고 주소를 가져오도록 하겠습니다.

쉘코드가 들어있는 환경변수의 주소는 0xbffffe2f네요.

20byte를 입력하고 주소값을 넣어 ret를 덮도록 하겠습니다.

정상적으로 cobolt의 쉘이 획득되었습니다.

 

cobolt의 비밀번호는 hacking exposed이네요.

LOB의 시작 계정은 gate/gate입니다.

gremlin.c의 소스를 확인해 보도록 하겠습니다.

간단한 코드네요.

strcpy를 사용 하고 있으므로 쉘코드를 등록하고 ret를 쉘코드의 주소로 변경해 주면 될것 같습니다.

gdb로 확인해 본 결과 strcpy에서 입력하는 주소의 위치가 ebp-256이므로 ret를 덮어 쓰기 위해서는 260byte를 채우고 쉘코드의 주소를 입력해 주면 될 것 같습니다.

 

그럼 쉘코드를 등록하고 주소를 확인 하도록 하겠습니다.

그전에 우선 bash에서는 \xff를 인식 못하는 버그가 있으므로 bash2를 사용하도록 하겠습니다.

bash2로 쉘을 변경해 주고, 쉘코드를 등록한 후 쉘코드의 주소를 확인했습니다.

쉘코드의 주소는 0xBFFFFE3D이네요.

 

이제 260byteA로 채우고 0xBFFFFE3D을 입력해주겠습니다.

 

…………

Segmentation fault…극혐이네요..

몇번을 해도 계속 Segmentation fault가 떠서 방법을 바꾸도록 하겠습니다.

(분명 그냥 풀땐 떴는데…… 라이트업 쓰려고 하니 안뜨네.. 망할 시연의 법칙ㅡㅡ)

 

대신 사용할 방법은 RTL입니다.

RTL이란 Return To Library의 줄임말로 기본적으로 system()를 이용합니다.

만약 system(“/bin/sh”);라는 명령을 입력할 수 있다면, 쉘이 뜨겠죠?

 

스택을 보면서 간단히 설명해 드리도록 하겠습니다.

argv

argc

ret

sFP

buffer(256byte)

현재 스택 상황입니다.

쉘코드를 통한 문제 풀이는 ret를 쉘코드가 들어있는 주소로 덮어 씌워 주는 것이죠.

 

RTL을 통한 문제풀이도 크게 다르지 않습니다.

만약 retsystem()이 들어있는 주소로 덮어 씌우면 함수가 끝날때 eipsystem()으로 바뀌게 됩니다.

그리고 system함수 시작지점에서 push ebp 를 해줄태고 mov ebp, esp를 해주게 됩니다.

그리고 system함수는 ebp+8지점을 첫번째 인자로 사용합니다.

 

즉 스택을 다음과 같이 구성하면 system(“/bin/sh”);를 호출하게 되겠죠.

“/bin/sh”’s address

Junk (4byte)

system()’s address

8byte가 아니고 4byte인지 이해가 안가실 수 있으니 다시 설명해 드리겠습니다.(제가 그랬습니다…)

 

함수가 끝나면 ret(pop eip)를 통해 system함수의 주소가 eip로 들어갑니다.

그럼 pop을 했으니 스택은 다음과 같이 됩니다.

“/bin/sh”’s address

Junk (4byte)

 

그리고 system함수의 프롤로그 push ebp, mov ebp, esp를 하게되면 스택이 다음과 같이 바뀌게 됩니다.

“/bin/sh”’s address

Junk (4byte)

SFP

이부분이 system함수의 프롤로그가 지난 부분입니다. Ebp+8지점에 첫번째 인자가 들어가 있음을 알수 있습니다. Junksystem함수가 끝난 후의 return 주소가 들어가게 되겠네요.

보통 프로그램의 정상적인 종료를 위해 junkexit()함수의 주소값을 넣어주기도 합니다.

 

그럼 우리가 만들어 주어야 할 스택의 전체적인 모습은 다음과 같이 됩니다.

“/bin/sh”’s address

junk (4byte)

system()’s address

SFP

buffer(256byte)

 

이러한 스택을 만들어 주기 위해서는 우선 system()함수가 들어있는 주소를 알아내야 합니다.

 

gremlin을 복사해 gdb로 열어 확인하도록 하겠습니다.

main에 중단점을 설정하고 실행한후 system함수의 위치를 구하였습니다. 0x40058ae0system이 들어있네요.

 

이제 /bin/sh의 문자열을 메모리에 넣고 주소값만 얻으면 됩니다.

메모리에 있는 /bin/sh문자열의 주소값을 비교를 통해 얻었습니다.

주소는 0x400fbff9이네요.

 

이제 다음과 같이 스택을 채우면 됩니다.

0x400fbff9

Junk (4byte)

0x40058ae0

SFP

Buffer(256byte)

 

“A”*260 + “\xe0\x8a\x05\x40” + “\x90”*4 + “\xf9\xbf\x0f\x40” 이렇게 입력해주면 될듯 합니다.

정상적으로 gremlin권한의 쉘이 떴네요.


gremlin의 패스워드는 hello bof world입니다.

+ Recent posts