버퍼가 40이 할당되어있습니다!
argc<2 일시 에러를 띄우고 종료를 해버리네요
egghunter에 보면 memset이라는 함수가 있네요
memset 참고 : http://itguru.tistory.com/104
egghunter는 미리 말씀 드리자면 환경변수와 에그쉘을 무효화 시킵니다
argv[1] 즉 첫번째 인자의 48번째 글자?는 /xbf여야합니다 안그러면 문구를 띄우고 종료를 시켜버리네요
또한 argv[1]을 strcpy를 이용해서 버퍼에 복사한후에 출력해버리네요
[strcpy 취약점 - 복사할때 크기를 체크하지않는다]
저는 여태까지 환경변수와 에그쉘을 이용하지 않앗기에 평소처럼 풀면되는 문제같네요 일단 gdb로 봐보겠습니다
<main> push %ebp
<main+1> mov %ebp , %esp
스택프레임을 설정하였습니다
<main+3> sub %esp , 44
buf 와 i 의 크기 총 44를 확장해줬습니다
<main+6> cmp DWORD PTR [%ebp+8] , 1
argc 과 1을 비교한다
<main+10> jg 0x8048523 <main+35>
argc가 1보다 클 경우 main+35로 이동한다
<main+12> push 0x8048630
stdin같은 입력스트림을 넣어줍니다
<main+17> call 0x8048410 <printf>
printf 함수를 호출합니다
<main+22> add %esp,4
printf에서 사용한 인자를 정리해줍니다
<main+25> push 0
0을 넣어줍니다
<main+27> call 0x8048420 <exit>
exit 함수를 호출합니다
<main+32> add %esp , 4
exit인자를 정리해줍니다
<main+35> nop
필요없음
<main+36> mov DWORD PTR [%ebp-44] , 0x0
0을 %ebp-44의 주소에 넣는다
<main+43> nop
필요없음
<main+44> lea %esi , [%esi*1]
%esi에 [%esi*1]의 주소값을 넣어줍니다
<main+48> mov %eax,DWORD PTR [%ebp-44]
eax에 [%ebp-44]의 주소값을 넣어줍니다
<main+51> lea %edx , [%eax*4]
edx에 [%eax*4]의 주소값을 넣어줍니다
<main+58> mov %eax,%ds:0x8049750
<main+63> cmp DWORD PTR [%eax+%edx] ,0
[%ebp-44 + %eax*4] 의 값과 0을 비교합니다
<main+67> jne 0x8048547 <main+71>
위에서 비교한 값이 같지 않으면 <main+71>로 이동합니다
<main+69> jmp 0x8048587 <main+135>
같으면 <main+135>로 점프합니다
간단히 스택을 표현하자면
buf sfp ret argc argv
40 4 4 4 4
ebp - 40 ebp ebp+4 ebp+8 ebp++@
이렇게 되잇는걸 알 수 있습니다 .
main ~ main+3 : 44바이트만큼 주어졌네요 buf[40]의 크기와 i[4]의 크기라고 짐작가능합니다 .
main+6 ~ main+35 : if문 부분이네요 ebp+8[argc]이 2이상이면 main+35로 점프하고 2미만일경우 프로그램을 종료시켜버리네요
<main+71> mov %eax , DWORD PTR [%ebp-44]
eax에 [%ebp-44]의 주소값을 넣어줍니다
<main+74> lea %edx , [%eax*4]
edx 에 [%eax*4] 주소를 넣어줍니다
<main+81> mov %eax,%ds:0x8049750
eax에 0x8049750을 넣어준다
<main+86> mov %edx , DWORD PTR[%eax+%edx]
edx에 [%ebp-44] + [%eax*4] 의 주소를 넣어준다
<main+89> push %edx
edx를 스택에 넣어준다
<main+90> call 0x80483f0<strlen>
strlen 함수를 호출한다
<main+95> add %esp , 4
4의 공간을 사용한다
<main+98> mov %eax , %eax
eax에 eax를 집어넣는다
<main+100> push %eax
eax를 스택에 집어넣는다
<main+101> push 0
0을 집어넣는다
<main+103> mov %eax, DWORD PTR[%ebp-44]
eax에 [%ebp-44]의 주소를 넣는다
<main+106> lea %edx,[%eax*4]
edx에 [%eax*4]를 넣는다
<main+113> mov %eax,%ds:0x8049750
eax에 0x8049750을 넣는다
<main+118> mov %edx , DWORD PTR [%eax+%edx]
edx에 %eax+%edx의 주소를 넣어준다
<main+121> push %edx
edx를 스택에 넣어준다
<main+122> call 0x8048430 <memset>
memset 함수를 호출한다
<main+127> add %esp , 12
12만큼 사용합니다
<main+130> inc DWORD PTR [%ebp-44]
[%ebp-44]의 주소값이 1 증가합니다
<main+133> jmp 0x8048530 <main+48>
main+48로 이동합니다
<main+135> mov %eax,DWORD PTR [%ebp+12]
eax에 argv[0] 을 넣어줍니다
<main+138> add %eax , 4
eax에 4를 더해줍니다
<main+141> mov %edx,DWORD PTR [%eax]
edx에 argv[1]을 넣어줍니다
<main+143> add %edx,47
argv[1]에서 47을 더해줍니다
<main+146> cmp BYTE PTR [%edx] , 0xbf
argv[1][47]의 주소를 0xbf와 비교합니다
<main+149> je 0x80485b0 <main+176>
argv[1][47]과 0xbf가 같으면 <main+176>으로 이동합니다
<main+151> push 0x804863c
stdin 함수를 넣어줍니다
<main+156> call 0x8048410 <printf>
printf 함수를 넣어줍니다
<main+161> add %esp , 4
printf가 사용한 인자를 정리해준다
<main+164> push 0
0을 넣어준다
<main+166> call 0x8048420 <exit>
exit 함수를 호출합니다
<main+171> add %esp , 4
exit가 사용한 인자를 정리해준다
<main+174> mov %esi , %esi
esi에 esi를 넣어줍니다
<main+176> mov %eax,DWORD PTR [%ebp+12]
eax에 argv[0]의 주소를 넣어줍니다
<main+179> add %eax , 4
eax에 4를 넣어줍니다
<main+182> mov %edx , DWORD PTR [%eax]
edx에 argv[1]의 주소를 넣어줍니다
<main+184> push %edx
edx를 스택에 넣어줍니다
<main+185> lea %eax , [%ebp-40]
eax에 [%ebp-40]의 주소값을 넣어줍니다
<main+188> push %eax
ebp-40의 주소를 넣습니다
<main+189> call 0x8048440 <strcpy>
strcpy 함수를 호출합니다
<main+194> add %esp , 8
strcpy 함수가 사용한 인자를 정리해줍니다
<main+197> lea %eax , [%ebp-40]
eax에 [%ebp-40]의 주소값을 넣어줍니다 .
<main+200> push %eax
ebp-40을 스택에 넣어줍니다
<main+201> push 0x8048659
stdin을 넣어줍니다
<main+206> call 0x8048410 <printf>
printf 함수를 호출합니다
<main+211> add %esp , 8
printf 함수가 사용한 인자를 정리해줍니다
------------------------추가했습니다-------------------------------------------------------
main+36부터 for문이 시작됩니다
main+44는 데이터를 복사하는거같습니다(확실치 않습니다 )
48~63까지는 i = 0으로 초기화 하는 작업같습니다
67에서는 값이 같지 않으면 71로 점프를 합니다
69에서는 main+135로 이동합니다
71에서는 eax값에 ebp-44를 복사하였습니다
74에서는 eax*4만큼을 edx에 복사합니다 (주소값..?)
81에서는 eax에 ds:0x8049750의 값을 넣습니다(데이타 세그먼트가 아닐까요?)
86에서는 eax와edx를 합해서 edx에 넣습니다.
89에서는 edx를 넣습니다 .
90에서는 strlen을 호출하네요
95에서는 스택을 4바이트만큼 줄입니다
98에서는 eax값에 eax를 넣습니다 (어떤 의미일까요 ?)
100에서는 eax를 넣습니다
101에서는 0을 넣습니다
103에서는 eax값에 ebp-44를 복사합니다
106에서는 eax*4에 저장되있는 값을 edx에 넣습니다 .
113에서는 ds:0x8049750의 값을 eax에 복사합니다
118에서는 eax와 edx를 합한값을 edx에 복사합니다
121에서는 edx를 넣습니다
122에서는 memset을 호출합니다
127에서는 스택을 12만큼 줄입니다
130에서는 ebp-44를 1만큼 증가시킵니다
133에서는 main+48로 이동합니다
135에서는 ebp+12를 eax에 복사합니다
138에서는 eax에서 4만큼 줄입니다
141에서는 eax를 edx에 복사합니다
143에서는 edx에서 47만큼 줄입니다
146에서는 edx와 0xbf가 값이 같다면
149에서는 main+176으로 이동합니다
151에서는 0x804863c만큼 넣어줍니다
156에서는 printf를 호출합니다
161에서는 esp에서 4만큼 줄입니다
164에서는 0만큼 넣어줍니다
166에서는 exit를 호출합니다
171에서는 esp에서 4만큼 줄입니다
174에서는 esi값을 esi에 복사합니다
176에서는 eax에 ebp+12만큼의 값을 넣습니다
179에서는 eax에서 4만큼을 줄입니다
182에서는 eax의값을 edx에 복사합니다
184에서는 edx의값을 넣습니다
185에서는 eax에 ebp-40에 저장되잇는 값을 넣습니다
188에서는 eax를 넣습니다
189에서는 strcpy를 호출합니다
194에서는 esp에서 8만큼 줄입니다
197에서는 ebp-40에잇는값을 eax에 넣습니다
200에서는 eax를 넣습니다
201에서는 0x8048659를 넣습니다
206에서는 printf를 호출합니다
211에서는 esp에서 8만큼 줄입니다
제가 제대로 분석한것인지는 모르겠습니다..
69에서 130과 133을 보시면 environn[i]의 조건문 부분이고 i++의 증감에 대해서 표현되잇다는걸 아실겁니다
90과 100을 보시면 strlen함수를 실행합니다
101에서는 두번째로 0을 넣습니다
121까지는 0x8049750 [eax+edx]를 이용하여서 environ을 넣는다는건 알겟습니다만 제대로 이해가 가지 않습니다 (gdb로 여러가지를 해봤는데 짧은 지식으로는 실패하였습니다 ㅠㅠ 아시는분은 도와주세요 배우고 싶습니다)
135에서는 ebp+12의 값 즉 argv[0]을 eax에 저장하네요
138에서는 4만큼의 값을 할당한 즉 argv[1]의 값을 만든다고 생각할 수 있습니다
*햇갈려서 맞지 않을 수 있으니 참고만 해주세요 *
141에서는 argv[0] , [1]의 값을 edx에 넣고
143에서는 edx에 47만큼의 값을 할당하는것을 보아하니argv[1][47]을 예상할수잇군요
146에서는 0xbf와 값을 비교한 후에
149에서 같을경우 176으로 이동을해서 프로그램을 쭉 진행하지만 틀릴경우 종료시킵니다.
176에서는 ebp+12 즉 argv[0]을 데려오고
179에서 4만큼 할당해서 argv[1]의 주소를 가리키고있네요
182에서 argv[1]의 주소를 edx에 저장합니다
184에서 edx를 넣습니다 (여기서 strcpy(buffer, argv[1]) 부분이 이뤄지는게 아닐까 예상해봅니다 지식이 부족해서 확신을 못하겠습니다.)
185에서 buffer[40]의 주소를 eax에 넣네요
189에서 strcpy를 호출합니다
194에서 esp에 8만큼을 줄이고
197에 eax 에 ebp-40의 주소를 넣네요
이렇게 대충 분석이 끝난거 같습니다..정말 허접하군요 lob를 끝마치는 날에는 완벽해져있기를 바랍니다 -_-;
공격코드를 테스트 해보려고 gdb로 디버깅을 하던차에
Program exited with code 01. 이라는 에러가 뜨네요
Program exited with code 01. 은 다른 유저의 setUid가 걸려있어서 디버깅이 안되는 에러입니다
이상하네요 tmp에 복사해서 한거같은데...
tmp폴더 내에서 ./를 붙여서 실행하지 않으면 본래 루트에 있던 원본이 실행되는거 같군요 신기합니다 처음알았어요
0xbffffad4 의 세번 째 칸을 보시면 0xbf424242가 출력된것을 보실 수 있습니다.
저 곳이 아마 리턴주소겠구요
이 주소가 argv[2]의 주소라고 생각할 수 있습니다.
그렇다면 a[44]+ret주소값(마지막 자리는 \xbf)+argv[2](쓰레기값들 + 쉘코드)
이렇게 구성될 수 있을거같네요
와 진짜 욕나오네요 ㅎㅎ bash2를 설정안해서 두시간동안 코어덤프 보면서 꼐에속 해맷습니다 계에솟고소오오오오옥 와 열받내요~~깔깔깔깔깔깔깔
사람 매우 열받게 하는 lob였습니다 .
'해커스쿨 lob' 카테고리의 다른 글
LOB darkelf (0) | 2016.05.02 |
---|---|
LOB wolfman (0) | 2016.05.02 |
LOB cobolt (0) | 2016.04.30 |
LOB gremlin (0) | 2016.04.30 |
LOB gate (0) | 2016.04.30 |