티스토리 뷰

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

 

main(int argc, char *argv[])

{

char buffer[40];

FILE *fp;

char *lib_addr, *execve_offset, *execve_addr;

char *ret;

 

if(argc < 2){

printf("argv error\n");

exit(0);

}

 

// gain address of execve

fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r");

fgets(buffer, 255, fp);

sscanf(buffer, "(%x)", &lib_addr);

fclose(fp);

 

fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");

fgets(buffer, 255, fp);

sscanf(buffer, "%x", &execve_offset);

fclose(fp);

 

execve_addr = lib_addr + (int)execve_offset;

// end

 

memcpy(&ret, &(argv[1][44]), 4);

if(ret != execve_addr)

{

printf("You must use execve!\n");

exit(0);

}

 

strcpy(buffer, argv[1]);

printf("%s\n", buffer);

}

 

giant에는 뭔가 복잡해 보이는 소스가 있었다.

아무래도 execve함수의 주소를 구하는 소스인 것 같았고, retexecve함수의 주소가 들어가야 했다. execve()를 이용하여 문제를 풀어야하는데 그럴려면 execve함수는 어떠한 인자값이 넘어가고 스택의 어느부분에 쌓이는지 알아야 했다. 지금까지 이용했던 system()은 인자값이 한 개였지만 execve()3개여서 까다로웠다. execve()는 파일의 경로, argv,envp가 인자로 전달 되었고, execve() 시스템콜을 한 주소의 +8byte주소의 스택에 차례대로 쌓였다.

 

buffersfp 44bytenop로 채운뒤 retexecve() 주소를 넣고 4bytenop로 채운다음 /bin/sh의 주소 0x400fbff9를 넣고 argv[]의 주소, envp의 주소 null이 있는 어딘가의 주소를 채워넣어 공격하면 될 것 같다. 그래서 파일 이름을 /bin/sh로 바꾼 다음 이 경로가 남아있는 스택의 주소를 찾아 넣기로 하였다.

 

우선, 파일이름을 mv를 이용하여 perl을 이용하여 /bin/sh의 주소로 바꿨다.

(주소를 알아보기 위해 giant를 복사한 Giant를 이용하였다.)

 

파일 이름과 경로가 남아있는 대략적인 주소 0xbfffffe9를 찾았고, 더 자세한 주소를 찾기 위해 주소를 올려가면서 스트링을 하나씩 출력해보았다.

파일 이름과 경로가 남아있는 주소 : 0xbfffff7 , null값이 들어있는 스택의 주소 : 0xbffffffb

 

다시 Giant로 바꾼 뒤, 권한이 있는 giant/bin/sh의 주소로 바꿔 공격하였다.

buffer 40bytesfp 4bytenop로 채운 뒤, execve()의 주소인 0x400a9d48을 넣고, 4bytenop/bin/sh의 주소인 0x400fbff9, 아까 찾은 주소인 0xbffffff70xbffffff를 넣었다.

 

 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday